Monitoring & Alerts
The ksUSD vault is one PDA — most monitoring reduces to watching that account plus a few external signals.
v1 monitors the Phoenix position and Ember margin.
Key metrics
Share price (share_price_1e9)
Derived from effective_nav_usdc / total_shares
Drops > 2% in 24h, or > emergency_close_dd_bps from peak_share_price_1e9
cached_nav_usdc vs. computed-live NAV
On-chain vs. off-chain reconciliation against Phoenix / Kamino positions
Discrepancy > 1%
Pyth SOL/USD staleness
Last-update timestamp on the Pyth feed
> 5 min
Pyth confidence
confidence / price
> 1.5% (program reverts at 2%)
jitoSOL/SOL depeg
Derived from jitosol_oracle.price / sol_oracle.price
> 80% of lst_depeg_bps
cached_nav_usdc cap utilization
cached_nav_usdc / deposit_cap_usdc
> 90% (raise cap or pause new deposits)
position_mode
vault.position_mode
Parked (Idle) for > 24h while funding signal is active
position_base_amount
vault.position_base_amount
Drifts > 1% from expected (1× of the jitoSOL spot leg)
funding_apr_smoothed_bps staleness
now - funding_smooth_last_ts
Approaching funding_max_staleness_seconds
consecutive_dd_settles_observed
vault.consecutive_dd_settles_observed
≥ 1 (single-tick warning before lethal)
Perp-venue health factor
Phoenix trader-account margin
< 1.5
SOL-PERP funding rate
Phoenix PerpAssetMap
Sustained across normal_thresh past dwell
Pending withdrawals
queue_next_id − queue_processed_through
> 0 for more than one keeper cycle
Reserve fund
reserve_fund_usdc and reserve_lent_kamino
Reserve ATA empty while reserve_fund_usdc > 0 (means unlend_reserve needed before any payout)
Lending balances
usdc_lent_kamino, reserve_lent_kamino
Sudden drop without a matching unlend_* event = Kamino-side anomaly
vault.paused
bool
Unexpected true = investigate LstDepeg or admin action
vault.position_mode == WindDown
enum
Terminal — only claim_wind_down should run
Reconciliation
Once per cycle, an off-chain script should compute the "true" NAV by summing:
Vault USDC ATA balance
usdc_lent_kamino × kamino USDC reserve cToken exchange rate(lent vault USDC, current value)reserve_fund_usdc(already includesreserve_lent_kaminoper the vault's accounting)(jitoSOL spot holdings) × Pyth jitoSOL price— the unlevered spot leg (normal basis only)Phoenix trader-account margin balance — posted USDC margin + settled funding + accrued PnL
Compare against vault.cached_nav_usdc. A discrepancy > 1% means:
settleis overdue, orattest_navis needed to capture unrealized PnL
Emergency conditions
Pyth SOL/USD stale > 10 min OR confidence > 2%
Pause new deposits + positions; manual emergency_close if a position is open
jitoSOL depeg > lst_depeg_bps
settle auto-pauses; investigate and either unpause or emergency-close
Phoenix outage / market halted
Same — pause and investigate
NAV drawdown ≥ emergency_close_dd_bps for consecutive_dd_settles_required settles
Anyone can call emergency_close permissionlessly; keeper should do it first
position_mode == WindDown
Stop the keeper; broadcast claim_wind_down instructions to depositors
Suggested external infra
A serverless function (Cloudflare Workers / AWS Lambda) running every 5 min: fetch
vault+ Pyth + Phoenix trader account, compute the deltas, push to Grafana / Datadog / PagerDuty.A
program.addEventListenerconsumer that subscribes toDepositEvent,WithdrawEvent,WithdrawalRequested,WithdrawalProcessed,FeesCollected,PositionOpened,PositionClosed,NavAttested,IdleLent,IdleUnlent,ReserveLent,ReserveUnlent,WindDownInitiated, and writes to a database for audit / reporting.A page in the operator dashboard tying
cached_nav_usdcto the reconciliation script's live computation, with a visible delta and an "attest now" button that callsattest_navwhen the delta crosses an internal threshold.
Related
Last updated