ADR-001: Single Canonical Order Book
Status
Accepted
Context
Binary prediction markets have two outcomes (YES and NO), which naturally suggests two order books - one for YES shares and one for NO shares. However, this design decision has significant implications for:
- Liquidity fragmentation - Two books split market makers' capital
- Complexity - Users must reason about two separate markets
- State size - Two orderbook accounts per market
- Matching logic - Cross-book arbitrage opportunities
The Core Insight
In a binary market, buying YES at price p is economically equivalent to selling NO at price 1-p:
Buy YES @ 60% = Pay 0.60 USDC, receive 1 YES share
Sell NO @ 40% = Receive 0.40 USDC, give 1 NO share
If outcome is UP:
- YES buyer: Paid 0.60, receives 1.00 = +0.40 profit
- NO seller: Received 0.40, owes 0.00 = +0.40 profit
The trades are equivalent.
Decision
Implement a Dual-View Single Engine architecture:
- Store all orders as YES share orders in a single canonical order book
- Convert NO orders to equivalent YES orders before storage
- Present users with four intuitive order types (BuyYes, SellYes, BuyNo, SellNo)
Conversion Rules
Buy YES @ p → Canonical BID @ p
Sell YES @ p → Canonical ASK @ p
Buy NO @ q → Canonical ASK @ (10000 - q)
Sell NO @ q → Canonical BID @ (10000 - q)
Examples
| User Order | User Price | Canonical Side | Canonical Price |
|---|---|---|---|
| Buy YES | 6000 bps | BID | 6000 bps |
| Sell YES | 6000 bps | ASK | 6000 bps |
| Buy NO | 4000 bps | ASK | 6000 bps |
| Sell NO | 4000 bps | BID | 6000 bps |
Consequences
Positive
-
Unified Liquidity
- All liquidity concentrates in one book
- Tighter spreads for users
- Better price discovery
-
Reduced State
- One orderbook account instead of two
- 50% reduction in storage costs
- Simpler account management
-
Simpler Matching
- Single matching engine
- No cross-book arbitrage needed
- Deterministic execution
-
Consistent Pricing
- YES @ 60% and NO @ 40% are always consistent
- No price divergence between books
- Intuitive implied probability
-
Natural Arbitrage Prevention
- No opportunity for cross-book arbitrage
- Prices stay aligned by construction
Negative
-
Conversion Overhead
- Extra computation for NO order conversion
- Users must understand the equivalence
-
Mental Model Complexity
- Advanced users see the canonical form
- May be confusing initially
-
Tick Rounding Asymmetry
- NO orders experience inverse tick effects
- Buy NO @ 4050 → Ask @ 5950 → rounded to 6000
Mitigations
-
Clear Documentation
- Explain equivalence in user guides
- Show both user and canonical views in UI
-
SDK Abstraction
- SDK handles conversion automatically
- Users interact with intuitive order types
-
Transparent Rounding
- Show effective price after rounding
- Warn about tick boundary effects
Alternatives Considered
Alternative 1: Two Separate Order Books
Maintain independent YES and NO order books.
Rejected because:
- Fragments liquidity
- Requires cross-book arbitrage mechanism
- Doubles state requirements
- More complex matching logic
Alternative 2: Combined YES/NO Shares
Use a single share type that can be positive (YES) or negative (NO).
Rejected because:
- Negative balances are confusing
- Harder to reason about solvency
- More complex accounting
Alternative 3: AMM Instead of Order Book
Use automated market maker (Uniswap-style) for pricing.
Rejected because:
- Impermanent loss for LPs
- Worse execution for large orders
- Less capital efficient for binary outcomes
- Price manipulation easier
Implementation Notes
Conversion Function
pub fn convert_to_canonical(
side: UserOrderSide,
price_bps: u16,
) -> (CanonicalSide, u16) {
const P_MAX: u16 = 10_000;
match side {
UserOrderSide::BuyYes => (CanonicalSide::Bid, price_bps),
UserOrderSide::SellYes => (CanonicalSide::Ask, price_bps),
UserOrderSide::BuyNo => (CanonicalSide::Ask, P_MAX.saturating_sub(price_bps)),
UserOrderSide::SellNo => (CanonicalSide::Bid, P_MAX.saturating_sub(price_bps)),
}
}
Invariant
After conversion, the standard order book invariant holds:
best_bid < best_ask (when both exist)
This is equivalent to:
best_yes_bid < best_yes_ask
best_no_bid < best_no_ask
best_yes_bid + best_no_ask <= P_MAX
best_no_bid + best_yes_ask <= P_MAX
References
- ORDERBOOK.md - Full order book specification
- Binary prediction market theory
- Polymarket's dual-book design (contrast)
Changelog
- 2026-01: Initial decision