Order-book depth the protocol itself will not let you withdraw.
0xf5e39c1fthe revert that proves it
Solidity
Somnia Shannon · 50312
@somnia-chain/markets-sdk
Foundry
viem
two rungs · one cancel · one axisPULLABLE dissolves · FIRM repels
02The hero moment
He could not take his own order back.
The wallet that paid for the resting order called cancelOrder. The pool refused it and named both parties in its own revert data.
0xf5e39c1f
IncorrectSender(address,address)
Transaction 0x959b4770…6ddb · status 0x0 · mined and permanent on Somnia Shannon. A failed transaction cannot be mocked, staged, or replayed.
03The problem
Displayed depth is only a promise.
On every order book that exists, the size at a level is size the maker can cancel in one block. Takers price that uncertainty in, and no venue can tell them which depth is real.
Wallet-owned depth
Can vanish in one block.
One cancelOrder from the owner and the level is gone — after you decided to trade against it.
Contract-owned depth
Stays until filled or expired.
Only a taker fill or the mandatory expireTimestampNs removes it. There is no third path.
Polymarket, Kalshi and every CEX show you the first bar. Nobody has ever shown you the second.
04The mechanism
Make the contract the owner.
FirmQuote holds the collateral, approves the Somnia BinaryPool, and calls placeBinaryOrder — so Order.owner is the contract, not a wallet. It exposes no cancel path, no reduce path, and grants no operator. Every withdrawal route is therefore closed by the pool's own rules.
cancelOrder(uint128)
owner only — and the owner is bytecode with no code path to ask
CLOSED
cancelOrderFor(owner, id)
an operator the owner approved — the contract never grants one
CLOSED
reduceOrderFor(owner, id, qty)
per-user approval only, no system allowlist — never granted
CLOSED
Deployed at 0x2a09b4c474828e6895af273e51Ba8C181c91191a on Somnia Shannon, chain 50312.
05Proof on Shannon · 2026-08-19
The chain refuses its own funder.
cast — Somnia Shannon · no wallet, no funds, no gas
$ cast call 0x1b8ed538…67ee "cancelOrder(uint128)" \
129127208515966879685 --from 0xFbc73Ce1…3595
execution reverted, data:
0xf5e39c1f
…fbc73ce1c0b43f87cd065f82df24697dec653595 ← caller
…2a09b4c474828e6895af273e51ba8c181c91191a ← expected
$ cast 4byte 0xf5e39c1f
IncorrectSender(address,address)# control — the same call, from the contract itself:
$ cast call … --from 0x2a09b4c4…191a
0x← no revert. It WOULD succeed.
shannon-explorer.somnia.network/tx/0x959b4770…6ddb · status 0x0
1The caller is the wallet that funded and paid for the order.
2The expected address is FirmQuote. The pool names both parties itself.
3The control makes it rigorous: the order is not uncancellable in general. The pool would let its owner cancel — the owner just has no way to ask.
Escrow verified still locked across both attempts: tUSDC 4,827,000 before and after, YES balance unchanged — the order rested, it did not fill.
06The product
Three classes, not two.
Order.owner is readable on-chain, so every price level can be typed. The third class is the one that makes the metric honest.
FIRM
owner is a contract whose EXTCODEHASH is attested, and it is still inside its lock window
This depth cannot be withdrawn.
PULLABLE
owner is a wallet — the empty code hash, keccak256("")
This depth can vanish in one block.
UNVERIFIED
owner is a contract whose code hash we have not attested
No claim is made.
UNVERIFIED is load-bearing. Every escape in our corpus mints UNVERIFIED depth, not FIRM — the book renders it as exactly what it is. The metric errs low by construction.
07The headline number
A naive check is fooled six times out of six.
Typing a level FIRM on EXTCODESIZE > 0 is forgeable. Rampart attests EXTCODEHASH under a static bytecode policy instead.
Attested EXTCODEHASH8 / 8
Naive EXTCODESIZE2 / 8
Corpus: the real FirmQuote, six attacker contracts that each look firm to a naive check, and a plain wallet. All eight are deployed on Shannon; five of the six escapes executed on-chain as real withdrawals.
Every one of these reads FIRM to an EXTCODESIZE check. Every one is typed UNVERIFIED by the attested classifier, each caught by a different check in the policy.
08Architecture
Owner in, typed book out.
The pool is the source of truth for who owns each resting order. Everything Rampart adds is a read — no indexer to trust, no off-chain state to keep in sync, nothing a maker can influence.
0.13 msfull-book retype · p95
0.13 ms
100 ms block budget
Re-typing the entire book and re-aggregating the percentage fits inside one Somnia block with three orders of magnitude to spare — so the metric can be live, not batch. Measured over a deterministic 2,000-order book by script/bench.mjs — fixed owners, fixed seed, so the number reproduces on any machine.
09Sponsor SDK — the engine, not the decoration
Three findings the docs do not have.
Rampart is built on @somnia-chain/markets-sdk and viem against a live Somnia binary pool. Integrating it turned up three things that are not written down anywhere.
01
The generic placeOrderreverts UseBinaryPlacement on a binary pool. Binary markets need placeBinaryOrder, with the YES/NO side as an explicit kind param — read out of markets-sdk/src/tradeAbi.ts, not the documentation.
02
The prose docs document SpotPool. BinaryPool differs, and the difference is fatal if missed — including builderFeeBpsTimes1k, which must be uint96 or the selector changes and the call reverts with nothing decodable.
03
The pool rejects cancelOrderFor from any operator with OnlyApprovedContracts — even for a valid grant. We found this by deploying an attacker whose whole escape was a late operator grant, and watching the pool block it anyway.
Written up as a 261-line feedback report — a required deliverable for this event, produced from the build rather than from a read-through. Rampart's entire mechanism is the pool's own ownership rule; there is no version of this project on another chain.
10Ecosystem impact
An observable no off-chain book can produce.
“Percent of book that cannot be withdrawn” needs an on-chain Order.owner to inspect. That requirement is the whole argument.
Off-chain book
Polymarket · Kalshi · every CEX
Resting orders are signed messages inside a private matching engine. There is no on-chain owner to inspect, so the metric is not hard to build — it is impossible to build. Even the venue itself cannot prove it without being believed.
On-chain order book
Somnia · DreamDEX
The owner is an address, its code is a public hash, and both are a free read. Liquidity quality stops being a marketing claim and becomes a number anyone can re-derive from chain state alone.
Firm depth is what a maker can charge for and a taker can price. This is a reason to put an order book on-chain that has nothing to do with decentralisation — it is a product capability that only exists here.
11What this is not
The limits, stated up front.
Testnet only
Somnia Shannon, chain 50312. Nothing is deployed to mainnet and nothing has been audited.
Buy side only
Selling firm needs an ERC-6909 operator grant — and granting no operator is exactly what keeps the lock airtight. v1 quotes the buy side and says so.
Sound, not complete
The static analyzer is sound for the six known escape classes. It is not a general proof of irrevocability, and we do not present it as one.
List, not oracle
The attestation registry is a transparency list anyone can re-derive from the same bytes. It is not a trustless oracle, and it never will be without governance.
No traction
No users, no volume, no adoption to report. A live firmness read returns 0% right now — the deployed lock window has lapsed, and we would rather show you that than a stale screenshot.
Each of these is in DEMO.md under Honest limits, with the exact reproduce command for the two escapes that did not complete on-chain.