> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kuru.io/llms.txt
> Use this file to discover all available pages before exploring further.

# OrderBook

> Matching, reserves, swaps, passive liquidity, and views.

`OrderBook` is the on-chain FIFO spot book implementation. It matches native spot orders, manages resting-order reserves through `ISpotBalanceAccount`, emits packed trade/book-update events, and supports passive liquidity bands.

## Contracts

* `SpotRouter` deploys spot market proxies, registers them with `AccountCore`, and administers market state.
* `OrderBook` stores canonical market configuration and handles matching, cancels, packed replace, post-fill hooks, swaps, passive liquidity, and execution state.
* `AccountCore` owns balances, account ids, signer permissions, builder approvals, reserves, and settlement.
* `SpotPeriphery` is an optional, unprivileged facade for deposits, signed session-authorization forwarding, and multi-market swap estimates.

Internally, `OrderBook` is split by responsibility rather than by product inheritance. Permanent storage and shared constants live in `OrderBookState`; later modules layer admin, pricing, events, accounts, settlement, queues, passive markers, hooks, matching, placement, packed replacement, passive-liquidity accounting, swaps, and views. The final deployed contract is `src/orderbook/OrderBook.sol`.

## Assets

Spot markets may use ERC20 tokens or native MON. Native MON is represented by `address(0)` in token configuration, market parameters, internal balances, reserves, settlement, and withdrawals. Because `address(0)` is a valid asset, market existence is tracked with explicit registration flags rather than by checking whether the stored base or quote token is nonzero.

Native/native markets are invalid: one side may be native MON, but base and quote must be different assets.

Quote token decimals are loaded from `AccountCore` during orderbook initialization, not supplied by the market deployer. ERC20 spot tokens must expose `IERC20Metadata.decimals()` when governance enables them; native MON is fixed at 18 decimals. The cached quote scale is then used for all quote-notional, reserve, passive-liquidity, and swap math.

Quote conversion is direction-aware. Resting-bid reserves, active-bid fills, and passive-bid fills floor in two deterministic stages: first `price * size / sizePrecision`, then quote-token scaling by `10 ** quoteTokenDecimals / pricePrecision`. Passive asks ceil those two stages per fill. Active asks instead accumulate the exact full-precision numerator within one match and credit each FIFO maker the incremental change in the cumulative ceil. Active-ask credits therefore sum to `ceil(sum(price * size * quoteScale) / (sizePrecision * pricePrecision))` without charging an unrelated fee recipient. `pricePrecision` remains the configured price-scale denominator; base sizing is handled by `sizePrecision`.

## Native Orders

`ISpotOrderBook.NativeOrder` contains:

* `side`
* `quantity`
* `price`
* `tif`
* `executionInstruction`
* `minSizeAfterBlock`

Spot orders do not carry product-risk flags. The packed replace flags are limited to side and ALO/post-only behavior. Packed replacements buffer queue metadata in small in-memory caches and flush those caches before any mid-batch BBO recomputation that may prune tree bits, keeping moved orders visible to matching and views.

## Exact-Input Swaps

`swap` is a min-out protected exact-input taker entrypoint for aggregator-style flows. `isBuy = true` spends quote for base, and `isBuy = false` spends base for quote. The returned `SwapResult` reports the input actually used and the output actually received after fees. `minAmountOut` is the swap slippage guard: the orderbook walks available active FIFO and passive liquidity, then reverts unless the final output is high enough.

Buy swaps treat `amountIn` as a fee-inclusive quote budget. The orderbook converts it once into the maximum raw quote principal. Passive asks consume their per-fill ceiled quote. Active asks consume incremental cumulative-ceil quote and carry the exact remainder across prices and FIFO heads in the match. Atomic budget can remain unused and a partial maker residual can be dust-cancelled. Passive fills debit raw input immediately but withhold output until finalization. The protocol taker fee is ceiling-rounded once on aggregate raw quote; an approved builder fee is ceiling-rounded once on aggregate base output.

`estimateSwap` is a view simulation of the same exact-input intent. It shadows passive-ask ceilings and the active-ask cumulative remainder across FIFO heads, including stale chunks and dust removal, without mutating queues, balances, or passive band inventory. It cannot predict liquidity or balance changes produced by stateful hooks or state changes between estimation and execution.

One swap is one fee match. A native batch or packed replacement may finalize several matches. Each match ceiling-rounds
taker and builder fees once across its active and passive totals; active maker fees remain per-fill floors.

Routers that only need quotes can call `SpotPeriphery.estimateSwap` or `estimateSwaps` instead of integrating with each market directly. The periphery does not execute swaps or bypass account permissions; actual `swap` calls must still come from the account or a signer authorized in `AccountCore`.

## Reserve Model

Resting bids reserve quote plus the maker fee. Resting asks reserve base. Reserves are deducted from free balance when an order rests.

For fills, the orderbook derives consumed reserve from the order's old size and residual size. Full fills consume the full reserve. Partial fills leave `spotReservedBalance` equal to the residual order reserve. Cancels and reductions release only the unfilled residual reserve back to free balance.

Maker settlement consumes filled reserves directly from `spotReservedBalance`; filled maker funds are never temporarily credited to free balance before post-fill hooks run. Taker settlement still debits and credits free balances directly. Protocol fees accrue to the configured fee collector. Builder fees credit the builder's free AccountCore balance and leave custody through `withdraw`.

## Packed Events

An action emits one `BookUpdatesPacked` or `TradesPacked` per contiguous run. Each cycle logs whichever run was appended first, then the other run. A nonempty
`protocolCancelBySlots` then emits `ProtocolOrdersCancelled` after those packed logs. Trade records are 64 bytes; the final record of
each nonempty match carries `MATCH_END`. Book-update records are 39 bytes. Active trade and live book records carry the
order's maker-fee snapshot; passive trade and delete records carry zero. See
[OrderBook indexing](/indexing/order-book) for the layouts and reconstruction rules.

Batch and packed-replace terminal outcomes reuse reserved bits in those same records. A zero-delta book sentinel represents
an otherwise silent IOC, POST\_ONLY/ALO skip, empty packed cancel, or non-resting completion. The event signatures and record
widths do not change; indexers must mask base flag bits and skip sentinels for L2/L3.

## Dust Handling

FIFO fills enforce the minimum base size that can settle to at least one atomic quote unit at the matched price. Resting orders below that executable unit are canceled as dust. Once a taker order has made a real fill, any remaining taker dust below the executable unit is treated as complete for IOC/FOK semantics rather than forcing a revert or leaving a meaningless unmatched tail. Partial fills that would leave an unexecutable maker residual cancel the residual instead of leaving it at the queue head.

## Passive Liquidity

Passive bands lock base and/or quote balances through `lockSpotPassiveLiquidity`. Burns and fee claims release balances back through the spot balance interface. See [Passive Liquidity Events](/matching-engine/passive-liquidity) for event indexing.

Passive activity changes visible depth and must be reconstructed from execution and band-update events; see [OrderBook Events](/indexing/order-book).

## Callable reference

Signatures and parameter types below are generated from the reviewed SDK 0.2.0 ABI (contract revision `cdac5ae1`). These are Solidity return values: SDK write methods return a transaction hash and require receipt reconciliation. Viem decodes small Solidity integers as numbers; the SDK normalizes account IDs to `bigint` on its account-client methods.

<AccordionGroup>
  <Accordion title="getMarketParams()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `uint32`, `uint96`, `uint32`, `uint96`, `uint96`, `uint256`, `uint256`.
  </Accordion>

  <Accordion title="baseToken()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `address`.
  </Accordion>

  <Accordion title="quoteToken()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `address`.
  </Accordion>

  <Accordion title="baseSizeMultiplier()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `uint96`.
  </Accordion>

  <Accordion title="quoteTokenDecimals()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `uint8`.
  </Accordion>

  <Accordion title="passiveSpreadTicks()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `uint32`.
  </Accordion>

  <Accordion title="marketState()">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    No parameters.

    **Returns:** `uint8`.
  </Accordion>

  <Accordion title="bestBidAsk()">
    **Mutability:** `view`. Visible best prices. Empty bid is uint32 max; empty ask is zero.

    No parameters.

    **Returns:** `uint32 bid`, `uint32 ask`.
  </Accordion>

  <Accordion title="getL2Book(uint256)">
    **Mutability:** `view`. Combined visible active and passive depth. Stale-order visibility caps are already applied.

    | Parameter | Solidity type |
    | - | - |
    | `levels` | `uint256` |

    **Returns:** `uint32[] bidPrices`, `uint96[] bidSizes`, `uint32[] askPrices`, `uint96[] askSizes`.
  </Accordion>

  <Accordion title="getOrderId(uint40, uint8)">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `slotIdx` | `uint8` |

    **Returns:** `uint64 orderId`.
  </Accordion>

  <Accordion title="getOrderMinSizeAfterBlock(uint40, uint8)">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `slotIdx` | `uint8` |

    **Returns:** `uint32 minSizeAfterBlock`.
  </Accordion>

  <Accordion title="batch(uint40, tuple[], uint8[])">
    **Mutability:** `nonpayable`. Live TRADE authority over the target account is required. Cancels run before the native orders. Post-only skips are possible in successful transactions; other validation failures can revert the whole call.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `orders` | `(uint8 side, uint96 quantity, uint32 price, uint8 tif, uint8 executionInstruction, uint32 minSizeAfterBlock)[]` |
    | `cancelSlotIdxs` | `uint8[]` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="batch(uint40, tuple[], uint8[], bytes32, tuple)">
    **Mutability:** `nonpayable`. Live TRADE authority over the target account is required. Cancels run before the native orders. Post-only skips are possible in successful transactions; other validation failures can revert the whole call.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `orders` | `(uint8 side, uint96 quantity, uint32 price, uint8 tif, uint8 executionInstruction, uint32 minSizeAfterBlock)[]` |
    | `cancelSlotIdxs` | `uint8[]` |
    | `clientOrderId` | `bytes32` |
    | `builderConfig` | `(address builder, uint32 feePps)` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="batch(uint40, tuple[], uint8[], bytes32)">
    **Mutability:** `nonpayable`. Live TRADE authority over the target account is required. Cancels run before the native orders. Post-only skips are possible in successful transactions; other validation failures can revert the whole call.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `orders` | `(uint8 side, uint96 quantity, uint32 price, uint8 tif, uint8 executionInstruction, uint32 minSizeAfterBlock)[]` |
    | `cancelSlotIdxs` | `uint8[]` |
    | `clientOrderId` | `bytes32` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="batch(uint40, tuple[], uint8[], tuple)">
    **Mutability:** `nonpayable`. Live TRADE authority over the target account is required. Cancels run before the native orders. Post-only skips are possible in successful transactions; other validation failures can revert the whole call.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `orders` | `(uint8 side, uint96 quantity, uint32 price, uint8 tif, uint8 executionInstruction, uint32 minSizeAfterBlock)[]` |
    | `cancelSlotIdxs` | `uint8[]` |
    | `builderConfig` | `(address builder, uint32 feePps)` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="replaceBySlotPacked(uint40, bytes, bytes32, tuple)">
    **Mutability:** `nonpayable`. Live TRADE authority required. Replacements lose queue priority. Slot indexes are reusable; use wallet expected-ID bindings for delayed signed requests.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `packedOps` | `bytes` |
    | `clientOrderId` | `bytes32` |
    | `builderConfig` | `(address builder, uint32 feePps)` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="replaceBySlotPacked(uint40, bytes)">
    **Mutability:** `nonpayable`. Live TRADE authority required. Replacements lose queue priority. Slot indexes are reusable; use wallet expected-ID bindings for delayed signed requests.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `packedOps` | `bytes` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="replaceBySlotPacked(uint40, bytes, tuple)">
    **Mutability:** `nonpayable`. Live TRADE authority required. Replacements lose queue priority. Slot indexes are reusable; use wallet expected-ID bindings for delayed signed requests.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `packedOps` | `bytes` |
    | `builderConfig` | `(address builder, uint32 feePps)` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="replaceBySlotPacked(uint40, bytes, bytes32)">
    **Mutability:** `nonpayable`. Live TRADE authority required. Replacements lose queue priority. Slot indexes are reusable; use wallet expected-ID bindings for delayed signed requests.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `packedOps` | `bytes` |
    | `clientOrderId` | `bytes32` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="cancelAllOrders(uint40)">
    **Mutability:** `nonpayable`. Cancels the target account’s active orders in this market at execution. Does not remove passive positions or automation schedules.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |

    **Returns:** No Solidity return value.
  </Accordion>

  <Accordion title="swap(uint40, bool, uint128, uint128, uint64, tuple)">
    **Mutability:** `nonpayable`. Exact-input amount and minimum output use raw token atoms. The caller needs TRADE permission and free funds. Reverts on self-trade, failed slippage/deadline checks, or other execution failures.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |
    | `minAmountOut` | `uint128` |
    | `deadline` | `uint64` |
    | `builderConfig` | `(address builder, uint32 feePps)` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="swap(uint40, bool, uint128, uint128, uint64)">
    **Mutability:** `nonpayable`. Exact-input amount and minimum output use raw token atoms. The caller needs TRADE permission and free funds. Reverts on self-trade, failed slippage/deadline checks, or other execution failures.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |
    | `minAmountOut` | `uint128` |
    | `deadline` | `uint64` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="estimateSwap(bool, uint128, uint32)">
    **Mutability:** `view`. Returns an estimated result without changing state. It cannot predict stateful hook effects or later liquidity changes. SDK 0.2.0 exposes a loosely typed helper; a direct typed ABI read preserves result types.

    | Parameter | Solidity type |
    | - | - |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |
    | `builderFeePps` | `uint32` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="estimateSwap(bool, uint128)">
    **Mutability:** `view`. Returns an estimated result without changing state. It cannot predict stateful hook effects or later liquidity changes. SDK 0.2.0 exposes a loosely typed helper; a direct typed ABI read preserves result types.

    | Parameter | Solidity type |
    | - | - |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="estimateSwap(uint40, bool, uint128, uint32)">
    **Mutability:** `view`. Returns an estimated result without changing state. It cannot predict stateful hook effects or later liquidity changes. SDK 0.2.0 exposes a loosely typed helper; a direct typed ABI read preserves result types.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |
    | `builderFeePps` | `uint32` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="estimateSwap(uint40, bool, uint128)">
    **Mutability:** `view`. Returns an estimated result without changing state. It cannot predict stateful hook effects or later liquidity changes. SDK 0.2.0 exposes a loosely typed helper; a direct typed ABI read preserves result types.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `isBuy` | `bool` |
    | `amountIn` | `uint128` |

    **Returns:** `(uint128 amountInUsed, uint128 amountOut) result`.
  </Accordion>

  <Accordion title="getPassiveBand(uint32)">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    | Parameter | Solidity type |
    | - | - |
    | `lowPrice` | `uint32` |

    **Returns:** `(uint32 lowPrice, uint32 highPrice, uint128 quoteAtLow, uint128 baseAtHigh, uint128 totalShares, uint256 feeGrowthBasePerShareX128, uint256 feeGrowthQuotePerShareX128) band`.
  </Accordion>

  <Accordion title="getPassivePosition(uint64)">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    | Parameter | Solidity type |
    | - | - |
    | `positionId` | `uint64` |

    **Returns:** `(uint40 ownerId, uint32 lowPrice, uint32 highPrice, uint128 shares, uint256 lastFeeGrowthBaseX128, uint256 lastFeeGrowthQuoteX128) position`.
  </Accordion>

  <Accordion title="getPostFillHook(uint40)">
    **Mutability:** `view`. Use the account, permission, and execution rules described above and in the linked SDK guide.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |

    **Returns:** `address hook`.
  </Accordion>

  <Accordion title="setPostFillHook(uint40, address)">
    **Mutability:** `nonpayable`. Requires live TRADE authority; a nonzero hook also needs AccountCore eligibility and valid hook code.

    | Parameter | Solidity type |
    | - | - |
    | `userId` | `uint40` |
    | `hook` | `address` |

    **Returns:** No Solidity return value.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.