PatrickAlphaC / hardhat-nft-fcc

100 stars 139 forks source link

Own Unit Test RandomIpfsNft: Minter shouldn't be the consumer (InvalidConsumer()) #77

Closed achimstruve closed 1 year ago

achimstruve commented 1 year ago

Hi everyone,

I tried writing my own tests, where I want to see if a minter who is not the deployer can mint an NFT, so that his balanceOf the NFT is equal to "1" and that calling the ERC721 ownerOf function returns the actual minter address.

I get the following error within my test and I know why. I just don't know how the architecture should be to solve it. Error: VM Exception while processing transaction: reverted with custom error 'InvalidConsumer()'

My understanding is that the minting process is initialized by the minter by calling the requestNft function on our RandomIpfsNft contract. This in turn calls the requestRandomWords function of the vrfCoordinatorV2, which returns our requestId through an event emit.

The fulfillRandomWords function of the vrfCoordinatorV2 calls the fulfillRandomWordsWithOverride function in it to generate our random number that will be used by calling our own written fulfillRandomWords in our RandomIpfsNft contract. The fulfillRandomWords function of the vrfCoordinatorV2 takes our requestId and a consumer address, which should be the address of our RandomIpfsNft contract instance that has been funded with $LINK.

However, the minting function and thereby the "consumer" that initilized the requestRandomWords was the minter, which shouldn't be the consumer (he should not pay the link).

How can I solve this?

I had a look in the tests of the Repo, but there it seems that the contract itself mints the NFT and thereby the minter is also the consumer, which then doesn't cause this issue.

Hope it makes sense and am very grateful for any suggestions. This is my test:

randomIpfsNft.test.js

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

!developmentChains.includes(network.name)
    ? describe.skip
    : describe("Random IPFS NFT unit test", function () {
          let randomIpfsNft, vrfCoordinatorV2Mock, deployer, mintFee
          const chainId = network.config.chainId
          beforeEach(async function () {
              deployer = (await getNamedAccounts()).deployer
              await deployments.fixture(["all"])
              randomIpfsNft = await ethers.getContract("RandomIpfsNft", deployer)
              vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer)
              mintFee = await randomIpfsNft.getMintFee()
          })

          describe("Mint NFT", function () {
              it("minter has balance of 1 after mint and is owner", async function () {
                  // get other accounts
                  const accounts = await ethers.getSigners()
                  const minter = accounts[1]

                  // let account 1 mint the nft
                  const accountConnectedToRandomIpfsNft = randomIpfsNft.connect(minter)
                  const tx = await accountConnectedToRandomIpfsNft.requestNft({ value: mintFee })
                  const txReceipt = await tx.wait(1)
                  const tx2 = await vrfCoordinatorV2Mock.fulfillRandomWords(
                      txReceipt.events[1].args.requestId,
                      randomIpfsNft.address
                  )
                  const tx2Receipt = await tx2.wait(1)
                  const mintedTokenId = tx2Receipt.events[1].args.tokenId

                  // get balance of NFTs from the minter
                  const minterBalanceOfNft = randomIpfsNft.balanceOf(minter)
                  assert(minterBalanceOfNft.toString() == "1")

                  // check if minter is owner of the NFT
                  const mintedNftOwner = randomIpfsNft.ownerOf(mintedTokenId.toString())
                  assert(mintedNftOwner == minter.address)
              })
          })
      })
PatrickAlphaC commented 1 year ago

Can you:

  1. Make this a discusson on the full repo? https://github.com/smartcontractkit/full-blockchain-solidity-course-js/
  2. Follow this section for formatting questions? https://www.youtube.com/watch?t=19846&v=gyMwXuJrbJQ&feature=youtu.be