如何从 chainlink VRF V2 获取 10000 个随机数?

1 random solidity smartcontracts chainlink

我想使用 chainlink VRF V2 生成 10000 个随机数,但一次请求的最大 NUM_WORDS 为 500,每次都失败\xef\xbc\x81\n我该怎么办?\n我的帐户有足够的 LINK,但我怎么办?做了下面的不起作用!

\n
// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\nimport "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";\nimport "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";\n\ncontract VRFCoordinatorTest is  VRFConsumerBaseV2 {\n    // Chainlink VRF Variables\n\n    address vrfCoordinatorV2 = 0x6168499c0cFfCaCD319c818142124B7A15E857ab;\n    uint64 subscriptionId = 14422;\n    bytes32 gasLane = 0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc;\n    uint32 public callbackGasLimit = 2500000; //already max gaslimit\n\n    //network coordinator\n    VRFCoordinatorV2Interface private immutable _vrfCoordinator;\n\n    // The default is 3, but you can set this higher.\n    uint16 public  REQUEST_CONFIRMATIONS = 10;\n\n    // retrieve NUM_WORDS random values in one request.\n    uint32 public NUM_WORDS = 500;\n\n    //keep the randomWords from fulfillRandomWords() function.\n   uint256[][] public _randomWords = new uint256[][](0);\n   //uint256[] public _randomWords;\n\n\n    event RequestedRandomWords(uint256 requestId ,address requester);\n\n    constructor() VRFConsumerBaseV2(vrfCoordinatorV2) {\n        _vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);\n    }\n\n    function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override{\n        _randomWords.push(randomWords);\n       // _randomWords = randomWords;\n    }\n\n    function requestRandomWords()public{\n        uint256 requestId = _vrfCoordinator.requestRandomWords(\n            gasLane,\n            subscriptionId,\n            REQUEST_CONFIRMATIONS,\n            callbackGasLimit,\n            NUM_WORDS\n        );\n        emit RequestedRandomWords(requestId, msg.sender);\n    }\n\n    function set_REQUEST_CONFIRMATIONS(uint16 comf)public{\n        REQUEST_CONFIRMATIONS = comf;\n    }\n    function set_NUM_WORDS(uint32 num)public{\n        NUM_WORDS = num;\n    }\n    function set_gasLimit(uint32 gasl) public{\n        callbackGasLimit = gasl;\n    }\n\n    function getMaxLengthAndNum()public view returns(uint256,uint256){\n        uint256 lth = _randomWords.length;\n        uint256[] memory tmpArray = _randomWords[lth-1];\n        uint256 lastNum = tmpArray[tmpArray.length-1];\n        //uint256 maxNum = _randomWords[_randomWords.length-1];\n\n        return (lth,lastNum);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Mya*_*ooo 5

我看到你正在 Rinkeby 上进行测试。我建议你在Goerli上测试一下。Rinkeby 被标记为已弃用(参见https://docs.chain.link/docs/vrf/v2/supported-networks/)。

\n

我测试了你的合约并指出它fulfillRandomWords耗尽了汽油。事实上,每个请求可以接收的最大随机字数是 500,回调函数支持的最大 Gas 限制是 2,500,000。因此,您必须确保回调函数不会耗尽 Gas(这意味着:您的回调函数消耗的 Gas 不能超过 2,500,000)。\n在您的示例中,您尝试存储 500 个随机单词。将一个值从非零设置到零大约需要 20,000 个 Gas(参见以太坊黄皮书附录 H)。使用 2,500,000 Gas,最多可以存储 125 个单词。这就是为什么附加合约无法在 NUM_WORDS=500 的情况下工作(fulfillRandomWords 耗尽燃料)。\n如果您想存储 10001 个随机值,我建议发出多个请求。例如:requestRandomWords您可以在内部多次循环vrfCoordinator.requestRandomWords(例如:NUM_WORDS = 100 表示 100 次运行。1 表示最后一次运行)。\n您的回调函数将被调用多次(= requestId 的数量),因此请确保实现一个等待所有请求得到满足的逻辑(例如,您可以s_requestsFulfilled在每次满足请求时更新状态变量)。

\n

这是一个您可以在 Goerli 上测试的示例,我修改了您的示例(重要提示:这是带有硬编码值的未经审核的代码。请勿将其用作生产代码的参考。请根据您的测试/更改它需要)

\n
// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\nimport "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";\nimport "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";\n\ncontract VRFCoordinatorTest_2 is  VRFConsumerBaseV2 {\n    // Chainlink VRF Variables\n\n    address vrfCoordinatorV2 = 0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D;\n    uint64 subscriptionId = 443;\n    bytes32 gasLane = 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15;\n    uint32 public callbackGasLimit = 2500000; //already max gaslimit\n\n    uint256 public requestsFulfilled = 0; // count number of request fulfilled\n\n    //network coordinator\n    VRFCoordinatorV2Interface private immutable _vrfCoordinator;\n\n    // The default is 3, but you can set this higher.\n    uint16 public  REQUEST_CONFIRMATIONS = 3;\n\n    //keep the randomWords from fulfillRandomWords() function.\n    struct RequestStatus {\n        bool fulfilled; // whether the request has been successfully fulfilled\n        bool exists; // whether a requestId exists\n        uint256[] randomWords;\n    }\n   mapping(uint256 => RequestStatus) public s_requests;\n   uint256[] public requestIds;\n   //uint256[] public _randomWords;\n\n\n    event ReceivedRandomWords(uint256 requestId ,uint256[] randomWords);\n    event RequestedRandomWords(uint256 requestId ,address requester);\n    event AllRequestsFulfilled();\n\n    constructor() VRFConsumerBaseV2(vrfCoordinatorV2) {\n        _vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);\n    }\n\n    function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override{\n        require(s_requests[_requestId].exists, \'request not found\');\n        require(!s_requests[_requestId].fulfilled, \'request already fulfilled\');\n        requestsFulfilled++;\n        s_requests[_requestId].fulfilled = true;\n        s_requests[_requestId].randomWords = _randomWords;\n        emit ReceivedRandomWords(_requestId,_randomWords);\n        if(requestsFulfilled==101){\n          emit AllRequestsFulfilled();\n        }\n    }\n\n    function requestRandomWords()public{\n        uint32 numWords = 100;\n        for(uint256 i=0;i<101;i++){\n        if(i==100){\n            numWords=1;\n        }\n        uint256 requestId = _vrfCoordinator.requestRandomWords(\n        gasLane,\n        subscriptionId,\n        REQUEST_CONFIRMATIONS,\n        callbackGasLimit,\n        numWords\n        );\n        s_requests[requestId]=RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false});\n        requestIds.push(requestId);\n        emit RequestedRandomWords(requestId, msg.sender);\n            \n        }\n        \n    }\n\n    function getRequestStatus(uint256 requestId) external view returns (bool fulfilled, uint256[] memory randomWords) {\n        require(s_requests[requestId].exists, \'request not found\');\n        RequestStatus memory request = s_requests[requestId];\n        return (request.fulfilled, request.randomWords);\n    }\n\n    function getRandomWordsAt(uint256 requestId,uint32 index) external view returns (uint256) {\n        require(s_requests[requestId].exists, \'request not found\');\n        RequestStatus memory request = s_requests[requestId];\n        return  request.randomWords[index];\n    }\n\n    function getRequestIdsLength() external view returns (uint256){\n        return requestIds.length;\n    }\n\n    function getRandomWords(uint256 requestId) external view returns (uint256[] memory){\n        require(s_requests[requestId].exists, \'request not found\');\n            return s_requests[requestId].randomWords;\n    }\n \n}\n\n
Run Code Online (Sandbox Code Playgroud)\n