I'm trying to guarantee that I'm not going to require more than the 200k gas limit on VRF fulfillrandomness call.

I'm running the truffles test and they present to me gasUsed on the txn value of the function call:

gasUsed as 88252

So the main question is: Is it gonna be the same gasUsed on mainnet? Calling this function with the same params at the same conditions but on different environments mainnet, testnet, or locally; is going to provide the same gasUsed for all of them?

Can I trust truffle test gasUsed?

PS: I know that gasPrice changes depending on moment.

1 Answer 1


The gasUsed value that Truffle shows you comes from the transaction receipt returned by the Ethereum client (see eth_getTransactionReceipt in json-rpc). In case of running tests locally with Truffle, the client used is Ganache.

The client calculates the gas by executing the transaction on its EVM implementation. In case of Ganache the EVM used is EthereumJS.

EthereumJS uses Ethereum Consensus Tests to ensure that it's compatible with other clients. This includes ensuring that the gas costs are the same. It's crucial that all clients get the same values because without it they can't validate blocks correctly. Of course bugs like e.g. trufflesuite/ganache#977 are always a possibility, but these generally get discovered and patched quickly.

The way EVM works does not change depending on whether the contract is executed on mainnet, testnet or locally. It does depend on the EVM version though. Make sure you're not using an older version in your settings because this does affect opcode pricing.

Note that gasUsed is the actual amount of gas used, not an estimate. Your concern might be coming from seeing inaccurate gas estimations. With gas estimation you're usually trying to get a ballpark figure for a given contract function, sometimes without even specifying concrete argument values and without taking into account any external deployed code your contract might call (or at least not using the exact external bytecode that will be called on the mainnet). The cost of different paths through a function can be vastly different and external code is often a big part of the gas used. Even if you only want an upper bound, getting a reliable number is often not easy.

I'm trying to guarantee that I'm not going to require more than the 200k gas

The tricky part is that while you can count on gasUsed being accurate, it only shows you how much gas was used for the exact arguments you have in your test suite and the exact blockchain state it was running on. Ultimately you can't guarantee you did not miss something unless your function is simple enough for this to be obvious. If you absolutely need a reliable upper bound, there's no easy way around it - you have to analyze the code thoroughly (including any external code you call), identify the most expensive paths and then verify your assumptions with test cases exercising these paths.

Even this can't be absolutely relied upon. Many contracts are upgradeable and you call them via a proxy. If they get updated, their cost may increase. This is always a possibility with fulfillRandomness() for example.

Similarly, when mainnet is updated with a new EVM version, some opcodes may get repriced resulting in a different cost for your contract. In such a case the difference could be insignificant or it could be dramatic - depending on how heavily you use these specific opcodes. This is not just a theoretical consideration either - take a look for example at the case of EIP-1884 that had the side-effect of breaking the gas stipend provided by Solidity's transfer() function because the stipend mechanism heavily depends on the fixed amount of 2300 gas being enough to do certain things. See Stop Using Solidity's transfer() Now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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