I am aware that eth_estimateGas is not intended to be exact,
but currently, I'm getting actual gasUsed values
that are approximately 6% of the value returned by eth_estimateGas.
In the following example, I invoke the same smart contract with the exact same inputs twice, with only 1 difference:
- In the 1st invocation,
gasLimit = eth_estimateGas - In the 2nd invocation,
gasLimit = eth_estimateGas * 0.064- This value is a very small fraction of the estimate
- This value was obtained through trial-and-error ... not through any calculations
// with exact estimated amount of gas
const estimatedGas2 = (await expendGasSc.estimateGas.updateState(1_000_000_123n)).toBigInt();
console.log('estimatedGas2', estimatedGas2);
const gasLimit2 = estimatedGas2 * 1n;
console.log('gasLimit2', gasLimit2);
const txResponse2 = await (await expendGasSc
.updateState(
1_000_000_123n,
{ gasLimit: gasLimit2 },
))
.wait();
const gasUsed2 = txResponse2.gasUsed.toBigInt();
console.log('gasUsed2', gasUsed2);
// with small fraction of estimated amount of gas
const estimatedGas4 = (await expendGasSc.estimateGas.updateState(1_000_000_123n)).toBigInt();
console.log('estimatedGas4', estimatedGas4);
const gasLimit4 = estimatedGas4 * 64n / 1000n; // <--- 6.4%
console.log('gasLimit4', gasLimit4);
const txResponse4 = await (await expendGasSc
.updateState(
1_000_000_123n,
{ gasLimit: gasLimit4 },
))
.wait();
console.log('txResponse4', txResponse4);
const gasUsed4 = txResponse4.gasUsed.toBigInt();
console.log('gasUsed4', gasUsed4);
Here are the results:
- When
gasLimitis 400,000,gasUsedis 320,000- This is exactly 80% of the specified
gasLimit, indicating that HIP-185's gas over-reservation penalty *is likely to have kicked in. - See this answer to my previous related question for context.
- This is exactly 80% of the specified
- When
gasLimitis 25,600,gasUsedis 23,816- This is greater than 80% of the specified
gasLimit, indicating that HIP-185's gas over-reservation penalty has not kicked in
- This is greater than 80% of the specified
estimatedGas2 400000n
gasLimit2 400000n
gasUsed2 320000n
estimatedGas4 400000n
gasLimit4 25600n
gasUsed4 23816n
Therefore, I am expecting eth_estimateGas to return a value
that is much closer to 23,816 than 400,000.
Why is it returning such an unexpectedly high estimate
compared to the actual?
Here's the smart contract:
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;
contract ExpendSomeGasDemo {
uint256 public state;
function updateState(
uint256 newState
)
public
returns (uint256 updatedState)
{
state = newState;
updatedState = newState;
}
}
Note that this contract is deployed on Hedera Testnet:
0x9C58D0159495F7a8853A24574f2B8F348a72424c
Note that the Javascript example above is using ethers.js.
Note that this question is a follow up to my previous one:
Large discrepancy in gasUsed values in near-identical transactions on Hedera - why?
You're querying
eth_estimateGasvia the Hedera JSON-RPC relay, which currently uses static values in lieu of actual gas estimation, this is what's responsible for the consistent estimations.Note, that this will soon be replaced with an actual gas estimation algorithm, when the implementation of HIP-584: Mirror EVM Archive Node is released.
Specifically, you can see
packages/relay/src/lib/constants.ts, to see the the gas-cost-related values defined as constants: These are used by the
estimateGasfunction inpackages/relay/src/lib/eth.tsin their return values.Note, that no actual gas estimation algorithm is being run at the moment. This line -
return this.defaultGas;, which maps toTX_DEFAULT_GAS_DEFAULTabove - is also why you will get the same value of 400,000 anytime you performeth_estimateGasfor a smart contract invocation. Here's the code snippet below