I'm looking to have an ERC1155 smart contract with a set number of tokens, each with their own max supply, and when a user mints it selects randomly from the available tokens.
Creating the 5 tokens (for example) I'm fine with. I have an ownerOnly createToken function that will mint a quantity of 1 of the new token to the owner and set the max supply for the new id which is just a custom mapping mapping(uint256 => uint256) private _maxSupply;
So now I have for example token ids 0 - 4, with a total supply of 1 for each of them and a max supply of 100 of each.
When somebody wants to mint I'd like to randomly select from the available tokens, taking into account total supply and max supply, and would like to use Chainlink VRF for the randomness.
Given the _mint
and _mintBatch
functions in ERC1155 require the token id(s) am thinking the public payable function would be something like a startMint
call to request the randomness, and the actual mint would occur later when the randomness is fulfilled.
I'm just stuck on a) how to get multiple random numbers when a user is minting more than one token; and b) the best / most efficient way to select the random tokens while keeping track of availability with each selection and then finally calling _mint
or _batchMint
with relevant tokenId(s) and qty(s).
I've written the following for the startMint
. The requestToQuantity
and requestToSender
are custom mappings so I can match up later for the mint.
function startMint( uint256 quantity, uint256 userProvidedSeed )
public
payable
whenNotPaused
returns (bytes32)
{
// validations etc and payment amount checks
// ...
bytes32 requestId = requestRandomness( keyHash, fee, userProvidedSeed );
requestToQuantity[requestId] = quantity;
requestToSender[requestId] = msg.sender;
return requestId;
}
And I've started the fulfillRandomness
function. Any help or guidance with this would be hugely appreciated.
function fulfillRandomness( bytes32 requestId, uint256 randomNumber )
internal
override
{
// TODO: determine the available token ids (using _totalSupply[id] and _maxSupply[id] mappings)
uint256 qty = requestToQuantity[requestId];
address to = requestToSender[requestId];
if ( qty == 1 ) {
// TODO: pick a random available token id
// _safeMint( to, id, 1, "" );
}
else if ( qty > 1 ) {
// TODO: pick multiple random available token ids
// keeping track of availability with each selection
// _mintBatch(to, ids, amounts, "");
}
}