eip | title | author | discussions-to | status | type | category | created |
---|---|---|---|---|---|---|---|
2542 |
New opcodes TXGASLIMIT, CALLGASLIMIT, TXGASREFUND |
Alex Forshtat <[email protected]> |
Draft |
Standards Track |
Core |
2020-02-29 |
A mechanism to allow smart contracts to access information on gas limits and gas refunds for the current transaction and execution frame.
Currently, there is an existing opcode 0x45 GASLIMIT
that provides access to the block gas limit. While this information may be useful in some cases, it is probably not a value that smart contract developers may be concerned about. The opcode 0x5a GAS
provides the remaining gas, not the initial one. Also it is worth noting how existing 0x32 ORIGIN
, 0x33 CALLER
,0x34 CALLVALUE
and 0x3a GASPRICE
opcodes set a pattern of having access to both the transacition and current execution frame state.
TBD: as 0x30 opcode range is exhausted, the proposed opcodes can be added to 0x50 range, or a new range can be added.
As concepts of relaying, meta-transactions, gas fees and account abstraction gain popularity, it becomes critical for some contracts to be able to track gas expenditure with absolute precision. Without access to this data on an EVM level, such contracts resort to approximation, mimicking EVM logic on chain, and some use-cases even become infeasible.
If block.number >= TBD, add three new opcodes:
TXGASLIMIT: 0x5c
Pushes the gas limit of the entire transaction onto the stack. Gas costs: 2 (same as GASLIMIT
)
CALLGASLIMIT: 0x5d
Pushes the gas limit of the current execution frame onto the stack. Gas costs: 2 (same as GASLIMIT
)
TXGASREFUND: 0x5e
Pushes the value of the gas refund counter of the entire transaction onto the stack. Gas costs: 2 (same as GASLIMIT
)
Also, consider renaming 0x45 GASLIMIT
to BLOCKGASLIMIT
to avoid confusion.
Consider a solidity smart contract that wants to emit an event like that:
event MyEvent(gasUsed, gasRefunded);
It is absolutely not possible with the current EVM. With a proposed changes, using a pseudo-Solidity syntax, this information would be easily available:
function keepTrackOfGas(string memory message, uint256 number) public {
uint256 initRefundCounter = tx.gasRefund;
this.storageNumber = number;
emit MyEvent(tx.gasLimit - gasleft(), initRefundCounter - tx.gasRefund);
}
The state-of-the-art solution, at least for the gasUsed
problem, is to access 'gasleft()' as the first line of your smart contract, but it can only provide some part of the expenses. Note how variable transaction input size means the gas used by the transaction depends on number of zero and non-zero bytes of input, as well GTXDATANONZERO
. Another issue is that Solidity handles public
methods by loading the entire input from calldata
to memory
, spending an unpredictable amount of gas. And, obviously, gas refund counter is completely unavailble.
This proposal introduces three new opcodes and renames an existing one, but stays fully backwards compatible apart from that.
The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.
Copyright and related rights waived via CC0.