> ## Documentation Index
> Fetch the complete documentation index at: https://docs.symmetry.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Fees & Oracles

> Fee structure (deposit, withdrawal, management, performance) and oracle configuration.

## Fees

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

### Fee Categories

| Category        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Deposit Fee     | Charged when users deposit tokens into the vault. Computed as a percentage of the vault tokens being minted, and deducted before the remainder is sent to the depositor.                                                                                                                                                                                                                                                                                                                                                 |
| Withdrawal Fee  | Charged when users withdraw tokens from the vault. Computed as a percentage of the vault tokens being burned, and deducted before the proportional underlying tokens are released.                                                                                                                                                                                                                                                                                                                                       |
| Management Fee  | Ongoing fee charged over time, specified as an annualized rate. For example, `100 bps` = 1% per year. The fee is accrued continuously and deducted from the vault's value proportionally over time.                                                                                                                                                                                                                                                                                                                      |
| Performance Fee | Charged on profits above the vault's **high watermark** — the all-time high vault token price. Only the gain above the high watermark is subject to this fee. For example, if the high watermark is $1.00 and the vault token price rises to $1.10, the performance fee applies to the $0.10 gain. If the price later drops to $0.90 and recovers to $1.05, no performance fee is charged because the price hasn't exceeded the previous $1.10 high watermark. This prevents double-charging on recovery from drawdowns. |

<Warning>
  **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](/concepts/global-config) for current status.
</Warning>

<Note>
  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.
</Note>

### Fee Tiers

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

| Tier                  | Set By                                       | Modifiable                                       |
| --------------------- | -------------------------------------------- | ------------------------------------------------ |
| **Host**              | Set at vault creation                        | Never (immutable)                                |
| **Creator**           | Creator or authorized manager                | Via `editFeesTx` (subject to modification delay) |
| **Managers**          | Authorized manager                           | Via `editFeesTx` (subject to modification delay) |
| **Vault**             | Authorized manager (deposit & withdraw only) | Via `editFeesTx` (subject to modification delay) |
| **Symmetry Protocol** | Protocol admin                               | Via global config                                |

### Host Fees (Immutable)

Set at vault creation and cannot be changed:

```typescript theme={null}
host_platform_params: {
  host_pubkey: "<HOST_PUBKEY>",
  host_deposit_fee_bps: 10,
  host_withdraw_fee_bps: 10,
  host_management_fee_bps: 0,
  host_performance_fee_bps: 0,
}
```

### Creator/Manager Fees

```typescript theme={null}
const tx = await sdk.editFeesTx(
  { vault: "<VAULT>", manager: "<MANAGER>" },
  {
    creator_deposit_fee_bps: 50,
    creator_withdraw_fee_bps: 50,
    creator_management_fee_bps: 100,   // currently disabled in global config
    creator_performance_fee_bps: 500,  // currently disabled in global config
    managers_deposit_fee_bps: 0,
    managers_withdraw_fee_bps: 0,
    managers_management_fee_bps: 0,    // currently disabled in global config
    managers_performance_fee_bps: 0,   // currently disabled in global config
    vault_deposit_fee_bps: 0,
    vault_withdraw_fee_bps: 0,
    modification_delay: 86400,
  }
);
```

### 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:

| Setting                              | Description                                                     |
| ------------------------------------ | --------------------------------------------------------------- |
| `symmetry_deposit_fee_bps`           | Flat deposit fee                                                |
| `symmetry_deposit_fee_share_bps`     | Share of total deposit fees going to protocol                   |
| `symmetry_withdraw_fee_bps`          | Flat withdrawal fee                                             |
| `symmetry_withdraw_fee_share_bps`    | Share of total withdrawal fees going to protocol                |
| `symmetry_management_fee_bps`        | Flat management fee (currently 0)                               |
| `symmetry_management_fee_share_bps`  | Share of total management fees going to protocol (currently 0)  |
| `symmetry_performance_fee_bps`       | Flat performance fee (currently 0)                              |
| `symmetry_performance_fee_share_bps` | Share of total performance fees going to protocol (currently 0) |
| `symmetry_trade_fee_bps`             | Trade fee                                                       |
| `symmetry_limit_order_fee_bps`       | Limit order fee                                                 |

### 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:

```typescript theme={null}
interface FormattedAccumulatedFees {
  symmetry_fees: number;
  creator_fees: number;
  host_fees: number;
  managers_fees: number;
}
```

Claiming fees is a two-step process:

**Step 1: Withdraw fees from vault**

```typescript theme={null}
const tx = await sdk.withdrawVaultFeesTx({
  claimer: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
});
```

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)**

```typescript theme={null}
const tx = await sdk.claimTokenFeesFromVaultTx({
  claimer: wallet.publicKey.toBase58(),
  withdrawVaultFees: "<WITHDRAW_VAULT_FEES_PUBKEY>",
});
```

### 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

```typescript theme={null}
const fees = await sdk.fetchAllWithdrawVaultFees({ type: "vault", pubkey: "<VAULT>" });
const managerFees = await sdk.fetchManagerWithdrawVaultFees("<MANAGER_PUBKEY>");
const creatorFees = await sdk.fetchCreatorWithdrawVaultFees("<CREATOR_PUBKEY>");
const hostFees = await sdk.fetchHostWithdrawVaultFees("<HOST_PUBKEY>");
const symmetryFees = await sdk.fetchSymmetryWithdrawVaultFees("<SYMMETRY_PUBKEY>");
```

***

## 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

| Type         | Enum | String         | Description                                                                                                                   |
| ------------ | ---- | -------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Pyth         | 0    | `pyth`         | Pyth Network price feeds via Hermes ([Price Feed IDs](https://docs.pyth.network/price-feeds/core/price-feeds/price-feed-ids)) |
| Raydium CLMM | 1    | `raydium_clmm` | Raydium Concentrated Liquidity AMM TWAP                                                                                       |
| Raydium CPMM | 2    | `raydium_cpmm` | Raydium Constant Product AMM TWAP                                                                                             |
| LST          | 3    | `lst`          | Liquid Staking Token exchange rate from an SPL or Sanctum stake pool account                                                  |
| Example      | 255  | `example`      | Placeholder                                                                                                                   |

### Quote Tokens

Oracle prices can be denominated in:

| Quote | Enum | String |
| ----- | ---- | ------ |
| USDC  | 0    | `usdc` |
| WSOL  | 1    | `wsol` |
| USD   | 2    | `usd`  |

<Note>
  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.
</Note>

### Oracle Configuration

Each oracle source has these settings:

```typescript theme={null}
interface OracleInput {
  oracle_type: "pyth" | "raydium_clmm" | "raydium_cpmm" | "lst" | "example";
  account_lut_id: number;
  account_lut_index: number;
  account: string;
  weight_bps: number;
  is_required: boolean;
  conf_thresh_bps: number;
  volatility_thresh_bps: number;
  max_slippage_bps: number;
  min_liquidity: number;
  staleness_thresh: number;
  staleness_conf_rate_bps: number;
  token_decimals: number;
  twap_seconds_ago: number;
  twap_secondary_seconds_ago: number;
  quote_token: "usdc" | "wsol" | "usd";
}
```

<Note>
  `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.
</Note>

### Oracle Aggregator

The aggregator combines prices from multiple oracle sources using weighted percentile calculations:

```typescript theme={null}
interface FormattedOracleAggregator {
  num_oracles: number;
  min_oracles_thresh: number;
  oracles: FormattedOracle[];
  min_conf_bps: number;
  conf_thresh_bps: number;
  conf_multiplier: number;
}
```

<Warning>
  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`.
</Warning>

### Default Oracle Settings (Pyth)

```typescript theme={null}
{
  oracle_type: "pyth",
  weight_bps: 10000,
  is_required: true,
  conf_thresh_bps: 200,
  volatility_thresh_bps: 200,
  max_slippage_bps: 1000,
  min_liquidity: 0,
  staleness_thresh: 120,
  staleness_conf_rate_bps: 50,
  twap_seconds_ago: 0,
  twap_secondary_seconds_ago: 0,
  quote_token: "usd",
}
```

### 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](https://docs.pyth.network/price-feeds/core/price-feeds/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:

```
price = (total_lamports / pool_token_supply) * quote_price
```

`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`.

```typescript theme={null}
{
  oracle_type: "lst",
  account_lut_id: 0,
  account_lut_index: 0,
  account: "<STAKE_POOL_STATE_ACCOUNT>",
  weight_bps: 10000,
  is_required: true,
  conf_thresh_bps: 100,
  volatility_thresh_bps: 200,
  max_slippage_bps: 1000,
  min_liquidity: 0,
  staleness_thresh: 120,
  staleness_conf_rate_bps: 50,
  token_decimals: 9,
  twap_seconds_ago: 0,
  twap_secondary_seconds_ago: 0,
  quote_token: "wsol",
}
```

### Multi-Oracle Example

Configure a token with both Pyth and Raydium CLMM oracles:

```typescript theme={null}
await sdk.addOrEditTokenTx(
  { vault: "<VAULT>", manager: "<MANAGER>" },
  {
    token_mint: "<TOKEN_MINT>",
    active: true,
    min_oracles_thresh: 1,
    min_conf_bps: 10,
    conf_thresh_bps: 300,
    conf_multiplier: 1.5,
    oracles: [
      {
        oracle_type: "pyth",
        account_lut_id: 0,
        account_lut_index: 0,
        account: "<PYTH_PRICE_ACCOUNT>",
        weight_bps: 7000,
        is_required: false,
        conf_thresh_bps: 200,
        volatility_thresh_bps: 200,
        max_slippage_bps: 1000,
        min_liquidity: 0,
        staleness_thresh: 120,
        staleness_conf_rate_bps: 50,
        token_decimals: 9,
        twap_seconds_ago: 0,
        twap_secondary_seconds_ago: 0,
        quote_token: "usd",
      },
      {
        oracle_type: "raydium_clmm",
        account_lut_id: 0,
        account_lut_index: 1,
        account: "<RAYDIUM_CLMM_POOL>",
        weight_bps: 3000,
        is_required: false,
        conf_thresh_bps: 300,
        volatility_thresh_bps: 300,
        max_slippage_bps: 1500,
        min_liquidity: 1000000,
        staleness_thresh: 300,
        staleness_conf_rate_bps: 100,
        token_decimals: 9,
        twap_seconds_ago: 300,
        twap_secondary_seconds_ago: 60,
        quote_token: "usdc",
      },
    ],
  }
);
```
