0

I am following Patrick Collins course. At chapter 9, when we do a testnet test on rinkeby. The event is not firing. I am using chainlink Keeper and VRF to run the the code as detailed below.

Console error log

fulfillRandomWords
        works with live Chainlink Keepers and Chainlink VRF, we get a random winner:
    Error: Timeout of 500000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (D:\coding-learning\solidityjsbypatrick\hardhat-smartcontract-lottery\test\staging\Raffle.staging.test.ts)

As you can see, I am getting timeout after 500sec.


helper-network file

const networkConfig: networkConfigInfo = {
    4: {
        name: "rinkeby",
        vrfCoordinatorV2: "0x6168499c0cffcacd319c818142124b7a15e857ab",
        raffleEntranceFee: "10000000000000000", // 0.01 ETH
        gasLane: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", //30 gwei
        subscriptionId: 7783,
        callBackGasLimit: "500000", // 500,000 gas
        keepersUpdateInterval: "30", // in seconds
    },
    .........
    ......
}

chain link VRF screenshot

04 07 2022_16 11 09_REC

Chainlink keeper screenshot image


Staging Test file (TypeScript)

import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { assert, expect } from "chai";
import { BigNumber } from "ethers";
import { ethers, network } from "hardhat";
import { developmentChains } from "../../helper-hardhat-config";
import { Raffle } from "../../typechain-types";

//run onlu on test/main net
developmentChains.includes(network.name)
    ? describe.skip
    : describe("Raffle Staging Test", function () {
          let player: SignerWithAddress;
          let deployer: SignerWithAddress;
          let raffle: Raffle;
          let raffleEntranceFee: BigNumber;
          beforeEach(async () => {
              const accounts = await ethers.getSigners();
              deployer = accounts[0];
              player = accounts[1];
              raffle = await ethers.getContract("Raffle", deployer); //connecting account[0]/deployer with contract. We can use player account to using .connect(player)
              raffleEntranceFee = await raffle.getEnteranceFee();
          });
          describe("fulfillRandomWords", function () {
              it("works with live Chainlink Keepers and Chainlink VRF, we get a random winner", async () => {
                  //enter the raffle
                  console.log("Setting up test...");
                  const startingTimeStamp = await raffle.getLastTimeStamp();

                  console.log("Setting up Listener...");
                  await new Promise<void>(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 {
                              // get data after the winner is picked and event is fired.
                              const recentWinner = await raffle.getRecentWinner();
                              const raffleState = await raffle.getRaffleState();
                              const endingTimeStamp = await raffle.getLastTimeStamp();
                              const winnerFinalBalance = await deployer.getBalance(); //here account[0]/deployer is the only entrant also. So he is the winner.
                              //start assertation
                              assert.equal(raffleState, 0);
                              assert.equal(recentWinner.toString(), deployer.address);
                              assert(endingTimeStamp > startingTimeStamp);
                              await expect(raffle.getPlayer(0)).to.be.reverted;
                              assert.equal(
                                  winnerFinalBalance.toString(),
                                  winnerStartingBalance.add(raffleEntranceFee).toString()
                              );
                              resolve();
                          } catch (e) {
                              console.log(e);
                              reject(e);
                          }
                      });

                      //Entering the raffle
                      console.log("Entering Raffle...");
                      const tx = await raffle.enterRaffle({ value: raffleEntranceFee });
                      await tx.wait(1);
                      const winnerStartingBalance = await deployer.getBalance(); //here account[0]/deployer is the only entrant also. So he is the winner.
                      // And this code Wont compelte untill our listener (above) has finished listening.
                      console.log("Ok, time to wait...");
                  });
              });
          });
      });

Raffle.sol file [Smart contract]


// 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/KeeperCompatible.sol";

error Raffle__SendMoreToEnterRaffle();
error Raffle__RaffleIsNotOpen();
error Raffle__TransferFailed();
error Raffle__UpkeepNotNeeded(uint256 currentBalance, uint256 numPlayers, uint256 raffleState);

contract Raffle is VRFConsumerBaseV2, KeeperCompatibleInterface {
   
    enum RaffleState {
        Open,
        Calculating
    }
    
    uint256 private immutable i_enteranceFee;
    address payable[] private s_players;
    address private s_recentWinner;
    uint256 private s_lastTimeStamp;
    uint256 private immutable i_interval;
    RaffleState private s_raffleState;

    
    VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
    bytes32 private immutable i_gasLane;
    uint64 private immutable i_subscriptionId;
    uint16 private constant REQUEST_CONFIRMATION = 3;
    uint32 private immutable i_callbackGasLimit;
    uint32 private constant NUM_WORDS = 1;

  
    event RaffleEnter(address indexed player);
    event RequestRafflewinner(uint256 indexed requestId);
    event WinnerPicked(address indexed winner);

    constructor(
        address vrfCoordinatorV2,
        uint64 subscriptionId,
        uint256 enteranceFee,
        bytes32 gasLane,
        uint32 callbackGasLimit,
        uint256 interval
    ) VRFConsumerBaseV2(vrfCoordinatorV2) {
        i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
        i_subscriptionId = subscriptionId;
        i_enteranceFee = enteranceFee;
        i_gasLane = gasLane;
        i_callbackGasLimit = callbackGasLimit;
        i_interval = interval;
        s_raffleState = RaffleState.Open;
        s_lastTimeStamp = block.timestamp;
    }

    // To enter into lottery
    function enterRaffle() public payable {
        if (msg.value < i_enteranceFee) {
            revert Raffle__SendMoreToEnterRaffle();
        }
        
        if (s_raffleState != RaffleState.Open) {
            revert Raffle__RaffleIsNotOpen();
        }
        s_players.push(payable(msg.sender));

       
        emit RaffleEnter(msg.sender);
    }

    
    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);
        return (upkeepNeeded, "");
    }

    
    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_CONFIRMATION,
            i_callbackGasLimit,
            NUM_WORDS
        );
        emit RequestRafflewinner(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_players = new address payable[](0);
        s_raffleState = RaffleState.Open;
        s_lastTimeStamp = block.timestamp;
       
        (bool success, ) = recentWinner.call{value: address(this).balance}("");
        if (!success) {
            revert Raffle__TransferFailed();
        }
        emit WinnerPicked(recentWinner);
    }

    //Rest of the getter function..
}

Contract address on rinkeby 0xdc6a50411fb987123bE0D048Cde60c66135e2FDe

1 Answer 1

1

Which Patrick's course are you doing? He has more than one course, could you add the link, with the time that was your doubt?

I saw your contract, and this address is not registered in your VRF Subscription #7783.

I don't know if this version of the course is using VRF v2.

I also saw that the Keepers upkeep [#2025] (https://keepers.chain.link/rinkeby/2025) was canceled.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.