This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

Testing your Chainlink VRF powered Smart Contract


This text might be quick (hopefully) and attempt to reply one of many burning questions of growing a wise contract which makes use of Chainlink Verifiable Random Operate – “How do I check my sensible contract which makes use of Chainlink VRF?”. To be frank, it isn’t that troublesome.

And whereas yow will discover tons of articles on tips on how to use hardhat, deploy on xyz chain and even on utilizing Chainlink’s merchandise (although Chainlink’s personal docs are second to none), this can be a query that has been seldom explored.

The reply really lies within the query – “How do I emulate a Chainlink VRF?”. You do this by way of one other contract (common terminology being mock contract) which ought to include the features which are invoked by your contract when making an attempt to make use of Chainlink’s VRF. Particularly talking, requestRandomWords and fulfillRandomWords that you simply discover on Chainlink’s VRF oracle contract on any explicit chain. Learn that bit once more. We aren’t speaking about features of comparable identify current in your personal contract however on the VRF oracle contract.

Fortunate for us, on the time of writing, Chainlink gives such mock contracts. Below the present package deal model of @chainlink/contracts, the mocks supplied are MockAggregator.sol, MockAggregatorValidator.sol, VRFCoordinatorMock.sol and VRFCoordinatorV2Mock.sol. The primary two are for Chainlink Price Feeds Oracle, the third one is for Chainlink VRF model 1. We’re extra within the final and the most recent one – VRFCoordinatorV2Mock.sol.



Earlier than We Start

This text might be a follow-up on the earlier article within the sequence however can be learn independently. It assumes primary information of solidity sensible contract improvement and familiarity with Chai testing framework. The code has been open-sourced at this GitHub repo. It’s a Hardhat Venture. You do not want to have familiarity with Hardhat as Chai works with Truffle as nicely and we might be specializing in just one hardhat command – npx hardhat check.

Additionally, I do know that there are paradigms of unit testing, staging assessments and so forth however I gained’t be trustworthy to these on this article because it focuses on simply exhibiting how a Chainlink VRF enabled sensible contract will be examined with Mock Contracts.

Contained in the contracts folder, within the above repo you can see a check folder which comprises our Mock contract. It’s a easy 2-line code which imports the VRFCoordinatorV2Mock.sol contained in the contract. This a basic sample of deploying a contract which can exist inside node_modules folder.



Writing the Checks

Head over to the check folder and you’ll discover the sample-test.js which comprises our assessments. In whole we are going to talk about 4 assessments:

  1. One for testing that our contract requests random numbers efficiently.
  2. One to point out that the Mock Coordinator receives the request from our contract.
  3. As soon as for testing that the Mock Coordinator sends again the random numbers.
  4. And One check to bind all of them.

Sorry about that final bit… my interior Ringer got here out on that final check. The final check will examine if our sensible contract receives the random numbers efficiently from Mock Coordinator. You might have a special logic with what you do with these random numbers however in our sensible contract (mentioned within the earlier article on this sequence) we mint an NFT (bleh… boring).


const { anticipate } = require("chai");
const { BigNumber } = require("ethers");
const { ethers } = require("hardhat");

describe("OurNFTContract", operate () {
  let proprietor;
  let hardhatOurNFTContract, hardhatVrfCoordinatorV2Mock;

  beforeEach(async () => {
    [owner] = await ethers.getSigners();
    let ourNFTContract = await ethers.getContractFactory("OurNFTContract");
    let vrfCoordinatorV2Mock = await ethers.getContractFactory("VRFCoordinatorV2Mock");

    hardhatVrfCoordinatorV2Mock = await vrfCoordinatorV2Mock.deploy(0, 0);

    await hardhatVrfCoordinatorV2Mock.createSubscription();

    await hardhatVrfCoordinatorV2Mock.fundSubscription(1, ethers.utils.parseEther("7"))

    hardhatOurNFTContract = await ourNFTContract.deploy(1, hardhatVrfCoordinatorV2Mock.deal with);
  })
/*
*
Our Checks
*
*/

});
Enter fullscreen mode

Exit fullscreen mode

The above is a few housekeeping earlier than we begin with the assessments. describe is used to (and also you guessed it!) describe the aim of the gathering of assessments. A basic conference is to group your assessments round your sensible contract. So, the identify OurNFTContract in describe means the next assessments are for that contract. The beforeEach hook is run earlier than each check is executed. Inside this hook we’re initializing the proprietor deal with (it will make all of the invocations in our assessments). We deploy VRFCoordinatorV2Mock.sol i.e., the Mock VRF contract.

After this, we create a subscription in our Mock VRF contract and fund it. It doesn’t actually matter right here since that is all accomplished domestically nevertheless it goes the size to emulate an precise Chainlink Verifiable Random Operate Oracle Contract.

Lastly, we deploy NFT contract by passing within the subscription ID and the deal with of the Mock VRF contract. It might be famous right here this for the reason that complete contract deployment course of is completed for the primary time for Mock VRF, the subscription ID generated will at all times be 1.

Understand that the code blocks mentioned beneath for assessments might be positioned in that little part within the code above which says “Our Check”.



Testing if our sensible contract locations the request accurately

Our NFT contract has the movement the place invoking the safeMint() operate will provoke a request to Chainlink VRF. The operate concludes with emitting RequestedRandomness occasion. If the decision has succeeded, then we should always get that occasion from our contract after we invoke the safeMint() operate.

The occasion comprises the next arguments:

  1. Subscription ID
  2. Invoker Deal with
  3. Title of the Character to be minted.

  it("Contract ought to request Random numbers efficiently", async () => {
    await anticipate(hardhatOurNFTContract.safeMint("Halley")).to.emit(
      hardhatOurNFTContract,
      "RequestedRandomness"
    ).withArgs( BigNumber.from(1), proprietor.deal with, "Halley");
  });

Enter fullscreen mode

Exit fullscreen mode

So, within the above check, we examine for that exactly. If you’re new to sensible contract testing, know that each contract invocation made might be comprised of the proprietor’s deal with by default. If you wish to use one other deal with whereas invoking a operate on that sensible contract, then it may be accomplished by <sensible contract identify>.join(<deal with>).<operate to invoke> each single time.



Mock Coordinator ought to obtain the request

When the Chainlink VRF Oracle Contract receives a profitable request from any contract to ship again random numbers, it emits a RandomWordsRequested occasion. Amongst different arguments, the occasion comprises the request ID and the deal with of the contract which despatched the request.

Observe, right here I exploit the phrases “profitable request” as a result of on mainnet/testnet, any contract can place request to Chainlink VRF contract on that chain. However the request will not achieve success if there is not a legitimate and funded subscription.

In case of our Mock VRF contract, on invoking safeMint() operate from our NFT sensible contract, it emits the RandomWordsRequested occasion then we are able to make certain that the primary section of invocation has been profitable and the check has achieved its objective.

  it("Coordinator ought to efficiently obtain the request", async operate () {
    await anticipate(hardhatOurNFTContract.safeMint("Halley")).to.emit(
      hardhatVrfCoordinatorV2Mock,
      "RandomWordsRequested"
    );
  });

Enter fullscreen mode

Exit fullscreen mode

So, within the check above, we’re invoking the safeMint() operate. However not like within the earlier check the place we handed in our NFT contract and occasion identify to .emit clause, we’re passing within the Mock VRF contract and the occasion we anticipate the Mock VRF to emit when our NFT contract requests random phrases on safeMint() invocation.



Mock Coordinator ought to course of and ship again random numbers

Within the subsequent check, the second section of Chainlink VRF invocation completes. Right here, the fulfillRandomWords() operate on the VRF oracle contract is invoked. Usually that is accomplished mechanically. However on this case, it must be invoked manually since there isn’t any agent (like Chainlink Keepers) to automate that motion.

The fulfillRandomWords() operate within the VRF Coordinator contract takes within the request ID and the deal with of the patron contract (the contract requesting the random numbers). It then invokes the rawFulfillRandomWords() operate on the client contract. This operate on the patron contract then invokes the fulfillRandomWords() operate on the patron contract itself and passes within the request ID and the random numbers returned by the VRF Coordinator Oracle Contract. On the completion of this sequence of occasions, the VRF Coordinator Contract emits a RandomWordsFulfilled occasion.

We don’t see this occurring usually. Any contract which desires to make use of Chainlink VRF v2 must inherit from VRFConsumerBaseV2.sol like we’ve in our NFT Contract. The rawFulfillRandomWords() operate is inherited mechanically and is, thus, current within the client contract.

The code beneath comprises the check which invokes the fulfillRandomWords() operate of the Mock VRF contract by passing within the request ID and the deal with of our NFT contract. The emission of RandomWordsFulfilled occasion would function affirmation of profitable invocation of the operate and we examine for this.
Within the above code there may be an additional little bit of code which is used to acquire the request ID from our NFT Contract. Bear in mind how our NFT contract emits RequestedRandomness occasion that comprises our request ID? We’d like that.

  it("Coordinator ought to fulfill Random Quantity request", async () => {
    let tx = await hardhatOurNFTContract.safeMint("Halley");
    let { occasions } = await tx.wait();

    let [reqId, invoker] = occasions.filter( x => x.occasion === 'RequestedRandomness')[0].args;

    await anticipate(
      hardhatVrfCoordinatorV2Mock.fulfillRandomWords(reqId, hardhatOurNFTContract.deal with)
    ).to.emit(hardhatVrfCoordinatorV2Mock, "RandomWordsFulfilled")

  });

Enter fullscreen mode

Exit fullscreen mode

The strains above the check is one thing basic to ethers.js library and to Ethereum transaction logs. When a transaction is profitable, the transaction receipt comprises an array of occasions emitted from that transaction. One can filter by way of these occasions by the occasion identify. We filter out the RequestedRandomness occasion after which from that occasion we extract the request ID which is then handed on.



Our Contracts ought to obtain Random numbers from Mock VRF

Lastly, we have to carry issues full circle. We began by making a request from our NFT contract to the Mock VRF Contract. The Mock VRF Contract obtained our request and recorded it. It then despatched out the random numbers we requested from. Now we have to affirm that we’re accurately receiving it in our contract.

We as soon as once more undergo an identical course of within the code of the check beneath because the check earlier than. However this time, after we invoke the fulfillRandomWords() operate on the Mock VRF contract, we examine if our NFT contract’s success operate is invoked from the Mock VRF.

it("Contract ought to obtain Random Numbers", async () => {

    let tx = await hardhatOurNFTContract.safeMint("Halley");
    let { occasions } = await tx.wait();

    let [reqId] = occasions.filter( x => x.occasion === 'RequestedRandomness')[0].args;

    await anticipate(
      hardhatVrfCoordinatorV2Mock.fulfillRandomWords(reqId, hardhatOurNFTContract.deal with)
    ).to.emit(hardhatOurNFTContract, "ReceivedRandomness")


    anticipate(await hardhatOurNFTContract.getCharacter(0))
    .to.embody(proprietor.deal with.toString(), "Halley");

  });
Enter fullscreen mode

Exit fullscreen mode

In our NFT contract, the fulfillRandomWords() operate receives the request ID and an array of random numbers. This can be a basic sample and is enforced by design. This operate on our contract emits ReceivedRandomness occasion on profitable minting of the NFT inside this operate. We examine for that occasion after we cross in our NFT contract and the ReceivedRandomness occasion to the .emit clause above.

A surer check could be to see if the NFT exists or not after this complete process concludes. Within the subsequent anticipate check we do precisely that. Since that is the primary NFT, its token ID might be 0. So if we invoke the getCharacter() operate in our NFT contract passing in 0 as token ID, we should always anticipate to get again an NFT which is owned by the proprietor deal with and is called Halley. The operate returns an array in our case and we examine if the array consists of these utilizing the .embody clause.

This completes the entire saga of testing our Chainlink Verifiable Random Operate enabled sensible contract.



So lengthy people!

That is the final article in our Chainlink VRF sequence. We began by discussing Chainlink VRF model 2 after which went on to jot down and deploy a boring NFT sensible contract on Polygon’s Mumbai testnet which used this performance. To conclude we examined out our sensible contract (although Testing ought to come earlier than deployment LOL).

Earlier than I finish this one, I want to advocate that you simply take a look at the contracts VRFCoordinatorV2Interface.sol and
VRFCoordinatorV2Mock.sol. You should use VRFCoordinatorV2Interface.sol to implement your personal customized Mock Contract and even your personal VRF. VRFCoordinatorV2Mock.sol is the Mock contract we used on this tutorial. On the time of writing that is beneath heavy improvement and a few features are but to be fully applied. However it will possibly nonetheless be used to check out functionalities like we did right here.

If in case you have any doubts or discussions, be at liberty to put up them beneath this text. If in case you have any article ideas be at liberty to get involved with me by way of my e-mail or social handles talked about on my style-tricks.com profile.

Till then, maintain growing superior issues on Web3 and WAGMI!

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?