How the vault works.
One stock, one token. The vault holds liquidity in a Meteora DAMM v2 pool that pairs two issuers' tokens of the same stock (MVP: INTCx from xStocks and INTC from Backpack). Holders own swINTC, a pro-rata claim on that liquidity. Conversions between issuers pay fees, and DAMM v2's compounding mode puts most of each fee back into the pool, so every swINTC is backed by more stock over time.
How it fits together
traders / Jupiter ──swap──▶ DAMM v2 pool (INTCx ↔ INTC, collect_fee_mode = Compounding)
│ fee split per swap:
│ 20% Meteora protocol fee
│ LP fee × compounding_fee_bps → stays in reserves (holders' yield)
│ LP fee × the rest → claimable by positions, in token B
▼
position NFT owned by the vault PDA
│
deposit / redeem ───┤ shares ↔ pro-rata liquidity
▼
swINTC (SPL mint, authority = vault PDA)
The vault program is not in the swap path. Swaps go straight to cp-amm, so any router can fill them.
Share accounting
A share is a pro-rata claim on the vault's position liquidity, L_vault:
- deposit
sshares → adds × ceil(L_vault / supply)liquidity - redeem
sshares → removes × floor(L_vault / supply)liquidity - single-token deposit adding
ΔL→ mintΔL × (1 − zap fee) / ceil(L_vault / supply)shares
liquidity_per_share is only the launch ratio. It applies when the supply is zero.
Two things make a share worth more stock over time:
- Pool fees. Compounding fees grow
pool.token_b_amountwhilepool.liquiditystays the same, so every unit of liquidity is backed by more tokens. - Vault fees. The single-token deposit keeps 0.05% of the liquidity it adds in the position without minting shares for it, so
L_vault / supplyrises for existing holders.
This has three consequences:
- No oracle, no NAV math on-chain. cp-amm's own
L × reserve / L_totalrule prices deposits and withdrawals. Every rounding favours the vault. - No donation or inflation attack. Only the vault can add liquidity to its position. Tokens sent to the vault do not change what a share is worth.
- Dust. Redeeming a few raw share units can pay out zero of a token. cp-amm rejects that, so the transaction fails and the holder keeps the shares.
Instructions
| Instruction | Who | What |
|---|---|---|
initialize_vault | admin | Creates the pool via initialize_customizable_pool (compounding, full range, flat fee). The vault PDA is the pool creator, so it owns the first position NFT. |
deposit(shares, max_a, max_b) | anyone | Pulls up to max_a/max_b into vault-owned reserves, adds liquidity signed by the vault, refunds what cp-amm did not take, and mints shares. |
deposit_single(input_is_a, amount_in, min_shares) | anyone | Takes one issuer's token, swaps the right part of it on the pool at the pool's price, adds both as liquidity, refunds the dust, and mints shares net of the 0.05% vault fee. min_shares bounds slippage. |
redeem(shares, min_a, min_b) | holder | Burns shares, then removes liquidity straight to the holder in both tokens. Never paused by the vault. |
harvest | anyone | Claims the position fee to the treasury. In compounding pools that fee is in token B only. It is the protocol's cut. |
set_deposits_paused | admin | Circuit breaker for issuer events (pause, freeze, depeg). Redemptions stay open. |
Reserve token accounts exist because cp-amm pulls liquidity from token accounts owned by the position's signer, which is the vault PDA.