Part III · Chapter 20 of 43 · Berlin

EIP-2929 & 2930: pricing state access by what it really costs

Reading state is the most disk-expensive thing a node does, but the EVM charged a flat, far-too-cheap price for it — so an attacker could touch thousands of slots for almost nothing and grind every node to a halt. The fix prices the first touch at its real cost and makes repeats cheap; access lists let a transaction pre-declare what it will touch.

Updated Sep 13, 2026 · 11 min
Assumed
  • the gas model
  • storage & SLOAD

Gas is supposed to track the real cost of work, so the chain can’t be cheaply overloaded. But for years the EVM mispriced its most expensive operation: reading state. An SLOAD or an account lookup forces a node to chase data through the Merkle-Patricia trie and off disk — slow, real work — yet it was billed a flat, tiny fee. That gap was more than inefficiency; it was an attack surface, and in 2016 it was used to bring Ethereum to a crawl. EIP-2929 repriced state access, and EIP-2930 softened the side effects with access lists. Let’s derive both.

1 step Underpriced, and dangerous

The problem: a flat price far below the real cost

Accessing state is the most expensive thing a node does per unit of gas, because it means a trie lookup To read a storage slot or account, a node walks the Merkle-Patricia trie, fetching nodes from disk along the path. It's I/O-bound and far slower than in-memory EVM computation — the real bottleneck in block validation. and disk I/O. Earlier repricings had already raised the flat price — after EIP-150 and EIP-1884, SLOAD sat at 800 gas and touching an account at 700 — yet a single flat number is still the wrong shape. Price it for a cold first touch that genuinely hits disk and you overcharge the common case of reading the same slot again from memory; price it for that common case and a transaction that touches thousands of distinct slots or accounts pays almost nothing per touch, forcing every node on Earth to do enormous disk work to validate your block.

flat, underpriced state access attacker tx cheap per touch 200 200 200 200 200 200 200 200 200 200 each ~200 gas → nodes do huge disk I/O a flat low price let cheap txs touch thousands of slots forcing every node into enormous disk work — the 2016 Shanghai DoS
A single flat price for state access is the wrong shape: set it high enough for a cold, disk-hitting first touch and it overcharges every warm repeat; set it low for the common case and thousands of distinct cold touches cost almost nothing, forcing every node into huge I/O.

This isn’t hypothetical: the 2016 “Shanghai” attacks spammed state-touching opcodes — then priced at just 20–50 gas — to drag block processing to tens of seconds. The flat raises of EIP-150 and EIP-1884 were the immediate patch; EIP-2929 is the structural fix they pointed to.

→ Step 2: notice that repeats aren’t expensive.

2 step Don't just raise it

Why a flat increase is the wrong fix

The obvious move — make SLOAD cost, say, 2100 gas across the board — overcharges the most common honest pattern. The first time you read slot X, the node really does pay for the trie lookup. But the second and third reads of the same slot in the same transaction are nearly free: the data is already loaded into the node’s memory. A flat high price bills all three at full cost, making ordinary contracts that re-read a slot in a loop dramatically more expensive for work the node isn’t actually redoing.

a flat raise overcharges repeats — the red is wasted gas access #1 · disk fetch 2100 access #2 · cached 2100 access #3 · cached 2100 green = real cost red = overcharged
Just raising the flat price overcharges the common case: a contract that reads the same slot three times pays full cost each time, even though after the first load the slot is already cached in memory and the repeats are essentially free.

So a single number can’t be right. The cost depends on whether you’ve already touched this thing in this transaction. That’s the insight the real fix is built on.

→ Step 3: split the price in two.

3 step Cold vs warm

EIP-2929: cold the first time, warm after that

Price by novelty. The EVM keeps a per-transaction access set Two sets the EVM tracks during a transaction — accessed_addresses and accessed_storage_keys. Touching an address or slot adds it to the set; the set determines whether the next access is cold (first) or warm (repeat). of every address and slot you’ve touched. The first access to a given address or slot is cold access The first touch of an address or storage slot in a transaction. It pays the real, high cost — 2600 gas for an account, 2100 for a storage slot — reflecting the trie/disk lookup. and pays the real cost — 2600 gas for an account, 2100 for a storage slot. Every subsequent access in the same transaction is warm and costs just 100 gas. The dangerous case (touch thousands of distinct slots) now pays full freight each time and is priced out of being a DoS; the common case (re-read the same slot) stays cheap. One distinction fixes both.

price the first touch cold, repeats warm 1st touch · cold 2100 gas 2nd · warm 100 gas 3rd · warm 100 gas access set: { slot X, addr A, … } the first touch is cold (real cost); every repeat is warm — 100 gas
EIP-2929 charges the first touch of an address or slot the real cold cost (2600 / 2100), then 100 gas for every warm repeat. A per-transaction access set remembers what's been touched — so DoS spam pays full price while honest re-reads stay nearly free.
Formula
access = cold (2100 / 2600) 1 warm (100) 2
  1. 1 first touch in the tx: a slot costs 2100, an account 2600 — the real disk cost
  2. 2 every later touch: already cached, so nearly free
Price by novelty: the expensive part is the first fetch, so that's where the gas goes.
cumulative gas for N reads of one slot 5k 10k 15k 20k naive flat 2100 each cold once, then warm 100 number of accesses to the same slot →
Why a flat increase is the wrong fix, as a curve. Reading one slot N times, real cold-then-warm pricing (2100 once, then 100 each) stays almost flat; the naive 'just raise the flat price' line (2100 every access) runs away. The shaded gap is exactly what warm pricing saves an honest contract.

→ Step 4: let the transaction warm things up in advance.

4 step Access lists

EIP-2930: declare what you’ll touch, and pre-warm it

Give transactions a way to pre-pay and pre-warm. An access list An optional list of (address, storage keys) a transaction declares it will access. Listed entries start the transaction already warm, so their first in-execution access is charged the warm price. Carried by the type-0x01 transaction. is a list of (address, storage keys) the transaction states up front. Everything declared is added to the access set before execution, so its first in-contract access is charged the warm price instead of cold. You pay a modest upfront fee for declaring — 2400 gas per address and 1900 per slot, slightly below the cold costs — so it’s a small discount, but more importantly it removes the cold-access surprise and was the escape hatch for contracts the repricing would otherwise have broken. And this is delivered by a brand-new transaction type, 0x01 — the very first user of the EIP-2718 typed-transaction envelope.

declare accesses up front to pre-warm them type 0x01 · access-list tx accessList: [addr A, keys k1 k2] [addr B, key k3] pre-warm declared = warm first access: 100 a small upfront fee (2400 / 1900) buys warm first-access EIP-2930 — the first user of the EIP-2718 typed envelope (type 0x01)
An access-list transaction (type 0x01) pre-declares the addresses and storage keys it will use. They enter the access set already warm, so their first access is charged 100 gas, for a small upfront fee (2400 per address, 1900 per slot).
04 Go Deeper Where to take it from here