Chainlink Issue, fulfillRandomness function uses 225k gas

Hi,
I have an issue with chainlink VRF. My function uses 225k gas and I dont know how to lower it anymore. Since chainlinks VRF max gas is 200k function is failing. Is there any other way to execute a function after random number has been returned.

Smart Contract Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "https://github.com/smartcontractkit/chainlink-mix/blob/master/contracts/VRFConsumer.sol";
pragma experimental ABIEncoderV2;

/**
 * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
 * PLEASE DO NOT USE THIS CODE IN PRODUCTION.
 */
/**
    * Constructor inherits VRFConsumerBase
    * 
    * Network: Mumbai
    * Chainlink VRF Coordinator address: 0x8C7382F9D8f56b33781fE506E897a4F1e2d17255
    * LINK token address:                0x326C977E6efc84E512bB9C30f76E30c160eD06FB
    * Key Hash: 0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4
    */
/**
 * Request testnet LINK and ETH here: https://faucets.chain.link/
 * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
 */


contract CoinFlipTest is VRFConsumerBase {
    
    bytes32 internal keyHash;
    uint256 internal fee;
    uint public result;
    string public state;

    mapping(address => Game[]) public games;
    mapping(address => bool) public isGameRunning;
    mapping(address => uint) activeGame;

    event CoinFlipped(uint id, uint side, uint resultedSide, address player, bool completed);

    struct Game {
        uint id;
        uint side;
        uint resultedSide;
        address player;
        bool completed;
    }

    struct LastGame {
        uint id;
        bool completed;
    }

    constructor() 
        VRFConsumerBase(
            0x8C7382F9D8f56b33781fE506E897a4F1e2d17255, // VRF Coordinator
            0x326C977E6efc84E512bB9C30f76E30c160eD06FB  // LINK Token
        )
    {
        keyHash = 0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4;
        fee = 0.0001 * 10 ** 18; // 0.1 LINK (Varies by network)
    }

 function getRandomNumber(uint _side) public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");

        //Sets mappings
        games[msg.sender].push(
            Game(games[msg.sender].length, _side, 0, msg.sender, false)
        );
        
        return requestRandomness(keyHash, fee);
    }

    //Callback function used by VRF Coordinator
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        Game storage game = games[msg.sender][games[msg.sender].length];
        game.resultedSide = (randomness % 2) + 1;
        game.completed = true;
    }

I know that this storage probably costs a lot of gas but is there any other way to update a mapping with struct?

Game storage game = games[msg.sender][games[msg.sender].length];
game.resultedSide = (randomness % 2) + 1;
game.completed = true;

Any help is appreciated :slight_smile:
Regards,
Tijan

*I have already lowered gas used from 300k to 225k

usually you can solve that problem by using 2 different functions, one called by chainlink where you save that random number in a variable, and another function that you call yourself that uses that random number that was saved

just curious, what is in msg.sender here?

1 Like

I was thinking if that but than user needs to call another function again with his/her wallet. And that is annoying in this usecase.

Ops my mistake :sweat_smile:. I think in this case is chainlink contract?

that is what I would expect it to be

1 Like

It works now :slight_smile:
Thank you very much @cryptokid !

how did you solve it?

I saved requestId the to the mapping as key pointing to the senders (players’) address:

bytes32 requestId = requestRandomness(keyHash, fee);
addressOf[requestId] = msg.sender;

And than in fallback function got the address of player:

    //Callback function used by VRF Coordinator
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        //Variables:
        address player = addressOf[requestId];
        uint _id = games[msg.sender].length;

        //Setting mappings:
        Game storage game = games[player][_id];
        game.resultedSide = (randomness % 2) + 1;
        game.completed = true;
        isGameRunning[player] = false;

        //Emitting event:
        emit CoinFlipped(games[player][_id]);
    }
1 Like