Skip to main content
Continuum’s price layer is simple by design: the keeper fetches Pyth Hermes price + confidence per market (~15 s cadence) and writes both onto the Market account via mint_redeem::update_risk_state. Everything that prices against NAV - mint, redeem, committed-order settlement, book repositioning - reads that one on-chain TWAP.

Sources

On devnet, Hermes is the oracle - not a fallback. Pyth’s on-chain devnet accounts for RWA feeds are unreliable (stale, sometimes empty), so they are not consulted at all. That is exactly what ProxyMode means: the program prices off the keeper-relayed user_twap_price instead of an on-chain Pyth account. All devnet markets run in ProxyMode permanently.
Mainnet prerequisite: committed-order settlement (settle_swap) currently prices off the keeper-relayed TWAP. Mainnet requires reading Pyth directly with publish_time > order.created_at.

What one push contains

  • user_twap_price - the Hermes price, 6 decimals. This is L_NAV.
  • oracle_confidence - the Hermes confidence interval. Used for worst-case quote markups, and the spread engine never quotes inside it.
  • new_risk_state - the keeper-derived risk regime. See Risk states.
Two safety rails bound each write:
  • On-chain move cap: the program rejects any TWAP move over 25% per call (MAX_TWAP_MOVE_BPS), so a compromised keeper key cannot teleport NAV.
  • Keeper-side envelope (mainnet only): the keeper refuses to push a Hermes price that deviates more than 10% from the prior on-chain TWAP. On devnet this check is deliberately disabled - the on-chain TWAP is the keeper’s own last Hermes write, so comparing against it would be self-referential and would deadlock after any pause.

The staleness chain: what happens when the market closes

Hermes keeps serving the last price after the underlying stops trading (nights, weekends for equities). Re-pushing that frozen price would keep mint/redeem open at a stale NAV all weekend. Instead, a chain of gates takes over:
While frozen:
  • Mint and redeem reject (OraclePriceUnavailable) - nothing prices off a dead oracle.
  • The CLMM books keep trading inside their standing band - off-hours price discovery within the last posted spread.
  • Committed orders cannot settle (settlement requires an oracle print strictly after the commit); after the 180 s TTL, cancel_swap refunds unconditionally.
  • At reopen, the first fresh print re-anchors NAV and the keeper re-pins the books.

Confidence intervals

Every Hermes response includes a confidence interval. It feeds two mechanisms:
  1. Worst-case quote markup on mint: mint_price = NAV × (1 + state_mult × confidence_bps / 10_000), with state_mult per risk state (configurable via configure_worst_case_quoting). Wider uncertainty → worse mint quote, paid into the collateral vault.
  2. Spread floor: the keeper’s spread engine includes oracle_conf + fixed in its max-of-floors stack - the books never quote inside oracle uncertainty.

Reading prices from a client

user_twap_price is a plain field on the Market account - no oracle CPI needed at read time. Always check twap_updated_at before assuming mint/redeem will accept a transaction.

2. Read from Hermes directly (off-chain)

The on-chain TWAP and Hermes agree to within one keeper tick (~15 s) during open hours. Use Hermes for a raw spot reference; use the on-chain TWAP for anything that affects user-facing pricing - the protocol prices off the on-chain value regardless of what your client computes.

Integration pattern

Read more

Risk states

What Normal / ProxyMode / Stress / Recovery mean for your operations.

mint-redeem reference

update_risk_state, staleness gates, error catalog.