JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Optimistic rollups: innocent until proven fraudulent

An optimistic rollup posts its results to Ethereum and dares the world to prove them wrong. Learn the fraud-proof bisection game, why a single honest verifier keeps it safe, and the price you pay for that trust: a seven-day wait to come home.

An auditor who stamps the books without re-doing the math

Picture an auditor at a year-end meeting. Instead of re-calculating every line of the accounts, she stamps the ledger "approved" on sight — but she announces a rule: *anyone in the room has one week to point at a specific line and prove it is wrong; if they do, the whole statement is thrown out and the person who signed it is fined.* Nobody re-does the full audit. The threat of being caught on a single line is what keeps the numbers honest. That is exactly the bet an optimistic rollup makes.

In the previous guide you saw the shared shape of every rollup: execute transactions off-chain in batches, then post the transaction data plus a new state root back to Ethereum, which acts as the settlement layer and data layer. That guide left one question hanging: L1 stores the new state root but never re-runs the transactions, so how does it know the root is correct? There are only two answers. Prove it up front with a validity proof — that is ZK-rollups, the next guide. Or assume it is right and allow disputes after the fact — that is the optimistic approach, and it is what this guide takes apart.

The optimistic bet: assert now, allow challenges

Mechanically, the sequencer orders and executes a batch of L2 transactions, then sends two things to an L1 contract: the batch data (compressed transactions, posted as a blob since EIP-4844) and an assertion — a claim of the form *"executing this batch takes the chain from previous state root A to new state root B."* Crucially, no proof of correctness is attached. The assertion is just a posted claim with a bond behind it.

  1. Sequence & execute. The sequencer orders incoming L2 transactions, runs them, and gives users an instant soft confirmation — the snappy UX that makes an L2 feel fast.
  2. Post data to L1. It publishes the compressed batch data to Ethereum so that anyone can later reconstruct the L2's state — this is the non-negotiable data-availability step.
  3. Assert the new root. It posts the assertion (A → B) plus a bond to the L1 rollup contract. The new root is treated as valid immediately for L2 purposes, but L1 does not yet trust it for withdrawals.
  4. Open the challenge window. A timer starts — the challenge period, roughly seven days on Arbitrum and OP Mainnet. During this window anyone may dispute the assertion.
  5. Confirm or contest. If the window closes with no successful challenge, the root becomes canonical and L1 withdrawals against it unlock. If someone challenges and wins, the assertion is rejected and the dishonest asserter loses its bond.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

// A drastically simplified optimistic-rollup contract on Ethereum (L1).
// The sequencer ASSERTS a new state root; it becomes canonical only after
// the challenge window passes with no successful fraud proof.
contract RollupAssertions {
    struct Assertion {
        bytes32 prevStateRoot;
        bytes32 newStateRoot; // claimed result of executing the batch
        bytes32 batchHash;    // commitment to the L2 tx data posted as a blob
        uint256 proposedAt;   // L1 timestamp when it was posted
        address asserter;
        uint256 bond;
        bool    confirmed;
    }

    uint256 public constant CHALLENGE_WINDOW = 7 days;
    uint256 public constant BOND = 1 ether;
    Assertion[] public assertions;

    // The sequencer posts a result WITHOUT proving it is correct.
    function assertState(bytes32 prevRoot, bytes32 newRoot, bytes32 batchHash)
        external payable
    {
        require(msg.value == BOND, "post a bond");
        assertions.push(Assertion(prevRoot, newRoot, batchHash,
                                  block.timestamp, msg.sender, msg.value, false));
    }

    // After the window closes with no challenge, the root becomes final.
    function confirm(uint256 id) external {
        Assertion storage a = assertions[id];
        require(!a.confirmed, "already final");
        require(block.timestamp >= a.proposedAt + CHALLENGE_WINDOW, "still challengeable");
        a.confirmed = true;
        payable(a.asserter).transfer(a.bond); // honest asserter reclaims the bond
        // newStateRoot is now trusted: L1 withdrawals against it unlock.
    }

    // Anyone may open a dispute during the window (the game is in the next section).
    function challenge(uint256 id) external payable {
        require(msg.value == BOND, "post a bond");
        Assertion storage a = assertions[id];
        require(!a.confirmed, "already final");
        require(block.timestamp < a.proposedAt + CHALLENGE_WINDOW, "window closed");
        // ... start the bisection game; the loser's bond is paid to the winner.
    }
}
A toy L1 contract showing the heart of the design: assertState posts a claim with no proof; confirm finalizes it only after the window elapses; challenge opens a dispute.

The whole security of this picture rests on the challenge window. Until it elapses, L1 has only an unverified claim — which is why a withdrawal back to L1 has to wait. And it only works if the batch data was genuinely posted: a challenger cannot prove fraud over data they cannot see, so data availability on the settlement layer is the bedrock the entire scheme stands on.

Fraud proofs: how one honest verifier wins the argument

Here is the obvious objection: to check whether the sequencer's root is right, doesn't L1 have to re-run the whole batch? If it did, the rollup would be pointless — that re-execution is the exact cost we moved off-chain. The escape from this trap is the fraud proof, and its genius is that it never asks L1 to run the batch. Instead it narrows the disagreement down to a single machine instruction and runs only that.

Production optimistic rollups do this with an interactive bisection game (also called a dispute game). The asserter has effectively committed to the entire execution trace — the hash of the machine's state after every single step. The challenger disagrees about the final root, which means they must disagree about some step along the way. So the two parties play binary search over the trace: "do we agree on the state halfway through?" Each answer halves the search space, until they have isolated the one instruction they disagree on.

# Interactive fraud proof = a bisection game over the execution trace.
# Asserter claims: running the batch takes state root A -> B in N machine steps,
# and commits to a hash of the machine state after every step.
# The challenger disagrees about the FINAL root, so they disagree about SOME step.

lo, hi = 0, N                       # the first disputed step lies in [lo, hi)
while hi - lo > 1:                  # ~log2(N) rounds, one cheap L1 tx each
    mid = (lo + hi) // 2
    h = asserter.stateHashAt(mid)   # asserter commits to the state hash at step mid
    if challenger.agreesWith(h):    # they agree through mid -> the fault is LATER
        lo = mid
    else:                           # they diverge at/before mid -> the fault is EARLIER
        hi = mid

# Now hi == lo + 1: they disagree on exactly ONE instruction.
# The L1 contract runs that single step on-chain -- the "one-step proof":
claimed = asserter.stateHashAt(hi)
actual  = L1.executeOneStep(asserter.stateHashAt(lo), program[lo])
if actual == claimed:
    slash(challenger)               # asserter was right; the challenge fails
else:
    slash(asserter)                 # FRAUD proven: reject the assertion, roll the root back
The bisection game in pseudocode: ~log2(N) rounds of cheap L1 messages narrow a billion-step dispute down to a single instruction, which L1 finally executes itself.

Put numbers on it. Suppose executing a batch takes N = 2^30 ≈ 1.07 billion machine steps. Binary search isolates the disputed step in just log₂(N) = 30 rounds, each round a single cheap L1 transaction. Then L1 runs exactly one instruction — the one-step proof — and the math decides the winner objectively. The loser's bond is slashed, paying the winner and covering gas. Both leading implementations work this way: Arbitrum Nitro bisects over a WebAssembly-style machine (WAVM), and Optimism's Cannon bisects over a MIPS execution trace. Different machines, identical idea.

Why one honest verifier is enough — and what it leans on

This is the security model worth memorizing: optimistic rollups need only one honest, watchful verifier — a *1-of-N* assumption. Compare that to a base chain's honest-majority assumption, where safety needs >50% (proof-of-work) or two-thirds of stake (BFT) to behave. Here, no matter how many liars post bad assertions, a single honest party who holds the data and is willing to challenge will always win the bisection game, because the one-step proof is decided by objective math, not by a vote. One honest soul defeats any number of cheats.

But "one honest verifier" leans on two unglamorous conditions. First, data availability. You cannot prove fraud over bytes you never received; if the sequencer withholds the batch data, no one can recompute the trace and the fraud proof is toothless. That is why posting data to L1 is mandatory, and why DA turns out to be the real scaling bottleneck — the subject of a later guide. Second, liveness. Someone has to actually be running a verifier, watching every assertion, and willing to spend gas to challenge. If everyone assumes "someone else will catch it," a bad root can slip through — the classic verifier's dilemma. Protocols answer it with bonds and rewards so that catching fraud is profitable.

The seven-day wait and the sequencer in the middle

The challenge window is also the price tag. To withdraw assets back to L1 through the rollup's canonical bridge, you must wait the full challenge period — roughly 7 days — because L1 refuses to trust the state root before the window closes. Note the asymmetry: depositing into the L2 and moving funds within the L2 are fast; only the L1 withdrawal eats the delay, since that is the only moment L1 must rely on an as-yet-unconfirmed root.

In practice users rarely wait a week, thanks to fast-withdrawal liquidity providers. A third-party bridge looks at your pending L2 withdrawal, judges it almost certainly valid, and hands you the funds on L1 immediately for a fee — then waits out the 7 days to reclaim the canonical withdrawal itself. They are selling you their patience and absorbing the (tiny, if the assertion is honest) risk. It is a clean market solution, but notice it reintroduces a counterparty you trust for speed.

And then there is the sequencer sitting in the middle. Today it is almost always a single, centralized operator (Offchain Labs for Arbitrum, OP Labs for Optimism). The upside is real: instant soft confirmations and a smooth UX. The downsides are equally real — it can censor transactions, it can go down (Arbitrum's sequencer suffered a notable outage in December 2023, halting new transactions for hours), and it captures MEV by choosing the order. Two defenses matter. A forced-inclusion escape hatch lets a censored user submit their transaction straight to an L1 inbox, so the sequencer cannot indefinitely silence anyone. And the longer-term fix is to decentralize sequencing entirely — shared sequencers, or based rollups that hand ordering to L1 block proposers.

Optimistic vs ZK: an honest trade-off

Optimistic rollups buy their security cheaply but pay for it in time and liveness. Because the happy path attaches no proof, proving costs essentially nothing and reaching full EVM-equivalence is comparatively easy — that is why optimistic rollups matured first and run unmodified Solidity faithfully. The bill comes due as the ~7-day challenge period, plus the requirement that someone stays honest and awake (the liveness assumption), plus the hard dependence on data availability.

ZK-rollups — the next guide — flip the trade. Instead of waiting to catch fraud, the sequencer attaches a succinct validity proof that the state transition was computed correctly, and L1 verifies it cheaply on the spot. The reward is near-instant finality, fast withdrawals (no week-long wait), and no liveness assumption — math, not a watchful crowd, guarantees correctness. The cost is heavy proof generation and the historically harder road to a full zkEVM. Notice both designs still post their data to L1, so data availability remains the bottleneck they share — and the subject of the guide after next.