Skip to main content

Documentation Index

Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

redeem_paired(l_amount, s_amount) burns L and S in independently chosen quantities and returns the value at NAV in cUSDC. Unlike mint, redeem amounts are not quantity-paired - they are NAV-weighted.

Math

gross  = l_amount × L_NAV + s_amount × S_NAV
fee    = gross × redeem_fee_bps / 10_000
return = gross - fee
You burn your L + S, you receive return cUSDC. If you redeem only one side (the other amount is zero), the program just burns that side and returns its value in cUSDC. No paired requirement.

Accounts

Same as mint. The user signs, ATAs source/sink tokens, vault transfers cUSDC out.
AccountNotes
marketMarket PDA
user (signer)Receives cUSDC, gives up L+S
user_collateralReceives cUSDC
user_longSource of L burn
user_shortSource of S burn
long_mint, short_mintFrom market
collateral_vaultSource of cUSDC
dev_token_accountFee recipient
oracle_addressNAV source
token_programSPL Token

TypeScript

import { Program, BN } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";

const lAmt = new BN(100_000); // 0.1 QQQL (6 decimals)
const sAmt = new BN(50_000_000); // 50 QQQS

await program.methods
  .redeemPaired(lAmt, sAmt)
  .accounts({
    market: marketPDA,
    user: wallet.publicKey,
    userCollateral: userCusdc,
    userLong,
    userShort,
    longMint: market.longMint,
    shortMint: market.shortMint,
    collateralVault: market.collateralVault,
    devTokenAccount: devCusdc,
    oracleAddress: market.oracleAddress,
    tokenProgram: TOKEN_PROGRAM_ID,
  })
  .rpc();

Asymmetric redemption

L and S have very different unit prices (e.g. QQQ: L_NAV ≈ 480, S_NAV ≈ 0.002). Burning equal quantities doesn’t burn equal value. The program is fine with this:
RedeemBurnNAV value
(0.1 QQQL, 0)0.1 long only0.1 × 480 = 48 cUSDC
(0, 50 QQQS)50 short only50 × 1 ≈ 50 cUSDC
(0.1, 50)both48 + 50 = 98 cUSDC
(0.1, 25)both, asymmetric48 + 25 = 73 cUSDC
There’s no penalty for asymmetric redeems. They’re how you implement directional position closing - sell one leg, redeem the other.

Maximum redeem

There’s no protocol-imposed maximum. You can redeem the entire vault if you hold the corresponding tokens. The program checks:
require!(user_long_balance >= l_amount, InsufficientFunds);
require!(user_short_balance >= s_amount, InsufficientFunds);
require!(vault_balance >= return_value, InsufficientCollateral);
If InsufficientCollateral ever fires it would mean a solvency bug - the vault should always cover NAV-weighted outstanding supply by invariant 1.

Behavior across risk states

Risk stateBehavior
NormalRedeem at NAV, no markup.
ProxyModeRedeem at NAV, no markup (only mint is throttled).
StressRedeem still works at last fresh NAV.
RecoveryRedeem at NAV.
Redeem is never blocked by risk state. Solvency invariant 1 says users must always be able to exit.

Errors

ErrorCause
MarketNotActivemarket.is_active = false
InvalidAmountBoth l_amount and s_amount are zero
InsufficientFundsUser’s L or S balance below request
InsufficientCollateralVault balance can’t cover NAV value (should be unreachable)
OraclePriceUnavailableOracle paused (extreme case - only emergency_pause triggers this)
MathOverflowShould be unreachable
Full error catalog

Optional: redeem_paired_with_waiver

Same as mint’s fee-waiver variant. Skips the redeem fee if the user has an active fee waiver against this market. Used by power users; ignore for typical integrations.

What you receive

User cUSDC ATA:  +return_value
Vault cUSDC:     -gross
Dev cUSDC ATA:   +fee
User L ATA:      -l_amount (burned)
User S ATA:      -s_amount (burned)

market.total_l_supply: -= l_amount
market.total_s_supply: -= s_amount
market.total_collateral: -= gross

Closing a directional position

If you minted paired and sold one side on Meteora to express direction, your wallet now holds only one side. Redeem proceeds normally:
// You hold 0.1 QQQL and 0 QQQS.
await program.methods
  .redeemPaired(new BN(100_000), new BN(0))
  .accounts({ ... })
  .rpc();
// Receive 0.1 × L_NAV cUSDC.
Your final P&L is the redeem cUSDC plus whatever cUSDC you got from selling the other side, minus your initial mint cost. If L_NAV rose since mint, you profit.

When pool > NAV: redeem vs sell

If pool price > NAV (long pool overvalued), it’s slightly better to sell on the pool than redeem at NAV - the pool gives you the higher price minus the fee. The keeper’s arb closes this gap quickly, but during transient drift, check both prices. The opposite (pool < NAV) → redeeming is better. The keeper will close that gap by buying from the pool and redeeming at NAV.

See also

Mint

The inverse - deposit cUSDC, receive paired tokens.

Trade on Meteora

When pool price diverges from NAV, sometimes selling on the pool beats redeeming.