Skip to main content
Every market carries a RiskState on its Market account, written by the keeper alongside each oracle push (update_risk_state). It gates mint pricing and availability - and works together with a hard TWAP-staleness gate that freezes mint/redeem when the underlying market is closed.
On devnet, every market runs in ProxyMode permanently. This is by design, not a degraded state: ProxyMode means “price off the keeper-relayed Hermes TWAP instead of an on-chain Pyth account” - and on devnet, Hermes is the sole oracle. Normal is the mainnet steady state, where the program reads Pyth directly.

The states

Redeem is never gated by risk state - only by TWAP freshness (below).

Transition rules

The on-chain transition matrix prevents a compromised keeper from short-circuiting recovery: Stress can only de-escalate via Recovery, where the stress fee multiplier unwinds over ~1 hour. A direct StressNormal jump is rejected. ProxyMode and Recovery transition freely; Normal can be entered from any non-Stress state. Each update_risk_state call also rejects TWAP moves over 25% (MAX_TWAP_MOVE_BPS) - one bad write is bounded, and the keeper adds its own 10% deviation envelope on mainnet before pushing at all.

The staleness chain (off-hours behavior)

Risk states handle oracle quality; a separate chain handles oracle absence - most commonly when the underlying market closes for the night or weekend:
This is program-enforced - no keeper action is required for the freeze, and no keeper action can bypass it. While frozen:
  • Mint and redeem reject. Nothing prices off a frozen NAV.
  • The CLMM books keep trading inside the last posted band. Off-hours price discovery happens here.
  • Committed orders cannot settle (no post-commit oracle print exists); cancel_swap refunds unconditionally after the 180 s TTL.
  • At reopen, the first fresh print re-anchors NAV; the keeper re-pins the books.
If you only check one thing before submitting a mint or redeem, check market.twap_updated_at.

What you should do in each state

ProxyMode (devnet default)

Operate normally. Quotes carry a 2× confidence markup on mint - usually a few bps. If you’re a bot, note that NAV freshness is bounded by the keeper’s ~15 s push cadence.

Stress

Mint is blocked (MintNotAllowedInStress). Redeem stays open at the last fresh NAV. If you’re a UI builder, surface it:
“QQQ is currently in Stress mode. Minting is paused; redeem remains open.”

Recovery

Mint resumes with size throttling (ExceedsStressMintCap on large mints) while the stress fee multiplier unwinds over ~1 hour.

How risk state affects mint pricing

Redeem prices are never marked up - otherwise users would be stranded when the oracle goes shaky. The multipliers are configurable via configure_worst_case_quoting.

Reading risk state

The risk state can lag oracle reality by up to one keeper tick (~15 s). The TWAP age check is the authoritative “will my transaction go through” signal.

State during maintenance

For a hard halt, operators flip market.is_active = false via update_market - all mint/redeem reject until re-enabled. The books and committed-order cancellation paths remain available (cancellation is unconditional by design).

Read more

Oracle

Hermes, the push pipeline, and the staleness chain in full.

Solvency

What the program enforces independently of risk state.