# 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 collateral × oracle jitoSOL price)      [normal basis]
    + Drift sub-account quote balance                  [funding settled — both modes]
    + USDC posted to Kamino                            [reverse basis]
    − (jitoSOL borrowed from Kamino × oracle price)    [reverse basis]
```

* Between cranks, *unrealized* funding/PnL on Drift 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keystonefi.xyz/reference/nav-calculation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
