I'm writing a little roulette contract that requires a random number to work. I set up a ChainlinkVRF subscription and am using a slightly modified version of Chainlink's example random number oracle contract (I removed the onlyOwner modifier). The way I set it up, I put out 2 contracts: the random number generator and the roulette game. The roulette game requests random numbers from the random number contract. It isn't working. At first it wasn't working because the transferOwnership() function wasn't working, so I took that out and wrote my own, but it still isn't working. Here's the important parts of the two contracts:


    modifier verified {
        require(msg.sender == owner || msg.sender == approvedContract);

    function requestRandomWords() verified external returns (uint256 requestId) {
        // Will revert if subscription is not set and funded.
        requestId = COORDINATOR.requestRandomWords(
        s_requests[requestId] = RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false});
        lastRequestId = requestId;
        return requestId;

    function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override {
        require(s_requests[_requestId].exists, 'request not found');
        s_requests[_requestId].fulfilled = true;
        s_requests[_requestId].randomWords = _randomWords;

    function getRequestStatus(uint256 _requestId) external view returns (bool fulfilled, uint256[] memory randomWords) {
        require(s_requests[_requestId].exists, 'request not found');
        RequestStatus memory request = s_requests[_requestId];
        return (request.fulfilled, request.randomWords);

And this is the roulette functions:

function setOracleAddress(address _oracle) public {
        oracle = _oracle;
        o = VRFv2Consumer(oracle);
function getRandNum() private {
        uint256 id = o.requestRandomWords();
        uint num = o.lastRequestId();
        require(id == num, "id does not match last request");
        (bool fulfilled, uint[] memory randomNumber) = o.getRequestStatus(id);
        while(fulfilled != true) {
            (fulfilled, randomNumber) = o.getRequestStatus(id);
        oracleValue = randomNumber[0];
        randNumFulfilled = true;

There's a few errors I'm getting. The most recent is a gas estimation error. Any ideas on how to fix this?

  • Could you please make your question a little more specific? Right now this is a bit of a generic "debug me" type question. It would be better if you got to the root of the problem and posted that as your question instead. Commented Oct 12, 2022 at 19:07

1 Answer 1


I wrote a funny, easy-to-grasp article about the topic, I guess you might check it out if you want.


Inside, I provided a tutorial on how to integrate the VRF functionality.

The easiest solution would be to use the template VRFV2Consumer.sol contract here

Also, remember that the contract receives the random number from the oracle when the oracle calls the fulfillRandomWords() function (which happens after requestRandomWords() is called:

    function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override {
        require(s_requests[_requestId].exists, 'request not found');
        s_requests[_requestId].fulfilled = true;
        s_requests[_requestId].randomWords = _randomWords;
/* _randomWords is the actual array of random numbers that you receive. By default they are 2. From this line below you can do whatever you want with them. */
        emit RequestFulfilled(_requestId, _randomWords);

Finally, don't forget to add the already deployed contract as a consumer in the subscription that you created from the VRF Dashboard.

Other than that, maybe you could post the errors that you get?

  • Yeah, the error I got was Gas estimation errored with the following message (see below). The transaction execution will likely fail. execution reverted { "originalError": { "code": 3, "data": "0xf5d7e01e000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000002625a0", "message": "execution reverted" } } however, I didn't add the roulette contract to the subscription, because the VRFV2Consumer.sol contract is the one getting the number, and then sending it to the roulette contract. Is that the problem?
    – Ilan Katz
    Commented Oct 12, 2022 at 22:59
  • I added the roulette contract to the subscription, it still is giving me the same error
    – Ilan Katz
    Commented Oct 12, 2022 at 23:03
  • Instead of the roulette contract, you should add the VRFV2Consumer.sol contract as a consumer in your subscription, as it is the one from which the request and receive cycle starts and ends at. I had the similar problems many times prior to writing my article. The solution that worked for me is that I used the VRFV2Consumer.sol as a foundation for my code, just added more functionality to it, changed its name, etc. Maybe you could try that. Remember that the consumer that must be added into the subscription must be the VRFV2Consumer.sol contract (since it's receiving the number) Commented Oct 13, 2022 at 9:41
  • I tried it. I added both contracts to the subscription, it's still giving me the gas estimation error. Now, when I run just the VRFV2Consumer.sol contract it isn't even working. I think maybe I messed too much with VRFV2Consumer.sol trying to add functionality.
    – Ilan Katz
    Commented Oct 13, 2022 at 18:13
  • Okay, with the original VRFConsumer.sol everything's working, so obviously I just messed that up a bit. Still trying to figure out how to send that number over to roulette.sol.
    – Ilan Katz
    Commented Oct 13, 2022 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.