For the complete documentation index, see llms.txt. This page is also available as Markdown.

Account Structure

The ksUSD vault uses two on-chain account types: a single Vault PDA and one WithdrawalRequest PDA per queued withdrawal.

Source: the vault account definition

Anchor client name: program.account.vault.fetch(vaultPda) and program.account.withdrawalRequest.fetch(requestPda).


Vault (singleton)

PDA seed: [b"vault"] · authority for ksUSD mint, vault USDC ATA, vault jitoSOL ATA, reserve USDC ATA, Phoenix trader account, and lend / reserve cToken ATAs.

Identity

Field
Type
Meaning

admin

Pubkey

Admin authority (transferable via two-step transfer_admin + accept_admin)

pending_admin

Pubkey

Pending admin during a transfer; Pubkey::default() = none pending

bump

u8

Vault PDA bump

usdc_mint

Pubkey

USDC mint (depositor token)

jitosol_mint

Pubkey

jitoSOL mint (LST spot leg — held unlevered for staking)

ksusd_mint

Pubkey

ksUSD share mint — vault PDA is mint + freeze authority

Phoenix integration

Field
Type
Meaning

phoenix_trader

Pubkey

The vault's Phoenix cross-margin trader PDA (authority = vault). Registered and capability-enabled off-chain via the Rise SDK, then pinned here

phoenix_market

Pubkey

SOL-PERP orderbook (market) account

phoenix_global_config

Pubkey

Phoenix GlobalConfig — constrained on every Phoenix CPI

canonical_mint

Pubkey

Ember canonical collateral mint. USDC wraps into this 1:1 to become Phoenix margin

phoenix_canonical_ata

Pubkey

The vault's canonical-token ATA, i.e. its Phoenix margin token account

phoenix_perp_asset_id

u64

SOL-PERP asset id in the PerpAssetMap (0), used to read the signed position

phoenix_initialized

bool

true after enable_phoenix succeeds

Trading capability itself is not a vault field. It lives on the Phoenix trader account as capability flags, granted by Ellipsis's risk_authority. A freshly registered trader can hold funds but can't post margin until that grant lands. | phoenix_perp_asset_map | Pubkey | Phoenix's perp asset map for phoenix_market, pinned at enable_phoenix. Every order instruction address-checks it | | perp_base_lot_lamports | u64 | Size of one Phoenix base lot in lamports (SOL-PERP = 0.01 SOL = 10_000_000). Converts lots ↔ SOL for hedge sizing and the fill-price bound | | client_order_seq | u64 | Monotonic client_order_id for venue orders — unique by construction, unlike the wall-clock it replaced |

Lending venues

Field
Type
Meaning

kamino_lend_reserve

Pubkey

Pinned Kamino USDC reserve (set by enable_lending)

vault_lend_collateral_ata

Pubkey

Vault's cToken ATA for Kamino lending

reserve_lend_collateral_ata

Pubkey

Reserve fund's cToken ATA — distinct so reserve yield tracks separately

kamino_lending_initialized

bool

true after enable_lending succeeds

usdc_lent_kamino

u64

USDC base units deposited at Kamino from vault main ATA

reserve_lent_kamino

u64

USDC base units deposited at Kamino from reserve ATA

reserve_ata

Pubkey

Reserve fund USDC ATA (vault-PDA-owned). Pinned at init.

Oracles (set by set_oracles)

Field
Type
Meaning

sol_oracle

Pubkey

Pyth SOL/USD pull-oracle account

jitosol_oracle

Pubkey

Pyth jitoSOL/USD pull-oracle account

oracles_initialized

bool

true after set_oracles succeeds

jito_stake_pool

Pubkey

Jito stake pool — source of the jitoSOL/SOL redemption rate the depeg guard measures against

Field
Type
Meaning

total_shares

u64

Total ksUSD outstanding (6 decimals)

cached_nav_usdc

u64

Last computed NAV in USDC base units

last_settle_ts

i64

Last settle crank timestamp

last_nav_attest_ts

i64

Last attest_nav timestamp — anchors the per-hour change cap

Performance fee & reserve

Field
Type
Meaning

hwm_share_price_1e9

u64

High-water mark, measured against the gross share price (1e9 scale). Only moves up. Advances on its own at hurdle_apr_bps/yr — see Fees

hurdle_apr_bps

u16

Benchmark the vault must beat before any performance fee applies. Not a fixed constant — init-v1.ts measures the live Kamino USDC supply APY at deploy and writes it (3.69% → 369 on the seven-day median as of 2 Sep 2026), and the keeper's watchdog warns when it drifts from the smoothed rate. 0 disables the hurdle

last_fee_accrual_ts

i64

When accrue_perf_fees last ran. Drives the hurdle ratchet; 0 means "never initialised" and suppresses it

peak_share_price_1e9

u64

Rolling peak share price (drawdown anchor). Reset only by reset_peak, never by fee collection

pending_perf_fees_usdc

u64

Performance fees accrued but not yet collected. Crystallized by accrue_perf_fees on every price change, and subtracted from effective_nav_usdc so the share price is net of fees owed. Zeroed by collect_fees

reserve_fund_usdc

u64

Reserve fund balance in USDC base units (reserve_ata balance + lent portion)

Position state

Field
Type
Meaning

position_mode

PositionMode

Idle / Normal / WindDown

position_base_amount

i64

Signed Phoenix position in base lots (negative = short SOL-PERP). SOL-PERP uses baseLotDecimals = 2

usdc_margin_posted

u64

USDC base units currently posted as Phoenix margin via Ember

last_mode_change_ts

i64

Anchors the min_dwell_seconds guard

last_rebalance_ts

i64

When rebalance_hedge last corrected delta

Withdrawal queue cursors

Field
Type
Meaning

queue_next_id

u64

Next request_id to assign

queue_processed_through

u64

Smallest request_id not yet processed (strict FIFO cursor)

queue_pending_usdc

u64

Total USDC owed across pending requests

Configurable parameters

Field
Type
Default

liquidity_buffer_bps

u16

1_000 (10%)

funding_threshold_normal_bps

i32

0 (safety floor — the keeper applies the tighter dynamic threshold above it)

perf_fee_bps

u16

2_000

hurdle_apr_bps

u16

measured live at init (Kamino USDC supply APY). 400 in InitializeParams::default() is a tests/localnet fallback only — mainnet init aborts rather than use it

min_margin_bps

u16

900 (bounds leverage at ~10x)

reserve_skim_bps

u16

500

min_dwell_seconds

u32

43_200 (12 h)

max_swap_slippage_bps

u16

50

emergency_close_dd_bps

u16

500

deposit_cap_usdc

u64

500_000_000_000 ($500k launch cap). u64::MAX = uncapped; 0 = paused.

min_request_shares

u64

1_000_000 (1 ksUSD)

max_pending_queue_usdc

u64

u64::MAX (disabled)

max_nav_change_bps_per_hour

u16

1_000 (±10%/hr on keeper attestations; deposits/withdrawals write cached_nav_usdc directly and are not capped by it)

funding_max_staleness_seconds

u32

21_600 (6 h)

consecutive_dd_settles_required

u8

2

consecutive_dd_settles_observed

u8

Running counter

lst_depeg_bps

u16

500 (5%)

max_position_base_lots

u64

Absolute ceiling on position size, in base lots. Breach reverts with PerpShortExceedsSizeCap

instant_buffer_bps

u16

Raw-USDC floor reserved for withdraw_instant, as bps of NAV

delta_band_bps

u16

Delta drift, as bps of NAV, that must accumulate before rebalance_hedge will act. 0 disables rebalancing

max_rebalance_clip_lots

u64

Per-call ceiling on a rebalance order, in base lots. 0 = unclipped — bounds market impact, not price

hard_margin_floor_bps

u16

Margin health below which anyone may call reduce_position to Margin. 0 leaves the margin defence entirely dependent on the keeper being alive

mint_window_seconds

u64

Length of the deposit rate-limit window. 0 disables the flow cap

mint_limit_per_window_usdc

u64

USDC that may be minted within one window — a FLOW cap, distinct from the deposit_cap_usdc stock cap

mint_window_start_ts

i64

Start of the current mint window

minted_in_window_usdc

u64

USDC minted so far in the current window

Risk flags & keeper allowlist

Field
Type
Meaning

paused

bool

Halts deposits + new positions; instant withdraw stays open

authorized_keeper

Pubkey

Gates settle / strategy opens / closes / lending cranks. Exact match requiredPubkey::default() (the post-init state) blocks every keeper-gated ix until admin runs update_params { authorized_keeper: <key> }

Smoothed funding signal

Field
Type
Meaning

funding_apr_smoothed_bps

i32

EMA of SOL-PERP funding, updated on every settle

funding_smooth_last_ts

i64

Last EMA update timestamp. 0 sentinel = first settle hasn't run yet.

Reserved

Field
Type
Meaning

_reserved

[u8; 10]

Forward compatibility


PositionMode (enum)

Variant
Value
Meaning

Idle

0

Parked (v1 name). No active perp position; capital in vault USDC (lent on Kamino).

Normal

1

Long jitoSOL spot (unlevered) + short SOL-PERP on Phoenix at 1× notional, USDC margin.

WindDown

3

Terminal. New positions / deposits blocked; users claim pro-rata via claim_wind_down.


WithdrawalRequest

PDA seed: [b"withdrawal_request", vault.key(), request_id_le_bytes] · created by request_withdrawal, closed by process_withdrawal (rent refunded to the original requester).

Field
Type
Meaning

vault

Pubkey

Vault this request belongs to

user

Pubkey

Original requester (rent refund recipient)

user_usdc_account

Pubkey

USDC destination — must match at process time

usdc_owed

u64

Upper bound USDC owed at burn time (FIFO at request)

shares_burned

u64

Shares burned at request — used for the price-at-process haircut

request_id

u64

Sequential ID assigned at enqueue

requested_ts

i64

Timestamp of request

bump

u8

PDA bump

process_withdrawal price-at-process haircut:

  • Re-prices usdc_owed against the current share price

  • Takes the lower of locked vs. live

  • Depositors can never extract more than their pro-rata share if NAV has fallen since they queued


Derivation helpers (TypeScript)


Last updated