This proposal introduces a deterministic, multi-block discount for the first access to accounts and storage keys in a transaction. The discount depends on how many blocks have passed since the item was last accessed, decaying smoothly to zero over a fixed recent window. Intra-block warming semantics are unchanged - there is no warming across transactions within a block.
The mechanism builds on block-level access lists (EIP-7928), which are committed in prior blocks. This allows a newly synced node to correctly price the first block it validates without replaying historical execution.
Motivation
Current warm and cold access pricing correctly models client state costs in the worst case but leaves a predictable efficiency gap in the common case. Clients maintain short-lived in-memory caches of recently accessed accounts and storage slots to handle short reorgs and pipeline execution across blocks. These caches make accesses from recent blocks materially cheaper than fully cold loads, yet the gas model does not reflect this.
As a result, Ethereum’s gas schedule is conservative: it prices every “first access” as if it were completely cold, even though for most active contracts those lookups are served from hot caches or SSD pages still in memory. The gap between average and worst-case cost limits how far the block gas limit can safely rise-clients must size for the worst case even if most blocks are far cheaper in practice.
We can adjust gas prices to surface this mechanical sympathy, rewarding patterns that align naturally with how hardware and clients already behave.
This proposal narrows that gap in a deterministic and consensus-safe way. It introduces a smoothly decaying, per-item discount based solely on publicly observable prior-block activity recorded in block-level access lists (EIP-7928). That achieves three effects:
Predictability at submission time - Unlike same-block or cross-transaction warming, discounts depend only on past blocks, so users, builders, and wallets can compute exact costs deterministically from on-chain data.
Behavioural alignment - The mechanism encourages natural temporal locality: dapps and operators who reuse state within a few blocks save gas, reflecting the real cost profile of client caching.
Improved L1 scalability - By reducing the average gas cost of realistic workloads without changing the worst case, 8057 effectively raises real execution throughput per gas, helping move toward the “Scale L1” goal of larger blocks and better hardware utilisation.
Empirically, traces show that most hot contracts are touched repeatedly within a few blocks. A 32-block (≈6-minute) window captures the majority of these recurrences. In this regime, total gas usage per block can fall by several percent in steady state, freeing execution capacity without altering consensus rules or transaction semantics.
In short, 8057 aligns Ethereum’s gas economics with real execution cost, using already-available data (BALs) to make temporal locality explicit, deterministic, and beneficial.
As the saving depends only on publicly observable prior-block activity, it is knowable at submission time. Unlike same-block effects, it is therefore behaviour-shaping rather than incidental. It nudges workloads that naturally cluster accesses to keep doing so, matching how clients amortise repeated recent accesses.
This proposal is intentionally scoped to per-transaction warming and does not apply intra-block warming across transactions.
Specification
Terminology and constants
Name
Description
Default
WINDOW_SIZE_BLOCKS
Number of recent blocks over which a discount may apply.
32
CURRENT_BLOCK_NUMBER
The block number of the transaction being executed.
-
LAST_ACCESS_BLOCK_NUMBER(item)
The most recent block number strictly less than CURRENT_BLOCK_NUMBER in which item was accessed by an executed transaction. If unknown or older than WINDOW_SIZE_BLOCKS, it is treated as not found.
-
BLOCK_DISTANCE_IN_BLOCKS(item)
Defined as CURRENT_BLOCK_NUMBER - LAST_ACCESS_BLOCK_NUMBER(item) when the latter is found, else a value greater than WINDOW_SIZE_BLOCKS.
-
Gas constants from existing behaviour:
Name
Value
SLOAD_WARM_GAS_COST
100
SLOAD_COLD_SURCHARGE_GAS
2100
ACCOUNT_WARM_GAS_COST
100
ACCOUNT_COLD_SURCHARGE_GAS
2600
Discount caps (this EIP treats maximum as full cold surcharge, minimum as zero):
Name
Value
DISCOUNT_MAX_SLOAD
SLOAD_COLD_SURCHARGE_GAS
DISCOUNT_MIN_SLOAD
0
DISCOUNT_MAX_ACCOUNT
ACCOUNT_COLD_SURCHARGE_GAS
DISCOUNT_MIN_ACCOUNT
0
This means the closest prior-block usage allows the first access in a transaction to be charged at warm cost, and the far edge of the window trends to the normal cold-plus-warm cost.
Scope of operations
This EIP applies the discount to the first access in a transaction of:
Storage keys accessed by SLOAD and by any operation that first reads a slot as part of its semantics (for example, SSTORE’s read step).
Account touches that incur the cold account access surcharge under the current gas schedule, including but not limited to: BALANCE, EXTCODEHASH, EXTCODESIZE, EXTCODECOPY, and the target account of CALL, CALLCODE, DELEGATECALL, STATICCALL.
Writes are affected only to the extent they perform an initial read or account touch that would have been charged as cold. Write-specific costs and any refund semantics are unchanged.
Precompiles remain unchanged and are always warm. Because they do not pay a cold surcharge, no discount is applied to precompile calls.
Access lists per EIP-2930 remain effective and, when present, pre-warm the listed addresses and storage keys at the start of the transaction. For items that are pre-warmed by an access list, this temporal discount does not apply.
Discount function
The discount decays smoothly with block distance, using a reversed Hermite smoothstep interpolation over the discount window.
$d_{\text{min}}$, $d_{\text{max}}$ = minimum and maximum discounts
This form maps:
$D = 1$ → full discount $(f = d_{\text{max}})$
$D = W$ → no discount $(f = d_{\text{min}})$
Programmatic form
Reference smoothstep helper:
defsmoothstep(edge0:float,edge1:float,x:float)->float:"""Scale and clamp x to [0, 1], then apply cubic Hermite smoothstep."""x=max(0.0,min(1.0,(x-edge0)/(edge1-edge0)))returnx*x*(3.0-2.0*x)
Calculation steps:
NORMALIZED_DISTANCE = (BLOCK_DISTANCE_IN_BLOCKS - 1) / (WINDOW_SIZE_BLOCKS - 1) clamped to [0, 1]. This maps distance 1 → 0 and distance WINDOW_SIZE_BLOCKS → 1.
All arithmetic must be implemented in integer space in consensus-critical code; floating point is shown here only for clarity. round() follows round half up semantics; any deterministic rule is acceptable if consistently applied across clients.
This mechanism is a discount, not a refund. It reduces gas charged upfront for a cold surcharge; it does not emit a rebate and does not affect refund accounting or receipts.
Charging rules (per transaction)
For the first access to an ITEMwithin a transaction:
If ITEM is already warm in this transaction due to same-transaction rules or pre-warmed via a transaction access list, charge the warm cost defined today. No temporal discount applies.
Otherwise compute BLOCK_DISTANCE_IN_BLOCKS(ITEM). If 1 <= BLOCK_DISTANCE_IN_BLOCKS(ITEM) <= WINDOW_SIZE_BLOCKS, apply the discount to the cold surcharge:
If BLOCK_DISTANCE_IN_BLOCKS(ITEM) > WINDOW_SIZE_BLOCKS or not found, charge the unmodified cold surcharge plus the warm component as today.
Subsequent accesses to the same ITEM within the same transaction are warm as per existing rules. This EIP does not introduce block-level warming across transactions.
Initial sync and pricing with block-level access lists
This EIP requires block-level access lists in blocks. Each block carries commitments to the sets of accounts and storage keys accessed during that block.
A newly synced node can price the very first block it validates as follows:
For a block to validate at CURRENT_BLOCK_NUMBER, gather the BALs for the previous WINDOW_SIZE_BLOCKS blocks.
For each of those blocks, obtain the committed sets of accessed accounts and storage keys from the block body.
Build a local index mapping each seen ITEM to the most recent block number in which it appears within that window. This becomes LAST_ACCESS_BLOCK_NUMBER(ITEM).
When validating CURRENT_BLOCK_NUMBER, for each first access to ITEM, compute
BLOCK_DISTANCE_IN_BLOCKS(ITEM) = CURRENT_BLOCK_NUMBER - LAST_ACCESS_BLOCK_NUMBER(ITEM)
when present, else treat as out-of-window. Apply the discount rules above.
Reorgs longer than WINDOW_SIZE_BLOCKS fall back to the same procedure as initial resync. Items not present in the new canonical window are treated as cold.
No execution of historical transactions is required to compute the discount at validation time. Stateless verifiers can price gas using the current block plus compact proofs that an item appears in one of the previous WINDOW_SIZE_BLOCKS access lists.
Wallet gas estimation guidance
Wallets and RPC endpoints should not assume that a temporal discount will apply at submission, because the exact landing block is uncertain. General-purpose estimators should price as if no temporal discount applies.
Operators who can predict landing with high confidence - for example via priority fees and private order flow - may account for the exact discount, but this is an advanced path and not the default.
Motivated operators who can reliably land transactions in a specific block - for example via private order flow and appropriately set priority fees - may account for the exact discount. This is an advanced use case and should not be the default behaviour for general-purpose wallets.
Here’s your section rewritten with consistent uppercase variable names and slightly tightened for clarity while preserving your meaning and tone:
Implementation guidance
Clients are expected to maintain a rolling in-memory index to avoid rescanning prior blocks for each block:
Keep a ring buffer of WINDOW_SIZE_BLOCKS buckets, one per recent block. Each bucket stores first-touched accounts and first-touched storage keys for that block.
Maintain two maps, LAST_SEEN_ACCOUNT and LAST_SEEN_STORAGE_KEY, which track the most recent block index within the window where each item was present. On block advance, drop the oldest bucket and delete items that only appeared there, or mark them as out-of-window.
During execution, when an opcode is about to charge a cold surcharge for an item not yet warm in the current transaction, look up BLOCK_DISTANCE_IN_BLOCKS from the LAST_SEEN_* map and charge using the rules above. Then record first touches for the current block in the current bucket and update the maps.
This design keeps memory bounded by WINDOW_SIZE_BLOCKS multiplied by the number of distinct first touches per block, which is itself bounded by the block gas limit divided by the minimum per-item cost.
This is one practical approach; clients may also implement this via existing caches or by embedding and pruning block-distance hints in their state trie.
Test cases
Example parameters and results
Assume the following defaults:
Name
Value
WINDOW_SIZE_BLOCKS
32
SLOAD_WARM_GAS_COST
100
SLOAD_COLD_SURCHARGE_GAS
2100
ACCOUNT_WARM_GAS_COST
100
ACCOUNT_COLD_SURCHARGE_GAS
2600
DISCOUNT_MAX_SLOAD
2100
DISCOUNT_MIN_SLOAD
0
DISCOUNT_MAX_ACCOUNT
2600
DISCOUNT_MIN_ACCOUNT
0
Example: first storage read in a transaction
BLOCK_DISTANCE_IN_BLOCKS
Discount
Charge
Notes
1
2100
100
Equal to warm
8
1827
373
-
16
1101
1099
Mid-window
24
347
1853
-
32
0
2200
Window edge
>32
0
2200
Fully cold
Example: first account touch in a transaction
BLOCK_DISTANCE_IN_BLOCKS
Discount
Charge
Notes
1
2600
100
Equal to warm
8
2262
438
-
16
1363
1337
Mid-window
24
430
2270
-
32
0
2700
Window edge
>32
0
2700
Fully cold
Exact integer results are determined by the reference implementation’s rounding rule (round_to_nearest, half-up).
Reference implementation (Python, integer only)
This implementation is normative for rounding and scaling. It uses a power-of-two fixed-point scale so divisions by the scale are exact shifts in low-level implementations. All intermediates fit below 2**53 so a JavaScript client can mirror these steps without a big number library.
# Gas constants
SLOAD_WARM_GAS_COST=100SLOAD_COLD_SURCHARGE_GAS=2100ACCOUNT_WARM_GAS_COST=100ACCOUNT_COLD_SURCHARGE_GAS=2600# Temporal discount parameters
WINDOW_SIZE_BLOCKS=32DISCOUNT_MAX_SLOAD=SLOAD_COLD_SURCHARGE_GASDISCOUNT_MIN_SLOAD=0DISCOUNT_MAX_ACCOUNT=ACCOUNT_COLD_SURCHARGE_GASDISCOUNT_MIN_ACCOUNT=0# Fixed-point scale (2^25 = 33,554,432)
SCALE_FACTOR=1<<25HALF_SCALE=SCALE_FACTOR>>1defsmooth_factor_scaled(block_distance_in_blocks:int,window_blocks:int=WINDOW_SIZE_BLOCKS)->int:"""
Returns round_to_nearest(SCALE_FACTOR * DISCOUNT_FACTOR) where:
normalized_distance = (block_distance_in_blocks - 1) / (window_blocks - 1),
clamped to [0, 1]
smoothstep_value = normalized_distance^2 * (3 - 2 * normalized_distance)
discount_factor = 1 - smoothstep_value
The result is in [0, SCALE_FACTOR].
"""ifblock_distance_in_blocks<=0orblock_distance_in_blocks>window_blocks:return0# Use exact rational form to minimize scaling multiplications:
# Let t = block_distance_in_blocks - 1, d = window_blocks - 1.
# discount_factor = (d^3 - 3*d*t^2 + 2*t^3) / d^3
t=block_distance_in_blocks-1d=window_blocks-1d3=d*d*dt2=t*tt3=t2*tnumerator=d3-3*d*t2+2*t3# Round half up
return(SCALE_FACTOR*numerator+(d3//2))//d3defdiscount_gas_units(block_distance_in_blocks:int,discount_max:int,discount_min:int)->int:"""
Integer discount within the window using the smooth falloff.
Returns an integer number of gas units to subtract from the cold surcharge.
"""ifblock_distance_in_blocks<=0orblock_distance_in_blocks>WINDOW_SIZE_BLOCKS:return0factor_scaled=smooth_factor_scaled(block_distance_in_blocks,WINDOW_SIZE_BLOCKS)span=discount_max-discount_minscaled=(span*factor_scaled+HALF_SCALE)//SCALE_FACTORreturndiscount_min+scaleddefsload_first_access_cost(block_distance_in_blocks:int)->int:disc=discount_gas_units(block_distance_in_blocks,DISCOUNT_MAX_SLOAD,DISCOUNT_MIN_SLOAD)cold_part=SLOAD_COLD_SURCHARGE_GAS-discifcold_part<0:cold_part=0returnSLOAD_WARM_GAS_COST+cold_partdefaccount_first_access_cost(block_distance_in_blocks:int)->int:disc=discount_gas_units(block_distance_in_blocks,DISCOUNT_MAX_ACCOUNT,DISCOUNT_MIN_ACCOUNT)cold_part=ACCOUNT_COLD_SURCHARGE_GAS-discifcold_part<0:cold_part=0returnACCOUNT_WARM_GAS_COST+cold_part
Using lookup tables
# SLOAD first access cost per block distance (1-32)
# WINDOW_SIZE_BLOCKS = 32
SLOAD_FIRST_ACCESS_COST_LUT=[100,106,125,155,196,246,306,373,447,528,615,706,800,898,998,1099,1201,1302,1402,1500,1594,1685,1772,1853,1927,1994,2054,2104,2145,2175,2194,2200]# Account first access cost per block distance (1-32)
# WINDOW_SIZE_BLOCKS = 32
ACCOUNT_FIRST_ACCESS_COST_LUT=[100,108,131,168,219,281,354,438,530,630,737,850,967,1088,1212,1337,1463,1588,1712,1833,1950,2063,2170,2270,2362,2446,2519,2581,2632,2669,2692,2700]defsload_first_access_cost(block_distance_in_blocks:int)->int:if1<=block_distance_in_blocks<=32:returnSLOAD_FIRST_ACCESS_COST_LUT[block_distance_in_blocks-1]return2200# fully cold
defaccount_first_access_cost(block_distance_in_blocks:int)->int:if1<=block_distance_in_blocks<=32:returnACCOUNT_FIRST_ACCESS_COST_LUT[block_distance_in_blocks-1]return2700# fully cold
Rationale
Determinism: discounts depend only on prior blocks, so users can predict costs at submission time. The block-level access lists in headers remove bootstrap ambiguity for new nodes. Intra-block dependent savings are inherently unknowable and non-actionable at submission, so they do not change behaviour; prior-block based savings do.
Smooth curve: the chosen polynomial keeps strong incentive for very recent history and eases toward zero, aligning with how caches deliver benefit for temporal locality. Linear ramps are simpler but produce harsher edges.
Window of 32: this captures longer-lived temporal locality without turning the feature into a long-term subsidy, and keeps proof and index sizes small.
Discount not refund: reduces upfront charge only; does not change refund semantics or receipts.
No correlation: simple to implement and reason about. The model is explicitly about last-access distance, not frequency.
Builder rotation and similar operational concerns are out of scope for this EIP.
Behavioural effects
The smoothstep curve over 32 blocks is gentle. Discount remains close to maximum for roughly the first 12 to 16 blocks and decays toward zero near the far edge of the window.
Storage slot (SLOAD) first-access pricing
(warm = 100, cold surcharge = 2100, window = 32)
BLOCK_DISTANCE_IN_BLOCKS
Discount
Charge
Notes
1
2100
100
fully warm equivalent
4
2045
155
almost full discount
8
1827
373
12
1494
706
16
1101
1099
midpoint of window
18
898
1302
20
700
1500
24
347
1853
28
96
2104
near-cold
32
0
2200
window edge
>32
0
2200
fully cold access
Account access first-access pricing
(warm = 100, cold surcharge = 2600, window = 32)
BLOCK_DISTANCE_IN_BLOCKS
Discount
Charge
Notes
1
2600
100
fully warm equivalent
4
2532
168
almost full discount
8
2262
438
12
1850
850
16
1363
1337
midpoint of window
18
1112
1588
20
867
1833
24
430
2270
28
119
2581
near-cold
32
0
2700
window edge
>32
0
2700
fully cold access
Observations
Accesses 1-6 blocks apart remain effectively warm, typically under 300-400 gas total.
Around 16 blocks (≈3.2 minutes), costs reach roughly half the cold surcharge.
By 28-32 blocks (≈5.5-6.4 minutes, one finalisation epoch), costs are nearly cold again.
The transition is smooth and monotone; there are no cliffs or discontinuities to game.
Both account and storage families charge exactly the warm rate for items accessed in the immediately preceding block.
As the discount depends only on prior blocks, users and dapps can plan around it. Unlike same-block effects, these savings are predictable: they are visible before submission and can be incorporated into automation or fee-scheduling logic.
If an operator wants to maintain most of the discount while sending as few transactions as possible, a practical cadence for items touched repeatedly is:
Maintain about 80 percent of the maximum discount by ensuring the item is touched again within 8-9 blocks (around two minutes).
Maintain about 50 percent of the maximum discount by touching again within 16 blocks (half an epoch).
Beyond roughly 28 blocks, the discount fades almost entirely; by 32 blocks, the access is fully cold again.
In short, a maintenance touch every 8-12 blocks is an efficient balance: high retained discount with modest transaction frequency. Applications seeking tighter control-such as bridges, keepers, or batching relayers-can choose shorter cadences, while ordinary usage patterns will keep frequently accessed state warm naturally.
The smooth decay curve is important. It means missing the ideal block due to a temporary spike in gas prices or unexpected congestion doesn’t abruptly forfeit the entire discount-costs rise gradually, not cliff-edge. This avoids brittle strategies that depend on exact timing and makes the mechanism more forgiving in volatile network conditions.
From a UX standpoint, humans are unlikely to act precisely within these timeframes, but automated systems can. Many popular contract surfaces-AMM reserves, token balances, or oracle feeds-stay warm simply through organic activity, letting users benefit indirectly.
Each account or storage key’s discount remains independent. Repeated touches within the window only update the item’s last-access block; they do not stack or correlate across different items.
Coordinated multi-EOA warm-up behaviour
Because the temporal discount depends only on prior-block access, a coordinated actor controlling multiple EOAs or contracts can sequence transactions to capture the maximum discount. For example, a lightweight “warm-up” transaction from one EOA in block N can touch a set of storage keys or accounts, allowing one or more follow-up transactions in block N+1 to execute those same accesses at warm-equivalent cost.
This inter-block pipelining remains predictable, verifiable, and legitimate. It does not distort consensus or introduce hidden state; it simply rewards actors who cluster related work in adjacent blocks. The discount gained is bounded by the cold surcharge itself, while the overhead of coordination, additional priority fees, and builder inclusion uncertainty all limit how aggressively this pattern can be used. In practice, it is most relevant for highly automated systems-keepers, rollup bridges, or arbitrage bundles-that already coordinate sequencing across blocks.
With the 32-block window, the value of pipelining falls off much faster. Missing a single block only slightly reduces the discount because of the smooth decay curve, but missing several in a row quickly erodes it. That makes warm-ups more predictable yet self-limiting: actors can’t cheaply “bank” state heat far ahead, only maintain it across a short epoch-length horizon.
Builders and MEV searchers may still find minor advantage in chaining related operations across consecutive blocks, but this behaviour is constructive: it improves temporal locality in state access and lowers aggregate load on clients. The overall effect is a gentle nudge toward efficient state reuse, not a new coordination game.
If desired, protocol parameters could trim the incentive surface further-for example, by setting DISCOUNT_MAX_* slightly below the full cold surcharge so that even D = 1 accesses remain marginally above the intra-transaction warm price. This specification treats that as optional tuning rather than a security necessity, accepting the small and predictable incentive as a reasonable trade-off for encouraging block-to-block efficiency.
Relationship to block-level warming proposals
This EIP does not introduce intra-block warming across transactions. If a block-level warming proposal is active, its semantics are unchanged. The temporal discount defined here applies only to the first access to an item in a transaction based on prior-block history.
Backwards Compatibility
This EIP changes gas charging and therefore requires a hard fork. It only decreases or equalises costs for affected opcodes and does not introduce new failure modes for existing contracts. Warm and cold cost upper bounds do not increase.
Security Considerations
Determinism and consensus safety:
All discounts are derived from previously committed block data. No client-local or probabilistic state (like caches or heuristics) affects consensus. Any node-stateless or fully synced-can price gas deterministically using the current block and the prior WINDOW_SIZE_BLOCKS access-list commitments. This preserves verifiability and supports stateless validation with compact proofs referencing recent blocks only.
Index growth and memory bounds:
Clients must maintain a rolling index of recently accessed items. With a 32-block window, memory use scales with the number of distinct first-accessed items per block-bounded by the block gas limit divided by the minimum per-item cost. This fits comfortably within existing cache budgets, and entries naturally expire as blocks advance.
Reorg handling: Reorgs shorter than the window are cheap to recompute: nodes rebuild the index from the new canonical access lists. Longer reorgs fall back to initial resync behaviour. No historical transaction replay is required. Because discounts depend on committed data only, there is no ambiguity or consensus divergence across reorgs.
Abuse and incentive surface: The design intentionally makes “warm-up” transactions unprofitable. Since the maximum discount equals the cold surcharge, warming a slot in block N and using it in N+1 costs slightly more than a single cold access (e.g. 2200 + 100 > 2200). Thus there is no economic gain from spamming to maintain heat. The smooth decay curve further discourages exact-block timing games: adjacent blocks differ by only a handful of gas units at small distances.
Economic neutrality: The mechanism reduces average per-access cost but leaves worst-case costs unchanged. Builders and block producers still target the same gas limit under EIP-1559, so total basefee burn and priority-fee dynamics remain stable. The network simply fits more real execution into the same gas target, improving efficiency without altering incentives for congestion or inclusion.
Stateless compatibility:
Earlier multi-block warming ideas were considered incompatible with stateless validation because pricing depended on uncommitted or ephemeral state. By tying discounts to BAL commitments, this proposal makes the pricing rule provable and verifiable. Stateless verifiers need only one compact proof of inclusion in a recent BAL-no historical execution replay, no private cache dependency.