We have two nested constructors, each from our inherited contracts. If you choose to parameterize the arguments for the nested constructor, you will have to pass them into the top-level constructor and then again into the nested - like so in VRFConsumerBase above.
With ERC721(), both name and symbol are going to be static, so we opt to pass them in directly.
Approach: createCollectible & fulfillRandomness
When a user calls createCollectible, a request for randomness is initiated to the VRF Coordinator. This request is subsequently passed off-chain to the oracle network for RNG, and back to the VRF Coordinator for on-chain verification.
On verification, VRF Coordinator calls the fulfillRandomness function on our contract, returning the random value.
Since fulfillRandomess receives the random number, we will have to house the breed selection and minting components within this function - different from SimpleCollectible.sol
createCollectible()
We want the user that called createCollectible() to be assigned the tokenId and breed generated from the RNG.
To capture this, we use a mapping between requestId and address.
functioncreateCollectible(stringmemory tokenURI) publicreturns(bytes32) {bytes32 requestId =requestRandomness(keyhash,fee); //catch requestID to associate RNG with user with tokenID requestIdtoSender[requestId] = msg.sender;}
use this to generate a random breed selection -> modulo 3 (since 3 breed types)
tokenCounter is current available tokenID -> grab it as mintingTokenId
map mintingTokenId to the random breed attribute selected:
// add to declaration sectionmapping (uint256=> Breed) public tokenIdToBreed;
increment tokenCounter and return mintingTokenId (which was just minted)
NFT attributes can be associated to their tokenID via mappings
mint NFT -> safeMint()
cannot use _safeMint(msg.sender, mintingTokenId)as we did before.
The caller of fulfillRandomness is VRF Coordinator, therefore msg.sender would yield that contract's address.
We need to get the original msg.sender of createCollectible
This is why the mapping requestIdtoSender was introduced earlier. It associates the original caller (user), with their requestId - with this we can extract the correct address. Like so:
functioncreateCollectible() publicreturns(bytes32) {bytes32 requestId =requestRandomness(keyhash, fee); //catch requestID to associate RNG with user with tokenID requestIdtoSender[requestId] = msg.sender;emitrequestCollectible(requestId, msg.sender);}