PatrickAlphaC / hardhat-smartcontract-lottery-fcc

MIT License
117 stars 183 forks source link

VM Exception while processing transaction: reverted with custom error 'InvalidConsumer() #171

Closed akashgreninja closed 1 year ago

akashgreninja commented 1 year ago

My Raffle.sol

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

error Raffle_NotENoughETHEntered(); error Raffle_TransferFailed(); error Raffle_NotOpen(); error Raffle_UpKeepNotNeeded(uint256 currentBalance ,uint256 numpLAYERS, uint256 rafflestate);

/**

contract Raffle is VRFConsumerBaseV2, AutomationCompatibleInterface { enum RaffleState { OPEN, CALCULATING } 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 constant NUM_WORDS = 1; uint32 private immutable i_callbackGasLimit; uint256 private s_lastTimeStamp; uint256 private immutable i_interval; // lottery variables address private s_recentWinner; RaffleState private s_raffleState;

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

constructor(
    address vrfCoordinatorV2,
    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 used by chainlink nodes they return true
 */
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);
}

function performUpkeep(bytes calldata /* performData */) external {
    (bool upkeepNeeded , )=checkUpkeep("");
    if (!upkeepNeeded){
        revert Raffle_UpKeepNotNeeded(address(this).balance ,s_players.length,uint256(s_raffleState));
    }
    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 {
    s_raffleState = RaffleState.CALCULATING;
    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);
}

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;
}

}`

My 01-deploy-raffle.js

`const { ethers, network } = require("hardhat");

const { developmentChains, networkConfig, } = require("../helper-hardhat-config"); const { verify } = require("../utils/verify");

const VRF_SUB_AMOUNT = ethers.utils.parseEther("30"); 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 vrfCoorinatorV2Mock = await ethers.getContract( "VRFCoordinatorV2Mock" ); // await vrfCoorinatorV2Mock.addConsumer(subscriptionId, vrfCoorinatorV2Mock.address) vrfCoordinatorV2Address = vrfCoorinatorV2Mock.address; const tansactionResponse = await vrfCoorinatorV2Mock.createSubscription(); const trasactionreciept = await tansactionResponse.wait(1); subscriptionId = trasactionreciept.events[0].args.subId; await vrfCoorinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_AMOUNT); await vrfCoorinatorV2Mock.addConsumer(subscriptionId, vrfCoordinatorV2Address) log('Consumer is added'); } else { vrfCoordinatorV2Address = networkConfig[chainId]["vrfCoordinatorV2"]; subscriptionId = networkConfig[chainId]["subscriptionId"]; console.log(subscriptionId) log("yeetus") } const entranceFee = networkConfig[chainId].entranceFee; const gasLane = networkConfig[chainId]["gasLane"]; const callbackGasLimit = networkConfig[chainId]["callbackGasLimit"]; log("callbackGasLimit", callbackGasLimit) log("gasLane", gasLane) const interval = networkConfig[chainId]["interval"]; const args = [ vrfCoordinatorV2Address, entranceFee, gasLane, subscriptionId, callbackGasLimit, interval, ]; 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("veryfyinh on etherscan"); await verify(raffle.address, args); log("-------------------------"); } };

module.exports.tags = ["all", "raffle"]; `

finally my Raffle.test `const { network, getNamedAccounts, deployments, ethers } = require("hardhat"); const { networkConfig, developmentChains, } = require("../../helper-hardhat-config"); const { assert, expect } = require("chai");

!developmentChains.includes(network.name) ? describe.skip : describe("Raffle", 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("Initilializes the contracts properly the constructor function check in the Raffle", async function () {
      const raffleState = await raffle.getRaffleState();
    //   const getInterval = await raffle.getInterval();
      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 and it is stored in an array ", async function () {
      await raffle.enterRaffle({ value: raffleEntranceFee });
      const player = await raffle.getPlayer(0);

      assert.equal(player, deployer);
    });
    it("emits event on enter ",async function(){
        await expect (raffle.enterRaffle({ value: raffleEntranceFee })).to.emit(raffle,"RaffleEnter");
    })
    it("does not allow when raffle is calculating  ",async function(){
        await raffle.enterRaffle({ value: raffleEntranceFee });
        await network.provider.send("evm_increaseTime",[interval.toNumber()+1])
        await network.provider.request({ method: "evm_mine", params: [] })
        await raffle.performUpkeep([])
        await expect(raffle.enterRaffle({value:raffleEntranceFee})).to.be.revertedWith("Raffle_NotOpen")

    })
  });
});

`

akashgreninja commented 1 year ago

I FIXEDDD IT LESSGOO so the thing is add these lines

      if (developmentChains.includes(network.name)) {
        const vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
        await vrfCoordinatorV2Mock.addConsumer(subscriptionId, raffle.address)
        console.log("Consumer is added and this was the fix ig");
    }

at the end of your 01-deploy-raffle

overall code is

const { ethers, network } = require("hardhat");

const {
  developmentChains,
  networkConfig,
} = require("../helper-hardhat-config");
const { verify } = require("../utils/verify");

const VRF_SUB_AMOUNT = ethers.utils.parseEther("30");
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 vrfCoorinatorV2Mock = await ethers.getContract(
      "VRFCoordinatorV2Mock"
    );
    // await vrfCoorinatorV2Mock.addConsumer(subscriptionId, vrfCoorinatorV2Mock.address)
    vrfCoordinatorV2Address = vrfCoorinatorV2Mock.address;
    const tansactionResponse = await vrfCoorinatorV2Mock.createSubscription();
    const trasactionreciept = await tansactionResponse.wait();
    subscriptionId = trasactionreciept.events[0].args.subId;
    log("subscriptionId", subscriptionId);
    await vrfCoorinatorV2Mock.fundSubscription(subscriptionId, VRF_SUB_AMOUNT);
    // await vrfCoorinatorV2Mock.addConsumer(subscriptionId, vrfCoordinatorV2Address)
    // log('Consumer is added');
  } else {
    vrfCoordinatorV2Address = networkConfig[chainId]["vrfCoordinatorV2"];
    subscriptionId = networkConfig[chainId]["subscriptionId"];
    console.log(subscriptionId);
    log("yeetus");
  }
  const entranceFee = networkConfig[chainId].entranceFee;
  const gasLane = networkConfig[chainId]["gasLane"];
  const callbackGasLimit = networkConfig[chainId]["callbackGasLimit"];
  log("callbackGasLimit", callbackGasLimit);
  log("gasLane", gasLane);
  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,
  });
      // Ensure the Raffle contract is a valid consumer of the VRFCoordinatorV2Mock contract.
      if (developmentChains.includes(network.name)) {
        const vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock")
        await vrfCoordinatorV2Mock.addConsumer(subscriptionId, raffle.address)
        console.log("Consumer is added and this was the fix ig");
    }

  if (
    !developmentChains.includes(network.name) &&
    process.env.ETHERSCAN_API_KEY
  ) {
    log("veryfyinh on etherscan");
    await verify(raffle.address, args);
    log("-------------------------");
  }
};

module.exports.tags = ["all", "raffle"];
21fahm commented 1 year ago

You can close if you found the solution 😁