本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
手續費等級
CLMM 池在建立時會綁定一個AmmConfig;該設定決定了交易手續費率、協議與基金的分成比例,以及 tick 間距(詳見 products/clmm/ticks-and-positions)。以下為已公開的典型等級(請對照 GET https://api-v3.raydium.io/main/clmm-config 確認最新資料):
AmmConfig 索引 | trade_fee_rate | Tick 間距 | 典型用途 |
|---|---|---|---|
| 0 | 100(0.01%) | 1 | 穩定幣對 |
| 1 | 500(0.05%) | 10 | 相關性高的藍籌代幣 |
| 2 | 2_500(0.25%) | 60 | 標準交易對 |
| 3 | 10_000(1.00%) | 120 | 高波動或長尾代幣 |
1/FEE_RATE_DENOMINATOR = 1/1_000_000 為單位,計算基礎為交易量。協議費率與基金費率採用相同分母,但以交易手續費為計算基礎,而非交易量——此慣例與 CPMM 相同。
每筆 swap 的手續費分配
在每個 swap 步驟中(詳見products/clmm/math):
step_lp流入fee_growth_global_{input_side}_x64,並按當前活躍流動性進行縮放:fee_growth_global += step_lp × 2^64 / pool.liquidity。step_protocol累積至PoolState.protocol_fees_token_{input_side},透過CollectProtocolFee提取。step_fund累積至PoolState.fund_fees_token_{input_side},透過CollectFundFee提取。
pool.liquidity,其數值不會因尚未提取的待結算手續費而膨脹。
手續費為何按幣種分側計算
在 CPMM 中,swap 手續費一律從輸入代幣收取,另一側不會看到本次 swap 的協議/基金累積。CLMM 同樣遵循此規則,但細化至每個步驟:手續費累積於該步驟的輸入代幣那側。由於多 tick 的 swap 方向一致,所有步驟都從同一代幣收取手續費——因此實際上,每筆 swap 的手續費只會計入一側。 若使用者執行 token0 → token1 的 swap,fee_growth_global_0_x64 會上升,fee_growth_global_1_x64 則不會。倉位在該 swap 中以 token0 賺取手續費。下一筆 swap 若方向相反,則會累積 fee_growth_global_1_x64。長期而言,平衡的池子兩側都會持續累積手續費。
單側手續費(CollectFeeOn)
透過 CreateCustomizablePool 建立的池子可選擇非預設的手續費收取模式。此模式在池子建立時固定,並儲存於 PoolState.fee_on。
CollectFeeOn 值 | fee_on 位元組 | 行為 |
|---|---|---|
FromInput(預設) | 0 | 經典 Uniswap-V3 模式——手續費一律從每個 swap 步驟的輸入代幣扣除,輸入代幣隨 swap 方向交替。 |
Token0Only | 1 | 手續費一律以 token0 計算。0→1 方向的手續費從輸入代幣扣除(與 FromInput 相同);1→0 方向的手續費則從輸出代幣(token0)扣除。 |
Token1Only | 2 | 與 Token0Only 對稱——手續費一律以 token1 計算。 |
Token0Only 或 Token1Only——這能讓 LP 以單一、可預期的幣種累積手續費收益。例如 MEMECOIN / USDC 這類以美元計價的 LP 就適合使用 Token1Only(手續費一律結算為 USDC),LP 的損益便不受哪一方向交易量較多的影響。取捨在於:當手續費從 swap 輸出中扣除時,使用者收到的是 out − fee 而非近似於 out 的金額,因此報價邏輯必須從輸出側扣除手續費。SDK 的 computeAmountOut 已根據 fee_on 處理此分支;直接讀取 pool.fee_on 的用戶端程式碼應參照 PoolState 上的輔助函式:
fee_growth_global_{0,1}_x64 累積器按每個 swap 步驟路由,因此倉位仍以相同的 fee_growth_inside 公式結算手續費。不對稱性僅體現在側向累積的方向,而不影響數學計算本身。
fee_on 建立後不可修改。透過舊版 CreatePool 建立的池子永遠為 FromInput。
動態手續費
以enable_dynamic_fee = true 建立的池子,會在 AmmConfig.trade_fee_rate 的基礎上疊加一個由波動率驅動的附加費率。其機制為 Trader Joe / Meteora 動態手續費設計的簡化移植版。
狀態
PoolState.dynamic_fee_info 儲存五個校準參數(建池時從 DynamicFeeConfig 快照而來)以及每次 swap 都會更新的四個狀態欄位。位元組佈局請參見 products/clmm/accounts。
每次 swap 的更新流程
每個 swap 步驟中,程式依序執行三個子步驟:-
衰減參考值。若
now - last_update_timestamp > filter_period,波動率參考值會衰減: -
更新累積器。新的累積器等於參考值加上已遍歷的絕對距離(以
tick_spacing為單位),乘以粒度縮放因子,並上限為設定的最大值: -
計算附加費率。附加費率與累積器呈二次方關係(因為標準公式中 swap 的「tick 距離」是平方項),並由
dynamic_fee_control進行增益縮放:
MAX_FEE_RATE_NUMERATOR = 100_000,以 1e6 為單位)為硬性安全上限;實際上,調校良好的參數設定遠低於此上限。
參數設定建議
試點池中已驗證可行的預設範圍:| 參數 | 典型範圍 | 備註 |
|---|---|---|
filter_period | 30 – 60 秒 | 在微波動期間維持參考值;數值越小反應越靈敏 |
decay_period | 300 – 1800 秒 | 靜默超過此時間窗口後,費率回歸基準值 |
reduction_factor | 4_000 – 8_000 | 分母為 10_000;數值越高,偏高費率維持越久 |
dynamic_fee_control | 1_000 – 50_000 | 分母為 100_000;曲線增益 |
max_volatility_accumulator | 100_000 – 10_000_000 | 附加費率的最高飽和點 |
dynamic_fee_control,使平均費率符合目標(例如:1σ 日為基準費率的 1.5 倍,3σ 日為 5 倍)。
LP 的視角
動態手續費收益流經與基礎手續費相同的累積器——fee_growth_global_{0,1}_x64,不存在獨立的「動態手續費成長」欄位。波動性池子的 LP 在波動期間自然賺取更高手續費,無需額外的領取或結算指令。
整合者須知
- 報價在第 N 個區塊返回後,即使池子儲備未發生變化,第 N+1 個區塊的費率也可能改變——每筆 swap 都會移動波動率累積器。Trade API 的報價僅在報價區塊有效;若反應靈敏的池子在報價與執行之間觸發更新,實際費率可能偏差數個基點。
volatility_accumulator與last_update_timestamp均為鏈上公開資料——用戶端可在離線模擬時於客戶端側重現計算公式。
倉位手續費記帳
每個倉位在最後一次觸碰時儲存:fee_growth_inside_0_last_x64與fee_growth_inside_1_last_x64——該快照時刻的範圍專屬手續費成長值。
IncreaseLiquidity、DecreaseLiquidity,以及任何隱式更新 tick 邊界手續費成長的狀態轉換):
-
程式從全域手續費成長值及兩個端點 tick 的
fee_growth_outside_*重新計算fee_growth_inside_{0,1}_x64。 -
差值乘以倉位流動性後累加至
tokens_fees_owed_{0,1}: -
fee_growth_inside_{0,1}_last_x64更新為最新值。
DecreaseLiquidity 或專屬的 CollectFees 路徑(在 Raydium 目前的指令集中,手續費作為 DecreaseLiquidity 的一部分一同提取)。在 DecreaseLiquidity 呼叫中將 liquidity = 0 是標準的「僅收取」慣用語法。
範圍外的倉位不賺取手續費
若倉位的範圍不包含tick_current,則為其計算的 fee_growth_inside 會受到上界限制,在價格處於範圍外期間不會移動。倉位停止累積手續費,直到價格重新回到其範圍內。這是設計特性而非缺陷——正是集中流動性將手續費收益與資本同樣集中的機制。
獎勵流
一個 CLMM 池最多可同時擁有三個獎勵流。每個獎勵流是一個(獎勵 mint、發放速率、開始時間、結束時間)的元組,儲存於PoolState.reward_infos[i]。
結算循環
每個觸碰流動性的指令(以及作為獨立指令的UpdateRewardInfos)都會將所有活躍獎勵流推進至當前時間:
pool.liquidity == 0,該期間的獎勵發放不會分配(因為無範圍內的流動性可接收)。剩餘預算留存於獎勵金庫。鑄造後不再管理的協議可透過 SetRewardParams 補充或終止獎勵流。
倉位獎勵累積
與手續費的計算方式完全相同,但每個獎勵流各自獨立:CollectReward 領取獎勵,程式會將 reward_amount_owed 從獎勵流的金庫轉給使用者,並將計數器歸零。
只有範圍內的倉位才賺取獎勵
reward_growth_inside 使用與 fee_growth_inside 相同的公式——透過 tick 外部累積器——因此處於當前價格範圍之外的倉位不會累積獎勵。這呼應了 Uniswap v3「激勵流向活躍流動性」的設計理念,同時將 LP 的利益與現貨價格覆蓋範圍對齊。
獎勵流的資金注入與終止
獎勵流透過InitializeReward 建立,並預先將全部預算(emissions_per_second × (end_time − open_time))存入獎勵金庫。若資金提供方餘額不足,程式會拒絕 InitializeReward。SetRewardParams 可延長 end_time 或提高發放速率;縮短期限或降低速率則被禁止,以避免砍掉已承諾給 LP 的獎勵。
當 now > end_time 時,獎勵流轉為 Ended 狀態,但其 reward_growth_global_x64 仍可被讀取——在發放停止後,LP 仍可透過 CollectReward 領取歷史已賺取的獎勵。
管理員收取
| 簽署者 | 指令 | 效果 |
|---|---|---|
amm_config.owner | CollectProtocolFee | 將 protocol_fees_token_{0,1} 提取至指定收款方。 |
amm_config.fund_owner | CollectFundFee | 將 fund_fees_token_{0,1} 提取至指定收款方。 |
pool.liquidity 之外。主網上持有這些簽署者的人員請參見 security/admin-and-multisig。
Token-2022 互動
手續費與獎勵均以池子或獎勵流的代幣計價。Token-2022 擴充功能的行為方式與在 CPMM 中相同:- swap 輸入 mint 的轉帳手續費。 池子收到
amount_in − mint_transfer_fee。CLMM 程式的步驟輸入基於淨額計算,因此池子的手續費累積器反映的是實際進入金庫的代幣。 - 輸出 mint 的轉帳手續費。 池子發送
amount_out,使用者收到amount_out − mint_transfer_fee。滑點檢查應以使用者實際收到的金額為基準。 - 獎勵 mint 的轉帳手續費。 獎勵以
InitializeReward時「存入金庫」的單位計算(資金提供方已支付存入時的 mint 轉帳手續費)。CollectReward提取時會再次產生 mint 轉帳手續費;LP 應預期在轉帳手續費獎勵代幣上有輕微折扣。 - 不可轉讓/機密/群組成員 mint。 在
CreatePool/InitializeReward時會被拒絕。
algorithms/token-2022-transfer-fees。
鏈下讀取手續費與獎勵
tokenFeesOwed* 與 rewardAmountOwed 是倉位最後一次被觸碰時的快照。若要查看當前數值(反映此後的成長),可在模擬中以零流動性呼叫 IncreaseLiquidity,或直接利用全域 fee_growth_* 及兩個 tick 外部快照重新計算。
延伸閱讀
products/clmm/math——fee_growth_inside的完整推導。products/clmm/instructions——CollectReward、InitializeReward、SetRewardParams的帳戶列表。algorithms/token-2022-transfer-fees——搭配轉帳手續費 mint 進行報價。reference/fee-comparison——CLMM/CPMM/AMM-v4 手續費對照表。
raydium-io/raydium-clmm—states/pool.rs,libraries/fixed_point_64.rs- “Uniswap v3 Core” 白皮書,第 7 節(手續費成長)

