> For the complete documentation index, see [llms.txt](https://docs.keystonefi.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keystonefi.xyz/reference/nav-calculation.md).

# NAV & Share Pricing

ksUSD uses a share-priced (sUSDe-style) accounting model. Your `ksUSD` balance is constant; the value it redeems for drifts up over time as carry accrues.

***

## Share price

```
effective_nav_usdc = cached_nav_usdc − queue_pending_usdc − reserve_fund_usdc
share_price_1e9    = effective_nav_usdc × 1e9 / total_shares   (when total_shares > 0)
                   = 1_000_000_000 (= $1.00)                    (when total_shares = 0)
```

* `cached_nav_usdc` — USDC base units (6 decimals)
* `total_shares` — ksUSD base units (6 decimals)
* `1e9` scale preserves precision without 128-bit arithmetic above the intermediate
* **Helper on the Rust struct:** `Vault::share_price_1e9() -> u64`

### Why `effective_nav_usdc` excludes the queue and the reserve

| Subtraction          | Reason                                                                                                                                                                                 |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `queue_pending_usdc` | Pending withdrawals are already-burned shares with a USDC liability. Including them in the denominator would let new depositors mark up the residual price against locked liabilities. |
| `reserve_fund_usdc`  | Reserve growth is loss-absorbing capital, not shareholder return. Excluding it keeps share price honest.                                                                               |

***

## What `cached_nav_usdc` includes

The vault refreshes `cached_nav_usdc` on every state-changing instruction. The math accumulates:

```
NAV = idle USDC in the vault's USDC ATA
    + reserve fund balance (whether parked or lent)
    + USDC lent on Kamino (idle-USDC leg)
    + (jitoSOL spot holdings × oracle jitoSOL price)    [normal basis — the unlevered spot leg]
    + perp-venue margin balance (settled funding + PnL) [normal basis — USDC margin on Phoenix]
```

* Between cranks, *unrealized* funding/PnL on the perp venue is **not** reflected in `cached_nav_usdc`
* Run `settle` (permissionless) to refresh on-chain margin
* For unrealized PnL the keeper can also run `attest_nav(new_nav_usdc)` — bounded by `max_nav_change_bps_per_hour`

***

## Oracle pricing

jitoSOL and SOL/USD prices come from Pyth, with two checks enforced on every read:

| Check      | Threshold                          | Effect                                               |
| ---------- | ---------------------------------- | ---------------------------------------------------- |
| Staleness  | < 5 minutes since last Pyth update | Stale → revert with `StaleOracle`                    |
| Confidence | conf / price < 2%                  | Out of band → revert with `OracleConfidenceExceeded` |

Both checks are tight enough to catch oracle outages or manipulated feeds without false positives during routine market hours.

***

## Drawdown peak

`vault.peak_share_price_1e9` is the rolling max share price seen by the `settle` crank. The drawdown guard is:

```
drawdown_bps = (peak - current) × 10_000 / peak
if drawdown_bps >= emergency_close_dd_bps:
    emergency_close is permissionless to crank
```

* Single-tick noise can't trigger emergency exit — requires `consecutive_dd_settles_observed ≥ consecutive_dd_settles_required` (default 2)
* A premature trigger reverts with `DrawdownTriggerLatent`
* Peak resets via `reset_peak` (admin) — **not** by fee collection
* Drawdown tracks live share price, **not** the post-fee HWM

***

## Worked example

Initial state:

* `cached_nav_usdc = 1_000_000_000_000` ($1M)
* `total_shares = 1_000_000_000_000` (1M ksUSD, 6 decimals)
* `share_price_1e9 = 1_000_000_000` ($1.0000)

A keeper opens a normal-basis position; over time funding accrues $30,000 of net PnL. After the next `settle` + NAV refresh:

* `cached_nav_usdc = 1_030_000_000_000` ($1.03M)
* `total_shares = 1_000_000_000_000` (unchanged)
* `share_price_1e9 = 1_030_000_000` ($1.0300)

A new depositor sends 100 USDC:

* Shares minted: `100_000_000 × 1e9 / 1_030_000_000 / 1_000 = 97_087.378…` → integer truncation → **97,087** ksUSD base units
* Vault state after: `total_shares ≈ 1_000_000_097_087`, `cached_nav_usdc = 1_030_100_000_000`

The new depositor sees \~97.087 ksUSD in their wallet redeemable for the same \~100 USDC they put in.

***

## Related

* [Fee structure](/reference/fees.md) — HWM math and reserve skim
* [Check position & NAV](/keystone-finance/check-position.md) — TypeScript snippets to query share price live
* [Security model](/reference/security.md) — oracle, slippage, drawdown guard
