Open tujigogo opened 2 years ago
I catched the same problem, I forgot to added timeout mocha to hardhat.config.js
mocha: {
timeout: 500000,
},
I was having the same issue.
Fixed it by changing
event RequestedRaffleWinner(uint256);
to
event RequestedRaffleWinner(uint256 indexed requestId);
in my Raffle.sol.
I still have this error, please has anyone solved it?
I still have this error, please has anyone solved it?
Can you attach your Raffle.sol?
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9;
// Import this file to use console.log import "hardhat/console.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; // import "@chainlink/contracts/src/v0.8/interfaces/KeeperCompatibleInterface.sol"; import "@chainlink/contracts/src/v0.8/KeeperCompatible.sol";
error LotteryNotEnoughEthSent(); error LotteryTransferFailed(); error LotteryLotteryNotOpen(); error LotteryNoUpdateNeeded();
// in the docs, the "VRFv2Consumer" is our Contract. So what that contract is doing is what our contract should be doing plus our own added functionalities ;)
/**
contract Lottery is VRFConsumerBaseV2, KeeperCompatibleInterface { //Enter the lottery (pay some amount) //Pick a random winner (verifyably random) //Winner to be selected every X minutes -> completely automated //Chainlink oracle -> Randomness (chainlink VRF), Automated execution (chainlink keepers)
/* Type Declarations */
enum LotteryState {
OPEN,
CALCULATING
}
/*State variables */
VRFCoordinatorV2Interface private immutable i_coordinator; //big guy coordinating the request
uint256 private immutable i_entranceFee;
address payable[] private s_players; // because one of these address will receive money
bytes32 private immutable i_keyhash; // this is to set a max gas price so incase a request for a random number is too high, that request fails. gotten from the VRF docs
uint64 private immutable i_subscriptionId;
uint32 private immutable i_callbackGasLimit; // gotten from the VRF docs
uint16 private constant REQUEST_CONFIRMATIONS = 3;
uint32 private constant NUM_WORDS = 1;
/*Lottery Variables */
address private s_recentWinner;
LotteryState private s_lotteryState;
uint256 private s_lastTimeStamp;
uint256 private immutable i_interval;
/*Events */
event LotteryEnter(address indexed player); // "indexed" so that it's easily searchable in the logs
event RequestedLotteryWinner(uint256 indexed requestId);
event WinnerPicked(address indexed winner);
constructor(
address vrfCoordinatorV2,
uint256 _entranceFee,
bytes32 keyHash,
uint64 subscriptionId,
uint32 callbackGasLimit,
uint256 interval
) VRFConsumerBaseV2(vrfCoordinatorV2) {
i_coordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_entranceFee = _entranceFee;
i_keyhash = keyHash;
i_subscriptionId = subscriptionId;
i_callbackGasLimit = callbackGasLimit;
s_lotteryState = LotteryState.OPEN;
s_lastTimeStamp = block.timestamp;
i_interval = interval;
}
function enterLottery() public payable {
if (msg.value < i_entranceFee) {
revert Lottery__NotEnoughEthSent();
}
if (s_lotteryState != LotteryState.OPEN) {
revert Lottery__LotteryNotOpen();
}
s_players.push(payable(msg.sender));
emit LotteryEnter(msg.sender);
}
/**
* @dev This is the function that the Chainlink keeper node calls
* they look for the "upkeepNeeded" to return true
* The following should be true for upkeepNeeded to return true:
* 1. Our time interval should have passed
* 2. The lottery should have at least 1 player and some ETH
* 3. Our subscription is funded with LINK
* 4. The lottery should be in an "open" state
*/
function checkUpkeep(
// this function is required by the chainlink Keepers nodes to check if an update is needed
bytes memory /*checkData */ // "public" makes this funtion accessible to us in the contract so we can read from it in "performUpkeep"
)
public
view
override
returns (
bool upkeepNeeded,
bytes memory /*performData*/
)
{
bool isOpen = (s_lotteryState == LotteryState.OPEN);
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(
/**
* this was used to replace the "requestRandomWords()" function required by chainlink VRF nodes so that the chainlink Keepers nodes can call it automatically when an update is needed
*/
bytes calldata /*performData */
) external override {
(bool updateNeeded, ) = checkUpkeep("");
if (!updateNeeded) {
revert Lottery__NoUpdateNeeded();
}
s_lotteryState = LotteryState.CALCULATING;
// Request the random Winner
// Once we get it, do something with it
uint256 requestId = i_coordinator.requestRandomWords(
i_keyhash,
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS // number of random values we requested for
);
// the first event will come when the "requestRandomWords" function is fired in our Mock VRF Coordinator
emit RequestedLotteryWinner(requestId); // this will actually be the second event emitted
}
function fulfillRandomWords(
// this function is required and automatically called by the chainlink VRF nodes to perform a task when valid request id is given and a random number is generated
uint256, /*requestId*/
uint256[] memory randomWords
) internal override {
uint256 indexOfWinner = randomWords[0] % s_players.length; // the vrf nodes send a random value using "randomWords" that can now be used in the contract as we please
address payable recentWinner = s_players[indexOfWinner];
s_recentWinner = recentWinner;
s_lotteryState = LotteryState.OPEN;
s_players = new address payable[](0);
s_lastTimeStamp = block.timestamp;
(bool success, ) = recentWinner.call{value: address(this).balance}("");
if (!success) {
revert Lottery__TransferFailed();
}
emit WinnerPicked(recentWinner);
}
/*View / Pure functions */
function getEntranceFee() public view returns (uint256) {
return i_entranceFee;
}
function getPlayer(uint256 index) public view returns (address) {
return s_players[index];
}
function getRecentWinner() public view returns (address) {
return s_recentWinner;
}
function getLotteryState() public view returns (LotteryState) {
return s_lotteryState;
}
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;
}
}
I replaced "Raffle" with "Lottery"
I replaced "Raffle" with "Lottery"
Check your arguments for the contract constructor especially your interval and hash value
I also have the same issue. I believe the problem is in :
await vrfCoordinatorV2Mock.fulfillRandomWords(
txReceipt.events[1].args.requestId,
raffle.address
)
I replaced "Raffle" with "Lottery"
Also please check if you have called resolve() in your try block
I also run into an issue when running a staging test. The CLI throws this error msg : For async tests and hooks, ensure "done()" is called . So the test will not finish and ends up being stopped by the mocha timeout set in hh config file.
abondance68 I'm on the same page as you right now. I'm not sure if you've figured out the problem yet but what I've seen so far is that the promise isn't being resolved due to something blanking out in here: `raffle.once("WinnerPicked", async () => { console.log("WinnerPicked event fired!") 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.getLastTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted
assert.equal(recentWinner.toString(), accounts[0].address)
assert.equal(raffleState, 0)
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalance.add(raffleEntranceFee).toString()
)
assert(endingTimeStamp > startingTimeStamp)
resolve()
} catch (error) {
console.log(error)
reject(error)
}`
I think this has to do with either fetching the random number from the chainlink oracle or could be that we can't enter the raffle. I'm interesting in hearing what you or anyone else has done with this.
I had the same issue with the staging test, but i just ran the same test again with more funds(20 links) in my VRF and the test got passed.
for the first time i ran the test i guess i had a problem in VRF saying that i'm having a low balance and add funds, i guess this might be a problem or if anyone found exactly whats going on would be helpful. nevertheless my test got passed
One more comment about this issue. Don't paste "done" in the async (done) function, it will produce this issue as well
Having same problem.. has anyone resolved? Marcin
Iam not able to pass staging test '// Inorder to test this in test network we need this things //1. Get our SubId for Chainlink VRF //2. Deploy our contract using the SubId //3.Register the contract with chainlink VRF and its subId //4. Register the contract with chainlink keepers //5. Run staging tests
const { assert, expect } = require("chai") const { network, deployments, ethers, getNamedAccounts } = require("hardhat") const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
developmentChains.includes(network.name) ? describe.skip : describe("Raffle Unit Tests", function () { let raffle, raffleEntranceFee, deployer // , deployer const chainId = network.config.chainId
beforeEach(async () => {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(["all"])
raffle = await ethers.getContract("Raffle", deployer)
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer)
interval = await raffle.getInterval()
raffleEntranceFee = await raffle.getEntranceFee()
})
describe("fulfillRandomWords", function () {
it("works with live Chainlink Keepers and Chainlink VRF, we get a random winner", async function () {
// enter the raffle
console.log("Setting up test...")
const startingTimeStamp = await raffle.getLastTimeStamp()
const accounts = await ethers.getSigners()
console.log("Setting up Listener...")
await new Promise(async (resolve, reject) => {
// setup listener before we enter the raffle
// Just in case the blockchain moves REALLY fast
raffle.once("WinnerPicked", async () => {
console.log("WinnerPicked event fired!")
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.getLastTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted
assert.equal(recentWinner.toString(), accounts[0].address)
assert.equal(raffleState, 0)
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalance.add(raffleEntranceFee).toString()
)
assert(endingTimeStamp > startingTimeStamp)
resolve()
} catch (error) {
console.log(error)
reject(error)
}
})
// Then entering the raffle
console.log("Entering Raffle...")
const tx = await raffle.EnterRaffle({ value: raffleEntranceFee })
await tx.wait(1)
console.log("Ok, time to wait...")
const winnerStartingBalance = await accounts[0].getBalance()
// and this code WONT complete until our listener has finished listening!
})
})
})
})'
Iam getting this issue 'ProviderError: Unsupported method: evm_snapshot. See available methods at https://docs.alchemy.com/alchemy/documentation/apis'
for the first time i ran the test i guess i had a problem in VRF saying that i'm having a low balance and add funds, i guess this might be a problem or if anyone found exactly whats going on would be helpful. nevertheless my test got passed
hey can you please tell that after creating contract of Raffel lottery how to deploy it so to get address to put in VRF consumer?As you have in your image Please reply.
I have the contract I just need its address to put in consumer address in vrf so how to get contract address what command should i use
Thanks for the help man. I was stuck at this
Has anyone managed to fix this issue? I have tried copying code from the respoistory for the staging test, raflle.sol, and hardhat config to no avail.... Would really appreciate any input (have also increased the timeout of to 1000000ms and still no luck).
Staging test: `const { assert, expect } = require("chai") const { getNamedAccounts, ethers, network } = require("hardhat") const { developmentChains } = require("../../helper-hardhat-config")
developmentChains.includes(network.name) ? describe.skip : describe("Raffle Staging 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 () {
// enter the raffle
console.log("Setting up test...")
const startingTimeStamp = await raffle.getLatestTimeStamp()
const accounts = await ethers.getSigners()
console.log("Setting up Listener...")
await new Promise(async (resolve, reject) => {
// setup listener before we enter the raffle
// Just in case the blockchain moves REALLY fast
raffle.once("WinnerPicked", async () => {
console.log("WinnerPicked event fired!")
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
assert.equal(recentWinner.toString(), accounts[0].address)
assert.equal(raffleState, 0)
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalance.add(raffleEntranceFee).toString()
)
assert(endingTimeStamp > startingTimeStamp)
resolve()
} catch (error) {
console.log(error)
reject(error)
}
})
// Then entering the raffle
console.log("Entering Raffle...")
const tx = await raffle.enterRaffle({ value: raffleEntranceFee })
await tx.wait(1)
console.log("Ok, time to wait...")
const winnerStartingBalance = await accounts[0].getBalance()
// and this code WONT complete until our listener has finished listening!
})
})
})
})
Raffle.sol ` // SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AutomationCompatibleInterface.sol"; import "hardhat/console.sol";
/ Errors / error RaffleUpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState); error RaffleTransferFailed(); error RaffleSendMoreToEnterRaffle(); error RaffleRaffleNotOpen();
/**@title A sample Raffle Contract
@dev This implements the Chainlink VRF Version 2 / contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface { / Type declarations / enum RaffleState { OPEN, CALCULATING } / State variables */ // Chainlink VRF Variables VRFCoordinatorV2Interface private immutable i_vrfCoordinator; uint64 private immutable i_subscriptionId; bytes32 private immutable i_gasLane; uint32 private immutable i_callbackGasLimit; uint16 private constant REQUEST_CONFIRMATIONS = 3; uint32 private constant NUM_WORDS = 1;
// Lottery Variables uint256 private immutable i_interval; uint256 private immutable i_entranceFee; uint256 private s_lastTimeStamp; address private s_recentWinner; address payable[] private s_players; RaffleState private s_raffleState;
/ Events / event RequestedRaffleWinner(uint256 indexed requestId); event RaffleEnter(address indexed player); event WinnerPicked(address indexed player);
/ Functions / constructor( address vrfCoordinatorV2, uint64 subscriptionId, bytes32 gasLane, // keyHash uint256 interval, uint256 entranceFee, uint32 callbackGasLimit ) VRFConsumerBaseV2(vrfCoordinatorV2) { i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2); i_gasLane = gasLane; i_interval = interval; i_subscriptionId = subscriptionId; i_entranceFee = entranceFee; s_raffleState = RaffleState.OPEN; s_lastTimeStamp = block.timestamp; i_callbackGasLimit = callbackGasLimit; }
function enterRaffle() public payable { // require(msg.value >= i_entranceFee, "Not enough value sent"); // require(s_raffleState == RaffleState.OPEN, "Raffle is not open"); if (msg.value < i_entranceFee) { revert Raffle__SendMoreToEnterRaffle(); } if (s_raffleState != RaffleState.OPEN) { revert Raffle__RaffleNotOpen(); } 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); }
/**
upkeepNeeded
to return True./**
checkUpkeep
is returning true
, this function is called/**
/* Getter Functions /
function getRaffleState() public view returns (RaffleState) { return s_raffleState; }
function getNumWords() public pure returns (uint256) { return NUM_WORDS; }
function getRequestConfirmations() public pure returns (uint256) { return REQUEST_CONFIRMATIONS; }
function getRecentWinner() public view returns (address) { return s_recentWinner; }
function getPlayer(uint256 index) public view returns (address) { return s_players[index]; }
function getLatestTimeStamp() public view returns (uint256) { return s_lastTimeStamp; }
function getInterval() public view returns (uint256) { return i_interval; }
function getEntranceFee() public view returns (uint256) { return i_entranceFee; }
function getNumberOfPlayers() public view returns (uint256) { return s_players.length; } } `
Hardhat config ` 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()
const GOERLI_RPC_URL = process.env.GOERLI_RPC_URL || "https://eth-rinkeby" //do process.env.goerly_rpc_url, and if that doesn't work, do the other seperated by || const PRIVATE_KEY = process.env.PRIVATE_KEY || "0xkey" const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || "key" const COINMARKETCAP_API_KEY = process.env.COINMARKETCAP_API_KEY || "key"
/* @type import('hardhat/config').HardhatUserConfig / module.exports = { defaultNetwork: "hardhat", networks: { hardhat: { chainId: 31337, blockConfirmations: 1 }, goerli: { url: GOERLI_RPC_URL, accounts: [PRIVATE_KEY], chainId: 5, blockConfirmations: 6, }, }, etherscan: { apiKey: ETHERSCAN_API_KEY, }, gasReporter: { enabled: false, currency: "USD", outputFile: "gas-reporter.txt", noColors: true, }, solidity: "0.8.7", namedAccounts: { deployer: { default: 0, }, player: { default: 1, }, }, //set time out for how long it takes an event to be emitted. 200 seconds mocha:{ timeout: 1000000 //500 seconds max for testing }
}; `
The async part of your test is simply not resolving before exceeding the timeout set by your "mocha">>hardhat.config due to one or more of the following reasons:
when i run hardhat test ( I tried both hardhat network and rinkeby network)
the test code is (i just pasted from the repository)
any idea for this ?