Hunting and the judge
What to submit, how it is protected, how the judge builds and replays it, and what a PASS pays.
What you submit
- A Rust crate as a zip or tar.gz, at most 5 MB, that builds into the target program.
- A payout wallet, which signs a message to bind the submission to it (the wallet opens only when you click).
- The snapshot you target: the page preselects the latest one.
The payout wallet signs this text, which binds the target, the snapshot, the source commitment and the wallet together:
teardown:submit:<program>:<snapshot slot>:<source sha256>:<wallet>:<time in ISO 8601, UTC>
I submit this source for replay against the snapshot above and ask that any payout go to this wallet. On PASS the source is published.Your source stays sealed until the verdict
The browser encrypts the archive before it leaves your machine: AES-256-GCM with a random key, and that key sealed to the judge's X25519 public key (tweetnacl box with an ephemeral key). Only the ciphertext is uploaded. The sha256 of the plaintext archive is the public source commitment: it is shown with the attempt and written in the proof record. The judge's private key lives only in the judge machine's secrets.
Rules checked before the build
- Rust only.
- No
asm!orglobal_asm!; noinclude_bytes!orinclude_str!of anything over 4 KB; nobuild.rs. - Procedural macro crates only from the allow-list: the
solana-programfamily,borsh,bytemuck,thiserror,num-derive,anchor-langandanchor-attribute-*,pinocchio. Cargo.lockpresent and used (--locked); dependencies from crates.io only.- The build uses one of the pinned Agave
cargo build-sbfversions of the judge image.
The judge compiles your crate itself; a submitted binary is never trusted. Builds run with no secrets in the environment, on an ephemeral machine, with a 10 minute cap.
The replay
The original binary (from the snapshot) and your candidate are loaded in two identical local SVMs (LiteSVM). Both receive exactly the same inputs: real instruction data from recent mainnet transactions to the program, the same current account states, the same sysvars, and then fuzzed variants of those instructions. Programs the instructions call into are loaded too. Both binaries run under the same compute budget, taken from each case's own ComputeBudget instructions, so an interpreter that embeds the original bytecode as data cannot pass.
For every case the judge compares:
- success, or the exact error, custom codes included;
- every byte of every account the instruction may write: data, lamports, owner;
- return data;
- the program logs line for line, with the
consumed N of M compute unitslines removed; - CPI invocations (
invoke [n]lines) and their order.
The verdict
PASS when every case matches and the corpus exercises the program for real: at least 100 cases where the original succeeds, so a corpus of pure errors cannot pass. Otherwise FAIL, with the share of matching cases as the attempt's match. The verdict is a JSON report with its sha256, the source commitment, the corpus hash and both binary hashes.
The target corpus is 1,000 real mainnet instructions and 10,000 fuzzed variants. When a program has fewer usable recent instructions, the corpus holds what exists, with a minimum of 200 to open a target to hunting, and every page prints the real number.
What the wall shows
Each attempt appears on the target page with its match, its hashes and its status. No code is shown before the verdict. The best match so far is printed on the target's tile, and the lock on the program's print dissolves as it rises.
On a PASS
- The source is published on the target page the same day. Always: the point is to rebuild in the open.
- 90% of the pot is paid to the payout wallet by the keeper, in USDC.
- 10% is bought into $TEARDOWN on Jupiter and burned; until the token exists it is held in the vault.
- The keeper records the verdict on Solana as a Memo:
teardown:proof:<target>:<submission>:<source sha256>:<report sha256>:<matched>/<total>. Until the keeper holds SOL the page says "Memo record pending", and every pending verdict is recorded in one run once it does.
House agents
The project can run its own AI hunters: a loop that reads a target's teardown kit, writes a Rust candidate, runs the local replayer and submits when it passes locally. They run only behind an inference key (INFERENCE_API_KEY); until it is connected the house agents are offline until inference is connected, and nothing they would produce is shown. The teardown kits, snapshots and the judge run without AI.