◆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 → verify02Dispute
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.
- 01
Assert
A proposer commits a state root under bond.
- 02
Challenge
A verifier that computed a different root opens a dispute, also under bond.
- 03
Bisect
Both sides commit to intermediate states, halving the disputed range each round.
- 04
One step
The disagreement is now a single instruction and its exact inputs.
- 05
Verify
Solana executes that one step and decides. The loser forfeits their bond.
The constraint every parameter answers to
| Parameter | Value | Why it matters |
|---|---|---|
| One-step verification | 322,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,000 | Measured 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-chain | Sets the number of on-chain interactions per dispute |
| Per-round timeout | At 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 cap | 35 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 duration | Must be < challenge window, with margin — refused at open if it is not | A dispute that cannot finish in time would make the window decorative, so opening one is rejected outright |
| Proposer bond | Devnet placeholder: 100,000 lamports, and a challenger posts 50,000. Production value sized against value at risk | Must 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 today | Value | Note |
|---|---|---|
| Blocks reporting a verdict | 290 of 290 | Every block from 1 to 290 carries one. |
| Defensible blocks | 275 | All 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. |
| Steps | 3,033 | A fee, each instruction of a transaction that succeeded, a deposit credit, a withdrawal — one state transition each. |
| Witnessed / opaque | 3,001 / 32 | The 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.
| Step | Measured cost (CU) | Where it stands |
|---|---|---|
| The fee, burned or paid to the sequencer | 322,863 – 323,201 | Witnessed 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 destination | 528,210 – 528,539 | Witnessed on gamma |
| A deposit credited from Solana | 326,566 – 326,739 | Witnessed on gamma |
| A withdrawal to Solana | 528,126 | Witnessed on gamma |
| An SPL token transfer | 532,232 | Witnessed on gamma |
| Minting SPL tokens (MintTo) | 619,729 | Built, for a new chain from state commitment 4. Opaque on gamma |
| Creating a mint (InitializeMint2) | 352,129 | Built, 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,868 | Built, for a new chain from commitment 6. Opaque on gamma |
| One SBF instruction of any program, interpreted | 58,939 | Built 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 write | — | Opaque, 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.
| Quantity | Example value | Note |
|---|---|---|
| Disputed batch | ~1,000,000 steps | Every instruction across every transaction in the batch — the thing you cannot re-run on L1. |
| Rounds to isolate one step | log₂(1,000,000) ≈ 20 | Each round halves the range: 1M → 500k → … → 1. Twenty on-chain moves, not a million. |
| Cost per round | one small L1 transaction each side | Commit to a midpoint state, nothing more. Cheap by construction. |
| Final step verification | one instruction + its state proofs | The only expensive move, and the whole design exists to make it fit one L1 transaction. |
| Worst-case duration | rounds × response deadline | Must 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.
Validity proofs, later and alongside
PlannedA 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.