Lesson 9: Error While testing performUpkeep #1733
-
raffke .test const { assert, expect } = require("chai")
const { getNamedAccounts, deployments, ethers, network } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
!developmentChains.includes(network.name)
? describe.skip
: describe("Raffle Unit tests", async function () {
let raffle, vrfCoordinatorV2Mock, raffleEntranceFee, deployer, interval
const chainId = network.config.chainId
beforeEach(async function () {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(["all"])
raffle = await ethers.getContract("Raffle", deployer)
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer)
raffleEntranceFee = await raffle.getEntranceFee()
interval = await raffle.getInterval()
})
describe("constructor", async function () {
it("initializes the raffle correctly", async function () {
// ideally we make our tests have just 1 assert per "it"
const raffleState = await raffle.getRaffleState()
assert.equal(raffleState.toString(), "0")
assert.equal(interval.toString(), networkConfig[chainId]["interval"])
})
})
describe("enterRaffle", async function () {
it("reverts when you dont pay enough", async function () {
await expect(raffle.enterRaffle()).to.be.revertedWith(
"Raffle__NotEnoughETHEntered()"
)
})
it("records players when they enter", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
const playerFromContract = await raffle.getPlayer(0)
assert.equal(playerFromContract, deployer)
})
it("emits event on enter", async function () {
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.emit(
raffle,
"RaffleEnter"
)
})
it("dosent alllow entrance when raffle is calculating", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
// We pretend to be a Chainlink Keeper
await raffle.performUpkeep([])
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.be.revertedWith(
"Raffle__NotOpen"
)
})
})
}) 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/KeeperCompatibleInterface.sol";
error Raffle__NotEnoughETHEntered();
error Raffle__TransferFailed();
error Raffle__NotOpen();
error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleSatate);
/** @title A Sample Raffle Contract
* @author Patrick Collins
* @notice This contract is for creating an untamperablee decentralized smart contract
* @dev This implements ChainnlinkVRF V2 and Chainlink Keepers */
contract Raffle is VRFConsumerBaseV2, KeeperCompatibleInterface {
/* Type declarations */
enum RaffleState {
OPEN,
CALCULATING
}
/* stateVariables*/
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 Varibales
address private s_recentWinner;
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);
constructor(
address vrfCoordinatorV2, //contract
uint256 entranceFee,
bytes32 gasLane,
uint64 subscriptionId,
uint32 callbackGasLimit,
uint256 interval
) VRFConsumerBaseV2(vrfCoordinatorV2) {
i_entranceFee = entranceFee;
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_gasLane = gasLane;
i_subscriptionId = subscriptionId;
i_callbackGasLimit = callbackGasLimit;
s_raffleState = RaffleState.OPEN;
s_lastTimeStamp = block.timestamp;
i_interval = interval;
}
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 RaffleEnter(msg.sender);
}
/**
* @dev This is the function that ChainLink Keeper nodess 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 passes
* 2. The Lottery should have at least 1 player , and have some ETH
* 3. Our subscriptiion is funded with LINK
* 4. The Lottery should be in an "open" state.
*/
function checkUpkeep(
bytes memory /*checkData*/
)
public
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);
//block
}
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,
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
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}("");
if (!success) {
revert Raffle__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 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;
}
}
|
Beta Was this translation helpful? Give feedback.
Answered by
sutarrohit
Aug 12, 2022
Replies: 3 comments 2 replies
-
Checkout this discussion. Inform us if it helps your issue. |
Beta Was this translation helpful? Give feedback.
1 reply
-
You have to add consumer manually when you deploy the contract on the local Hardhat network. Add below code in Raffle-deploy.js file if (chainId == 31337) {
await VRFCoordinatorV2Mock.addConsumer(subscriptionId.toNumber(), raffle.address)
} Full Code : const { network, ethers } = require("hardhat")
const { devlopmentChains, networkConfig } = require("../helper-hardhat_config")
const { verify } = require("../utils/verify")
require("dotenv").config()
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY
//Contract Number : 0x165224DC69394A35483b49e89751842011429B05
module.exports = async function (hre) {
const { getNamedAccounts, deployments } = hre
const { log, deploy } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
/**Constructor parameterss */
let vrfcoordintorV2Address
const entranceFee = networkConfig[chainId]["entranceFee"]
const gasLane = networkConfig[chainId]["gasLane"]
let subscriptionId
const callbackgasLimit = networkConfig[chainId]["callbackgasLimit"]
const interval = networkConfig[chainId]["interval"]
let VRFCoordinatorV2Mock
//Calling Mocks function
if (devlopmentChains.includes(network.name)) {
VRFCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
vrfcoordintorV2Address = VRFCoordinatorV2Mock.address
console.log(`Address ${vrfcoordintorV2Address}`)
// /**creating subscription id for mock */
const transactionResponse = await VRFCoordinatorV2Mock.createSubscription()
const transactionReceipt = await transactionResponse.wait()
subscriptionId = transactionReceipt.events[0].args.subId
} else {
vrfcoordintorV2Address = networkConfig[chainId]["vrfCoordinatorV2"]
subscriptionId = networkConfig[chainId]["subscriptionId"]
}
const args = [vrfcoordintorV2Address, entranceFee, gasLane, subscriptionId, callbackgasLimit, interval]
const raffle = await deploy("Raffle", {
from: deployer,
args: args,
log: true,
waitConfirmations: network.config.blockconfirmations || 1,
})
/////ADD HERE : ------------------------------------------------------
// we have to add the Raffle contract's address to VRFCoordinatorV2Mock's consumers
if (chainId == 31337) {
await VRFCoordinatorV2Mock.addConsumer(subscriptionId.toNumber(), raffle.address)
}
///-------------------------------------------------------------------------------
if (!devlopmentChains.includes(network.name) && ETHERSCAN_API_KEY) {
log("Verifying")
await verify(raffle.address, args)
}
log("---------------------------------------------------------------------------------")
}
module.exports.tags = ["all", "raffle"] |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
ritesh798
-
Reply with the helper hardhat config file |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You have to add consumer manually when you deploy the contract on the local Hardhat network.
Add below code in Raffle-deploy.js file
eg.
Full Code :