EIP-2780 - Resource-based intrinsic transaction gas

Created 2020-07-11
Status Draft
Category Core
Type Standards Track
Authors
Requires

Abstract

This EIP decomposes the flat 21,000 intrinsic transaction cost into explicit primitives, each priced to match the resources a transaction actually consumes. The costs of plain ETH transfers and contract creation transactions remain equal, while ETH transfers to new accounts and 7702-related transactions

In addition, the new primitives are split into intrinsic gas and runtime gas. Intrinsic gas is the state-independent cost of including the transaction in a block and is the sole input to the transaction-validity check. Runtime gas covers the state-dependent charges, such as new account creation and delegation resolution. Runtime gas is charged as the first frame is entered, metered in same way as inside the frame. Running out of gas in runtime does not invalidate the transaction. Instead, the transaction is included, execution is skipped, and all state changes are reverted, as for any out-of-gas halt inside a frame.

This EIP does not change calldata or access-list metering.

Motivation

The flat 21,000 intrinsic cost charges every transaction the same amount regardless of what it does. A zero-value transaction to an existing account and a value transfer that creates a new account both pay 21,000, even though the latter touches an extra account, writes an extra balance, emits a log, and permanently grows the state. The single constant both over-prices the simplest paths and under-prices the ones that consume real, lasting resources.

This EIP replaces the constant with a decomposition into named primitives, each priced to the resource it represents. The goal is to make every transaction's cost reflect its actual work:

Specification

Parameters

Name Value Definition
TX_BASE_COST 12,000 Sender cost: ECDSA recovery, the sender's account access, the sender's account write and inclusion in block
TX_VALUE_COST 4,244 Recipient balance write performed by a value transfer
TRANSFER_LOG_COST 1,756 EIP-7708 transfer log: GAS_LOG + 3 × GAS_LOG_TOPIC + 32 × GAS_LOG_DATA_PER_BYTE

The remaining values are defined in other EIPs and referenced here:

Name Value Source Definition
COLD_ACCOUNT_ACCESS 3,000 EIP-8038 Cold account touch
WARM_ACCESS 100 EIP-8038 Warm account touch
ACCOUNT_WRITE 8,000 EIP-8038 First write to an account leaf
CREATE_ACCESS 11,000 EIP-8038 Contract-deployment account access and write
REGULAR_PER_AUTH_BASE_COST 7,816 EIP-8037 Per-authorization base: calldata, ECDSA recovery, cold authority access, and warm writes
STATE_BYTES_PER_NEW_ACCOUNT × CPSB 183,600 EIP-8037 State gas for one new account leaf
STATE_BYTES_PER_AUTH_BASE × CPSB 35,190 EIP-8037 State gas for one 23-byte delegation indicator

The two state-gas products change whenever CPSB changes. Regular-gas and state-gas semantics are defined by EIP-8037.

Intrinsic gas costs

A transaction's intrinsic base cost is decomposed into the following explicit primitives:

The recipient touch and the authority access (inside REGULAR_PER_AUTH_BASE_COST) are charged at the cold rate every time, even if the account would be warm (for example, via an access list) keeping intrinsic gas computable without any state read. =

These charges replace the legacy contract-creation transaction charges and EIP-7702's flat PER_EMPTY_ACCOUNT_COST × authorization_list_length intrinsic charge.

Calldata and access-list metering remain unchanged.

Runtime gas costs

Once the transaction passes the intrinsic gas check, the state-dependent gas costs (i.e., runtime costs) are applied. The runtime charges happen in a distinct window — the pre-execution phase — after the transaction is already deemed valid but before the first EVM frame is entered. This phase includes the following action, by order:

  1. The available gas is split into gas_left and state_gas_reservoir, and all the gas accounting counters are initialized, per EIP-8037;
  2. EIP-7702 authorizations are processed;
  3. The recipient account is added to the EIP-7928's Block-Level Access List (its access was already charged at the cold rate at the intrinsic phase, and it is warm from transaction start);
  4. The remaining account creation and access costs are applied.

Like every charge in this EIP, each runtime charge is split into regular gas and state gas per EIP-8037: account accesses and writes are regular gas, while durable state growth (new account leaves and net-new delegation bytes) is state gas. This mirrors how a CALL frame is metered: accesses, account creation, and writes are charged as state is touched, not up front.

Running out of gas during these runtime charges does not invalidate the transaction. Validity is decided solely by the intrinsic gas check.

If the transaction goes out-of-gas in this pre-execution phase, the sender pays for all gas consumed, and all state changes are reverted, including any EIP-7702 delegations. By contrast, if the transaction goes out-of-gas after entering the first EVM frame, the already applied delegations during pre-execution phase stay in place, per EIP-7702, and all runtime charges remain consumed.

If a contract-creation transaction's initcode reverts, the transaction remains valid and any state gas charged at runtime is refilled in last-in, first-out (LIFO) order, per EIP-8037: the portion the charge drew from gas_left is credited back to gas_left, and only the remainder returns to the state_gas_reservoir.

On an exceptional halt, the same LIFO refill applies. A plain value transfer to a new account executes no code and so cannot revert. Its new-account state charge is therefore never rolled back this way. The exception is a transfer to an empty precompile, which does execute and can fail, though on mainnet all precompiles are already prefunded.

EIP-7702 authorization processing

While processing each valid authorization, the following charges are applied at most once per authority:

For each authorization, after the gas charges of that authorization are processed, the authority is added to accessed_addresses, per EIP-7702.

Account creation and access charges

If the transaction is not a self-transfer nor a contract creation, then the following charges are applied:

For a contract-creation transaction, if the deployment address does not already exist, per the existence rule of EIP-8037, charge STATE_BYTES_PER_NEW_ACCOUNT × CPSB in state gas.

Transaction reference cases

Costs are split between the intrinsic phase and the runtime phase, each in regular gas and state gas, per EIP-8037. "execution" denotes contract execution charged at the standard schedule; it, and every runtime charge, is drawn from the gas passed into the first frame, so that frame is entered with the gas remaining after the runtime regular and state charges. The recipient touch is charged at the cold rate at the intrinsic phase; the only runtime account access is the delegation-target load, shown at the cold rate — a target warmed beforehand pays WARM_ACCESS rather than COLD_ACCOUNT_ACCESS. Create rows assume the deployment target does not already exist; a pre-existing target pays no new-account state charge. The intrinsic + runtime totals match the legacy headline numbers.

Case Intrinsic (regular / state) Runtime (regular / state) Total (regular / state)
ETH transfer to self TX_BASE_COST / 0 0 / 0 12,000 / 0
No-transfer to EOA / empty account TX_BASE_COST + COLD_ACCOUNT_ACCESS / 0 0 / 0 15,000 / 0
No-transfer to contract TX_BASE_COST + COLD_ACCOUNT_ACCESS / 0 execution / 0 15,000 + execution / 0
ETH transfer to existing EOA TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST + TRANSFER_LOG_COST / 0 0 / 0 21,000 / 0
ETH transfer to contract TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST + TRANSFER_LOG_COST / 0 execution / 0 21,000 + execution / 0
No-transfer to 7702 delegated TX_BASE_COST + COLD_ACCOUNT_ACCESS / 0 COLD_ACCOUNT_ACCESS + execution / 0 18,000 + execution / 0
ETH transfer to 7702 delegated TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST + TRANSFER_LOG_COST / 0 COLD_ACCOUNT_ACCESS + execution / 0 24,000 + execution / 0
ETH transfer to self, sender 7702 delegated TX_BASE_COST / 0 COLD_ACCOUNT_ACCESS + execution / 0 15,000 + execution / 0
ETH transfer creating new account TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST + TRANSFER_LOG_COST / 0 0 / STATE_BYTES_PER_NEW_ACCOUNT × CPSB 21,000 / 183,600
Create transaction, tx.value = 0 TX_BASE_COST + CREATE_ACCESS / 0 0 / STATE_BYTES_PER_NEW_ACCOUNT × CPSB 23,000 / 183,600
Create transaction, tx.value > 0 TX_BASE_COST + CREATE_ACCESS + TRANSFER_LOG_COST / 0 0 / STATE_BYTES_PER_NEW_ACCOUNT × CPSB 24,756 / 183,600
Create transaction, tx.value > 0, created_address.balance > 0 TX_BASE_COST + CREATE_ACCESS + TRANSFER_LOG_COST / 0 0 / 0 24,756 / 0

Interactions with other EIPs

Rationale

Intrinsic versus runtime gas

The split follows a single line: can the charge be computed without reading state? Signature recovery, the sender's access and write, the transaction's block bytes, the value charges, and the per-authorization base are all fixed by the transaction's fields alone, so they are intrinsic and decide validity. The recipient touch and the authority access are also intrinsic, charged unconditionally at the cold rate: a top-level account is loaded from cold state once per transaction, and pricing that load at a fixed cold rate — rather than discounting the rare case where an access list pre-warmed it — keeps the charge state-independent without underpricing the work. The state-touching remainder is runtime, billed as each account is actually loaded: whether the recipient, an authority, or a deployment target exists, and whether a delegation must be resolved.

Charging the runtime part as the first frame is entered makes the top-level transaction behave like an ordinary CALL: a frame is metered against the gas handed to it, and exhausting that gas halts the frame without unwinding the caller's decision to make the call. Here the "caller" is block inclusion, and the intrinsic check is its decision; a runtime out-of-gas therefore cannot retract validity. Keeping validity on a state-independent quantity is also what lets a block builder decide inclusion without executing the transaction, and lets later EIPs price new state-dependent work at runtime without ever touching the validity boundary.

Pricing only the work each transaction does

The decomposition charges each primitive once, where the resource is consumed: signature recovery and the sender's access and write in TX_BASE_COST; the recipient touch in COLD_ACCOUNT_ACCESS; the recipient balance write in TX_VALUE_COST; the transfer log in TRANSFER_LOG_COST; and durable state creation in STATE_BYTES_PER_NEW_ACCOUNT × CPSB. A zero-value transaction pays only for the touches it makes, while a value transfer that creates an account pays for the new leaf it adds. This removes the cross-subsidy in the flat base, where simple transactions overpaid and state-creating ones underpaid.

The new-account state charge does not apply to CREATE/CREATE2: the GAS_CREATE opcode base already prices internal account creation, and top-level contract-creation transactions pay CREATE_ACCESS intrinsically plus the same state-gas charge at runtime when the deployment target does not already exist. Charging the state-growth cost on top-level value transfers that create accounts aligns them with the CALL-based creation path, which has always paid for the new leaf.

Deriving the decomposition from client runtimes

The values of TX_BASE_COST and TX_VALUE_COST are not set by intuition; they are derived from measured client execution times, using the same approach as EIP-8038.

The derivation uses the EELS test_ether_transfers_onchain_receivers benchmark, executed across all major execution-layer clients (Besu, Erigon, Geth, Nethermind, Reth). The benchmark fills blocks with ether transfers to four kinds of receiver, each exercising a different work path:

For each (client, receiver) pair, a non-negative least-squares (NNLS) model fits measured block runtime as a linear function of the number of transfers and the number of value-bearing transfers. The two fitted coefficients are the per-transfer base runtime and the additional runtime of moving value. Each coefficient is converted to gas at a fixed throughput anchor of 100 Mgas/s (gas = ceil(100,000 × runtime_ms)).

For any candidate target, the analysis surfaces each client's worst case across receiver types, separating clients that already meet the target from those that must optimize to reach it. The proposed TX_BASE_COST and TX_VALUE_COST are set as such targets: they align intrinsic cost with the resource usage of well-optimized clients while leaving slower clients a defined optimization goal.

The two empirical coefficients map onto the decomposition as follows:

COLD_ACCOUNT_ACCESS is taken directly from EIP-8038, since the recipient touch is the same cold-account access priced there, and TRANSFER_LOG_COST is fixed by the EIP-7708 log shape (see Transfer log cost). TX_BASE_COST and TX_VALUE_COST are the residual parameters this EIP introduces.

As in EIP-8038, these numbers are provisional. At the 100 Mgas/s anchor some clients are currently slower than the target on the heaviest paths and must optimize to meet it; the values will be refined as client optimizations land and the benchmarks mature.

Transfer log cost

TRANSFER_LOG_COST assumes a 32-byte log data payload because that is exactly the EIP-7708 transfer-log shape, not an arbitrary choice. The log is LOG3-shaped: three indexed topics (keccak256("Transfer(address,address,uint256)"), from, to) and a data field carrying a single uint256 wei amount. Indexed topics do not count as data bytes, so the only data payload is the 32-byte amount — always a full word, never variable length. Hence:

TRANSFER_LOG_COST = GAS_LOG + 3 × GAS_LOG_TOPIC + 32 × GAS_LOG_DATA_PER_BYTE = 375 + 3 × 375 + 32 × 8 = 1,756

Not metering the transaction envelope as calldata

Only tx.data bytes are metered at the calldata schedule; the envelope RLP (nonce, gas*, to, value, v, r, s) is not. Pricing full-transaction bytes would make intrinsic gas depend on gas_limit and variable-length signature elements — creating a fixed-point estimation problem, since gas_limit would depend on the signature, which itself encodes gas_limit — and would couple the fee to one serialization, weakening EIP-2718 type neutrality and future encodings. Treating calldata as opaque bytes avoids both issues. A plain ETH transfer carries empty tx.data and so pays zero calldata gas regardless.

Self-transfers

A self-transfer (tx.sender == tx.to) charges neither the recipient touch nor the value cost: the account is already accessed and written as the sender, and EIP-7708 emits no transfer log when sender and recipient coincide. Only TX_BASE_COST applies.

Decomposing authorization cost

EIP-7702 charges PER_EMPTY_ACCOUNT_COST per authorization at the intrinsic phase and refunds it when the authority already exists, over-reserving gas the transaction may never use. Splitting the cost removes the over-charge: only REGULAR_PER_AUTH_BASE_COST — the calldata, signature recovery, cold authority access, and warm writes every authorization performs — is knowable without state access and stays intrinsic. The new-account leaf, the first-write ACCOUNT_WRITE, and the delegation-indicator bytes depend on state and are charged at runtime during authorization processing, billed only for the authorities that incur them.

Backwards Compatibility

This EIP is not backward compatible. It is a consensus gas repricing that must be activated at a network upgrade. Wallets, RPCs, gas estimators, and any logic that assumes a flat 21,000 intrinsic base must update, particularly to account for the state-gas charge on transactions that create new accounts.

Test Cases

Costs are given as intrinsic + runtime, by case:

  1. Self-transfer (from == to): 12,000 intrinsic, 0 runtime.
  2. Zero-value transaction to any address (existing, empty, or contract): 15,000 intrinsic (TX_BASE_COST + COLD_ACCOUNT_ACCESS), 0 runtime, 0 state. A self-target is 12,000.
  3. Value transfer to an existing EOA: 21,000 intrinsic, 0 runtime, 0 state.
  4. Value transfer creating a new account (recipient non-existent): 21,000 intrinsic regular; STATE_BYTES_PER_NEW_ACCOUNT × CPSB = 183,600 runtime state.
  5. Value transfer to a 7702-delegated account: 21,000 intrinsic + COLD_ACCOUNT_ACCESS runtime = 24,000 regular plus execution.
  6. Contract-creation transaction, value = 0: 23,000 intrinsic regular; 183,600 runtime state if the deployment target did not exist, 0 otherwise.
  7. Contract-creation transaction, value > 0: 24,756 intrinsic regular; 183,600 runtime state if the deployment target did not exist, 0 otherwise.
  8. EIP-7702 transaction: TX_BASE_COST is unchanged even when the sender assumes code. Each authorization is charged REGULAR_PER_AUTH_BASE_COST (which already covers the cold authority access) at the intrinsic phase; at runtime, a non-existent authority additionally pays STATE_BYTES_PER_NEW_ACCOUNT × CPSB state, the first write to the authority within the transaction pays ACCOUNT_WRITE regular, and net-new delegation bytes add STATE_BYTES_PER_AUTH_BASE × CPSB state — replacing the flat PER_EMPTY_ACCOUNT_COST intrinsic charge and refund.
  9. Contract-creation transaction whose initcode reverts (value-bearing or not): the transaction remains valid; the 183,600 new-account state-gas charge is refilled in LIFO order per EIP-8037 — credited to gas_left up to the portion the charge drew from it, with the remainder returning to the state_gas_reservoir.
  10. Transaction whose gas covers intrinsic cost but not a runtime charge — e.g. a value transfer to a non-existent recipient or a contract creation to a non-existent target lacking gas for the new-account state charge, or a transfer to a delegated account lacking gas for the delegation-target access: the transaction is valid and included, halts out-of-gas, and all runtime state changes — including any applied EIP-7702 delegations — are reverted; it is not invalidated.

Blocks of pure ETH transfers should be tested across all EL clients (e.g. on Perfnet) to confirm the pricing matches measured runtimes at the chosen throughput anchor.

Security Considerations

The decomposed charges, intrinsic plus runtime, sum to at least the legacy 21,000 for any transaction that moves value to a distinct, cold account, and add state gas for transactions that grow the state. No path is cheaper than under the flat base in a way that increases per-block resource consumption; the change reallocates cost to match resources and prices state growth that was previously unpriced.

Moving the state-dependent charges to runtime lowers the validity threshold (a simple call is valid at TX_BASE_COST + COLD_ACCOUNT_ACCESS rather than 21,000), but does not enable underpriced work. A transaction that passes the intrinsic check yet runs out of runtime gas is still included and the sender still pays for every gas unit consumed, with all state changes reverted — exactly the cost profile of an out-of-gas inside a call frame. The runtime mechanism thus charges the same resources as before; it only relocates where, in the lifecycle, the gas is metered.

The semantics of SELFDESTRUCT are unchanged. Per EIP-6780, only contracts created within the same transaction may be fully deleted; this EIP does not reprice or modify any SELFDESTRUCT side effects.

Copyright

Copyright and related rights waived via CC0.