CCIP is now live for all developers. See what's new.


VRF-Enabled Mystery Box

Build a mystery box smart contract using VRF.


This is a template for NFT collection with a mystery box mechanic powered by Chainlink VRF.

Smart contracts are based on the gas efficient ERC721Psi and are fully tested. It's super easy to deploy and configure with most of the steps automated in the deploy script.

Some of the key features of this template include private minting stage with a merkle tree, rate limited batch minting, delayed reveal with randomization technique to save gas, provenance hash to verify the authenticity of the metadata, royalties for secondary sales, and configurable parameters.


You will use a HardHat project with the Chainlink Hardhat Plugin to deploy an existing MysteryBox application on Avalanche Fuji testnet.

Before you begin

Before you start this tutorial, complete the following items:

  • Set up a cryptocurrency wallet such as MetaMask.
  • Fund your wallet with AVAX and LINK from
  • Install git. Run git --version to check the installation.
  • Install Nodejs version 16 or later.
  • Optionally, you can install Yarn and use it to run this example instead of using npm.
  • Create an SnowTrace API key if you do not already have one. This is used to verifiy your contracts onchain.
  • Create an account with Infura or Alchemy to use as an RPC endpoint if you do not already have one.

Steps to implement

1 Clone the example repo and install dependencies

Clone the repo and install all dependencies.

If you want to use npm, run:

git clone && \
cd quickstarts-mysterybox && \
npm install

Alternatively, you can use yarn to install dependencies:

git clone [email protected]:smartcontractkit/quickstarts-mysterybox.git && \
cd quickstarts-mysterybox && \
yarn install
2 Configure your project

Copy the .env.example file to .env and fill in the values.

cp .env.example .env

Set the parameters for the NFT contract. If you don't have a VRF subscription, delete the VRF_SUBSCRIPTION_ID parameter.

NFT_NAMEThe name of the NFT collectionMysteryBox
NFT_SYMBOLThe symbol of the NFT collectionBOX
NFT_UNREVEALED_URIThe metadata URI for all tokens before reveal
NFT_MAX_SUPPLYThe maximum number of tokens that can be minted100
NFT_MAX_MINT_PER_USERThe maximum number of tokens that can be minted per user address10
NFT_FEEThe fee for minting a token in ETH0.1
NFT_ROYALTY_BPSThe royalty fee for selling a token in basis points500
VRF_SUBSCRIPTION_IDA funded Chainlink VRF subscription ID. If you leave this blank, a new subscription will be created and funded on deploy.123
3 Configure the Hardhat project

Hardhat is an Ethereum development environment that is used here to configure and deploy the mystery box contract. You need the following information:

FUJI_URLThe RPC URL for Avalanche Fuji testnet. You can use the default, or use your own URL. If you later decide to use Polygon Mumbai or another testnet, set the appropriate parameter from the template.
PRIVATE_KEYThe private key of the account you want to deploy from.0xabc123abc123abc123abc123abc123...
SCANNER_API_KEYThe API key for SnowTrace used for contract verification. If you decide to deploy on Polygon Mumbai or another testnet, use that key instead.ABC123ABC123ABC123ABC123ABC123ABC1
3 Test the contracts locally

To run the unit tests, run the following command:

npm run test

If you want to see gas usage, run the following command:

REPORT_GAS=true npm run test

For coverage reports, run the following command:

npm run coverage
3 Deploy the example contract

Run the npx hardhat run command and replace <network> with the network that you want to deploy to. The network must be configured in hardhat.config.ts.

npx hardhat run scripts/deploy.ts --network <network>

In addition to deploying the contract, the deploy script also completes the following steps automatically:

  1. Create and fund a VRF subscription if one is not provided. Make sure the deployer account has enough LINK to fund the subscription. The initial funding amount is configured in network-config.ts. For testnets, you can use the LINK faucet to get LINK. If your subscription is underfunded, your VRF request will be pending for 24 hours. If this happens, check the Subscription Manager to see the additional balance needed.

  2. Add the deployed contract address as a consumer to the VRF subscription. If you provided a subscription ID, make sure the deployer account is the owner of the subscription. Otherwise, comment out the addVrfConsumer function in the deploy script and add the contract address manually.

  3. Generate a Merkle tree for the allowlist. The merkle tree is generated from the address list in scripts/data/whitelist.json file. Leave the file empty if you don't want to do a private mint.

  4. Verify the contract on SnowTrace. This is important to show users the source code for the contract so they can confirm how it works. It's also required to run the example yourself.

After the deployment is complete, the terminal prints the link to view your contract on SnowTrace.

4 Run the example

After the contract is deployed, run the example using contract functions on SnowTrace.

  1. Open the SnowTrace link from your terminal to view your contract.
  2. On the Contract tab, click the Write Contract tab to view your contract's write functions.
  3. Click Connect to Web3 to connect your wallet to SnowTrace so you can run the functions.
  4. Enable public minting:
  5. Open the setPublicMint function.
  6. Enter a value of true.
  7. Click Write to run the function. Approve the transaction in MetaMask.
  8. Mint an NFT to test the contract:
  9. Open the publicMint function.
  10. Enter a publicMint value of 0.1 AVAX and an amount of 1.
  11. Click Write to run the function. Approve the transaction in MetaMask.
  12. Reveal the box:
  13. Open the reveal function.
  14. Click reveal to reveal the mystery box.
  15. After the reveal, you can find the NFT in the token list for your externally owned account (EOA).

Explore the code

After you complete the example, see the Mystery Box repository to learn about more capabilities of this example and how to configure them. For example, you can learn more about the various Configuration Options for this example and modify it to meet the needs of your application.

Stay updated on the latest Chainlink news