2
Error: VM Exception while processing transaction: reverted with custom error 'InvalidConsumer()'

Environment:

  • Hardhat
  • Ethers
  • VsCode

Dependencies:

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();

Replicate the error:

Tests containing await raffle.performUpkeep([])- (Chainlink Keepers) break when reaching this line. No solution found so far after several days of research online.

================================================================

CODE BITS:

| Making reference to this function in VRFCoordinatorV2Mock.sol

  modifier onlyValidConsumer(uint64 _subId, address _consumer) {
    if (!consumerIsAdded(_subId, _consumer)) {
      revert InvalidConsumer();
    }
    _;
  }

================================================================

There is no apparent reason for the test to break as my setup, dependencies and script are in theory identical to the one in the video besides from running all tests succesfully until now.

Test example returning error:

              it("doesn't allow 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"
                  )

================================================================

Setup:

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

!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()
          })

================================================================

| Raffle.sol contract snippet were checkUpkeep() & performUpkeep() are being called

    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, "0x0");
    }

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

================================================================

How can I fix this error by adding a consumer? What would be the proper steps to follow in this scenario?

Thank you!

12
  • 1
    Thanks for making this. When it comes to stackoverflow and stack exchange ETH, please don't link to an external git repo and tell others to run your test suite. That changes the question from "I have a specific question X" -> "debug me". We don't want to answer "debug me" questions, but we do want to answer "I have a specific question X". Jul 11 at 11:42
  • That error usually means that you have an invalid consumer, and you need to add a consumer. Can you add more information to this (but keep all the information contained in the question) Jul 11 at 11:53
  • 1
    Hi Patrick, I was unable to solve this so I started the lesson over to see if I can pinpoint what went wrong. Ifc I figure it out I will post the answer for sure :) Jul 26 at 15:11
  • 2
    I'm also facing this issue with the new version of "@chainlink/contracts": "0.4.2". Switched to the previous version @"0.4.1" and it started working.
    – nikhil
    Jul 28 at 17:49
  • 2
    Can confirm @nikhil that downgrading to 0.4.1 using the following command eliminates the issue: npm i @chainlink/contracts@0.4.1 Jul 30 at 22:38

4 Answers 4

1

I had this issue as well and the solution for me was..edit your deploy-raffle js using the following steps 1 make the the variable that holds "VRFCoordinatorV2Mock" contract a global variable 2 after the raffle contract is deployed use the below code to add raffle's address as a consumer then you are done..

if (chainId == 31337) {
        await vrfCoordinatorV2Mock.addConsumer(subscriptionId.toNumber(), raffle.address)
    }
1
  • For anyone writing tests for lesson 14, you can add the following lines to 02-deploy-random-ipfs-nft.js after deploying the random IPFS contract to eliminate any InvalidConsumer errors: if (developmentChains.includes(network.name)) { vrfCoordinatorV2Mock.addConsumer(subscriptionId.toNumber(), randomIPFSNFT.address ) } Aug 10 at 21:29
0

I have the exact same issue. And I have checked what Patrick said about creating a new costumer. It should have been created when running the .createSubscription on the Deploy function, no ?

module.exports = async ({ getNamedAccounts, deployments }) => {

const { deploy, log, get } = deployments;
const { deployer } = await getNamedAccounts();
const chainId = network.config.chainId;

const VRF_SUBS_FUND_AMT = ethers.utils.parseEther('30');

let vrfCoordinatorV2address, subsId;
if (devChains.includes(network.name)) {
    const VRFCordinator = await ethers.getContract('VRFCoordinatorV2Mock');
    vrfCoordinatorV2address = VRFCordinator.address;
    //Create a subscription using the mock
    **const txResponse = await VRFCordinator.createSubscription();**
    const txReceipt = await txResponse.wait(1);
    subsId = txReceipt.events[0].args.subId;
1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Aug 2 at 10:52
0

I have the exact same issue. After debugging the code, I found we have to add the Raffle contract's address to VRFCoordinatorV2Mock's consumers by add the following code to your deploy file (for me it is 01-deploy-raffle.js):

if (chainId == 31337) {
        await vrfCoordinatorV2Mock.addConsumer(subscriptionId.toNumber(), raffle.address)
    }
0

as done manually for testnet (Look into https://youtu.be/rdJ5d8j1RCg by chainlink) , we have to create a VRFCoordinatorV2 (VRFCoordinatorV2Mock in case of local testing), fund it and then have to add our contract to allowedConsumers list.

Following code we should add after deploying our raffle smart contract

if (developmentChains.includes(network.name)) {
    await vrfCoordinatorV2Mock.addConsumer(subscriptionId, raffle.address);

    log('Consumer is added');
  }
New contributor
Deept Shukla is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
1
  • Here the issue is that we should be adding our smartcontract as the consumer to the chainLink vrfCoordinator. We do the same through GUI: Creation of vrfCoordinator (Only required for local testing, on test-net this is already provided by the chainlink) Creation of subscription Addition of your smart contract to the consumers list (Only after this, our smartcontract can use requestRandomWords) When doing this programatically, we have to add the above code after we deploy our raffle smart contract Aug 9 at 18:33

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.