-
Hi there, I'm stuck at my unit test in lesson 9 and after reading a lot of discussions I cannot come to a solution. The issue is that I'm unable to successfully call the
I have a test file where I manipulate the time and block mined and call the 1. describe("enterRaffle", async () => {
2. it("should not allow entrance when the raffle state is set to calculating", async () => {
3. await raffle.enterRaffle({ value: raffleEntranceFee })
4. const increasedInterval = Number(interval) + 10
5.
6. // manipulate time on evm
7. await network.provider.send("evm_increaseTime", [increasedInterval])
8. await network.provider.send("evm_mine", []);
9.
10. // calling chainlink keeper
11. const zeroBytes = new Uint8Array()
12. await raffle.performUpkeep(zeroBytes)
13.
14. await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.be.revertedWithCustomError(raffle, "Raffle__NotOpen")
15.
16. })
17. }) Line 11 results in the following error:
Interval is coming from my "31337": {
name: "hardhat",
entranceFee: ethers.parseEther("0.01"),
gasLane: "0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c", // doesn't matter on hh
subscriptionId: "0",
callbackGasLimit: "500000",
interval: 30
}, My 1. const deployRaffle: DeployFunction = async ({ getNamedAccounts, deployments, network }) => {
2. const { deploy, log } = deployments;
3. const { deployer, player } = await getNamedAccounts();
4. const chainId: number = network.config.chainId!;
5.
6. let vrfCoordinatorV2Adress: (string | Addressable) | (string | undefined),
7. subscriptionId: number | string | undefined,
8. vrfCoordinatorV2Mock;
9.
10. if (developmentChains.includes(network.name)) {
11. vrfCoordinatorV2Mock = await ethers.getContractAt("VRFCoordinatorV2Mock", deployer);
12.
13. vrfCoordinatorV2Adress = vrfCoordinatorV2Mock.target;
14.
15. // create a subscription programmatically
16. const transactionResponse: ContractTransactionResponse = await vrfCoordinatorV2Mock.createSubscription();
18. const transactionReceipt: ContractTransactionReceipt = (await transactionResponse.wait()) as ContractTransactionReceipt;
19.
20. // NOT WORKING => transactionReceipt.events[0].args.subId;
21. subscriptionId = 1;
22.
23. // fund the subscription
24. await vrfCoordinatorV2Mock.fundSubscription(subscriptionId, FUND_AMOUNT);
25.
26. } else {
27. vrfCoordinatorV2Adress = networkConfig[chainId].vrfCoordinatorV2;
28. subscriptionId = networkConfig[chainId].subscriptionId;
29. }
30.
31.
32. // constructer arguments
33. const args = [
34. vrfCoordinatorV2Adress,
35. networkConfig[chainId].entranceFee,
36. networkConfig[chainId].gasLane,
37. subscriptionId,
38. networkConfig[chainId].callbackGasLimit,
39. networkConfig[chainId].interval,
40. ];
41.
42. const deployOptions = {
43. from: deployer,
44. args: args,
45. log: true,
46. waitConfirmations: 1,
47. };
48. const raffle: DeployResult = await deploy("Raffle", deployOptions);
49.
50. if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) {
51. log("[deploy script] verifying contract...");
52. await verify(raffle.address, args);
53. }
54. };
55.
56. export default deployRaffle;
57. deployRaffle.tags = ["all", "raffle"]; Note: I had some trouble earlier with line 20 but found out about the hard coded solution in an other discussion, which seems to work. Because I'm using hardhat locally My solidity contract 1. // SPDX-License-Identifier: MIT
2. pragma solidity ^0.8.19;
3.
4. import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
5. import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
6. import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";
7.
8. // * errors
9. error Raffle__NotOpen();
10. error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState);
11.
12. contract Raffle is VRFConsumerBaseV2, AutomationCompatible {
13. // * type declarations
14. enum RaffleState {
15. OPEN,
16. CALCULATING
17. }
18.
19. // * state variables
20. uint256 private immutable i_entranceFee;
21. address payable[] private s_players;
22. VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
23. bytes32 private immutable i_gasLane;
24. uint64 private immutable i_subscriptionId;
25. uint16 private constant REQUEST_CONFIRMATIONS = 3;
26. uint32 private immutable i_callbackGasLimit;
27. uint32 private constant NUM_WORDS = 1;
28. uint256 private s_lastTimestamp;
29. uint256 private immutable i_interval;
30.
31. // * lottery variables
32. RaffleState private s_raffleState;
33.
34. // * functions
35. constructor(
36. address vrfCoordinatorV2, //contract
37. uint256 entranceFee,
38. bytes32 gasLane,
39. uint64 subscriptionId,
40. uint32 callbackGasLimit,
41. uint256 interval
42. ) VRFConsumerBaseV2(vrfCoordinatorV2) {
43. i_entranceFee = entranceFee;
44. i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
45. i_gasLane = gasLane;
46. i_subscriptionId = subscriptionId;
47. i_callbackGasLimit = callbackGasLimit;
48. s_raffleState = RaffleState.OPEN;
49. s_lastTimestamp = block.timestamp;
50. i_interval = interval;
51. }
52.
53. function checkUpkeep(
54. bytes memory /* checkData */
55. ) public view override returns (bool upkeepNeeded, bytes memory /* performData */) {
56. bool isOpen = (RaffleState.OPEN == s_raffleState);
58. // (block.timestamp - lastBlockTimestamp) > interval
59. bool timePassed = ((block.timestamp - s_lastTimestamp) > i_interval);
60. bool hasPlayers = (s_players.length > 0);
61. bool hasBalance = address(this).balance > 0;
62. upkeepNeeded = (isOpen && timePassed && hasPlayers && hasBalance && hasPlayers);
63. return (upkeepNeeded, "0x0");
64. }
65.
66. function performUpkeep(bytes calldata) external override /* performData */ {
67. // check if upkeep is needed
68. (bool upkeepNeeded, ) = checkUpkeep("");
69.
70. if (!upkeepNeeded) {
71. revert Raffle__UpkeepNotNeeded(
72. address(this).balance,
73. s_players.length,
74. uint256(s_raffleState)
75. );
76. }
77.
78. // request random number
79. // revert if subscription is not set and funded.
80. s_raffleState = RaffleState.CALCULATING;
81. uint256 requestId = i_vrfCoordinator.requestRandomWords(
82. i_gasLane, // gasLane
83. i_subscriptionId,
84. REQUEST_CONFIRMATIONS,
85. i_callbackGasLimit,
86. NUM_WORDS
87. );
88.
89. // once we get it, do something with it
90. emit RequestedRaffleWinner(requestId);
91. }
92.
93. // * view, pure functions
94. function getInterval() public view returns (uint256) {
95. return i_interval;
96. }
97. }
The error points to line 80 but I cannot figure out what's wrong. Looking forward to suggestions! :) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
Hi @r-bytes The problem might be in ethers v6 as for v5 I know that both of below methods works when passing empty bytes array: raffle.performUpkeep([])
raffle.performUpkeep("0x") For ethers v6 I belive only Same this with below: await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
// or you can call it like below:
await network.provider.request({ method: "evm_mine", params: [] })
// Only one method works in ethers v6 |
Beta Was this translation helpful? Give feedback.
-
Update: I was not able to fix this issue with I found out that my subscription simply wasn't created, no matter what I did. For some reason I'm unable to successfully create a subscription using this piece of code: await vrfCoordinatorV2Mock.createSubscription() With For everybody reading this: just use Like this: const deployOptions = {
from: deployer,
args: args,
log: true,
waitConfirmations: 1,
};
const raffle: DeployResult = await deploy("Raffle", deployOptions);
if(developmentChains.includes(network.name)) {
console.log("adding raffle contract as consumer");
await vrfCoordinatorV2Mock?.addConsumer(subscriptionId.toNumber(), raffle.address)
console.log("consumer added!");
} If anyone managed to get it to work with |
Beta Was this translation helpful? Give feedback.
Update: I was not able to fix this issue with
ethers v6
.I found out that my subscription simply wasn't created, no matter what I did.
For some reason I'm unable to successfully create a subscription using this piece of code:
With
ethers v5
I was able to create the subscription but got an other error:reverted with custom error 'InvalidConsumer()'
For everybody reading this: just use
ethers v5
and make sure to add your smart contract as a consumer at the bottom of your01-deploy-raffle.ts
script, right after you deploy the contract.Like this: