Receipts

We tried to break it. Here is what held.

Every test, drill and soak the venue, the oracle and the index have been through, with the numbers and what each one found. It is what the code did when we tried to break it, updated as we go.

In plain terms: we wrote down 77 ways this could be attacked before writing the venue, built it, ran two simulated fortnights of trading against a local copy of the chain and checked that the books balanced after every single transaction. Then we put it on a public testnet. Everything below is the evidence, including the bugs those runs found and the days the testnet sat frozen. New to the words on this page? The glossary defines book, mark, epoch root, forward TWAP and keeper in a line each.

309automated tests, 0 failed
14,120orders in two simulated fortnights
10,068epoch roots under soak
77attacks written down before the code
roots posted since 11 September
40books live on chain

Counted 14 September 2026: forge test 156 · node --test chain/offchain/test 71 · npm test 82.

The soak

Two simulated fortnights, solvent after every transaction.

The harness spins up a local chain, lists six markets and runs fourteen days in 240-second steps. The prices are random walks with jumps: a 55% crash on day three, an 18% single-epoch jump on day five that the oracle has to hold, a relayer outage on day seven long enough to freeze the venue, a 36% slide on day eight and an 80% pump on day ten. Twelve funded accounts trade eight strategies against it, from trend-following and hedging to maximum-leverage and high-churn accounts.

After every single transaction it checks that the venue is solvent, and the moment the books diverge it walks back to the block, names the transaction and dumps every bucket movement. It also checks fill bands and spreads, that only liquidatable positions get liquidated, that every order either fills or is cancelled, that the status ladder reaches FROZEN during the outage and NORMAL again after it, and it classifies every revert.

Two runs, 8 September 2026Run A · seed 1337Run B · seed 42
Steps of 240 s5,0405,040
Epoch roots posted5,0345,034
Orders committed / executed / cancelled6,987 / 6,982 / 87,133 / 7,113 / 20
Liquidations (with a shortfall)61 (1)34 (3)
Insurance fund, low-water mark$20,000 → $25,438, never below $20,000$20,000 → $26,499, never below $20,000
Backstop vault NAV (net asset value)$300,000 → $432,743$300,000 → $405,541
Reverts, every one a rule refusing an order2,4072,118
Outage ladderNORMAL → REDUCE_ONLY → FROZEN → NORMALNORMAL → REDUCE_ONLY → FROZEN → NORMAL
Solvency after every transactionheldheld

In both runs the venue was NORMAL again one step after the relayer returned. Three orders in Run A executed in part and were cancelled for the rest, so they count in both columns. Wall time for each fortnight: about five hours.

Every revert in both runs was a refusal the rules require: not enough free balance, the skew budget, an open-interest cap, below initial margin, or a market that was reduce-only, gapped or frozen during the outage. None was a bug.

What the soak found

  • FoundFlip orders minted margin. An order that closed a long and opened a short in one fill charged margin for the closed side only. Fixed in the venue, with a regression test, and both fortnights were run again from scratch.
  • FoundReceipt waits that never returned. A race in the client library's block poller left the keeper waiting forever on a transaction that had long been mined. Every service now polls the receipt itself, with a timeout.
  • FoundWindows across a stale root gap. After the outage the keeper priced fills over a window that straddled the gap and the venue refused it. The planner now re-anchors to the first fresh root, covered by five tests.
  • FoundA lone trader could not close. With nobody on the other side, a close whose spread exceeded the gain made the vault's ledger underflow. The vault flow is now two-phase: absorb, then settle. Two tests.
  • FoundOrders committed just before the freeze. Six orders across the two runs were placed in the minutes before the outage and were still open one step after the venue returned to NORMAL. The harness flags that as an anomaly by design; every one of them was filled or cancelled by the end of the run, and the venue never traded on a stale number in between.
The contracts

156 Foundry tests on the venue, the oracle and the bond.

Unit tests on every function, fuzz tests on the maths, and one adversarial file per attack that the chain has to defend against on its own. The suite runs in under a second and is green at every commit.

SuiteTestsWhat it proves
EpochOracle62Roots post only in order, inside the timestamp window, chained to the previous root, under the current params version, with enough bonded signers and no duplicate group. Markets register with an opening state and can be relisted after settlement. A touch stores every leaf field, is idempotent, tracks gaps and honours resume leaves. Digests match the chain's own tooling.
PerpMath, unit and fuzz22 + 16Notional, PnL, maintenance, initial margin, liquidation price and fraction, taker fee, spread, skew term and funding, checked against the reference vectors and at every rounding direction. Fuzzed: net-position round trips, liquidation restores health, spreads grow with volatility, and every rounding direction is pinned.
PublisherBond16Bonding, top-ups, the unbond cooldown, a pending unbond dropping the bond immediately, and the oracle reading the bond on every root.
PerpVenue10Listing state, a commit that fills at the forward TWAP, the vault absorbing skew, a 40% slide liquidating while a healthy position never is, the stale-oracle ladder, a wild fill cancelled by the band, a flip charging margin for the new side, and a lone trader closing above or below the spread.
Adversarial A36, A55, A56, A5730A 10,000x leaf is rejected by move sanity and an accumulator off by one unit reverts. Malformed leaves are dropped while the root still posts and the other markets are untouched. One compromised publisher group cannot post; two of three can, but their step is capped at 25% per epoch and skipping epochs does not beat the cap. Signatures are bound to the chain and the contract: a root signed for another oracle, or replayed, fails.
Total1560 failed, 0 skipped
The oracle pipeline

71 tests on the publishers, the aggregation and the keeper.

The off-chain side is where a bad number would come from, so it gets the same treatment. Golden hashes come from the chain's own tooling; two machines must produce identical roots from identical inputs.

Aggregation

  • Medians over an agreeing set: an outlier is excluded and the ledger hash follows the median member.
  • Fewer than the threshold agreeing leaves a degraded leaf that keeps the previous mark. A listed market is never dropped from a root.
  • A move above 15% is held, then confirmed or cleared; three holds request a freeze; a confirmed step is never re-held; resume markets are exempt.
  • Roots are deterministic across submission order and every proof verifies against them.

Signatures and encoding

  • EIP-712 typed-data digests recomputed by hand and bound to the chain and the contract; a set signed for another oracle fails.
  • Leaf encodings hash to golden values; changing any field changes the hash; out-of-range fields are refused before anything is hashed.
  • Merkle trees are ordered by market id, reject duplicates, and verify for every leaf from one to twelve.

Signer rules

  • At most one signature per epoch, epochs strictly increasing, and an epoch timestamp within 10 seconds of the signer's own clock.
  • An own move above 15% is refused unless carried as a held leaf, then confirmed at the held value or cleared, never a third value.
  • State survives a restart with the reference marks intact; an epoch whose root never posted can be forgotten and signed again.

Keeper and relayer

  • Fill windows re-anchor across a degraded epoch and across a stale root gap; a block timestamp of zero is treated as unknown rather than as a decades-long gap.
  • The relayer's next timestamp: six cases, including the one that froze the testnet for two hours on 11 September 2026 and can no longer happen.
  • A root post that ran out of gas is recognised from its receipt, the epoch is forgotten and signed again: seven cases, including the one from 12 September 2026.
  • Each publisher signs its own books' leverage from concentration, and falls back to fixtures when the backend is down.
The index

82 tests on the number everything settles on.

The mark is what the market would pay for a trader's whole account. The tests pin down the two things that make it tradeable: nothing but prices can move it, and no bag is worth more than the pools could absorb. The full method is public.

  • OKFlows are invisible. A deposit, a withdrawal, a trade at market, a token we never saw them buy, an airdrop: none of them move the mark. Only the price move afterwards counts, and the trader's own slippage is real.
  • OKMoving a bag out cannot hide a dump. Tokens that leave an account with no sale in sight keep counting for thirty days at the lower of their value when they left and their value now, and come back without moving the mark.
  • OKNothing without a real pool. A token whose only pools are quoted in another memecoin or a fake stable is worth nothing, however high its last print.
  • OKDepth caps the bag. A position the market cannot absorb is capped at a multiple of the slow depth; half the float is valued at instant exit; a young token starts at the floor and blends in over seven days; value never exceeds spot and grows with depth and volume.
  • OKLeverage follows concentration. An account more than 60% in one token gets 1x, and the ceiling is never exceeded; thin, tiny and single-token accounts are halted with a stated reason; markets still being measured are reduce-only, not halted.
  • OKThe worked example holds. The spec's unipcs case values the PONS bag at $9.20M in the time-to-liquidate regime, against $9.94M at its last prints, and the test asserts that figure to 1%.
  • OKThe beta venue's maths. Liquidation price sits where equity equals maintenance, funding moves it closer, increases average the entry, partial reduces realise pro rata, a flip closes and reopens at the fill.
On chain

Live on Robinhood Chain testnet since 7 September 2026.

The same contracts the soak ran against, deployed with every admin role held by a timelock and the deployer's roles renounced in the same script run. Every root the publisher has signed has been posted for 40 books: from a workstation for the first two days, and from a supervised server continuously since 11 September 2026, with the two outages listed under incidents.

reading the chain…
46630chain id
1 htimelock on every admin action
25,000mUSDC publisher bond
30–180 sbetween roots
40books listed
1–5xmax leverage per book, set daily from tier and concentration
0.15%taker fee on every fill (15 bps)
180 sforward TWAP: fills at the average mark over the three minutes after commit

The drill, passed 8 September 2026

One script, one wallet, real transactions on the public chain, in this order:

  • OKGas balance and a claim of mUSDC (mock USDC: free test collateral, worth nothing) from the faucet contract
  • OKApprove and deposit; free balance credited
  • OKA NORMAL market found from the latest signed root
  • OKA $60 long committed with the leaf and its Merkle proof
  • OKExecuted by the keeper three minutes later at the forward TWAP, inside the band
  • OKPosition open with the expected size and margin
  • OKReduce-only close committed and executed; position size back to zero
  • OKWithdrawal paid out
  • OKVenue solvent: collateral balance equals every accounted bucket

Anyone can repeat it on the on-chain venue with a wallet, testnet ETH from the official faucet and the daily mUSDC claim. The guide walks through every step.

Contracts

Incidents, found and fixed

Everything that went wrong, and the test that now catches it.

12 to 13 September 2026

A root post ran out of gas and the venue froze for fourteen hours

Gas on the chain rose between the relayer's estimate and the block that included its transaction, so the post reverted. The relayer never checked the receipt, recorded the epoch as posted, and its signer then refused to sign that epoch again. With no fresh roots every book read FROZEN, which is the designed behaviour: no fills, no liquidations, no position at risk on a stale number.

The fix: every send carries 30% headroom above the estimate, every receipt's status is checked, and an epoch whose root never posted is forgotten and signed again on the next tick. Seven new tests. Roots resumed on the first tick after the fix was deployed.

11 September 2026

The relayer refused its own timestamp for two hours

A tick chose an epoch timestamp, then spent 18 seconds on chain reads during a backend restart. Its own signer refused the timestamp as stale, which is the rule, and the relayer kept retrying that same timestamp. No root for two hours.

What held: the venue read FROZEN on every book at the 900-second stale age written into the contract. No fills, no liquidations, no new risk while the number was stale. That is the ladder doing its job.

The fix: a timestamp nobody signed is never kept, an unpostable signed epoch is forgotten and re-signed, the reads run in parallel and the timestamp is chosen last. Seven new tests. Roots resumed four seconds after the restart; one book that had halved during the gap was held and confirmed at the next epoch.

8 to 11 September 2026

Three days frozen during the move to a server

Between the drill and the move to hosted infrastructure the relayer ran from a workstation that was switched off. With no fresh roots the venue froze every book on its own, exactly as designed: no fills, no liquidations, nothing to recover.

The fix: the services run under a supervisor on a server that restarts them, and every chart draws the window as a gap rather than gluing the segments together; recording gaps are found and reconstructed by tested code.

8 September 2026

A close ran out of gas on the public chain

The keeper touched the market between the wallet's gas estimate and the transaction's inclusion, so the close needed more gas than estimated and reverted.

The fix: every send from the relayer and from the on-chain venue page carries headroom above the estimate.

Still open

What is not done yet, so nobody has to guess.

  • OpenA third-party audit of the contracts. Not started. The contracts are unaudited testnet code until it lands, and this line changes when it does.
  • OpenThree independent publishers in three groups with a threshold of two. The aggregation and the bond are built and tested; the testnet set is one publisher today.
  • OpenSettlement, conditional orders and vault deleveraging. Specified, not implemented; the entry points revert.
  • OpenContract size. The venue is 53 KB of runtime bytecode, above Ethereum's usual 24 KB limit. Robinhood Chain testnet accepts it, verified with a 60 KB deployment on 8 September 2026; a mainnet that enforces 24 KB needs the venue split in two.
  • OpenA four-week bake on testnet with every alarm quiet or explained.
  • OpenThe provenance ledger behind the index as the next publisher, so received tokens and withdrawn lots are booked from on-chain events rather than balance sheets.