Solidity单交易中生成多个随机数的实现方案咨询
问题解答
首先直接给出核心结论:单笔交易可以通过Chainlink VRF生成多个安全随机数,不需要每笔交易仅申请一个。
你现有方案的问题
你当前使用的基于block.difficulty、block.timestamp加nonce生成伪随机数的方案确实存在风险:
- 块相关属性可以被矿工有限度操纵,高价值场景下存在被攻击的可能
- 随机数可被提前预测,不符合公平性要求
Chainlink VRF实现多随机数的方案
Chainlink VRF v2及以上版本原生支持单次请求返回多个随机数,你不需要逐次发起请求:
- 发起随机数请求时,调用
requestRandomWords方法,将最后一个参数numWords设置为你需要的随机数数量,最多可支持单次请求100个随机数 - 节点完成验证后会在回调交易里返回对应长度的随机数数组,你可以直接在回调逻辑里遍历数组实现你的while循环逻辑
示例代码如下:
// 继承VRF消费端基础合约 contract YourContract is VRFConsumerBaseV2 { // 发起随机数请求示例 function requestRandomNumber(uint32 count) external returns (uint256 requestId) { requestId = COORDINATOR.requestRandomWords( keyHash, subscriptionId, 3, // 块确认数 200000, // 回调gas限制 count // 你需要的随机数数量 ); } // 节点回调方法,接收随机数数组 function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { uint _prob = 你的阈值参数; uint i = 0; // 循环使用返回的随机数,和你原有逻辑完全适配 while(i < randomWords.length && (randomWords[i] % 100) < _prob) { // 你的原有业务逻辑 i++; } } }
额外说明
- 如果你无法提前确定需要的随机数数量,可以一次性请求足够多的随机数备用,单次请求100个的gas成本远低于分100次请求的成本
- 如果你的场景对安全性要求极低,不想引入Chainlink VRF,也可以将伪随机数的种子替换为最近的块哈希等更难操纵的链上属性,但仍存在被攻击的风险,仅建议低价值场景使用
内容的提问来源于stack exchange,提问作者Joncarre
相关产品推荐
相关产品推荐

