Inspiration

An application reports two completed tasks. So does the current chain. But they are the wrong two tasks.

A small event indexer can retain events from a discarded branch while its totals still look plausible. Reorg Lab gives developers working with a small getLogs projection a controlled way to expose that failure, inspect its consequences and demonstrate a bounded recovery.

What it does

The experiment deploys an original TaskBoard contract on a local development EVM. Branch A completes tasks 42 and 99. The runner restores only the node to an earlier snapshot, deliberately preserving the indexer's database. Different transactions create branch B at the same height, completing tasks 7 and 9.

A deliberately flawed height-only cursor sees no increase in the head number, fetches nothing and keeps A. Its total remains two, yet it contains two orphaned event rows, misses two canonical rows and has four incorrect task states.

The recovering adapter compares block hashes, finds the common ancestor, removes discarded rows and replays canonical events. The report checks exact event identities and task state against contract storage, canonical logs and a clean rebuild.

The browser is an interactive saved-run viewer. Compare projections, inspect the A/B branch timeline, expand event identities and import JSON from your own run. It displays evidence from a real local EVM execution; it does not run that EVM in the browser.

How we built it

Solidity supplies independently readable contract state and transaction events. TypeScript coordinates Hardhat 3/EDR, ethers and the installed solc compiler. The recorded environment uses Hardhat 3.16.0, Solidity 0.8.37 and Node.js 24.16.0 on local chain 31337.

Contract reads use eth_call with an EIP-1898 block hash and requireCanonical. Logs are pinned to canonical block hashes. The target hash is checked before and after reference reads and before committing an index snapshot. Recovery assembles a candidate in memory and replaces the JSON file only after the reads succeed.

Memory and JSON storage implement the same Store interface. A reusable Projector interface exposes initialization and event application. A second example counts completion transitions, then checks its result against the contract after task 7 is reopened. These interfaces support adapting the lab; connecting an external indexer requires integration work.

React, Vite and TypeScript provide the static viewer. Imports are read locally and checked for structural and internal consistency. Their provenance is not authenticated.

Reproduce it

With Node.js 24, clone the repository and run:

npm ci
npm run lab

The runner creates a fresh local EVM and writes portable JSON and standalone HTML reports, plus persisted index snapshots. Dependency installation needs the npm registry; the experiment itself requires no public RPC, wallet, API key or funds. Run npm test and npm run build for validation, then import the generated JSON into the viewer.

Challenges and evidence

A meaningful test must preserve the stale database. Restoring the index together with the node would erase the failure under examination. Another challenge is avoiding circular validation: a clean rebuild alone can repeat the same reducer error, so contract storage and exact row identities provide additional checks.

The saved run rl-1e4e5f8aae75 verifies equal branch height, distinct hashes and an unchanged index during node restoration. Recovery removes two old rows, replays two canonical rows and matches the pinned contract state and clean reconstruction.

It records 7 passing controls and 2 expected inconclusive outcomes. Replay adds no duplicates, and a fresh adapter instance recovers from stale JSON. Insufficient rollback history and an injected RPC failure preserve the old index and remain inconclusive. They do not demonstrate recovery.

Separately, 17 automated tests pass, including missing blocks, changed heads, malformed or duplicate logs and contradictory imported verdicts. Production compilation passes. These are bounded fixture results, not performance or production-safety claims.

What we learned and what's next

A matching aggregate is weak evidence of consistency. The useful result is an inspectable failure case with the exact rows, state and reference block that explain it.

Ponder and SQD already handle reorganizations; portal-ponder documents consistency testing. Reorg Lab's contribution is a focused, portable experiment for small projections. It does not claim universal database repair or proven superiority.

Next is adapting the harness to an existing external projection and testing developer usability. That work remains unperformed. Snapshot/revert on one local EVM does not reproduce public-network consensus, propagation or finality.

Authorship and credits

Created by Jhonatan del rio mejia with OpenAI Codex assistance in research, design, implementation, tests, documentation and presentation. The original contract, scenarios and interface were created for this project. The video uses genuine saved-run captures, synthetic ElevenLabs narration and English subtitles. Source is MIT licensed; dependencies retain their own licenses. No user study or external adoption is claimed.

Built With

Share this project:

Updates

Submission history