Vaults
Summary
Vaults are on-chain capital pools managed by a single vault manager. Depositors provide USDC liquidity and receive LP shares in return. The manager trades on behalf of the vault using the Perps Program, and earns a performance fee on profits.
The design is inspired by Hyperliquid vaults and StrikeFinance v2: performance-only fee, deposit lockup enforced by last_deposit_time, and a high-water mark that prevents the manager from earning fees on recovered losses.
Vaults interact with the Perps Program via CPI (place_order_as_vault). The Vault Program is not optional, the protocol launches with two system vaults that are essential for protocol liveness:
| Vault | Role |
|---|---|
| Market-Making Vault | Places limit orders on both sides of the order book to provide depth. Acts as the primary counterparty when no matching resting order exists |
| Liquidation Vault | Holds capital to cover insolvent positions — when a position's collateral is insufficient to cover the loss, this vault absorbs the shortfall |
These two vaults are created by the admin at protocol deployment and managed by the protocol team. Any additional vault created by external managers follows the exact same on-chain mechanism , there is no technical distinction between protocol vaults and user vaults.
Key Concepts
| Term | Definition |
|---|---|
| AUM (Assets Under Management) | Total USDC currently held in the vault. Increases on deposits and profitable trades, decreases on withdrawals and losses |
| NAV per share | AUM / total_shares - the current value of one LP share in USDC |
| LP Share | SPL token minted on deposit, burned on withdrawal. Represents a proportional claim on vault AUM |
| High-water mark | The highest NAV per share ever recorded. The manager can only claim a performance fee when current NAV per share exceeds this value |
| Lockup period | Minimum time a depositor must wait between their last deposit and a withdrawal. Set by the manager at creation, must be >= protocol minimum |
| Performance fee | A percentage of profits paid to the manager. Fixed at vault creation, immutable |
| Min owner share | Minimum percentage of total vault shares the manager must always hold. Enforced on-chain: the manager's vault_withdraw is rejected if it would bring their share below this threshold, and new depositor deposits are blocked if they would dilute the manager below it. |
Vault Lifecycle
Capital Flow
USDC never moves directly between a wallet and a vault. It always passes through the user's UserAccount in the Perps Program. This keeps all capital inside the protocol ecosystem and lets traders move funds between their trading margin and vaults without leaving and re-entering the protocol.
Wallet → deposit_margin → UserAccount → vault_deposit → Vault AUM
Vault AUM → vault_withdraw → UserAccount → withdraw_margin → Wallet
Deposit Flow
NAV per share on first deposit: When the vault has no shares yet (total_shares == 0), the ratio is initialised as 1 share = 1 USDC.
Lockup reset: Every deposit updates last_deposit_time. Adding more USDC resets the lockup countdown. The UI shows this as a warning before confirming.
Withdrawal Flow
Lockup check: If now < last_deposit_time + vault.lockup_period, the transaction is rejected. The UI shows the exact date/time when withdrawal becomes available.
Performance fee: Only applies to the profit portion. If the vault lost value, no fee is charged. After withdrawal, the USDC lands in UserAccount — the user then calls withdraw_margin to move it to their wallet.
NAV and Share Calculation
Example
| Event | AUM | Total Shares | NAV/share |
|---|---|---|---|
| Vault created, manager deposits 10,000 USDC | 10,000 | 10,000 | 1.00 |
| Trader A deposits 5,000 USDC | 15,000 | 15,000 | 1.00 |
| Manager opens a profitable position (+3,000 USDC) | 18,000 | 15,000 | 1.20 |
| Trader B deposits 6,000 USDC | 24,000 | 20,000 | 1.20 |
| Manager opens a losing position (-2,000 USDC) | 22,000 | 20,000 | 1.10 |
| Trader A withdraws all 15,000 shares | 5,500* | 5,000 | 1.10 |
*Trader A receives 15,000 * 1.10 = 16,500 USDC. Profit = 16,500 - 15,000 = 1,500 USDC. With 10% performance fee: 16,500 - 150 = 16,350 USDC to user, 150 USDC to manager.
Performance Fee and High-Water Mark
The performance fee prevents the manager from profiting on paper gains that simply recover previous losses.
Example
| Event | NAV/share | High-water mark | Fee claimable? |
|---|---|---|---|
| Vault created | 1.00 | 1.00 | No |
| Profitable month | 1.30 | 1.00 | Yes - on 0.30 gain |
| Manager claims fee | 1.30 | 1.30 | - |
| Losing month | 1.10 | 1.30 | No |
| Recovering month | 1.25 | 1.30 | No - still below HWM |
| Further gain | 1.40 | 1.30 | Yes - on 0.10 gain above HWM |
Manager Operations
The vault manager interacts with the vault in the trading app.
Place orders on behalf of the vault
The manager uses place_order_as_vault, which performs a CPI into the Perps Program. The vault's USDC is used as margin — not the manager's personal wallet.
Freeze and unfreeze
The manager can freeze the vault to halt new deposits — for example during high volatility or while adjusting strategy. Existing depositors can still withdraw at any time.
Admin Operations
Admin operations are executed from the backoffice app. They exist to protect depositors from malicious or negligent managers.
Force freeze
force_freeze_vault immediately freezes any vault regardless of manager action. Used when suspicious activity is detected. The manager cannot override an admin freeze, only the admin can lift it with force_unfreeze_vault.
Deprecate
deprecate_vault is irreversible. After deprecation, only withdrawals are allowed. Used to wind down a vault permanently. The manager cannot reverse deprecation.
Protocol pause (two levels)
The protocol has two freeze levels that affect all vaults simultaneously.
| Operation | Soft freeze (pause_protocol) | Hard freeze (hard_freeze_protocol) |
|---|---|---|
| New deposits | No | No |
vault_withdraw (vault tokens) | No | No |
withdraw_margin (personal margin) | Yes - always available | No - blocked |
| Manager placing orders | No | No |
| Manager freeze / unfreeze | Yes | No |
| Keeper liquidations | No | No |
Soft freeze (pause_protocol / unpause_protocol) is for routine incidents - preventive measures, suspicious activity, planned maintenance. Vault withdrawals are blocked but traders can always recover their personal margin from UserAccount via withdraw_margin.
Hard freeze (hard_freeze_protocol / unfreeze_protocol) is a last resort. Only used when withdrawals themselves are the exploit vector. Completely blocks all activity including withdraw_margin.
Protocol pause does not change individual vault status, a vault that was Active returns to Active when the protocol resumes.
Security Properties
| Property | Mechanism |
|---|---|
| Manager cannot steal deposits | USDC stays in the vault PDA, manager can only trade, not withdraw to personal wallet |
| Manager cannot earn fees on losses | High-water mark prevents fee claims below the previous NAV peak |
| Manager cannot be removed | min_owner_share enforced on-chain — manager's withdrawal is rejected if it would bring their share below the minimum; new deposits blocked if they would dilute the manager below it |
| Depositors cannot be locked indefinitely | Lockup is per-depositor (last_deposit_time) not a global vault lock |
| Admin cannot steal funds | Admin can freeze/deprecate but not withdraw vault funds, withdrawals always go to depositors |
| Performance fee is transparent | Fixed at creation, immutable, visible on-chain before depositing |