在mint时随机指定tokenId,可以实现一定程度的随机分配图片,Meebits只用了一个数组且是O(1)的时间复杂度就实现了随机分配tokenId。
function randomIndex() internal returns (uint) {
uint totalSize = TOKEN_LIMIT - numTokens;
uint index = uint(keccak256(abi.encodePacked(nonce, msg.sender, block.difficulty, block.timestamp))) % totalSize;
uint value = 0;
if (indices[index] != 0) {
value = indices[index];
} else {
value = index;
}
// Move last value to selected position
if (indices[totalSize - 1] == 0) {
// Array position not initialized, so use position
indices[index] = totalSize - 1;
} else {
// Array position holds a value so use that
indices[index] = indices[totalSize - 1];
}
nonce++;
// Don't allow a zero index, start counting at 1
return value.add(1);
}
在mint时随机指定tokenId,可以实现一定程度的随机分配图片,Meebits只用了一个数组且是O(1)的时间复杂度就实现了随机分配tokenId。
总体思想是,keccak256哈希后对剩余可mint数量totalSize进行取模,得到index值,再到indices里取值。如果indices里的值为0表示这个index没用过,就可以直接用index当做tokenId,然后将最末尾的tokenId(也就是totalSize-1)赋值给indices[index]槽位(如果最末尾的tokenId被分配过,就取indices[totalSize-1]的值赋值给indices[index]槽位),表示如果下次取模后的值又是index,那么就取这时候的最后一个tokenId分配给用户,以此来保证不会重复分配tokenId;如果indices里的值不为0,则说明此index被使用过,那么就要用indices[index]槽位存储的值来做tokenId。
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
uint256 tokenId = chainlinkTokenId[requestId];
if (tokenInternalInfo[tokenId].requested && tokenInternalInfo[tokenId].revealId == 0) {
uint256 randomIndex = randomWords[0] % (totalMysteryBoxes - revealedTokens) + revealedTokens;
uint256 revealId = _tokenIdMap(randomIndex);
uint256 currentId = _tokenIdMap(revealedTokens);
tokenIdMap[randomIndex] = currentId;
tokenInternalInfo[tokenId].revealId = uint64(revealId);
revealedTokens ++;
emit RevealReceived(tokenId, revealId);
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!