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

# Token-2022 轉帳費用在交換中的應用

> Token-2022 的轉帳費用擴展如何改變交換前後的金額計算、Raydium 哪些產品支援它，以及整合者需要處理的邊界情況（非對稱費用、費用更新、最高費用上限、不可轉帳擴展）。

<Info>
  **本頁內容由 AI 自動翻譯，所有內容以英文版本為準。**

  [查看英文版 →](/algorithms/token-2022-transfer-fees)
</Info>

<Info>
  支援矩陣：**CPMM** 完全支援 Token-2022，包括轉帳費用代幣。**CLMM** 透過明確的 `SwapV2` 帳戶支援轉帳費用的 Token-2022。**AMM v4** 完全不支援 Token-2022。**LaunchLab** 透過 `InitializeV2` 建立經典 SPL 基礎代幣，但有專用的 `InitializeWithToken2022` 進入點，可建立 Token-2022 基礎代幣並選擇性地附加 `TransferFeeConfig`；其報價端接受任一代幣程式。參見 [`products/launchlab/platform-config`](/zh-Hant/products/launchlab/platform-config#token-2022-transfer-fee-authorities)。**Farm v6** 在質押和獎勵代幣上都支援 Token-2022。
</Info>

## 什麼是轉帳費用

Token-2022 是第二個 SPL Token 程式（`TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` → `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`）。在其擴展中，**轉帳費用**擴展使得每次在代幣鑄造上進行 `TransferChecked` 都會從轉帳金額中扣除費用。費用會路由到由鑄造權限人指定的收款人，並且可由權限人更新（在限制範圍內）。

具有轉帳費用的鑄造有兩個相關參數：

* **`transfer_fee_basis_points`** — 費率（例如 100 = 1%）。
* **`maximum_fee`** — 每次轉帳的絕對上限（這樣大額轉帳者就不會支付無限制的費用）。

一個鑄造可以同時有**兩個**活躍的轉帳費用配置：「較新」的（現在生效）和「較舊」的（正在排程退出）。這是「時期轉換」設計 — 轉帳費用變更在時期邊界生效，以避免對進行中的交易造成驚訝。

## 為什麼這對交換很重要

池的金庫持有實際餘額。當使用者呼叫 Raydium 交換時：

1. 使用者將 `amount_in` 發送到池金庫。如果**入金代幣**有轉帳費用，金庫收到的是 `amount_in − fee_in`，而不是 `amount_in`。
2. 交換數學在金庫收到的金額上運作。
3. 池將 `amount_out` 發送到使用者的 ATA。如果**出金代幣**有轉帳費用，使用者收到的是 `amount_out − fee_out`，而不是 `amount_out`。

如果交換程式天真地使用原始 `amount_in` 參數，不變量檢查會失敗，因為金庫收到的少於程式認為的。反之，如果它計算 `amount_out` 時沒有減去出站轉帳費用，使用者會看到短缺並責怪程式。

Raydium CPMM 和 CLMM（透過 `SwapV2`）透過以下方式處理：

* **交換前**：計算 `in_after_fee = amount_in − transfer_fee_on(amount_in, in_mint)`，並在曲線數學中使用 `in_after_fee`。
* **交換後**：計算 `out_gross = amount_out_from_curve`，透過 `TransferChecked` 將其發送給使用者，Token-2022 程式本身會將其減少轉帳費用。

使用者的 `minAmountOut` 滑點界限是針對 `out_gross`（池發送的）檢查的，**不是**針對使用者收到的。這是每個主要 Solana DEX 處理 Token-2022 的方式，這很重要，因為：

* 如果池檢查費後金額，報價和執行之間的費用更新會導致交易回復。
* 檢查費前金額將失敗固定在報價本身的品質上，而不是使用者的帶外費用變更。

UI 應在向使用者顯示「你將收到」時減去預期的 Token-2022 轉帳費用。

## 計算 Token-2022 費用

SPL Token-2022 程式公開了一個確定性的輔助函數。在 Rust 中：

```rust theme={null}
use spl_token_2022::extension::transfer_fee::TransferFeeConfig;
use spl_token_2022::extension::StateWithExtensions;

let mint_data = ...;
let state = StateWithExtensions::<Mint>::unpack(&mint_data)?;
let config = state.get_extension::<TransferFeeConfig>()?;

let epoch = Clock::get()?.epoch;
let fee_bp = config.get_epoch_fee(epoch).transfer_fee_basis_points;
let max_fee = u64::from(config.get_epoch_fee(epoch).maximum_fee);

let fee = (amount as u128 * fee_bp as u128 / 10_000).min(max_fee as u128) as u64;
```

在 TypeScript 中（透過 `@solana/spl-token`）：

```ts theme={null}
import { getTransferFeeConfig, getTransferFeeAmount } from "@solana/spl-token";

const config = getTransferFeeConfig(mintAccount);
const currentEpochFee = config.olderTransferFee.epoch <= currentEpoch
  ? config.newerTransferFee
  : config.olderTransferFee;

const rate   = currentEpochFee.transferFeeBasisPoints;
const maxFee = currentEpochFee.maximumFee;
const fee    = Math.min(Math.floor(amount * rate / 10_000), Number(maxFee));
```

## 調整後的交換公式（CPMM，精確輸入）

令 `f_pool` 為池費率，`f_in` 為入金代幣轉帳費率，`max_in` 為其最高上限，`f_out` 為出金代幣轉帳費率，`max_out` 為其最高上限。

```
transfer_fee_in  = min(amount_in · f_in / 10_000, max_in)
vault_received   = amount_in − transfer_fee_in

pool_fee         = ceil(vault_received · f_pool / 1_000_000)
amount_after     = vault_received − pool_fee
amount_out_gross = y · amount_after / (x + amount_after)

transfer_fee_out = min(amount_out_gross · f_out / 10_000, max_out)
user_receives    = amount_out_gross − transfer_fee_out
```

滑點檢查：`amount_out_gross ≥ min_amount_out`（不是 `user_receives ≥ min_amount_out`）。使用者的 `minAmountOut` 由 SDK 設定為 `expected_gross · (1 − slippage)` — 將界限保持在「發送」端，而不是「接收」端。

## 調整後的公式（CPMM，精確輸出）

SDK 迭代以找到 `amount_in` 使得 `user_receives = amount_out_exact`：

```
# 使用者想在轉帳費用後接收 amount_out_exact
amount_out_gross = amount_out_exact + transfer_fee_out_for(amount_out_exact)

# 然後求解 CPMM 精確輸出以獲得 amount_after：
amount_after     = ceil(x · amount_out_gross / (y − amount_out_gross))

# 然後加上池費：
vault_received   = ceil(amount_after · 1_000_000 / (1_000_000 − f_pool))

# 然後加上入金轉帳費：
amount_in = ceil(vault_received · 10_000 / (10_000 − f_in))
# （或迭代 — 見下面的費用上限邊界情況）
```

`max_in` / `max_out` 上限使計算非線性，因為一旦達到上限，費用就停止增長。SDK 的 `computeAmountIn` / `computeAmountOut` 透過在天真公式會超過上限時迭代來處理。

## 邊界情況

### 非對稱費用（一側有費用，另一側沒有）

在實踐中很常見。上面的公式已經處理了這種情況 — 如果一側有 `f_in = 0`，相關項會消失。程式中沒有特殊情況。

### 交換中途的費用更新

如果鑄造的轉帳費用在報價時間和執行時間之間變更，交換要麼以略差的經濟狀況著陸（使用者在滑點容限內承擔差異），要麼回復（毛輸出下降到 `minAmountOut` 以下）。滑點界限吸收了這一點；不需要額外保護。

### 最高費用上限

一旦交易足夠大以達到 `maximum_fee`，費用飽和，進一步增長為零。這使得對於非常大的交易，有效費率漸近於零，這可能在深度流動性不足的市場上造成奇怪的定價曲線。SDK 的 `computeAmountOut` 考慮了這一點。

### 不可轉帳擴展

某些 Token-2022 鑄造使用 `NonTransferable` 擴展，它拒絕除了往返鑄造權限人之外的所有 `Transfer` 呼叫。這樣的鑄造**根本無法**在 Raydium 池中使用。`CreatePool` 在初始化時拒絕它們。

### 計息代幣

Token-2022 也支援 `InterestBearingConfig` 擴展，使餘額隨時間增長。Raydium 的池讀取原始金庫餘額（忽略利息應計），所以在具有計息代幣的池上，LP 在贖回時捕獲應計利息作為純禮物（金庫餘額增長速度快於 LP 供應表示）。整合者應將其視為非問題，但應為 LP 端記錄。

### 轉帳掛鉤

Token-2022 的 `TransferHook` 擴展允許在每次轉帳上進行任意 CPI。Raydium CPMM 支援這些 — 交換指令轉發掛鉤帳戶 — 但它增加了 CU 開銷並要求掛鉤表現良好。CLMM `SwapV2` 也支援掛鉤。AMM v4 完全不支援 Token-2022，所以這個問題不會出現。

## 實際例子

CPMM 池，`x = 1_000_000 USDY, y = 1_000_000 USDC`，池費 0.25%。

* USDY 有 1% 轉帳費用，`max_fee = 10_000`（6 位小數的 0.01 USDY）。
* USDC 沒有轉帳費用。

使用者交換 `amount_in = 1_000 USDY` 以換取 USDC（精確輸入）。

```
transfer_fee_in = min(1_000 · 100 / 10_000, 10_000)  = 10     // 1%，遠低於上限
vault_received  = 1_000 − 10 = 990

pool_fee        = ceil(990 · 2_500 / 1_000_000)  = 3    // 0.25%
amount_after    = 990 − 3 = 987

amount_out_gross = 1_000_000 · 987 / (1_000_000 + 987)  ≈ 986.03
```

≈ 986.03 USDC。沒有出站轉帳費用，所以使用者收到 ≈ 986.03 USDC。

## 參考資源

* [`products/cpmm/overview`](/zh-Hant/products/cpmm/overview) — CPMM Token-2022 支援。
* [`products/clmm/instructions`](/zh-Hant/products/clmm/instructions) — `SwapV2` 對比 `Swap` 用於 Token-2022 路由。
* [`solana-fundamentals/spl-token-and-token-2022`](/zh-Hant/solana-fundamentals/spl-token-and-token-2022) — 一般 Token-2022 擴展模型。

來源：

* [SPL Token-2022 轉帳費用擴展文件](https://www.solana-program.com/docs/token-2022/extensions#transfer-fees)
* Raydium CPMM 程式原始碼（`SwapBaseInput` / `SwapBaseOutput` Token-2022 處理）。
* Raydium CLMM 程式原始碼（`SwapV2`）。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.