A mechanism to allow smart contracts to access information on gas limits for the current transaction and execution frame.
Abstract
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 transaction 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.
Motivation
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.
Specification
If block.number >= TBD, add three new opcodes:
TXGASLIMIT: 0x5c
Pushes the gas limit of the entire transaction onto the stack. This is a value of the âstartgasâ parameter signed by the externally owned account.
Gas costs: 2 (same as GASLIMIT)
CALLGASLIMIT: 0x5d
Pushes the gas limit of the current execution frame onto the stack. This is the âcallGasâ value that was obtained after the application of the EIP-150 âall but one 64thâ rule.
Gas costs: 2 (same as GASLIMIT)
Also, consider renaming 0x45 GASLIMIT to BLOCKGASLIMIT to avoid confusion.
Rationale
Consider a solidity smart contract that wants to know how much gas the entire transaction or a part of it had consumed. It is not entirely possible with the current EVM. With proposed changes, using a pseudo-Solidity syntax, this information would be easily available:
function keepTrackOfGas(string memory message, uint256 number) public {
...
uint gasUsed = msg.gasLimit - gasleft();
}
This is an extremely common use case, and multiple implementations suffer from not taking the non-accessible expenses into consideration. The state-of-the-art solution for the gasUsed problem is to access âgasleft()â as the first line of your smart contract.
Note how variable transaction input size means the gas used by the transaction depends on the 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.
Another application is for a method to have a requirement for a gas limit given to it. This situation arises quite commonly in the context of meta-transactions, where the msg.senderâs account holder may not be too interested in the inner transactionâs success. Exaggerated pseudocode:
function verifyGasLimit(uint256 desiredGasLimit, bytes memory signature, address signer, bytes memory someOtherData) public {
require(ecrecover(abi.encodePacked(desiredGasLimit, someOtherData), signature) == signer, "Signature does not match");
require(tx.gasLimit == desiredGasLimit, "Transaction limit does not match the signed value. The signer did not authorize that.");
...
}
In this situation it is not possible to rely on âgasleft()â value, because it is dynamic, depends on opcode and calldata pricing, and cannot be signed.
Backwards Compatibility
This proposal introduces two new opcodes and renames an existing one, but stays fully backwards compatible apart from that.
Forwards Compatibility
A major consideration for this proposal is its alignment with one or many possible future modifications to the EVM:
EIP-2489 Deprecate the GAS opcode (a.k.a. 39-UNGAS proposal)
There is a sentiment that the ability of smart contracts to perform âgas introspectionâ leads to the contracts being dependent on current opcode pricing.
While criticizing said misconception is beyond the scope of this EIP, in case there is a need to make a breaking change to the behavior of the existing 0x5a GAS opcode, the same considerations will apply to the proposed opcodes. This means this EIP does not add any new restraints on EMV evolution.
Stateless Ethereum
The UNGAS proposal is said to be related to the ongoing project of Stateless Ethereum. Itâs not strictly necessary for stateless Ethereum, but it is an idea for how to make future breaking changes to gas schedules easier.
As long as the concept of âgas limitâ is part of the EVM, the author sees no reason proposed opcodes would conflict with Stateless Ethereum. Gas schedules are not exposed by this proposal.
Comparison with other controversial opcodes
There are opcodes that are not proposed for deprecation but face criticism. Examples include 0x32 ORIGIN being misused by smart contract developers, or 0x46 CHAINID making some smart-contracts âunforkableâ.
This EIP neither encourages nor enables any bad security practices, and does not introduce any concepts that are new for EVM either.
Security considerations
Existing smart contracts are not affected by this change.
Smart contracts that will use proposed opcodes must not use them for the core of any security features, but only as a source of information about their execution environment.
Implementation
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.