Lesson 9: Error: invalid BigNumber value #2207
-
Hi, everyone! Getting an Error deploying to Rinkeby testnet. Tried all the answers connected to this error, still no luck. "Error: ERROR processing /home/marblemaster/hh-fcc/hardhat-smartcontract-lottery-fcc/deploy/01-deploy-raffle.js:
Error: invalid BigNumber value (argument="value", value=undefined, code=INVALID_ARGUMENT, version=bignumber/5.6.2)" 01-deploy-raffle.js const { network, ethers } = require("hardhat")
const { developmentChains, networkConfig } = require("../helper-hardhat-config")
const { verify } = require("../helper-hardhat-config")
const VRF_SUB_FUND_AMOUNT = ethers.utils.parseEther("2")
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
let vrfCoordinatorV2Address, subscriptionId
if (developmentChains.includes(network.name)) {
const vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
vrfCoordinatorV2Address = vrfCoordinatorV2Mock.address
const transactionResponse = await vrfCoordinatorV2Mock.createSubscription()
const transactionReceipt = await transactionResponse.wait(1)
subscriptionId = transactionReceipt.events[0].args.subId
// Fund the subscription
// Usually, you'd need the link token on a real network
await vrfCoordinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_FUND_AMOUNT)
} else {
vrfCoordinatorV2Address = networkConfig[chainId]["vrfCoordinatorV2"]
subscriptionId = networkConfig[chainId]["subscriptionId"]
}
const entranceFee = networkConfig[chainId]["entranceFee"]
const gasLane = networkConfig[chainId]["gasLane"]
const callbackGasLimit = networkConfig[chainId]["callbackGasLimit"]
const interval = networkConfig[chainId]["interval"]
const args = [
vrfCoordinatorV2Address,
subscriptionId,
gasLane,
interval,
entranceFee,
callbackGasLimit,
]
const raffle = await deploy("Raffle", {
from: deployer,
args: args,
log: true,
waitConfirmations: network.config.blockConfirmations || 1,
})
if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
log("Verifying...")
await verify(raffle.address, args)
}
if (developmentChains.includes(network.name)) {
const vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
await vrfCoordinatorV2Mock.addConsumer(subscriptionId, raffle.address)
log("Consumer is added")
}
log("-----------------------------------------------------")
}
module.exports.tags = ["all", "raffle"] helper-hardhat-config.js const { network, ethers } = require("hardhat")
const networkConfig = {
default: {
name: "hardhat",
interval: "30",
},
31337: {
name: "hardhat",
entranceFee: ethers.utils.parseEther("0.01"),
gasLane: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc",
subscriptionId: "0",
callbackGasLimit: "500000",
interval: "30",
},
4: {
name: "rinkeby",
vrfCoordinatorV2: "0x6168499c0cFfCaCD319c818142124B7A15E857ab",
subscriptionId: "18416",
gasLane: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", // 30 gwei
keepersUpdateInterval: "30",
entranceFee: ethers.utils.parseEther("0.01"), // 0.1 ETH
callbackGasLimit: "500000", // 500,000 gas
},
1: {
name: "mainnet",
keepersUpdateInterval: "30",
},
}
const developmentChains = ["hardhat", "localhost"]
const VERIFICATION_BLOCK_CONFIRMATIONS = 6
const frontEndContractsFile = "../nextjs-smartcontract-lottery-fcc/constants/contractAddresses.json"
const frontEndAbiFile = "../nextjs-smartcontract-lottery-fcc/constants/abi.json"
module.exports = {
networkConfig,
developmentChains,
VERIFICATION_BLOCK_CONFIRMATIONS,
frontEndContractsFile,
frontEndAbiFile,
} hardhat-config.js require("@nomiclabs/hardhat-waffle")
require("@nomiclabs/hardhat-etherscan")
require("hardhat-deploy")
require("solidity-coverage")
require("hardhat-gas-reporter")
require("hardhat-contract-sizer")
require("dotenv").config()
/** @type import('hardhat/config').HardhatUserConfig */
const COINMARKETCAP_API_KEY = process.env.COINMARKETCAP_API_KEY || ""
const KOVAN_RPC_URL =
process.env.KOVAN_RPC_URL || "https://eth-mainnet.alchemyapi.io/v2/your-api-key"
const RINKEBY_RPC_URL =
process.env.RINKEBY_RPC_URL || "https://eth-mainnet.alchemyapi.io/v2/your-api-key"
const PRIVATE_KEY =
process.env.PRIVATE_KEY || "0x11ee3108a03081fe260ecdc106554d09d9d1209bcafd46942b10e02943effc4a"
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || ""
const API_URL =
process.env.API_URL || "https://eth-rinkeby.alchemyapi.io/v2/UoxMYEe56_n36Ya5-uavkt_TjPOSgMF0"
module.exports = {
solidity: "0.8.7",
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: 31337,
blockConfirmations: 1,
},
rinkeby: {
chainId: 4,
blockConfirmations: 6,
url: RINKEBY_RPC_URL,
accounts: [PRIVATE_KEY],
},
},
gasReporter: {
enabled: false,
currency: "USD",
outputFile: "gas-report.txt",
noColors: true,
},
namedAccounts: {
deployer: {
default: 0,
1: 0,
},
player: {
default: 1,
},
},
mocha: {
timeout: 300000, // 300 seconds
},
} Raffle.sol // Raffle
// Enter the lottery (paying some amount)
// pick a random winner (verifiably random)
// Winner to be selected every X minutes --> completely automated
// Chainlink Oracle --> Randomness, Automated Execution (Chainlink Keeper)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/KeeperCompatible.sol";
import "hardhat/console.sol";
error Raffle__NotEnoughETHEntered();
error Raffle__TransferFailed();
error Raffle__NotOpen();
error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 RaffleState);
/** @title A sample Raffle Contract
* @author Patrick Collins
* @notice This contract is for creating an untamperable decentralized smart contract
* @dev This implements Chainlink VRF v2 and Chainlilnk Keepers
*/
contract Raffle is VRFConsumerBaseV2, KeeperCompatibleInterface {
/* Type declarations */
enum RaffleState {
OPEN,
CALCULATING
} //uint256 0 = OPEN, 1 = CALCULATING
/* State Variables */
uint256 private immutable i_entranceFee;
address payable[] private s_players;
VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
bytes32 private immutable i_gasLane;
uint64 private immutable i_subscriptionId;
uint16 private constant REQUEST_CONFIRMATIONS = 3;
uint32 private immutable i_callbackGasLimit;
uint32 private constant NUM_WORDS = 1;
// Lottery Variables
address private s_recentWinner;
bool private s_state; // to pending, open, closed, calculating
RaffleState private s_raffleState;
uint256 private s_lastTimeStamp;
uint256 private immutable i_interval;
/* Events */
event RaffleEnter(address indexed player);
event RequestedRaffleWinner(uint256 indexed requestId);
event WinnerPicked(address indexed winner);
/* Functions */
constructor(
address vrfCoordinatorV2,
uint64 subscriptionId,
bytes32 gasLane, // keyHash
uint256 interval,
uint256 entranceFee,
uint32 callbackGasLimit
) VRFConsumerBaseV2(vrfCoordinatorV2) {
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_subscriptionId = subscriptionId;
i_gasLane = gasLane;
i_interval = interval;
i_entranceFee = entranceFee;
i_callbackGasLimit = callbackGasLimit;
s_raffleState = RaffleState.OPEN;
s_lastTimeStamp = block.timestamp;
}
function enterRaffle() public payable {
if (msg.value < i_entranceFee) {
revert Raffle__NotEnoughETHEntered();
}
if (s_raffleState != RaffleState.OPEN) {
revert Raffle__NotOpen();
}
s_players.push(payable(msg.sender));
// Emit an event when we update a dynamic array or mapping
// Named events with the function name reversed
emit RaffleEnter(msg.sender);
}
/**
* @dev This is the function that the Chainlink Keeper nodes call
* they look for the `upkeepNeeded` to return true.
* The following should be true in order to return true:
* 1. Our time interval should have passed
* 2. The lottery should have at least 1 player, and have some ETH
* 3. Our subscription is funded with LINK
* 4. The lottery should be in an "open" state.
*/
function checkUpkeep(
bytes memory /*checkData */
)
public
view
override
returns (
bool upkeepNeeded,
bytes memory /* performData */
)
{
bool isOpen = (RaffleState.OPEN == s_raffleState);
bool timePassed = ((block.timestamp - s_lastTimeStamp) > i_interval);
bool hasPlayers = (s_players.length > 0);
bool hasBalance = address(this).balance > 0;
upkeepNeeded = (isOpen && timePassed && hasPlayers && hasBalance);
}
function performUpkeep(
bytes calldata /* performData */
) external override {
(bool upkeepNeeded, ) = checkUpkeep("");
if (!upkeepNeeded) {
revert Raffle__UpkeepNotNeeded(
address(this).balance,
s_players.length,
uint256(s_raffleState)
);
}
s_raffleState = RaffleState.CALCULATING;
uint256 requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane, //gasLane
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
// This is redundant because the vrfCoordinator emits a requestId
emit RequestedRaffleWinner(requestId);
}
function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
uint256 indexOfWinner = randomWords[0] % s_players.length;
address payable recentWinner = s_players[indexOfWinner];
s_recentWinner = recentWinner;
s_raffleState = RaffleState.OPEN;
s_players = new address payable[](0);
s_lastTimeStamp = block.timestamp;
(bool success, ) = recentWinner.call{value: address(this).balance}("");
// require(success)
if (!success) {
revert Raffle__TransferFailed();
}
emit WinnerPicked(recentWinner);
}
/* View / Pure functions */
function getEntranceFee() public view returns (uint256) {
return i_entranceFee;
}
function getPlayer(uint256) public view returns (address) {
uint256 index;
return s_players[index];
}
function getRecentWinner() public view returns (address) {
return s_recentWinner;
}
function getRaffleState() public view returns (RaffleState) {
return s_raffleState;
}
function getNumWords() public pure returns (uint256) {
return NUM_WORDS;
}
function getNumberOfPlayers() public view returns (uint256) {
return s_players.length;
}
function getLatestTimestamp() public view returns (uint256) {
return s_lastTimeStamp;
}
function getRequestConfirmations() public pure returns (uint256) {
return REQUEST_CONFIRMATIONS;
}
function getInterval() public view returns (uint256) {
return i_interval;
}
}
Raffle.staging.test.js const { inputToConfig } = require("@ethereum-waffle/compiler")
const { assert, expect } = require("chai")
const { getNamedAccounts, deployments, network, ethers } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
developmentChains.includes(network.name)
? describe.skip
: describe("Raffle Unit Tests", function () {
let raffle, raffleEntranceFee, deployer
beforeEach(async function () {
deployer = (await getNamedAccounts()).deployer
raffle = await ethers.getContract("Raffle", deployer)
raffleEntranceFee = await raffle.getEntranceFee()
})
describe("fulfillRandomWords", function () {
it("works with live Chainlink Keepers and Chainlink VRF, we get a random winner", async function () {
const startingTimeStamp = await raffle.getLatestTimeStamp()
const accounts = await ethers.getSigners()
await new Promise(async (resolve, reject) => {
// setup the listener before we enter the raffle
// Just in case the blockchain moves REALLY fast
raffle.once("WinnerPicked", async () => {
// This is the listener
console.log("WinnerPicked event fired!")
resolve()
try {
// add our asserts here
const recentWinner = await raffle.getRecentWinner()
const raffleState = await raffle.getRaffleState()
const winnerEndingBalance = await accounts[0].getBalance()
const endingTimeStamp = await raffle.getLatestTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted // Makes sure raffle players array has been reset
assert.equal(recentWinner.toString(), accounts[0].address) // Makes sure recentwinner just equals our deployer
assert.equal(raffleState, 0) // Raffle state back to zero
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalance.add(raffleEntranceFee).toString()
) // Deployer ending balance is equal to his starting balance plus the raffle entrance fee since he's the only player.
assert(endingTimeStamp > startingTimeStamp)
resolve()
} catch (error) {
console.log(error)
reject(e)
}
})
// Now we enter the raffle, since our listener has been setup.
await raffle.enterRaffle({ value: raffleEntranceFee })
const winnerStartingBalance = await account[0].getBalance()
// and this code WONT complete until our listener has finished listening
})
})
})
}) Raffle.test.js const { assert, expect } = require("chai")
const { network, deployments, ethers } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
!developmentChains.includes(network.name)
? describe.skip
: describe("Raffle Unit Tests", function () {
let raffle, raffleContract, vrfCoordinatorV2Mock, raffleEntranceFee, interval, player // , deployer
beforeEach(async () => {
accounts = await ethers.getSigners() // could also do with getNamedAccounts
// deployer = accounts[0]
player = accounts[1]
await deployments.fixture(["mocks", "raffle"]) // Deploys modules with the tags "mocks" and "raffle"
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock") // Returns a new connection to the VRFCoordinatorV2Mock contract
raffleContract = await ethers.getContract("Raffle") // Returns a new connection to the Raffle contract
raffle = raffleContract.connect(player) // Returns a new instance of the Raffle contract connected to player
raffleEntranceFee = await raffle.getEntranceFee()
interval = await raffle.getInterval()
})
describe("constructor", function () {
it("intitiallizes the raffle correctly", async () => {
// Ideally, we'd separate these out so that only 1 assert per "it" block
// And ideally, we'd make this check everything
const raffleState = (await raffle.getRaffleState()).toString()
// Comparisons for Raffle initialization:
assert.equal(raffleState, "0")
assert.equal(
interval.toString(),
networkConfig[network.config.chainId]["keepersUpdateInterval"]
)
})
})
describe("enterRaffle", function () {
it("reverts when you don't pay enough", async () => {
await expect(raffle.enterRaffle()).to.be.revertedWith(
// is reverted when not paid enough or raffle is not open
"Raffle__SendMoreToEnterRaffle"
)
})
it("records player when they enter", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
const contractPlayer = await raffle.getPlayer(0)
assert.equal(player.address, contractPlayer)
})
it("emits event on enter", async () => {
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.emit(
// emits RaffleEnter event if entered to index player(s) address
raffle,
"RaffleEnter"
)
})
it("doesn't allow entrance when raffle is calculating", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
// for a documentation of the methods below, go here: https://hardhat.org/hardhat-network/reference
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
// we pretend to be a keeper for a second
await raffle.performUpkeep([]) // changes the state to calculating for our comparison below
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.be.revertedWith(
// is reverted as raffle is calculating
"Raffle__RaffleNotOpen"
)
})
})
describe("checkUpkeep", function () {
it("returns false if people haven't sent any ETH", async () => {
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert(!upkeepNeeded)
})
it("returns false if raffle isn't open", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
await raffle.performUpkeep([]) // changes the state to calculating
const raffleState = await raffle.getRaffleState() // stores the new state
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert.equal(raffleState.toString() == "1", upkeepNeeded == false)
})
it("returns false if enough time hasn't passed", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() - 5]) // use a higher number here if this test fails
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert(!upkeepNeeded)
})
it("returns true if enough time has passed, has players, eth, and is open", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert(upkeepNeeded)
})
})
describe("performUpkeep", function () {
it("can only run if checkupkeep is true", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const tx = await raffle.performUpkeep("0x")
assert(tx)
})
it("reverts if checkup is false", async () => {
await expect(raffle.performUpkeep("0x")).to.be.revertedWith(
"Raffle__UpkeepNotNeeded"
)
})
it("updates the raffle state and emits a requestId", async () => {
// Too many asserts in this test!
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const txResponse = await raffle.performUpkeep("0x") // emits requestId
const txReceipt = await txResponse.wait(1) // waits 1 block
const raffleState = await raffle.getRaffleState() // updates state
const requestId = txReceipt.events[1].args.requestId
assert(requestId.toNumber() > 0)
assert(raffleState == 1) // 0 = open, 1 = calculating
})
})
describe("fulfillRandomWords", function () {
beforeEach(async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
})
it("can only be called after performupkeep", async () => {
await expect(
vrfCoordinatorV2Mock.fulfillRandomWords(0, raffle.address) // reverts if not fulfilled
).to.be.revertedWith("nonexistent request")
await expect(
vrfCoordinatorV2Mock.fulfillRandomWords(1, raffle.address) // reverts if not fulfilled
).to.be.revertedWith("nonexistent request")
})
// This test is too big...
// This test simulates users entering the raffle and wraps the entire functionality of the raffle
// inside a promise that will resolve if everything is successful.
// An event listener for the WinnerPicked is set up
// Mocks of chainlink keepers and vrf coordinator are used to kickoff this winnerPicked event
// All the assertions are done once the WinnerPicked event is fired
it("picks a winner, resets, and sends money", async () => {
const additionalEntrances = 3 // to test
const startingIndex = 2
for (let i = startingIndex; i < startingIndex + additionalEntrances; i++) {
// i = 2; i < 5; i=i+1
raffle = raffleContract.connect(accounts[i]) // Returns a new instance of the Raffle contract connected to player
await raffle.enterRaffle({ value: raffleEntranceFee })
}
const startingTimeStamp = await raffle.getLastTimeStamp() // stores starting timestamp (before we fire our event)
// This will be more important for our staging tests...
await new Promise(async (resolve, reject) => {
raffle.once("WinnerPicked", async () => {
// event listener for WinnerPicked
console.log("WinnerPicked event fired!")
// assert throws an error if it fails, so we need to wrap
// it in a try/catch so that the promise returns event
// if it fails.
try {
// Now lets get the ending values...
const recentWinner = await raffle.getRecentWinner()
const raffleState = await raffle.getRaffleState()
const winnerBalance = await accounts[2].getBalance()
const endingTimeStamp = await raffle.getLastTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted
// Comparisons to check if our ending values are correct:
assert.equal(recentWinner.toString(), accounts[2].address)
assert.equal(raffleState, 0)
assert.equal(
winnerBalance.toString(),
startingBalance // startingBalance + ( (raffleEntranceFee * additionalEntrances) + raffleEntranceFee )
.add(
raffleEntranceFee
.mul(additionalEntrances)
.add(raffleEntranceFee)
)
.toString()
)
assert(endingTimeStamp > startingTimeStamp)
resolve() // if try passes, resolves the promise
} catch (e) {
reject(e) // if try fails, rejects the promise
}
})
// kicking off the event by mocking the chainlink keepers and vrf coordinator
const tx = await raffle.performUpkeep("0x")
const txReceipt = await tx.wait(1)
const startingBalance = await accounts[2].getBalance()
await vrfCoordinatorV2Mock.fulfillRandomWords(
txReceipt.events[1].args.requestId,
raffle.address
)
})
})
})
}) |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
Push to a repo please; this is incomprehensible. I will look into it. Also, the entire terminal for the error please. |
Beta Was this translation helpful? Give feedback.
-
Hey @marblemaster69 just a simple corrections, change In the meantime, we need more context, what command did you run, and what was the full error logged out in your console? |
Beta Was this translation helpful? Give feedback.
-
@marblemaster69 Push it to GitHub and leave link here, I will debug. |
Beta Was this translation helpful? Give feedback.
Hey @marblemaster69 just a simple corrections, change
keepersUpdateInterval
tointerval
in your helper-hardhat-config.js file because you are usingconst interval = networkConfig[chainId]["interval"]
to retrieve the interval. This might cause problems if you are deploying to rinkeby or mainnet.In the meantime, we need more context, what command did you run, and what was the full error logged out in your console?