CanonicCanonic Docs
Documentation

Read-only Quoting

Overview

MAOB is designed to be quoted offchain using a combination of:

  • oracle mid price (getMidPrice)
  • rung configuration (getRungs, rungCount)
  • live liquidity depth (getDepth, getRungState)
  • per-order claimability (previewOrder) for maker UX

This page describes practical patterns for quoting and choosing taker guardrails.

Reading market state

Mid price

Use:

  • getMidPrice() -> (price, precision, updatedAt)

If updatedAt is stale relative to your own policies, you should refuse to quote.

Rungs

Use:

  • getRungs() to read the configured bps offsets.
  • Interpret bps as 0.1 bps units (denom 100_000).

Depth

Use:

  • getDepth(maxPerSide) to fetch up to maxPerSide non-zero rungs per side.

Returns:

  • ask rung bps values + volumes (base token units)
  • bid rung bps values + volumes (quote token units)

This is a “summary” view (closest rungs first by rung index scan) and is often enough for UI depth and rough quoting.

Per-rung detailed state

Use:

  • getRungState(rung) to read volumes and generation/cumulative fill values.
  • getLastSegment(rung, isAsk) for debugging or advanced inspection.

Other parameters to fetch

For accurate quotes and guardrails, you will also want:

  • takerFee() + FEE_DENOM() to compute taker fees.
  • minQuoteTaker() for minimum notional checks.
  • marketState() (and stateExpiresAt() if UnwindOnly) to avoid quoting when halted.
  • RUNG_DENOM() and PRICE_SIGFIGS() to match price math and rounding.

Choosing taker guardrails

maxRung

maxRung controls how far from the midpoint you will cross. A common approach:

  • choose a rung limit based on acceptable slippage from mid
  • quote a price impact using depth
  • set maxRung to the furthest rung needed

minQuotePerRung

Minimum quote value per rung to consider (set to 0 to disable). Rungs with total quote value below this threshold are skipped, which can avoid dust-heavy traversal.

deadline

Set a short deadline to reduce the risk of stale offchain quotes being executed after market conditions have changed.

  • deadline == 0 disables checks (generally not recommended for UI trading flows)

Slippage parameters

  • For buy exact out: set maxQuoteIn
  • For buy target in: set minBaseOut
  • For sell target in: set minQuoteOut
  • For sell exact out: set maxBaseIn

Minimum quote checks (minQuoteTaker)

MAOB enforces a minimum quote notional. For quoting:

  • Buy exact out & sell target in: the check is against the midpoint value of baseAmount (rounded with PRICE_SIGFIGS).
  • Buy target in & sell exact out: the check is against quoteIn / quoteOut directly.

Onchain previewing (MAOBPreviewer)

MAOBPreviewer is a stateless view helper that simulates MAOB taker fills against live state. It mirrors MAOB rounding, remainder carry, taker fees, and guardrails. Use it via eth_call to get an exact quote before submitting a transaction, or to validate an offchain simulator.

The official Canonic public MAOBPreviewer deployments are listed in Contract Deployments. For production integrations, prefer those verified deployments unless you intentionally want to operate your own copy.

Each function has a maxRung overload; the version without maxRung traverses all rungs (maxRung = rungCount - 1).

  • previewBuyBaseExactOut(maob, baseAmount, maxQuoteIn, maxRung, minQuotePerRung) -> (quoteUsed, baseFeePaid, baseOut)
  • previewBuyBaseTargetIn(maob, quoteIn, minBaseOut, maxRung, minQuotePerRung) -> (baseOut, baseFeePaid, quoteUsed)
  • previewSellBaseTargetIn(maob, baseAmount, minQuoteOut, maxRung, minQuotePerRung) -> (quoteOut, quoteFeePaid, baseUsed)
  • previewSellBaseExactOut(maob, quoteOut, maxBaseIn, maxRung, minQuotePerRung) -> (baseUsed, quoteFeePaid, netQuoteOut)

Notes:

  • baseAmount and quoteIn are pre-fee inputs; baseOut / quoteOut outputs are after fee.
  • For previewSellBaseExactOut, quoteOut is net (after fee); the previewer computes the gross quote required and then applies fees.
  • Previewer checks marketState (halts only), oracle validity (updatedAt != 0), and minQuoteTaker the same way MAOB does; per-leg staleness is enforced inside the OracleAdapter.
  • The previewer is shared per chain. Pass the target MAOB market address as the maob argument when quoting.

Failure modes to expect (previewer reverts; surface these in UIs):

  • MAOB__InvalidAmount(), MAOB__InvalidRung()
  • MAOB__TakerPaused()
  • MAOB__OraclePriceMissing(), MAOB__OracleStale(), MAOB__OracleOutOfRange()
  • MAOB__InsufficientLiquidity()
  • MAOB__MaxQuoteExceeded() / MAOB__MaxBaseExceeded()
  • MAOB__MinBaseNotMet() / MAOB__MinQuoteNotMet() / MAOB__QuoteAmountTooLow()

Notes on precision and rounding

MAOB rounds internal priceQ to a fixed significant-figure configuration. This means:

  • exact offchain simulation is possible but must match rounding behavior
  • small trades can be affected by rounding “dust”

The previewer uses getLastSegment(rung, isAsk) to carry per-rung remainder state on the ask side. If you simulate offchain, you must incorporate this remainder logic; otherwise, your quote may be slightly optimistic or pessimistic.

For critical integrations, prefer conservative slippage buffers.