Skip to main content
A fraud proof is a demonstration, verified on L1, that a committed block breaks a ledger rule. A successful proof removes the block from the state queue and slashes its operator. Anyone can submit one.

How a proof is verified

Verifying a rule violation can be too large for one L1 transaction. The proof protocol splits it into steps.
  • The fraud proof catalogue lists the categories of proof. It is fixed when the L2 instance is initialized and can’t be changed afterwards.
  • A computation thread is a chain of spending validators, one per step. Each step reads the computation state from its datum, advances it, and passes the new state to the next step.
  • A fraud proof token is minted when the last step succeeds. It is the permanent record of the proof, and it is what the state queue requires in order to remove the block.
The watcher that starts a thread signs the first transaction and is recorded as the fraud prover. Only that party can advance or cancel the thread. Cancelling returns the ADA locked in it.

The reference catalogue

The reference instance defines four categories. The validators are in onchain/aiken/validators/fraud-proofs/. The whitepaper gives a fraud proof construction for every violation below. The catalogue has room for 232 categories.

Worked example: a double spend

Alice’s output holds 10 ADA. Operator Bob commits a block in which two transactions both spend it. Watcher Charley reads the block from the data availability layer and notices. Charley proves it in six L1 transactions:
1

Init

Charley references the catalogue and the block’s state queue node, and mints a thread token named after the category and the block’s header hash. Signing this records him as the fraud prover.
2

Step 1, first run

He presents the first transaction with a Merkle proof that it is in the block’s transactions_root. The step records the root of that transaction’s input set.
3

Step 1, second run

He presents the second transaction with its proof. The step requires that the two transaction IDs differ.
4

Step 2

He names Alice’s output and proves it is in the first transaction’s input set.
5

Step 3

He proves the same output is in the second transaction’s input set. The step mints the fraud proof token and burns the thread token.
6

Removal

He uses the fraud proof token to remove the block from the state queue. Bob’s bond is slashed, and Charley receives the fraud prover reward.
If later blocks were appended after the fraudulent one, they are removed first, one transaction each.

Ledger rules

Every block must satisfy 21 ledger rules. Rules 1 to 16 follow the L1’s ledger rules. Rules 17 to 21 enforce the restrictions of the L2 transaction type. That is 30 violations.

Data availability rules

One further rule binds published block data to the header: each root in a header must be the trie root of the corresponding set in the block body. It has four violations, one per set: UTXOS-ROOT-MISMATCH, TRANSACTIONS-ROOT-MISMATCH, DEPOSITS-ROOT-MISMATCH, WITHDRAWALS-ROOT-MISMATCH. See Data availability.

Block-level conditions

Three conditions concern a block as a whole:
  1. Event inclusion. The block’s deposits, transaction orders and withdrawal orders are exactly the L1 events whose inclusion time lies in its event interval, and each corresponds to a real L1 event.
  2. Event application order. Withdrawals, then transaction orders, then transaction requests, then deposits.
  3. Event validity tags. Each withdrawal order and transaction order carries the validity tag that its content determines.

How the node applies the rules

A node doesn’t wait for fraud proofs to keep its own blocks valid. Its rule engine checks every transaction at admission, in two phases: stateless checks first, then checks against the ledger state. A rejected transaction gets one of 21 reject codes. See Reject codes.

Running a watcher

Run a watcher covers what a watcher needs to do in practice.