Proof system

Proving the state is right

How an invalid state root gets caught and removed, why re-running the batch cannot work, what the parameters have to satisfy, and which steps a dispute can actually prove today.

A proof system is what turns "the operator says this is the state" into "this is the state, and anyone can show otherwise." It is the hardest component to build and the one most often quietly deferred, so this page is specific about how much of it stands today, how it works, and what it costs.

01The constraint

Why you cannot just re-run the batch

The obvious design — re-execute the disputed batch on Solana and compare — does not fit. A Solana transaction has a bounded compute budget, and a batch of thousands of transactions exceeds it by orders of magnitude. Any fraud proof design that says "re-execute and compare" has not been costed.

batch of N transactions
   └─ re-execute on L1?
        needs   N × per-transaction compute
        budget  one L1 transaction
        result  exceeds the budget by orders
                of magnitude — not viable

narrow instead:
   log₂(N) rounds → one instruction → verify

02Dispute

Narrowing instead

Challenger and proposer disagree about a final state. They bisect: each round splits the disputed execution range in half and both commit to the state at the midpoint. They disagree about exactly one half; that half becomes the new range. After a logarithmic number of rounds the disagreement is a single instruction, which Solana can verify directly against proofs of the state that instruction touched.

  1. 01

    Assert

    A proposer commits a state root under bond.

  2. 02

    Challenge

    A verifier that computed a different root opens a dispute, also under bond.

  3. 03

    Bisect

    Both sides commit to intermediate states, halving the disputed range each round.

  4. 04

    One step

    The disagreement is now a single instruction and its exact inputs.

  5. 05

    Verify

    Solana executes that one step and decides. The loser forfeits their bond.

The constraint every parameter answers to

ParameterValueWhy it matters
One-step verification322,863 to 532,232 compute units, by step class, on the sparse state tree the live chain uses — under the 700,000 the node requests for a witnessed step, inside a transaction's 1,400,000Measured on the real compiled program, each class verified from Merkle witnesses inside one instruction; every class's figure is in the coverage table below. Folding a proof through a 256-level tree is most of the cost whatever the size of the state, which is why this sits far above the 19,216 the retired sorted-leaf tree measured — a tree that could not create an account. Still the load-bearing feasibility claim of the design, with less room in it than that old number suggested
Bisection rounds≈ log₂(execution steps) — exactly 7 rounds for an 8-step trace, on-chainSets the number of on-chain interactions per dispute
Per-round timeoutAt least 1,500 slots a move, enforced by the program; a watchtower opening a dispute asks for at most 9,000. Against the 48-hour window (ADR-0016) the worst-case game is 5.8 h at the floor and 35 h at the cap35 moves for the largest trace the proposer bond can fund, at Solana's 400 ms slot target. Deadlines count slots, so a halted Solana freezes them instead of timing anyone out. The floor clears the window by more than 8×; the cap clears it by about 1.4×, so the move length is the parameter with the least slack in it and should not be lengthened without re-running the arithmetic
Full dispute durationMust be < challenge window, with margin — refused at open if it is notA dispute that cannot finish in time would make the window decorative, so opening one is rejected outright
Proposer bondDevnet placeholder: 100,000 lamports, and a challenger posts 50,000. Production value sized against value at riskMust exceed what a bad root could extract, and be re-derived as TVL grows. The devnet figure exists to exercise the mechanism, not to deter anyone

The measured figures come from the protocol repository's execution harness running the real compiled programs: the disputed step is verified from Merkle proofs of the accounts it touches, against the batch it belongs to, inside a single instruction. The dispute program is deployed on Solana devnet at its pinned id, and the settlement program there accepts challenge verdicts only from it, by cross-program call — a direct key cannot inject one. No dispute has yet been played on devnet; the harness plays them against the same compiled bytes. Which steps a dispute can actually decide is the next section, because that, not the cost, is where the open work is.

03Coverage

What a dispute can prove today

Bisection narrows a dispute to one step. That only settles anything if the dispute game can then execute the step, and for a step with no class — an instruction it has no native re-implementation of — it cannot: an honest proposer would lose that dispute by timeout. The chain reports this rather than leaving it to be discovered. Every block in the explorer carries a card that reads defensible, or not defensible with how many of its steps are opaque to the verifier. It answers one question — could this root be defended if it were challenged — and it is not a step towards finality.

On gamma todayValueNote
Blocks reporting a verdict290 of 290Every block from 1 to 290 carries one.
Defensible blocks275All of blocks 1 to 268. The fifteen that are not begin at block 269, when gamma started running SPL Token; Metaplex and the CRADLE programs followed.
Steps3,033A fee, each instruction of a transaction that succeeded, a deposit credit, a withdrawal — one state transition each.
Witnessed / opaque3,001 / 32The 32 are instructions no class covers: creating a mint or a token account, minting on a chain that predates that class, a Metaplex metadata write, calls into the CRADLE programs.

Read from gamma's own per-block report — the defence field of getBlock — for blocks 1 to 290, on 2026-09-14. No dispute has been played on devnet, so no verdict here has met a real challenge.

Step by step

Each row is a class of step the dispute game re-executes natively, with its cost measured on the real compiled program. Witnessed on gamma means gamma's node records the step in that class, which is what its verdicts count. Built means proven in the harness — a challenger narrows a settled root to that step and the proposer wins — but only a chain started at that state commitment or later records it.

StepMeasured cost (CU)Where it stands
The fee, burned or paid to the sequencer322,863 – 323,201Witnessed on gamma. The figure is the burned class; gamma pays its fee to the sequencer, which moves a second leaf, and that variant has no published measurement yet
A SOL transfer, including one that creates its destination528,210 – 528,539Witnessed on gamma
A deposit credited from Solana326,566 – 326,739Witnessed on gamma
A withdrawal to Solana528,126Witnessed on gamma
An SPL token transfer532,232Witnessed on gamma
Minting SPL tokens (MintTo)619,729Built, for a new chain from state commitment 4. Opaque on gamma
Creating a mint (InitializeMint2)352,129Built, for a new chain from commitment 7, which binds the instruction variant into the leaf; the cost was measured just before that binding. Opaque on gamma
Creating a token account (InitializeAccount3)378,868Built, for a new chain from commitment 6. Opaque on gamma
One SBF instruction of any program, interpreted58,939Built and measured on the real program. Not deployed, and wired to no game: a dispute cannot yet descend from an L2 step into the instructions inside it
Anything that reaches a syscall or another program — a log, a Metaplex metadata writeOpaque, and outside the one-step model

Why a step is opaque, and what changes that

The dispute game cannot call the program it is judging. The accounts in a dispute exist on Solana only as Merkle witnesses, so there is nothing to invoke: every class of step the game can decide is re-implemented natively inside it and held to the real program by a differential test. A step outside every class is opaque — committed under bond, but not something the game can execute.

Two things widen that, and both need a new chain rather than an upgrade of gamma. The commitment first: before state commitment 3, an opaque step's leaf recorded only its position, so no verifier could ever have been checked against what ran; from commitment 3 it binds the program, the accounts and the instruction data. Then the classes: minting has one from commitment 4, creating a token account from 6 and creating a mint from 7, each proven in the harness by a challenger narrowing a root to that step and the proposer winning.

The interpreter is the general answer, and it has a hard edge. It executes a program's SBF instructions one at a time inside the verifier — registers, control flow, calls and returns, and 8-byte memory access inside the runtime's own memory map — but it faults by design on syscalls, cross-program calls, division, 32-bit arithmetic and narrower memory access, because a step verified against semantics that differ from the runtime's proves the wrong thing. Real programs reach those, so a Metaplex metadata write, or anything that logs or calls another program, stays outside the one-step model even once the interpreter is wired to a game.

There is a second edge, on the steps the game can already execute. A witnessed class re-derives the disputed step from its arguments and checks it against the batch root the proposer committed — but nothing yet binds that step to the signed transaction that authorised it, so a proposer could place a step nobody signed into a witnessed class and win its dispute. So a defensible block means the game could execute its steps, not yet that each was authorised by a signature. Closing this is specified in ADR-0021 — every step bound to the signed transaction in a published, sealed batch — and is staged behind a version flag, not yet active; until it is, a forged step is held off by the chain's single trusted operator, the same interim the launch scope below relies on.

The honest interim: refuse what cannot be defended

One mechanism makes “every accepted transaction is fraud-provable” true today: launch scope. With it on, the node refuses at submission, for nothing, any transaction containing a step the game could not defend, so the chain only ever commits roots it can stand behind. A forced entry carrying such a step is consumed without effect rather than refused, because a slot promised through Solana's inbox is never left behind. It is off on gamma; on, it would refuse the token and NFT creation gamma runs, which is where the fifteen blocks above come from.

04Worked example

A dispute, with worked numbers

Illustrative figures — chosen round to keep the arithmetic visible, labelled as such. The published parameters will carry real ones.

QuantityExample valueNote
Disputed batch~1,000,000 stepsEvery instruction across every transaction in the batch — the thing you cannot re-run on L1.
Rounds to isolate one steplog₂(1,000,000) ≈ 20Each round halves the range: 1M → 500k → … → 1. Twenty on-chain moves, not a million.
Cost per roundone small L1 transaction each sideCommit to a midpoint state, nothing more. Cheap by construction.
Final step verificationone instruction + its state proofsThe only expensive move, and the whole design exists to make it fit one L1 transaction.
Worst-case durationrounds × response deadlineMust close comfortably inside the challenge window with margin for L1 congestion — this inequality sizes the window.

The proposer's bond makes lying expensive: an invalid root costs the entire stake when caught, so fraud has to out-earn a known, large loss against a public detection mechanism. The challenger's bond makes noise expensive: frivolous disputes forfeit it, so you cannot freeze withdrawals for free by challenging everything. Sizing matters more than existence — a bond smaller than the value a bad root could extract during the window is a fee, not a deterrent, which is why the parameter table above ties it to value at risk and re-derives it as the network grows.

Who is actually watching

Fraud proofs protect nobody unless someone runs a verifier and checks. If fraud never happens, nobody is paid for watching, and the rational choice is to stop — which is exactly when it becomes worth attempting. Solieum treats independent verification as infrastructure to fund rather than community goodwill to hope for: a one-command verifier image, and verifiers running outside the team before Stage 1 is claimed. The watchtower now runs continuously as one command, solieum-node verify --watch: it re-derives the chain from Solana through its own RPC readers, which must agree, verifies each new sealed batch as it lands, checks that bridged supply still fits the vault, posts alarms to a URL as well as the terminal, and can open a challenge under bond on a real divergence — with agree, diverge and not-yet-derivable kept distinct so withheld data or a lying reader is never mistaken for fraud. It is drilled against a poisoned provider (2026-09-04). What is not done: nobody outside the operator runs one yet.

Run a verifier →

Validity proofs, later and alongside

Planned

A validity proof settles correctness at commit time rather than after a waiting period, which is what makes short withdrawals possible without weakening the guarantee. The catch is that a soundness bug in a prover is silent and total — nothing looks wrong while everything is. That is why the plan is a second, independently implemented prover rather than a replacement: withdrawals gate on agreement, and disagreement halts rather than picking a winner.

Building something the base layer can't hold?

Tell us the workload. If Solieum is the wrong answer for it, we would rather say so early than have you find out at launch.