本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
手續費等級
CLMM 池在建立時會綁定一個AmmConfig;該設定決定了交易手續費率、協議與基金的分成比例,以及 tick 間距(詳見 products/clmm/ticks-and-positions)。以下為已公開的典型等級(請對照 GET https://api-v3.raydium.io/main/clmm-config 確認最新資料):
交易手續費率以
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。
為何池子會選擇
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 為單位)為硬性安全上限;實際上,調校良好的參數設定遠低於此上限。
參數設定建議
試點池中已驗證可行的預設範圍:
建議離線以歷史 swap 資料對公式進行回測,再調整
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 領取歷史已賺取的獎勵。
管理員收取
兩者均不影響曲線——已累積的金額本就在
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 節(手續費成長)

