Opcode to require a minimal gas value while ensuring a useful eth_estimateGas
Simple Summary
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.
Abstract
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 eth_estimateGas
)
Specification
Let specify 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 REQUIRE_GAS
at <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 REQUIRE_GAS
As mentioned the result of an eth_estimateGas
is now
max(<gas used>, minimalGas)
The operation costs G_base
+ G_verylow
to execute.
Rationale
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 gasleft()
Alternative Solutions
Make 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 Compatibility
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.
Test Cases
TBD
Implementation
TBD
Copyright
Copyright and related rights waived via CC0.