> ## Documentation Index
> Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Risk states

> The per-market risk regime, why devnet runs in ProxyMode, and the staleness chain that freezes mint/redeem off-hours.

Every market carries a `RiskState` on its [`Market`](/programs/mint-redeem#market-account) 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.

<Note>
  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.
</Note>

## The states

| State       | Meaning                                          | User mint                  | User redeem | Mint price                 |
| ----------- | ------------------------------------------------ | -------------------------- | ----------- | -------------------------- |
| `Normal`    | Pyth-direct steady state (mainnet)               | ✅                          | ✅           | NAV + 1× confidence markup |
| `ProxyMode` | Pricing off keeper-relayed TWAP (devnet default) | ✅                          | ✅           | NAV + 2× confidence markup |
| `Stress`    | Oracle unreliable - defensive                    | ❌ `MintNotAllowedInStress` | ✅           | n/a                        |
| `Recovery`  | Post-stress wind-down                            | ✅ (size-throttled)         | ✅           | NAV + 1× confidence markup |

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 `Stress` → `Normal` 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:

```
underlying closes
  → Hermes publish_time > 120 s stale     keeper withholds the push
  → on-chain TWAP > 300 s old             MAX_TWAP_AGE_SECS gate trips
  → mint/redeem self-freezes              OraclePriceUnavailable
  → books float at their standing band    off-hours price discovery
```

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

```
mint_price = NAV × (1 + state_mult × confidence_bps / 10_000)
```

| State       | `state_mult` (default) |
| ----------- | ---------------------- |
| `Normal`    | 1×                     |
| `ProxyMode` | 2×                     |
| `Stress`    | n/a (blocked)          |
| `Recovery`  | 1×                     |

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

```typescript theme={null}
const market = await mintRedeem.account.market.fetch(marketPDA);

// market.riskState is an enum: { normal: {} } | { proxyMode: {} } | ...
const riskState = Object.keys(market.riskState)[0];
const twapAge = Date.now() / 1000 - market.twapUpdatedAt.toNumber();

console.log("Risk state:", riskState);
console.log("TWAP age (s):", twapAge.toFixed(0), twapAge > 300 ? "(frozen)" : "(fresh)");
```

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

<CardGroup cols={2}>
  <Card title="Oracle" icon="tower-broadcast" href="/concepts/oracle">
    Hermes, the push pipeline, and the staleness chain in full.
  </Card>

  <Card title="Solvency" icon="shield" href="/concepts/solvency">
    What the program enforces independently of risk state.
  </Card>
</CardGroup>
