# Stateless by design: a contract that holds nothing is a contract that cannot lose it

> Canonical: https://blazephoenix.xyz/learn/stateless-contracts
> License: CC BY 4.0 (attribution + link) · © 2026 BlazePhoenix
> Updated: 2026-07-29

The smallest attack surface is the state you never keep. A contract that ends every transaction holding nothing — no idle balance, no persistent cross-call flag — removes whole exploit classes by construction, using transient storage that cannot be poisoned across transactions.

The cheapest thing to secure is the thing you never hold. Persistent state is standing attack surface: every slot a contract keeps between transactions is a slot an attacker has unlimited time to poison, and every token it holds at rest is a token a later crafted transaction can try to sweep. A large class of exploits is not about breaking the logic of a single call at all — it is about corrupting something the contract left lying around between calls. Statelessness is the discipline of leaving nothing there.

## Two meanings of stateless, one instinct

The word carries two layers. At the base layer, statelessness is a protocol research direction: stateless clients and state expiry aim to let a validator verify a block without holding the entire world state, carrying proofs instead of the full tree. At the contract layer — the subject here — statelessness means a contract that keeps no persistent state of its own between calls: it opens, executes, settles, and returns to rest carrying nothing. The layers are different, but the instinct is the same one running in both directions: state you must hold is a cost and a liability, so hold as little of it as the job allows.

## Hold nothing

The strongest form of the discipline is an invariant: the contract is left holding nothing at rest. A swap pulls an input, routes it through pools, pays the output, and ends with a zero balance. Real execution leaves residuals — a partial fill at a price limit, rounding across split legs, a non-conforming pool that declined what it was handed — and the naive contract either strands them (where a later crafted route can sweep them) or reverts a legitimate swap. The stateless discipline does neither: it sweeps every residual back to the caller in the same transaction, so nothing accumulates. There is no idle balance, so there is nothing for a future transaction to steal, and the whole class of stuck-or-sweepable-funds bugs is removed by construction rather than patched.

## The primitive: transient storage

The concrete tool that makes contract-level statelessness practical is transient storage — a per-transaction scratch space that is written and read like storage but is automatically wiped when the transaction ends. A reentrancy lock, the pool and token context handed to a swap callback, the input and output currencies for a settlement sequence: all of it lives in slots that do not survive the transaction that created them.

The security consequence is precise. State that cannot persist across transactions cannot be poisoned across transactions. A reentrancy guard in transient storage is set at entry and cleared at exit, and even if that clearing were skipped, the value evaporates with the transaction rather than lingering as a corruptible flag. Cross-call context that would be a standing liability as a storage slot becomes a value that exists only while the work is in flight.

> equation: tstore(LOCK, 1) → body → tstore(LOCK, 0) // auto-cleared at tx end — A reentrancy guard in transient storage: scratch state that lives for one transaction and cannot be corrupted across them because it does not survive them (EIP-1153).

## Why ephemerality shrinks the surface

A system that carries no history has a defect window of a single block and a blast radius that is local to one transaction. There is no accumulator to drift, no stored multiplier to go stale, no clock whose advance can be left unwritten — the entire time-dimension family of defects is simply absent, because there is no time dimension. The number a stateless quoter returns is computed by the same code path that would execute the trade, in the same call, so the quote is the execution rather than a stored figure that can diverge from it.

This is the sharp contrast with systems that must accrue over time. A staking or lending book cannot be stateless — its entire purpose is to remember who was present while value accrued — and that memory is exactly where its hardest defects live. The lesson is not that every contract can be ephemeral; it is that the state a contract chooses to hold should be the minimum its job truly requires, because every unit of held state is a unit of attack surface and a unit of the harder, time-shaped risk that conservation cannot see.

## Statelessness is not austerity

Refusing to hold state is often read as giving something up. It is the opposite: it is refusing to hold what can be lost. A contract with no idle balance cannot be drained of an idle balance. A contract with no persistent cross-call flag cannot have that flag corrupted. A system that recomputes rather than remembers cannot serve a stale memory. The austere-looking contract is the one whose set of things-that-can-go-wrong is small enough to enumerate — and enumeration, as the companion pieces argue, is the whole game.

**Verify it yourself:** Read the contract's own balance of any token at rest, between transactions — a hold-nothing design returns zero, so there is no idle balance for a later crafted transaction to sweep; then look for persistent flags a reentrancy or callback path leaves in storage, because transient-storage equivalents cannot be poisoned across transactions

Related: https://blazephoenix.xyz/learn/invariant-driven-design · https://blazephoenix.xyz/learn/on-chain-quoting · https://blazephoenix.xyz/learn/web25-vs-web30
