Lesson 9: Rinkeby: "Error: invalid BigNumber value (argument="value", value=undefined, code=INVALID_ARGUMENT," #1980
-
So I had this exact error before when we deployed to our localhost and I'm having it again as we deploy to rinkeby. Someone helped me solve it the first time by letting me know to have all my arguments in the same order across the Raffle.sol, 01-deploy-raffle.js, and helper-hardhat-config.js. That fixed it while I was deploying to localhost. I made sure all my arguments were in the same order this time around too but, that didn't resolve it. I would appreciate help. helper-hardhat-config.js const { network, ethers } = require("hardhat")
const networkConfig = {
default: {
name: "hardhat",
keepersUpdateInterval: "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,
} 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.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;
}
} 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
}
}; 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"] Please let me know if you need anything else from me! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Could you share |
Beta Was this translation helpful? Give feedback.
-
Hey @emmanuelf37 please share your 01-deploy-raffle.js file and in the meantime, rename the variable |
Beta Was this translation helpful? Give feedback.
Hey @emmanuelf37 please share your 01-deploy-raffle.js file and in the meantime, rename the variable
keepersUpdateInterval
asinterval
in yourhelper-hardhat-config.js
This is if you use
networkConfig[chainId]["interval"]
in your deploy scripts to retrieve the interval