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

Deposit

Send USDC to the ksUSD vault and get ksUSD back at the current share price. How many tokens you get depends on that price, so a deposit made later buys fewer tokens, each worth more.

New here? Read What is ksUSD? first.


The instruction

deposit(usdc_amount: u64)

One transaction does all three steps, or none of them:

  • Moves your USDC into the vault's USDC account

  • Mints ksUSD to you at the current share price

  • Updates the vault's record of what it holds

The accounts below use two Solana conventions. A PDA is an account the program controls directly, with no private key behind it. An ATA is the standard token account a wallet holds a given token in.

Account
Mutability
Purpose

vault

mut

Vault PDA (seeds: [b"vault"])

vault_usdc_account

mut

Vault's USDC ATA — receives the deposit

ksusd_mint

mut

ksUSD share mint — vault PDA is authority

user_usdc_account

mut

Depositor's USDC source ATA

user_ksusd_account

mut

Depositor's ksUSD destination ATA

user

signer

Depositor

phoenix_trader

Phoenix trader account — read to true up the venue's contribution to NAV before pricing. Pinned to vault.phoenix_trader

sol_oracle

Pyth SOL/USD — values the perp leg for that same correction. Pinned to vault.sol_oracle

token_program

SPL token program

phoenix_trader and sol_oracle are required on every deposit, not only in Normal mode. While the vault is Parked they are read and ignored; in Normal mode the deposit re-books the venue's real equity into NAV first, so the shares you mint are priced against the position as it actually stands.


Share-price math

In plain terms, one division:

Deposit $100 while a share is worth $1.03 and you get 97.09 ksUSD. Deposit $100 while it's worth $1.00 and you get 100. Either way you own $100 of the vault the moment the transaction lands — the price only decides how many tokens that is.

The same thing in the integers the program actually stores:

share_price_1e9 is dollars scaled by 1e9, so 1_030_000_000 reads as $1.03. Multiplying by 1e9 before dividing by it cancels the scale out, which is why usdc_amount and shares_to_mint are both plain 6-decimal amounts. The division truncates, so any fraction of a base unit is left in the vault rather than minted — it can never round in the depositor's favour at other holders' expense.

deposit calls accrue_perf_fees before it prices your mint. That advances the high-water mark to the current price first, so you're never charged a performance fee on gains the vault made before you arrived.

The first deposit into an empty vault mints shares 1:1 at $1.00, since the starting share_price_1e9 is 1_000_000_000. Every deposit after that mints fewer shares, because the share price has drifted up with the carry earned so far. Full derivation and a worked example in NAV & share pricing.


Capacity

The vault ships with a $500k deposit cap. That isn't a demand estimate — it's roughly the largest short Phoenix's book can absorb, and it re-sizes as the venue grows.

It's a hard cap rather than a soft target because the vault only earns while its dollars are in the hedge. Whatever it can't short sits in USDC lending instead. A cap set above what the venue can hold doesn't add yield, then — it dilutes the part that does, until ksUSD is a Kamino deposit wearing a wrapper, carrying all of the operational risk for none of the carry.

So the cap tracks the venue:

On current Phoenix numbers the volume limb binds, by roughly a factor of two, because exit is harder than entry — a clean unwind is about a quarter of a day's flow.

The word median is load-bearing. The 30-day mean runs well above the median, since a few spike days sit inside any window, and sizing off the mean would imply a short the venue couldn't absorb on an ordinary day.

The ramp

Phase
Cap
Opens when Phoenix has

Launch

$500k

roughly today's book

Private beta

$1M

roughly twice today's open interest

Public

$5M → $25M

a far deeper book, or a second venue to split the short across

Tiers open against the live book, not on a date. Drift went down in January 2025, so there's no second Solana perp venue wired into v1 to split across yet.

Reading the cap live

deposit_cap_usdc is a u64 on the Vault account. 0 pauses deposits outright, u64::MAX means uncapped, anything else is a hard ceiling.

Admins move the cap with update_params. Recompute it against the live book first, rather than trusting a constant, since both inputs move week to week.


Guardrails

A deposit can be blocked by any of three things:

  • The vault is paused. The admin can pause it with set_pause in an emergency.

  • The deposit cap is hit. A deposit reverts with DepositCapExceeded if cached_nav_usdc + usdc_amount > deposit_cap_usdc. See Capacity above.

  • The amount is zero. usdc_amount must be greater than 0.


TypeScript example


Events

DepositEvent is emitted on success:


Last updated