technical paper - june 2026 - devnet prototype

Native re-execution as a fraud proof: trustless settlement of real-time games on Solana

tickproof - verifiable game engine & stake escrow. Source repository. All figures reproduce from the repo against Solana devnet.

Abstract

Real-time games cannot run on a blockchain - 60 Hz tick rates and sub-millisecond input latency are incompatible with global consensus. So every “play for money” product on Solana today runs the game on a server and asks the chain to believe the server's result. We describe a system that keeps the game off-chain at full speed but makes its outcome objectively enforceable: game logic is compiled once to SBF, executed off-chain inside the real Solana program runtime, and committed to with Merkle state roots. In a dispute, an interactive bisection narrows disagreement to a single tick, and that tick is re-executed natively by the L1 itself - the same SBF bytecode, as an ordinary program invocation. On top of this we build a stake escrow in which two players wager real funds on a match and no server, oracle, or counterparty is ever trusted with the pot. The complete fraud proof costs ~19k compute units (about 1.4% of one transaction's budget); a full adversarial settlement - lie, challenge, bisection, native replay, payout - completed in 20 transactions over 47 seconds on devnet.

1. The problem

A two-player wager has a simple shape: both sides lock a stake, a game produces a winner, the winner takes the pot. The hard part is the middle. Whoever reports the result can steal the pot, so the reporter must be trusted - and on Solana today that reporter is always a backend server, sometimes dressed up as an oracle or a multisig. The result is custodial risk wearing a decentralization costume.

There are three known ways out, and two of them do not work for real-time games:

The observation behind tickproof: on Solana, the L1 already executes the exact VM the game runs in. If game logic is SBF bytecode, the chain can re-execute any disputed tick as a plain CPI - no interpreter-in-a-contract (we measured one: 80+ CU per emulated instruction, so an interpreted tick starts at ~157k CU before memory proofs), no proving infrastructure. The fraud proof is the program itself.

2. Deterministic tick programs

Everything rests on bit-exact replay, so the game kernel is deliberately austere. A game is a pure state transition:

state' = tick(state, inputs, tick_index)

written in no_std Rust with no floats, no heap, no clock, no host entropy (crates/tick-core). Numerics are Q32.32 fixed point; randomness, if a game wants it, is a seeded xorshift64* whose seed is part of the state. The same crate compiles to both native code and SBF, and the test suite pins them to each other: a thousand ticks of randomized input produce bit-identical state in both builds, and a frozen golden hash catches semantic drift.

The reference game (games/arena) is a small physics arena - eight balls, impulse inputs, wall bounces, friction - chosen to exercise the pipeline, not to be fun. One arena tick costs at most ~2,000 CU under the real runtime, and the off-chain engine pushes ~17k ticks/s through the full pipeline on one core - room for hundreds of simultaneous 60 Hz sessions.

3. Commitments: state roots and the input chain

The engine (crates/runtime) drives the SBF build through the actual agave program runtime (via mollusk) and periodically emits checkpoints. A checkpoint commits to two things:

A claim is therefore 64 bytes - state root plus input chain - and the claim at tick 0 (the genesis claim) is computable by anyone, including this website, which derives it in the browser byte-for-byte when opening a match.

4. The referee: bisection to a single tick

The referee program (programs/referee) runs the optimistic game. An operator asserts a checkpoint at some tick with a bond. If nobody objects within the challenge window, it finalizes. If a challenger bonds and disagrees, the two parties play an interactive bisection: the operator publishes the claim at the midpoint of the disputed range, the challenger says “agree below / disagree above” (or vice versa), and the range halves. After log2(n) rounds the disagreement is exactly one tick wide.

That tick is then settled by the chain itself, in one transaction:

  1. the submitted pre-state must hash to the agreed lower claim,
  2. the submitted inputs must extend the lower input chain to the asserted upper chain,
  3. a scratch account is seeded with the pre-state via CPI into the game program,
  4. the game program executes the tick natively - the same SBF the operator ran off-chain,
  5. the resulting state root either matches the asserted claim or it does not. Winner takes both bonds.

Anyone may submit the replay; the outcome is decided by execution, not by who called it. One deliberate asymmetry: if the disputed tick cannot execute at all (the operator committed to inputs the game program rejects), the replay transaction can never land and the challenger wins by timeout - the burden of proof sits with the asserter. The complete one-step proof - both hash checks, two CPIs, payout - lands at ~19k CU.

5. The wager layer: escrow without a reporter

programs/wager turns the referee into money. A match account pins both players, the game program, the stake, the final tick, a settlement deadline, and the genesis claim. Player A escrows a stake to open; player B matches it to join. Settlement has two paths:

Per-player session slots

Each player binds their own referee session to the match, and can only ever rebind their own slot. This closes a real griefing lane: with a single shared slot, a cheater could rebind a fresh virgin session right before the honest player's settlement transaction lands, invalidating it forever and converting a certain loss into a deadline refund. With per-player slots a player can only sabotage their own path to settlement; the opponent's proof stands.

Punishment and payout are separate concerns

A subtle property worth making explicit: when a cheater's assertion is destroyed in a dispute, they lose their bond to the challenger - but the pot still goes to whoever actually won the game, as named by the verdict over the true final state. Lying about a match you genuinely won costs you the bond and nothing else; lying about a match you lost costs you the bond and the match. Incentives stay aligned in both directions.

Liveness

Funds cannot deadlock. An unjoined match is cancellable by its creator; a live match that nobody manages to settle refunds both sides after the deadline. The optimistic assumption is the standard one: each player (or anyone watching on their behalf) comes online at least once per challenge window.

6. Measured results

Prototype windows are deliberately short (64-slot challenge window, 150-slot move deadline) to make devnet runs watchable; mainnet values would be hours. Everything below is from confirmed devnet transactions or the real agave runtime:

QuantityMeasured
one arena tick (real runtime)≤ ~2,000 CU
complete one-step fraud proof~19k CU (~1.4% of a tx budget)
trustless settle instruction~13k CU
interpreted re-execution (comparison)80+ CU per emulated instruction; ~157k CU per tick before memory proofs
SP1 Groth16 verify (comparison)~280k CU
honest match, end to end on devnet6 tx / ~31 s / 65k lamports in fees
adversarial match on devnet20 tx / ~47 s; lie injected at tick 21 cornered to exactly ticks 20→21
state root cost~11 CU/byte, linear
engine throughput~17k ticks/s per core through the full runtime pipeline

The adversarial run is worth reading on an explorer: the native replay transaction is the cluster re-executing the disputed tick and convicting the cheater, and the settlement transaction is the escrow paying the true winner through the game's own verdict. Both times the cluster's replay matched the locally computed trace bit for bit.

7. Security model and known gaps

This is an early prototype. The honest list:

8. Why this matters beyond games

The deeper claim is about the substrate: any deterministic computation expressible as an SBF program with byte-array state can be run off-chain at native speed and held accountable by the chain at ~19k CU per dispute, with zero proving overhead in the happy path. Real-time games are the most demanding instance - tick rates, adversarial counterparties, money on the line - which is exactly why they make a good proof. Order matching, simulations, multi-step agent workflows: anything with a pure state transition fits the same mold.

The chain is not a computer you run things on. It is a court you never have to visit - but whose verdicts are mechanical.

Appendix: deployed artifacts

Reproduce the honest run with cargo run -p devnet-match --release and the adversarial run with --cheat.