基于Chainlink VRF生成抽奖系统指定范围随机数的技术问询
使用Chainlink VRF生成指定范围随机数的解决方案
要生成0到ticketOwners.length - 1(数组合法索引范围)的随机数,只需修改fulfillRandomness函数对返回随机数的处理逻辑,同时补充必要的前置检查避免越界:
核心修改点
- 在
getRandomNumber中增加检查,确保抽奖已有参与者,避免数组为空导致模运算错误 - 在
fulfillRandomness中通过模运算将VRF返回的超大随机数映射到目标范围
修改后的完整代码
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/VRFConsumerBase.sol"; contract Random is VRFConsumerBase { bytes32 internal immutable keyHash; uint256 internal immutable fee; uint256 public immutable ticketPrice; uint256 public result; address payable[] public ticketOwners; constructor ( address _ChainlinkVRFCoordinator, address _ChainlinkLINKToken, bytes32 _ChainlinkKeyHash, uint256 _ticketPrice ) VRFConsumerBase ( _ChainlinkVRFCoordinator, _ChainlinkLINKToken ) { keyHash = _ChainlinkKeyHash; fee = 0.1 * 10 ** 18; ticketPrice = _ticketPrice; } function enterRaffle() public payable { require(msg.value >= ticketPrice, "Invalid ticket price"); ticketOwners.push(payable(msg.sender)); } function getRandomNumber() public returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); // 新增:确保已有参与者,避免数组为空 require(ticketOwners.length > 0, "No participants in raffle"); return requestRandomness(keyHash, fee); } function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { // 将随机数映射到0到ticketOwners.length-1的范围 result = randomness % ticketOwners.length; } }
补充说明
- 你之前调用
getRandomNumber()返回的是requestId(bytes32类型),而非最终随机数,最终随机数会在Chainlink节点回调fulfillRandomness后写入result变量,这是VRF的异步流程特性。 - 模运算
randomness % ticketOwners.length会将任意大的随机数映射到0到ticketOwners.length-1的区间,刚好匹配数组的合法索引范围,直接用result即可从ticketOwners中取出获奖者地址:ticketOwners[result]。
内容的提问来源于stack exchange,提问作者gggggggggg
相关产品推荐
相关产品推荐

