Skip to main content

Fees

Symmetry has a multi-tier fee system. Fees are measured in basis points (bps), where 10,000 bps = 100%.

Fee Categories

Management fees and performance fees are currently disabled at the protocol level (global config). Setting non-zero values for these fees in vault configuration will have no effect until they are re-enabled. Only deposit and withdrawal fees are active. See Global Config for current status.
When enabled, performance fees are collected via supply dilution: the protocol mints new vault tokens to fee recipients (host, creator, managers, protocol) rather than removing underlying tokens from the vault. This increases the total vault token supply, which proportionally dilutes existing holders by the fee amount. The high watermark is updated after minting to prevent double-charging.

Fee Tiers

Each fee category is split across 4 vault-level configurable tiers plus a protocol fee layer (global config), collected independently:

Host Fees (Immutable)

Set at vault creation and cannot be changed:

Creator/Manager Fees

Vault Fees

vault_deposit_fee_bps and vault_withdraw_fee_bps stay inside the vault rather than being distributed. This fee benefits all existing vault token holders.

Protocol Fees

Set in the global config by the protocol admin:

Fee Limits

The global config enforces maximum fee limits: max_deposit_fee_bps, max_withdraw_fee_bps, max_management_fee_bps, and max_performance_fee_bps.

Fee Accumulation & Claiming

Fees accumulate in the vault’s accumulatedFees field, tracked separately for each tier:
Claiming fees is a two-step process: Step 1: Withdraw fees from vault
This automatically determines which fee types the claimer can collect based on their role, creates WithdrawVaultFees accounts, and transfers the fee tokens. Step 2: Claim remaining tokens (if needed)

Manager Fee Splitting

Manager fees are split based on fee_split_weight_bps. All manager weights must sum to 10,000. Example: if manager A has weight 6,000 and manager B has weight 4,000, A gets 60% and B gets 40%.

WithdrawVaultFees Account

There are 4 WithdrawVaultFees accounts per vault (one per fee type: symmetry=0, creator=1, host=2, managers=3). Each stores:
  • The vault it belongs to
  • Owners and their weight splits
  • Accumulated fee tokens and amounts

Fetching Fee Accounts


Oracles

Each token in a vault has an oracle aggregator that computes its price from up to 4 oracle sources. This applies to both SPL and Token Extensions (Token22) assets.

Oracle Types

Quote Tokens

Oracle prices can be denominated in:
The quote_token field tells the protocol what denomination the oracle feed reports prices in. For Pyth, most price feeds are denominated in USD, so use "usd". If a feed reports prices in USDC or WSOL, use the corresponding quote token — the protocol will automatically convert to a common base using the on-chain WSOL/USD and USDC/USD Pyth feeds.

Oracle Configuration

Each oracle source has these settings:
account_lut_id (0 or 1) selects which of the vault’s two Address Lookup Tables contains the oracle account. account_lut_index is the position within that LUT. When adding a new token, use account_lut_id: 0 and account_lut_index: 0 — the SDK and rewriteLookupTablesTx will handle LUT management. After adding multiple tokens, call rewriteLookupTablesTx to rebuild the LUTs with all oracle accounts.

Oracle Aggregator

The aggregator combines prices from multiple oracle sources using weighted percentile calculations:
The weight_bps values across all oracles for a single token must sum to exactly 10,000 (100%). Additionally, min_conf_bps must be strictly less than conf_thresh_bps.

Default Oracle Settings (Pyth)

Pyth Integration

For Pyth oracles, the account field is the Pyth price account pubkey. You can look up price feed IDs for all supported assets at Pyth Price Feed IDs. During price updates, the SDK:
  1. Fetches feed IDs from the on-chain price accounts.
  2. Requests VAAs from the Pyth Hermes API.
  3. Creates, initializes, writes, and verifies VAAs on-chain.
  4. Updates the individual price feeds.
  5. Runs the vault’s updateTokenPrices instruction.
  6. Closes the temporary VAA accounts.
This is handled automatically by updateTokenPricesTx.

Raydium CLMM Oracle

Uses on-chain TWAP observations and tick arrays to compute prices. Requires twap_seconds_ago to be set (e.g., 300 for a 5-minute TWAP).

Raydium CPMM Oracle

Uses on-chain TWAP observations and vault reserves to compute prices. Requires twap_seconds_ago to be set.

LST Oracle

Derives a liquid staking token’s price directly from its on-chain stake pool. The account field is the stake pool state account owned by either the SPL Stake Pool program (SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy) or the Sanctum Stake Pool program (SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY). The oracle reads total_lamports and pool_token_supply and computes:
quote_token controls the denomination of the resulting price:
  • wsol — price is the LST/SOL exchange rate scaled by the live WSOL price (i.e. the LST priced in USD via SOL).
  • usdc — same shape but scaled via USDC.
  • usd — raw exchange rate without quote-price scaling (treated as 1.0 quote).
token_decimals should match the LST mint’s decimals (typically 9). Because the price is derived from on-chain state, no off-chain VAA or TWAP configuration is needed — twap_seconds_ago and twap_secondary_seconds_ago can be left at 0.

Multi-Oracle Example

Configure a token with both Pyth and Raydium CLMM oracles: