Opcode to require a minimal gas value while ensuring a useful eth_estimateGas
Add an opcode to require a specific amount of gas (similar to
require(gasleft()>X) in solidity) that allow
eth_estimateGas to return a value that will represent enough gas to make the transaction succeed, even though the actual gas used will be less.
Currently when using
require(gasleft()>X), a call to
eth_estimateGas will return a value that while representing the correct amount of gas used by the transaction when sent with more than enough gas, might be returning an amount that in itself is not sufficient to make the tx to succeed. This is because when checking for
gasleft() the actual gas used afterward might be less than the requirement.
This proposal add a new opcode that perform the same check as
require(gasleft()>X) but ensure that
eth_estimateGas return the minimum amount of gas required for the call to succeed (the use case for
minimalGas as a new variable that the EVM need to keep track for the purpose of
eth_estimateGas. At the start of a tx, it is set to zero.
At the end of an
eth_estimateGas call, the gas spent is compared to
minimalGas. The bigger value of the two is returned as “estimate”. It does not have any other role in the context of a transaction call, its only purpose is to fix the current behavior of
eth_estimateGas that do not consider code like
require(gasleft()>X) when asked to return the gas required to perform a tx.
Adds a new opcode
<TBD>, which uses 1 stack argument : a 32 bytes value that represent the gas required for the contract code to proceed. It will check if the gas left at that point is greater or equal to that value.
If not it will revert the call.
If there is enough gas, the gas amount specified will be added to the gas spent up to that point. If that amount is bigger than
minimalGas it replaces it. In other words:
minimalGas = max(minimalGas, X + <gas spent so far including the gas used for the opcode>)
where X is the value passed to
As mentioned the result of an
eth_estimateGas is now
max(<gas used>, minimalGas)
The operation costs
G_verylow to execute.
eth_estimateGas is currently returning the gas used, and not the gas required for the operation to succeed. While in most case, these two values are equals, there are cases where this is not the case.
In those cases, applications can’t relies on
eth_estimateGas to give them a useful value. They can’t even know what increase in gas they need for the transaction to succeed unless they perform a binary search by executing
eth_estimateGas multiple time.
These cases happen as soon as a smart contract is using code like
require(gasleft() > X)
where X is greater than the gas actually used after that check.
This is a common pattern for meta-transaction where it is not possible for the smart contract to know whether that value X is an over estimation of the gas actually required.
With the introduction of EIP-1706 such problem will also arise for contract that simply use
SSTORE, even existing contract, unless a similar mechanism (using
minimalGas tracking) is used to ensure
eth_estimateGas continue to work as expected (see comment here)
This mechanism will also be useful for EIP-1930 that also implicitly check for
eth_estimateGas to execute the call multiple time until it finds the minimum gas required for the call to succeed. This require
log2(N) calls to the smart contract code where N is the difference between the initial gas given (usually the block gas limit) and the gas value returned by that first call.
eth_estimateGas is already an expensive call to make for user interface and such solution would require up to 20 calls to find the minimal safe value.
Backwards compatible for smart contract as it introduce a new opcode.
eth_estimateGas will continue to work as intended : allow wallet to compute the amount of gas to send for the transaction to succeed.
Copyright and related rights waived via CC0.