Overview
The Midpoint Anchored Order Book (MAOB) is a discrete-rung order book anchored to an oracle midpoint. It is engineered to make on-chain order books practical: bounded loops, deterministic rounding, and O(log n) claim accounting without per-order fill updates on every trade, allowing for O(1) matching within rungs.
Core responsibilities
MAOB implements the core on-chain trading engine:
- Order management: create, store, and manage maker orders through placement, fills, claims, and cancellations.
- Order matching: price-time priority across rungs, FIFO ordering within each rung.
- Token custody: custody base tokens and quote tokens for makers, and settle to withdrawable balances.
Engineering Highlights
The contract combines several techniques that make a fully on-chain order book feasible:
- Bounded execution: a 64-rung design plus bitmask traversal yields predictable, bounded loops for takers.
- Fixed rung lattice: replaces skip list traversal with a compact rung grid and
active*Rungsbitmasks. - Generation-based queues: when a rung empties, a new generation resets queue state without costly cleanup.
- Fenwick tree accounting: queue end and cancellation trees provide O(log n) prefix sums, enabling scalable FIFO claims.
- Segmented settlement: cumulative fill segments allow computing any order's output by range without updating every order on every fill.
- O(1) per-rung matching: each rung match updates aggregated totals and emits a single fill event without iterating maker orders.
These choices let MAOB deliver deterministic pricing, fair FIFO ordering, and scalable claims while keeping gas usage predictable.
Architecture at a glance
- Oracle anchor:
IOracleAdapter.getPrice(address orderBook)provides a midpoint price with precision and staleness checks. - Fixed rung lattice:
bpsRungsdefines up toMAX_RUNGS = 64discrete price offsets in 0.1 bps units. - Side-specific liquidity pools:
askRungs(base tokens) andbidRungs(quote tokens) track rung totals. - Active rung bitmasks:
activeAskRungsandactiveBidRungsenable fast rung traversal. - FIFO queue accounting: per-rung
QueuePosition, per-runggen(generation), and claim ranges. - Fenwick trees:
fwEndandfwCanceltrack queue sizes and cancellations for O(log n) claims. - Fill segments: per-rung+side+generation
FillSegment[]stores cumulative input/output and rounding remainder. - Withdrawable ledger:
withdrawableBaseandwithdrawableQuotecollect claimed output before withdrawal.
Order lifecycle
Maker placement
Makers add liquidity using:
addLiquidityAsk(rung, baseAmount)addLiquidityBid(rung, quoteAmount)addLiquidityBatch(liquidityOrders)
Key mechanics:
- Oracle safety:
_getMidPrice()enforces non-zero price/precision and staleness bounds. - Min quote token checks:
minQuoteMakerensures orders meet minimum value thresholds. - Single transfer per side in batch: base tokens and quote tokens are transferred once per batch.
- Queue positioning:
_createOrderassignsclaimRangeStart/claimRangeEndusing a frontier computed from cumulative fills and cancellations for FIFO fairness. - Rung activation:
activeAskRungs/activeBidRungsare toggled as rungs become non-empty.
Taker execution
Taker flows include:
buyBaseExactOut/buyBaseTargetInsellBaseTargetIn/sellBaseExactOut
Key mechanics:
- Bounded traversal:
_activeMask(maxRung, active*Rungs)plus_lsbIndexwalks only active rungs up tomaxRung. - Deterministic pricing: rung prices are derived from the oracle midpoint with fixed bps offsets and rounding to
PRICE_SIGFIGS. - Segmented fills:
_recordFilland_recordFillWithRemainderupdate cumulative fill segments without touching each maker order. - O(1) per-rung matching: fills update rung totals, fill segments, and emit a single
RungFilledevent without iterating makers. - Guardrails: deadline, min quote token checks, and slippage limits (
maxQuoteIn,minBaseOut,minQuoteOut,maxBaseIn).
Claims and cancellations
- Claiming:
_claimOrdercomputes claimable output using per-order claim ranges and fill segments, then credits withdrawable balances. - Cancelling:
_cancelOrderInternalmarks remaining input in the cancel Fenwick tree, refunds remaining input to withdrawable balances, and preserves filled amounts for later claims. - Withdrawals:
_withdrawtransfers accumulated base tokens and quote tokens to the maker.
Claim range settlement (FIFO)
Every resting order owns a continuous claim range (claimRangeStart, claimRangeEnd) representing its slice of the rung queue. The rung frontier advances as takers fill the rung, with cancellations tracked in the Fenwick trees.
Claimable input is computed from the frontier and the order's range:
filled = min(frontier, claimRangeEnd) - claimRangeStart
This keeps FIFO ordering without iterating other makers and allows claims to remain O(log n) even as the queue grows.
Pricing and rounding
MAOB prices each rung relative to the oracle midpoint:
- Ask price:
mid * (RUNG_DENOM + rungBps) / RUNG_DENOM - Bid price:
mid * (RUNG_DENOM - rungBps) / RUNG_DENOM
Key precision mechanics:
baseScaleandquoteScalenormalize token decimals._roundPriceQrounds toPRICE_SIGFIGSsignificant figures for deterministic pricing._applyRemaindercarries remainder across fills so rounding is fair and consistent across partial fills and claims.