2

I am trying to create a chain of 3 random requests in a row. Source Code:

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.16;

// Debugging
import "hardhat/console.sol";

// VRF
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "./utils/BreakdownUint256.sol";
import "./utils/Destructible.sol";

contract HackjackVRF is VRFConsumerBaseV2, BreakdownUint256, Destructible { 
    // VRF
    VRFCoordinatorV2Interface COORDINATOR;
    uint64 subscriptionId;
    address vrfCoordinator = 0x7a1BaC17Ccc5b313516C5E16fb24f7659aA5ebed;
    bytes32 keyHash =
        0x4b09e658ed251bcafeebbc69400383d49f344ace09b9576fe248bb02c003fe9f;
    uint32 callbackGasLimit = 2500000;
    uint16 requestConfirmations = 3;
    uint32 numWords = 1;
    uint256[] public s_randomWords;
    uint256 public s_requestId;
    address s_owner;
    uint8[] public fulfilledRandomUint8;
    
    event random_received(address sender);
    constructor() VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        subscriptionId = 1720;
    }
    mapping(uint256 => uint256) s_requestIdToRequestIndex;
    mapping(uint256 => uint256[]) public s_requestIndexToRandomWords;
    uint256 public requestCounter;

    uint c = 0;
    function requestRandomWords() public {
        emit random_received(msg.sender);
        // Will revert if subscription is not set and funded.
        // require(msg.sender == owner() || msg.sender == vrfCoordinator, "Only owner or VRF can fulfill.");
        uint256 requestId = COORDINATOR.requestRandomWords(
            0x4b09e658ed251bcafeebbc69400383d49f344ace09b9576fe248bb02c003fe9f,    
            1720,
            3,
            2500000,
            1
        );
        s_requestIdToRequestIndex[requestId] = requestCounter;
        requestCounter += 1;
}
    

    function fulfillRandomWords(
        uint256 requestId,
        uint256[] memory randomWords
    ) internal override {
        emit random_received(msg.sender);
        c += 1;
        uint256 requestNumber = s_requestIdToRequestIndex[requestId];
        s_requestIndexToRandomWords[requestNumber] = randomWords;
        if (c <= 3) {
            requestRandomWords();
        }
    }
}

As you can see, fulfillRandomWords is supposed to call requestRandomWords the first three times it's called. However, I'm getting the first fulfillRandomWords to succeed and then the transactions is reverting:

https://mumbai.polygonscan.com/tx/0x15df675e40e52837e997329b1c2f62d95507ff1ad41323cec1dd912020828040

First call success:

https://mumbai.polygonscan.com/tx/0x8b95c0d3c61d009606b782490866ccf20791cea294d2137fbd310ea5e9191e15

I can see from the logs the random request is being returned but I'm not sure why the randomWords are not getting saved and the transaction is failing.

1
  • Why not request 3 random words in one request? Sep 2, 2022 at 4:02

2 Answers 2

2

I plugged in the tx into tenderly and I'm seeing it's failing here:

modifier nonReentrant() {
    if (s_config.reentrancyLock) {
      revert Reentrant(); // here 
    }
    _;
  }
1

Hello Danny B

Like freeslugs already said, the VRFCoordinatorV2 doesn't allow reentrancy.

You can check it out here

Why you don't request the 3 numbers in one single call?

1
  • Yeah, that's what I'll probably end up doing. The idea for my system is to have a queue containing all the random requests and have fulfilled responses fulfill as many random requests as possible, and call requestRandomWords if they're not all fulfilled. This won't be an issue starting out but trying to make it able to scale. Any other ides to solve this?
    – Danny B
    Sep 4, 2022 at 19:27

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.