Solidity 生成不可重复随机数源码
场景
在合约中某些时候需要生成不可重复的随机数,比如NFT的TokenId由已开始的自增序列改为散列随机出现在可允许的范围内。就像开盲盒一样,可以随机开出。同时以太坊的随机数安全性是未知的,因为生成随机数的所有数值在生成之前都是可见的。如果需要生成真随机数可以使用”预言机“。
代码
contract TestHash{ //散列随机数的范围,此处为6,表明最终的随机数范围 [1,6] uint constant public TOKEN_LIMIT = 6; //散列数组,用于解决随机时出现重复数值的情况 uint[TOKEN_LIMIT] public indices; //该方法被调用了多少次,等于已经产生的随机数数量。 uint nonce; function randomIndex() public returns (uint) { uint totalSize = TOKEN_LIMIT - nonce; 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+1; } }
解释
这段代码的逻辑,仔细思考一下其实不难的。 index是产生随机数,具体做法是将一段bytes进行sha256哈希。然后得到一个uint256长整型对上确界取模。上确界就是总数减去已产生的次数比如总数是6个如果调用这个方法已经产生了2个随机数那么此时的上确界就是4。这段代码解决多次随机到同一个数(上面提到每次调用产生不不重复的数)的方式是,如果随机数相同则把当前的上确界返回,同时把下一个上确界赋值给当前indices数组随机数索引的位置,等待下一次调用。
这段代码的源码来源于 Meebits 的主网合约。
原文链接:https://blog.csdn.net/topc2000/article/details/118976251