Roardex

Indexing infrastructure

Every generic indexer trusts a block
the moment it sees one.
On GIWA, that's already wrong.

Flashblocks give GIWA ~200ms preconfirmations inside every ~1s block — and the transaction set behind a block hash can still change before it's final. Roardex is the indexing layer built to expect that, instead of being surprised by it.

Balance mismatches, naive indexer
100/100
Balance mismatches, Roardex
0/100
Panics over the extended live run
0

The problem

A wrong answer that looks completely normal

The Graph, Ponder, Envio — every general-purpose indexer we looked at assumes a block is final the instant it's observed. GIWA's own docs say plainly that this doesn't hold: "even for the same block, the hash may change if the set of preconfirmed transactions changes." No generic indexing stack accounts for that.

The failure mode isn't a crash. It's a balance, a log, a fill status that's confidently wrong for exactly as long as it takes a preconfirmation to revise — with nothing in the response telling you so.

What we measured

Same feed, two indexers

Naive indexerRoardex
Balance mismatches100 / 1000 / 100
Log query mismatches500 / 5000 / 500

Naive here means the default behavior of every generic indexing tool against a feed shaped like the real Flashblocks cadence — wrong on every answer, with no indication anything is off.

The fix

One idea, applied uniformly

A Flashblocks revision is structurally a depth-1 reorg. Track exactly what each revision contributed, undo it cleanly when superseded, replay the canonical version — the same mechanism handles a 200ms preconfirmation flip and a multi-block chain reorg with an identical code path.

  • Revision-tagged writes

    Every write is tagged with its revision and rolled back cleanly when superseded — nothing is ever overwritten blind.

  • Compressed bitset log index

    Roaring-style address/topic indexing for eth_getLogs-shaped queries — measured 17× less memory than a naive bitset at scale.

  • LSM-backed durable storage

    Pebble, not a B-tree — sustained high-write ingestion is exactly the workload LSM engines were built for.

  • Merkle Mountain Range, anchored on-chain

    Sealing is gated behind finalized, never latest — the MMR is append-only and can't un-see a leaf a later reorg reaches back into. Every sealed root is also posted to a small contract on GIWA Sepolia, so it's checkable independent of us.

  • Reorg vs. catch-up classification

    A genuine chain reorganization is counted separately from a pending-tier view simply not being final yet — two different events, two different signals.

Validated against the real chain

Run continuously on the live testnet

Two indexing strategies, side by side, on real testnet traffic.

Log lines observed
72,800+
Blocks sealed into the MMR
126
Panics / fatal errors
0
Memory vs. naive bitset
17× less

Found and fixed a real O(n²) growth bug mid-validation — a 500k-log indexing pass went from ~9s to ~150ms. The 17× memory gap kept widening the longer the run went, not a one-time benchmark number.

Live right now

The indexer, running

The status below comes from the actual indexer, polling GIWA Sepolia as you read this. You can hit the endpoint yourself.

Checking live status…

Every root above is also posted on-chain as it's sealed — MMRAnchor on Blockscout.

Limitations

Where things stand

  • Reorg repair is scoped to unfinalized blocks by design — MMR-sealed data is intentionally out of scope for automatic repair. The alternative is silent corruption, which is worse.
  • Public testnet RPC is genuinely rate-limited — a meaningful share of pending polls failed over our extended live run. Production needs dedicated or self-hosted node access.
  • The MMR root is anchored on GIWA Sepolia itself after every seal, via a small owner-gated contract — a consumer verifying a proof doesn't have to trust our HTTP response for the root, only the chain. See the contract for the exact call.

What we're looking for

  • Dedicated or self-hosted GIWA RPC access — our own measurements show the public endpoint isn't viable for sustained production use.
  • Introductions to early GIWA Wallet / dApp teams who'd be real first consumers of a Flashblocks-aware log API.