EIP-1153: a scratchpad that lasts exactly one transaction
Contracts often need to pass data between calls inside one transaction — reentrancy locks, transient approvals, flash-accounting. The only shared mutable store was persistent storage: ~20,000 gas a slot, written to disk forever, even though you throw the value away when the transaction ends. EIP-1153 adds transient storage — same idea, but it vanishes at tx end.
- storage vs memory
- the EVM call model
The EVM gives a contract two places to keep data, and neither fits a common need. Memory is cheap but wiped at the end of every call — it can’t carry anything across a sub-call. Storage survives across calls (and forever after), but it’s the most expensive resource in the EVM because it’s written to disk. Yet contracts constantly need a third thing: a place to stash data that survives across calls but only for the current transaction — a reentrancy lock, a transient approval, flash-accounting in an AMM. With only storage to reach for, they pay disk prices for a sticky note. EIP-1153 adds exactly the missing tool. Let’s derive it.
The problem: storage is the only shared mutable store
Take the classic reentrancy guard: set a locked flag before making an external call, clear it after, and refuse to re-enter while it’s set. The flag has to be visible to the re-entrant call, so it can’t live in memory — it must go in persistent storage The contract's permanent key→value store, read/written with SLOAD/SSTORE. It's committed to the state trie and lives on every node's disk forever, which is why writing it is the most expensive common EVM operation. . So you SSTORE the flag (≈20,000 gas to set from zero, ≈5,000 to update), do the work, then SSTORE it back to zero — every single call. You’re writing to every node’s disk, permanently, to hold a value whose entire useful life is a few microseconds inside one transaction.
It gets worse: the “reset to zero” half leans on gas refunds to claw back some cost, but EIP-3529 sharply capped and reduced those refunds (they’d been gamed as gas tokens). So the pattern is expensive, indirect, and it permanently bloats state with values nobody ever needs again.
→ Step 2: give contracts a scratchpad.
Add a second store that lives for one transaction
The fix is to stop overloading storage and add a parallel store with a different lifetime. transient storage A second per-contract key→word store introduced by EIP-1153. It behaves like storage within a transaction but is discarded (reset to all-zero) when the transaction ends and is never written to the state trie or disk. is a contract-keyed slot → 32-byte word map, exactly like storage — except it is never written to the state trie or to disk, and it is wiped back to all-zero when the transaction ends. Because nothing is persisted, there’s no disk write to pay for and no permanent footprint: it’s a scratchpad the protocol hands each contract for the duration of one transaction and then shreds.
That single change — don’t persist it — is what makes it cheap. The cost of SSTORE is dominated by the disk and state-growth it causes; remove those and the operation becomes a flat, warm-priced write.
→ Step 3: two opcodes, shared across the call stack.
Two opcodes — and they’re shared across calls
Transient storage gets two new opcodes that mirror the storage pair: TSTORE / TLOAD TSTORE(key, value) writes a word to transient storage; TLOAD(key) reads it. Both are fixed-cost (100 gas, like a warm storage access) with no refund machinery, and operate on the calling contract's own transient namespace. — TSTORE(key, value) and TLOAD(key). Each costs a flat 100 gas (the warm-access price), with no refund accounting to reason about. And like persistent storage, transient storage persists across the call frames of a transaction: if the caller does TSTORE(k, v) and then makes a sub-call, the callee’s TLOAD(k) reads back v. That cross-call visibility is the whole point — it’s what lets a guard set by the outer frame be seen by a re-entrant inner one, or a router stash context a callback will read.
- 1 write a word to transient storage
- 2 read it back — across calls, within the same tx
- 3 a flat warm price; no refunds, and it never touches disk
→ Step 4: make it follow revert and tx-end rules.
It rolls back on revert, and clears itself at tx end
Two clean-up rules make it safe. First, transient storage obeys revert exactly like persistent storage: if a call frame reverts, every TSTORE it made is rolled back as if it never happened. (This rule was added during standardization precisely so reentrancy guards stay correct — a guard set in a frame that then reverts must not leave the lock stuck on.) Second, when the transaction ends, all transient storage is reset to zero automatically. So the reentrancy guard no longer needs its trailing SSTORE(slot, 0) reset at all — the cleanup is free and automatic.