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.
What one push contains
user_twap_price- the Hermes price, 6 decimals. This isL_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.
- 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:- 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_swaprefunds 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:- Worst-case quote markup on mint:
mint_price = NAV × (1 + state_mult × confidence_bps / 10_000), withstate_multper risk state (configurable viaconfigure_worst_case_quoting). Wider uncertainty → worse mint quote, paid into the collateral vault. - Spread floor: the keeper’s spread engine includes
oracle_conf + fixedin its max-of-floors stack - the books never quote inside oracle uncertainty.
Reading prices from a client
1. Read from the Market account (recommended)
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)
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.
