Bitget: haz trading inteligente. Lionel Messi, Official Partner. Regístrate

Patrick Collins .- Generating random numbers in a non-fungible token ( NFT ) following the ERC721 standard has always been a problem for smart contract developers.

Now that Chainlink VRF is live on mainnet, Solidity-based smart contracts can seamlessly generate tamper-proof on-chain random numbers that are provably fair and backed by a cryptographic proof.

With Chainlink VRF, creating dynamic NFTs that need a secure source of randomness is now easier and more secure than ever. While Chainlink also enables dynamic attributes of any kind for an NFT using off-chain data sources, we will focus on random numbers with ERC721 or NFTs.

In this tutorial, we’ll look at how to build a Dungeons & Dragons character on the Ethereum blockchain. D&D (Dungeons and Dragons) is a popular role-playing game (RPG) in which people create characters and go on adventures.

One of the important pieces of character creation is giving them attributes or stats to show their strength, dexterity, intelligence, and so on.

To create truly random numbers for their stats on the blockchain, we’ll show how to give your characters random attributes using Chainlink VRF. Random number generation on the blockchain is easy with Chainlink VRF!

What Is an NFT?

NFTs (following the ERC721 standard) define a framework for making tokens that are unique and different from each other (hence the term non-fungible), while the popular ERC20 standard defines tokens that are “fungible”, meaning all the tokens are interchangeable and guaranteed to have the same value.

Examples of “fungible” currencies are the US dollar, the euro and the yen, while examples of fungible blockchain tokens are AAVE, SNX and YFI.

In these cases, 1 fungible token equals 1 other of the same type, just as one dollar equals one dollar and 1 LINK equals 1 LINK. However, NFTs / ERC721s are different in that each token is unique and does not represent the same value or interchangeable item.

Since all NFTs are unique, they can represent tokenized ownership claims over real-world assets, such as a specific plot of land, or actual ownership of digital assets, such as a rare digital trading card. And they are gaining popularity. You can read even more by referring to OpenSea’s NFT Bible.

Building your random character

We’re going to look at how to create a character that has the six main attributes of a D&D character, namely:

uint256 strength;
       uint256 dexterity;
       uint256 constitution;
       uint256 intelligence;
       uint256 wisdom;
       uint256 charisma;

We’ll also give them:

uint256 experience;
       string name;

So we can level them up and give them a fun name.

We’re taking a few liberties here and not following the Dungeons & Dragons guide 100%, but this can easily be modified if you want a more accurate representation of the game.

This contract should establish the following:

  1. It allows you to transfer ownership of the NFT and all the other NFT standards.
  2. Give this character a name and random attributes.

We won’t get into the dynamics of the contract just yet, but stay tuned for a future article that will build on what we learn here!

We’ve already created the repository for you, but we’ll look at how to work with the repository!

Clone the repository

git clone https://github.com/PatrickAlphaC/dungeons-and-dragons-nft
cd dungeons-and-dragons-nft
npm install

Set up your environment variables

You’ll need a MNEMONIC environment variable and a rinkeby RINKEBY_RPC_URL. Your MNEMONIC is the seed phrase of your wallet. You can get a RINKEBY_RPC_URL from a node service provider such as Infura .

Then, set them in a bash_profile file or export them to your terminal like:

export MNEMONIC='cat dog frog....'
export RINKEBY_RPC_URL='www.infura.io/YOUR_PROJECT_ID_HERE'

What’s in this folder?

This will get all of our boilerplate code set up, but the real magic is in the DungeonsAndDragonsCharacter.sol file.

We can see it starts out as a normal Solidity file, but we have several imports at the top:

pragma solidity ^0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

contract DungeonsAndDragonsCharacter is ERC721, VRFConsumerBase, Ownable {

OpenZepplin is a collection of packages that makes life easier for Solidity and smart contract engineers. If you haven’t used it before, get ready to use it a lot more! Since ERC721 is just a token standard and every ERC721 should be more or less the same, we know we can use a template. The ERC721.sol file we import defines all the standards for an NFT. We simply inherit it in our contract by defining contract DungeonsAndDragonsCharacter is ERC721.

We need VRFConsumerBase.sol to interact with Chainlink VRF and get our random numbers. The last two imports just help us with permissions and working with Strings.

The Character struct and constructor

We define which attributes our character will have in the Character struct, and we make a list of characters so we can keep track of all the characters created. Since we are using an array to store the list of characters, we know each character will have a unique ID in that array that defines it. This is known as the tokenId, and we’ll refer to it more later.

struct Character {
       uint256 strength;
       uint256 dexterity;
       uint256 constitution;
       uint256 intelligence;
       uint256 wisdom;
       uint256 charisma;
       uint256 experience;
       string name;
   }

   Character[] public characters;

Once we have that set up, we can now create our constructor.

   constructor()
       public
       VRFConsumerBase(VRFCoordinator, LinkToken)
       ERC721("DungeonsAndDragonsCharacter", "D&D")
   {
       keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
       fee = 0.1 * 10**18; // 0.1 LINK
   }

The VRFConsumerBase and ERC721 each take the parameters we need to set them up.

Chainlink VRF needs the VRF coordinator address and the LinkToken address. We’ve hardcoded these for the Rinkeby network. There are a few other variables defined for Chainlink VRF, such as keyHash and fee.

You can read more about what they do in the Chainlink VRF documentation .

The line ERC721("DungeonsAndDragonsCharacter", "D&D") defines the name of the NFT and then its symbol.

The "D&D" will be what is shown in MetaMask and on NFT marketplaces.

Generate your random character

We want each of our six attributes to have random stats, but we want to be able to name our character! A simple call to Chainlink VRF allows us to generate random numbers in this NFT / ERC721.

We don’t need to do much in our request function; we just need to give our new character a name and a userProvidedSeed.

The seed we give it is how the VRF coordinator will verify whether the number provided is actually random or not. You can choose any seed you want, and you can read more about choosing a random seed to learn more.

   function requestNewRandomCharacter(
       uint256 userProvidedSeed,
       string memory name
   ) public returns (bytes32) {
       require(
           LINK.balanceOf(address(this)) >= fee,
           "Not enough LINK - fill contract with faucet"
       );
       bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
       requestToCharacterName[requestId] = name;
       requestToSender[requestId] = msg.sender;
       return requestId;
   }

We want to keep track of the requestId so that when the random number is fulfilled we can map it to the character we are creating.

This will kick off the Chainlink job, and we just have to wait for the Chainlink node to call back into our contract!

You can read more about the request model in the Chainlink documentation to learn more about how sending Chainlink requests works.

Once the Chainlink node has finished processing the request, it responds by calling the fulfillRandomness function.

This function has all the math behind assigning the attributes, adding the character to the list and minting the NFT.

function fulfillRandomness(bytes32 requestId, uint256 randomNumber)
       internal
       override
   {
       uint256 newId = characters.length;
       uint256 strength = ((randomNumber % 100) % 18);
       uint256 dexterity = (((randomNumber % 10000) / 100) % 18);
       uint256 constitution = (((randomNumber % 1000000) / 10000) % 18);
       uint256 intelligence = (((randomNumber % 100000000) / 1000000) % 18);
       uint256 wisdom = (((randomNumber % 10000000000) / 100000000) % 18);
       uint256 charisma = (((randomNumber % 1000000000000) / 10000000000) %
           18);
       uint256 experience = 0;

       characters.push(
           Character(
               strength,
               dexterity,
               constitution,
               intelligence,
               wisdom,
               charisma,
               experience,
               requestToCharacterName[requestId]
           )
       );
       _safeMint(requestToSender[requestId], newId);
   }

We can see that we’re only using the random number once to create all six attributes. We use the modulo function to take a subset of the massive random number returned. If we didn’t want to do that, we could also call Chainlink VRF six times, but this way works just as well. The last two digits of the returned random number are used for strength, the two digits before that are used for dexterity, and so on.

This is similar to how CryptoKitties uses genes to assign values to its cats.

Just a note: bitwise manipulation would be more efficient than the way we’re doing it here, but this is easier to understand, so we don’t have to get into how bit manipulation works.

_safeMint is the function inherited from ERC721.sol that allows us to easily keep track of the owners of ERC721s. This is especially important when you want your NFT to perform some action, but you don’t want anyone else to be able to perform that action. We’ll learn more about this in the next NFT article.

We’ll be working with Truffle and Chainlink, so if you’re not familiar with Truffle, this blog post on how to use Chainlink with Truffle will give you a refresher, but we’ll also go over all the commands in this blog!

Deployment and Quickstart

Now that we know what’s going on, let’s deploy our random NFT! You’ll need Rinkeby LINK and Rinkeby ETH to run these scripts.

truffle migrate --reset --network rinkeby
truffle exec scripts/fund-contract.js --network rinkeby
truffle exec scripts/generate-character.js --network rinkeby
truffle exec scripts/get-character.js --network rinkeby

This will do a few things:

  1. Deploy your NFT contract
  2. Fund the contract so it can make Chainlink VRF calls
  3. Generate a character with a call to Chainlink VRF
  4. Return the value of your NFT!

Once deployed, you can also verify the contract and even read the contract on Etherscan using the etherscan plugin. You’ll need to get an Etherscan API key and set the environment variable ETHERSCAN_API_KEY. But once you do, you can run:

truffle run verify DungeonsAndDragonsCharacter --network rinkeby --license MIT

And it will give you a link to your NFT on Etherscan. Once there, you can go to the contract section and click Read Contract.

chainlink

This will take you to the page where you can interact with the contract. If you go to the characters section, you can enter the tokenId we just generated, 0, and see the stats of your new D&D character!

You can check out the example of this contract on Rinkeby here . Some of the characters have interesting names!

Summary

Random numbers in NFTs are easy with Chainlink VRF, and there’s a whole different world to explore when it comes to hosting and using them. We’ve only scratched the surface here, so look out for the next blog on how to sell them on the marketplace, render images and work with metadata. We’d love to see some amazing characters and games built with Chainlink VRF so they are truly fair. If you create a cool #PoweredByChainlink NFT, be sure to tweet at us!

If you’re a developer and want to connect your smart contract to off-chain data and systems, visit the developer documentation and join the technical discussion on Discord . If you want to schedule a call to discuss the integration more in depth, reach out here .

Smart contract developers are launching a whole new world with random attributes in NFTs. Will you be one of the pioneers leading the charge?

See the original article by Patrick Collins here

Website | Twitter | Reddit | YouTube | Telegram | Events | GitHub | Price Feeds | DeFi

MORE ABOUT CHAINLINK