Skip to content

System architecture

Components and state ownership

Component Owns Does not own
ProtocolAuthority Governance, ops, and emergency role addresses Market or user state
AccountCore Account identity, custody, free/reserved Spot balances, signer permissions, builder approvals, fee policy, verified market routes FIFO queues, perpetual positions, risk calculations
SpotRouter Spot deployment registry, token whitelist, orderbook proxy ownership and market-state routing User funds or matching state
SpotEngine Immutable Spot market configuration Activation state, balances, or matching
OrderBook Spot FIFO state, order IDs, matching, passive bands, hook configuration, packed market-data events Token custody
PerpRouter Quote-engine registry, global market IDs, perpetual deployment routes, engine/orderbook ownership Margin or positions
PerpEngine One quote asset's markets, cross/isolated margin, positions, exposure, maker-fee reserves, funding, open interest, health, liquidation state Token custody or FIFO queues
PerpOrderBook One market's FIFO state, order intent, order/trade IDs, local settlement journals Collateral, positions, funding, OI, protocol fees
Periphery contracts Optional deposits, quoting, signed Spot intent forwarding, example maker automation Privileged settlement authority

Trust and call boundaries

Spot action

account or TRADE signer
  -> OrderBook
     -> match and mutate FIFO state
     -> AccountCore.applySpotReserveDelta(...)
     -> AccountCore.settleSpotTradesWithBuilder(...)
     -> emit TradesPacked / BookUpdatesPacked

Resting bids reserve quote plus their maker fee; resting asks reserve base. Matching and balance settlement occur in one transaction, so any custody or fee failure reverts the orderbook mutation.

Perpetual action

account or TRADE signer
  -> PerpOrderBook
     -> match and mutate FIFO state
     -> build exposure and maker-fill journals
     -> AccountCore.executePerpOrderAction(...)
        -> validate market route and fee policy
        -> PerpEngine.executePerpOrderAction(...)
        -> accrue protocol and builder fees
     -> emit packed market-data events

The perpetual orderbook never mutates the Engine directly during a normal user action. One AccountCore call applies order exposure, maker-fee escrow, fills, funding settlement, PnL, open interest, protocol fees, builder fees, and final health checks atomically.

Liquidation action

Liquidation intentionally reverses the normal direction: AccountCore authorizes the keeper and calls PerpEngine; the Engine calls restricted orderbook functions that return cancellation or fill journals without calling back into AccountCore. The Engine applies those journals before returning. This avoids a circular AccountCore -> Engine -> orderbook -> AccountCore callback.

Product separation

  • Spot has no leverage, borrowing, funding, mark price, open interest, or liquidation.
  • Each PerpEngine has exactly one quote asset and quote scale. Cross margin is shared only among markets registered in that Engine.
  • Spot-free balance, Spot order reserve, passive-liquidity custody, perpetual cross margin, and perpetual isolated margin are distinct claims even though tokens remain in AccountCore custody.
  • Unallocated free balance does not automatically protect a perpetual position.
  • The shared active-orderbook core provides storage and FIFO mechanics, not product settlement logic.

Upgrade model

AccountCore, SpotRouter, SpotEngine, PerpRouter, PerpEngine, and deployed orderbooks use UUPS/ERC-1967 patterns where implemented. Proxy ownership is part of the routing design: routers own the market proxies they deploy, and a PerpEngine must be owned by PerpRouter before registration. Changing a router's orderbook implementation pointer affects future deployments only; existing verified proxies require the router's explicit upgrade entrypoint.

Storage layout and initialization data are therefore protocol invariants. An upgrade must be checked against populated state, not only against a clean deployment.