my smart contract keeps stopping in a for loop while testing with hardhat.

Here is the solidity Code:

function fulfillRandomWords(
    uint256 requestId,
    uint256[] memory randomWords
) internal override {
    uint256 randNumVRFDiceRolls = randomWords[0];
    uint256 randNumVRFDecisions = randomWords[1];
    bytes32 randNumDiceRolls;
    bytes32 randNumDecicions;

    assembly {
        randNumDiceRolls := randNumVRFDiceRolls
        randNumDecicions := randNumVRFDecisions

    round[requestId].diceRolls = alterRandomValue(randNumDiceRolls, 20);
    round[requestId].smartContractDecisions = alterRandomValue(randNumDecicions, 101);

    emit DiceLanded(requestId, round[requestId]);

function alterRandomValue(bytes32 randomNum, uint8 modOperatorValue) private pure returns (bytes32){
    bytes32 result;

    for (uint8 i = 0; i < 32; i++) {
        uint8 byteValue = uint8(randomNum[i]);
        uint8 moduloValue = byteValue % modOperatorValue;
        result |= bytes32(uint256(moduloValue)) << (8 * i);
    return result;

Here is the test part from the *.js file

const eventName = "DiceLanded";

      const eventPromise = new Promise((resolve) => {
        Game.once(eventName, (param1, param2) => {
        // Perform any necessary assertions on the event parameters
        console.log("reqID: ", param1, " \nPRNG: ", param2)
        // Resolve the promise to indicate that the event was emitted
      await Game.rollDice(deplAddr); 
      reqID = await Game.s_requestId(); 
      // simulate callback from the oracle network
      await VRFCoordinatorV2Mock.fulfillRandomWords(

      // Wait for the event promise to resolve
      await eventPromise;

In this part i first had an expect statement

await expect(VRFCoordinatorV2Mock.fulfillRandomWords(reqID, Game.address)).to.emit(Game, eventName)

that the function emits the dice landed event, but it kept failing with the error:

AssertionError: Expected event "DiceLanded" to be emitted, but it wasn't

So i removed the assertion and added a console.log in the smart contract after "round[requestId].diceRolls = alterRandomValue(randNumDiceRolls, 20);" and after "round[requestId].smartContractDecisions = alterRandomValue(randNumDecicions, 101);" but it only got through the first function call. If i add console.log int the for loop of alterRandomValue e.g.

for (uint8 i = 0; i < 32; i++) {
        uint8 byteValue = uint8(randomNum[i]);
        uint8 moduloValue = byteValue % modOperatorValue;
        result |= bytes32(uint256(moduloValue)) << (8 * i);

i get to iteration 28. If i add another console.log e.g with ouputtin the i i get to iteration 20.

Does anybody have an explanation for this and knows how to fix that?

Thanks and have a nice day/night :)

2 Answers 2


Try increasing the gas limit when calling the alterRandomValue function. Maybe after some iterations, the transaction runs out of gas.

  • So i gave the rollDice function and the fulfillRandomWords function a gasLimit of 30_000_000 and it still does not work. Here are the edited lines: await Game.rollDice(deplAddr, { gasLimit: 30_000_000}); await expect(VRFCoordinatorV2Mock.fulfillRandomWords( reqID, Game.address, { gasLimit: 30_000_000 } )).to.emit(Game, eventName) . I also estimated the gas with gasEstimate = await Game.estimateGas.fulfillRandomWords(...) and got a gasEstimate of 124409. Am I doing something wrong?
    – Bl4d3rR
    Jun 21 at 11:22

So i fixed it, it was the gasLimit. But in the requestRandom words function from Chainlink Oracle. I set the callbackGasLimit a bit earlier in the Code.

s_requestId = COORDINATOR.requestRandomWords(
        callbackGasLimit, // <-- that one here

That here was the bad guy.

Thanks :)

Your Answer

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

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