Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions EIPS/eip-2780.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ requires: 2718, 2929, 2930, 6780, 7623, 7702, 7708, 7928, 8037, 8038

## 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](./eip-7702.md)-related transactions
This EIP decomposes the flat `21,000` intrinsic transaction cost into explicit primitives, each priced to match the resources a transaction actually consumes. A plain ETH transfer to an existing account remains at `21,000` execution gas, and contract-creation transactions cost the same whether or not they carry value. Transactions that create new accounts or interact with [EIP-7702](./eip-7702.md) pay the additional runtime costs they incur.

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.
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 before the first frame is entered and is metered in the same way as gas inside the frame. Running out of runtime gas does not invalidate the transaction. Instead, the transaction is included, execution is skipped, and the pre-execution state changes are reverted.

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

Expand Down Expand Up @@ -69,15 +69,15 @@ A transaction's intrinsic base cost is decomposed into the following explicit pr
- otherwise, charge `TX_VALUE_COST` in execution gas.
- each [EIP-7702](./eip-7702.md) authorization is charged `EXECUTION_PER_AUTH_BASE_COST` in execution gas.

The recipient touch and the authority access (inside `EXECUTION_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. =
The recipient touch and the authority access (inside `EXECUTION_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:
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 actions, in 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](./eip-8037.md);
2. [EIP-7702](./eip-7702.md) authorizations are processed;
Expand All @@ -88,7 +88,7 @@ Like every charge in this EIP, each runtime charge is split into execution gas a

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](./eip-7702.md) delegations. By contrast, if the transaction goes out-of-gas after entering the first EVM frame, the delegations applied during the pre-execution phase stay in place, per [EIP-7702](./eip-7702.md); the state gas that paid for them — each authority's account-creation and delegation-indicator bytes — therefore stays consumed, since that state persists beyond the frame. Runtime state charges whose state is instead rolled back with the frame (for example, a contract-creation transaction's new-account charge; see below) are refilled in LIFO order per [EIP-8037](./eip-8037.md), and execution-gas runtime charges (such as a delegation-target access) remain consumed.
If the transaction goes out-of-gas in this pre-execution phase, the sender pays for all gas consumed, and all pre-execution state changes are reverted, including any [EIP-7702](./eip-7702.md) delegations. The included transaction still increments the sender's nonce and pays its gas fees. By contrast, if the transaction goes out-of-gas after entering the first EVM frame, the delegations applied during the pre-execution phase stay in place, per [EIP-7702](./eip-7702.md); the state gas that paid for them — each authority's account-creation and delegation-indicator bytes — therefore stays consumed, since that state persists beyond the frame. Runtime state charges whose state is instead rolled back with the frame (for example, a contract-creation transaction's new-account charge; see below) are refilled in LIFO order per [EIP-8037](./eip-8037.md), and execution-gas runtime charges (such as a delegation-target access) 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](./eip-8037.md): the portion the charge drew from `gas_left` is credited back to `gas_left`, and only the remainder returns to the `state_gas_reservoir`.

Expand All @@ -103,22 +103,22 @@ While processing each valid authorization, the following charges are applied **a
- is `tx.sender`, covered by `TX_BASE_COST`;
- was written by a preceding valid authorization;
- is `tx.to` of a value-bearing transaction, covered by `TX_VALUE_COST`;
- if the authorization writes the 23-byte delegation indicator into a previously empty slot (net-new delegation bytes), charge `STATE_BYTES_PER_AUTH_BASE × CPSB` in state gas.
- if the authorization sets a non-zero delegation target, the authority had no delegation indicator at transaction start, and no earlier authorization set one for that authority in this transaction, charge `STATE_BYTES_PER_AUTH_BASE × CPSB` in state gas. Clearing an indicator does not refund this charge or make a later set chargeable again. An indicator present at transaction start can be cleared and re-set without paying this charge.

For each authorization, after the gas charges of that authorization are processed, the authority is added to `accessed_addresses`, per [EIP-7702](./eip-7702.md).
Authorization validation and warming retain the ordering in [EIP-7702](./eip-7702.md): check the chain ID and nonce bound, recover the authority, add it to `accessed_addresses`, and then check its code and current nonce. An authorization skipped because of the latter checks still warms the recovered authority; one rejected before recovery does not. The state-dependent charges above apply only after validation succeeds, before applying the authorization.

#### Account creation and access charges

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

- if the recipient is non-existent and `tx.value > 0`, charge `STATE_BYTES_PER_NEW_ACCOUNT × CPSB` in state gas;
- if the recipient is non-existent and `tx.value > 0`, charge `STATE_BYTES_PER_NEW_ACCOUNT × CPSB` in state gas (never applies to a self-transfer, whose recipient is the already-existing sender);
- if the recipient is an [EIP-7702](./eip-7702.md) delegated account, additionally charge the delegation-target access in execution gas: `COLD_ACCOUNT_ACCESS` if cold, `WARM_ACCESS` if warm.

For a contract-creation transaction, if the deployment address does not already exist, per the existence rule of [EIP-8037](./eip-8037.md), 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 execution gas and state gas, per [EIP-8037](./eip-8037.md). "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 execution 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.
Costs are split between the intrinsic phase and the runtime phase, each in execution gas and state gas, per [EIP-8037](./eip-8037.md). "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 execution 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. A plain ETH transfer to an existing EOA remains at the legacy `21,000` execution gas; the other rows show the decomposition for each transaction shape.

| Case | Intrinsic (execution / state) | Runtime (execution / state) | Total (execution / state) |
| :---- | :---- | :---- | :----: |
Expand All @@ -139,8 +139,8 @@ Costs are split between the intrinsic phase and the runtime phase, each in execu

- **[EIP-2929](./eip-2929.md) (warm/cold accounting).** The sender access folded into `TX_BASE_COST`, the recipient's `COLD_ACCOUNT_ACCESS`, and the authority access inside `EXECUTION_PER_AUTH_BASE_COST` are all charged at the intrinsic phase at fixed cold rates, independent of the account's warm/cold state — an access-list entry for the recipient or an authority does not discount them. The sender, the recipient, and each processed authority are added to `accessed_addresses`, so subsequent execution-level touches are warm. The only runtime account access is the delegation-target load, which follows the standard EIP-2929 warm/cold model: `COLD_ACCOUNT_ACCESS` if cold, `WARM_ACCESS` if warm. The same model governs all execution-level account touches, including internal `CALL`s.
- **[EIP-2930](./eip-2930.md) (access lists).** Access lists keep their existing per-entry charges and warming semantics for execution-level touches. Listing the recipient or an authority does not reduce the intrinsic cold-rate charges; it only pre-warms the address for execution.
- **[EIP-7623](./eip-7623.md) (calldata floor).** EIP-7623 floors a transaction's cost at `21,000 + TOTAL_COST_FLOOR_PER_TOKEN × tokens_in_calldata`, where the flat `21,000` is the intrinsic base this EIP decomposes. With this EIP active, that base term is replaced by the transaction's decomposed execution-gas intrinsic — the sum of the execution-gas intrinsic primitives (`TX_BASE_COST + COLD_ACCOUNT_ACCESS + TX_VALUE_COST` for value transfers, `TX_BASE_COST + CREATE_ACCESS` for contract creation) so the floor and its validity check rest on the same per-transaction base as the rest of intrinsic gas rather than a stale constant. Like the floor, this base is state-independent, so the state-dependent runtime charges (the new-account state-gas charge and the delegation-target access) do not enter it. The calldata schedule itself is unchanged; only the base the floor sits on moves.
- **[EIP-7702](./eip-7702.md) (set EOA code).** `TX_BASE_COST` is unchanged even when the sender temporarily assumes code; clients must not perform a disk code load to classify the sender, since EIP-7702 provides the code inline. When `tx.to` is a delegated account, resolving the delegation loads the target's code, charged `COLD_ACCOUNT_ACCESS` on first touch or warm thereafter, following the standard EIP-2929 `accessed_addresses` model. Setting a delegation (writing the 23-byte pointer) is distinct from resolving one (reading the target's code); the resolution charge is genuine work and is not prepaid by the authorization. Authorization cost itself is decomposed: `EXECUTION_PER_AUTH_BASE_COST` — which already includes the authority's cold access — is charged per authorization at the intrinsic phase, while the state-dependent charges (`STATE_BYTES_PER_NEW_ACCOUNT × CPSB` for a non-existent authority, `ACCOUNT_WRITE` for the first write to the authority within the transaction, and `STATE_BYTES_PER_AUTH_BASE × CPSB` for net-new delegation bytes) are charged at runtime during authorization processing, replacing the worst-case `PER_EMPTY_ACCOUNT_COST` intrinsic charge and refund.
- **[EIP-7623](./eip-7623.md) (calldata floor).** EIP-7623 floors a transaction's cost at `21,000 + TOTAL_COST_FLOOR_PER_TOKEN × tokens_in_calldata`, where the flat `21,000` is the intrinsic base this EIP decomposes. With this EIP active, that base term is replaced by the transaction's decomposed base — `TX_BASE_COST` plus the applicable recipient and value primitives (`COLD_ACCOUNT_ACCESS` and `TX_VALUE_COST` for a value transfer to a different account, or `CREATE_ACCESS` for contract creation). Per-authorization charges and initcode word charges are excluded from this base, so the floor and its validity check rest on the same per-transaction base as the rest of intrinsic gas rather than a stale constant. Like the floor, this base is state-independent, so the state-dependent runtime charges (the new-account state-gas charge and the delegation-target access) do not enter it. The calldata schedule itself is unchanged; only the base the floor sits on moves.
- **[EIP-7702](./eip-7702.md) (set EOA code).** `TX_BASE_COST` is unchanged when the sender is delegated or an authorization changes its delegation. An authorization supplies a delegation target address, not the target's code. Computing the intrinsic charge does not require loading that code; resolving a delegation for execution does. When `tx.to` is a delegated account, resolving the delegation loads the target's code, charged `COLD_ACCOUNT_ACCESS` on first touch or warm thereafter, following the standard EIP-2929 `accessed_addresses` model. Setting a delegation (writing the 23-byte pointer) is distinct from resolving one (reading the target's code); the resolution charge is genuine work and is not prepaid by the authorization. Authorization cost itself is decomposed: `EXECUTION_PER_AUTH_BASE_COST` — which already includes the authority's cold access — is charged per authorization at the intrinsic phase, while the state-dependent charges (`STATE_BYTES_PER_NEW_ACCOUNT × CPSB` for a non-existent authority, `ACCOUNT_WRITE` for the first write to the authority within the transaction, and `STATE_BYTES_PER_AUTH_BASE × CPSB` for net-new delegation bytes) are charged at runtime during authorization processing, replacing the worst-case `PER_EMPTY_ACCOUNT_COST` intrinsic charge and refund.
- **[EIP-7708](./eip-7708.md) (ETH transfers emit a log).** Every non-zero-value transfer to a different account emits a transfer log; its cost is folded into `TX_VALUE_COST` alongside the recipient balance write rather than priced as a separate primitive.
- **[EIP-7928](./eip-7928.md) (block-level access lists).** `tx.sender` is accessed at the intrinsic phase and `tx.to` at the runtime phase, so both are included in the block-level access list even when the transaction reverts.

Expand Down Expand Up @@ -188,7 +188,7 @@ Only `tx.data` bytes are metered at the calldata schedule; the envelope RLP (`no

### 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.
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 to the intrinsic base. If the sender is delegated, the delegation-target access and any delegated execution are still charged at runtime.

### Decomposing authorization cost

Expand All @@ -200,10 +200,10 @@ This EIP is **not** backward compatible. It is a consensus gas repricing that mu

## Test Cases

Costs are given as intrinsic + runtime, by case:
Costs are given as intrinsic + runtime, by case. These examples omit calldata, access-list, and initcode word charges and, except in case 8, authorization charges; executed code is charged separately. Delegation-target accesses shown at the cold rate cost `WARM_ACCESS` instead when the target is already warm:

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`.
1. Self-transfer (`from == to`): `12,000` intrinsic, `0` runtime. If the sender is 7702-delegated, the delegation-target access is additionally charged at runtime, per case 5.
2. Zero-value transaction to a distinct existing or empty EOA: `15,000` intrinsic (`TX_BASE_COST + COLD_ACCOUNT_ACCESS`), `0` runtime, `0` state. A contract recipient additionally pays for execution; a delegated recipient also pays for the delegation-target access. A self-target has a `12,000` intrinsic base, with delegated execution charged as in case 1.
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 execution; `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` execution gas plus contract execution.
Expand Down
Loading
Loading