本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
本頁與
products/clmm/accounts(帳戶說明)及 products/clmm/math(數學原理)配套閱讀,是參數與帳戶順序的權威來源;具體位元組佈局請參閱 IDL。指令一覽
大多數僅限管理員的指令(
CreateAmmConfig、UpdateAmmConfig、UpdatePoolStatus、CreateSupportMintAssociated、CreateOperationAccount、UpdateOperationAccount、CloseProtocolPosition)由程式硬編碼的 admin 公鑰控管。獎勵流管理指令(TransferRewardOwner、CollectRemainingRewards)則由獎勵資助方控管,而非程式管理員。
V2 後綴表示「支援保險庫/NFT 的 Token-2022,需要 bitmap-extension slot」。SDK 預設對新池使用 V2。
CreatePool
參數
前置條件
token_mint_0 < token_mint_1(依位元組順序排列)。amm_config.disable_create_pool == false。- Mint 未被 Token-2022 擴充允許清單拒絕。
pool_state.sqrt_price_x64 = sqrt_price_x64,tick_current = floor(log_{1.0001}(price))。pool_state.liquidity = 0(尚無倉位)。pool_state.fee_on = FromInput(舊版預設值)。pool_state.dynamic_fee_info歸零(動態費用停用)。
CreateCustomizablePool
建議新池使用。效果與 CreatePool 相同,額外支援每池費用收取模式及選擇性動態費用啟用。
參數
CreatePool 相同,當 enable_dynamic_fee = true 時額外需要:
前置條件 — 與
CreatePool 相同。若 enable_dynamic_fee = false,則忽略 dynamic_fee_config。
後置條件
pool_state.fee_on設為所選的CollectFeeOn變體。- 若啟用動態費用:
pool_state.dynamic_fee_info從提供的DynamicFeeConfig初始化(複製五個校準參數;狀態欄位歸零)。 - 否則:
pool_state.dynamic_fee_info歸零(= 此池永久停用動態費用)。
fee_on 及動態費用啟用位元僅在池建立時設定,無法事後升級——透過舊版 CreatePool 建立的池無法追加動態費用或單側費用。新部署應預設使用此指令。
OpenPositionV2 / OpenPositionWithToken22Nft
在現有池中建立新倉位。
參數
數學 — 請參閱
products/clmm/math。依據 base_flag,程式將 liquidity 或 (amount_0_max, amount_1_max) 解析為實際的 L 及實際消耗的代幣數量。
前置條件
tick_lower < tick_upper,兩者均為pool.tick_spacing的倍數,且在[MIN_TICK, MAX_TICK]範圍內。- 所需 tick array 已傳入並初始化(或在此交易中透過
InitTickArrayCPI 建立)。 - 使用者來源 ATA 中至少持有
amount_0_max及amount_1_max。
personal_position已存在,liquidity已設定,fee_growth_inside_last已快照。tick_lower和tick_upper的 tick-array 條目已更新(liquidity_gross += L、liquidity_net ± L、費用增長快照維護)。- 若倉位在範圍內(
tick_lower ≤ tick_current < tick_upper),則pool_state.liquidity += L。
InvalidTickIndex、NotApproved、ZeroAmountSpecified、TransactionTooLarge(tick array 過多時)。
IncreaseLiquidityV2
向已開啟的倉位增加流動性。
參數
OpenPosition 類似,但不需要 NFT mint(倉位已存在;NFT 以擁有者持有 1 個代幣的 ATA 形式傳入)。
效果
- 將
amount_0_actual/amount_1_actual從使用者轉入保險庫。 - 遞增
personal_position.liquidity及pool_state.liquidity(若在範圍內),並相應調整端點 tick 的liquidity_gross/liquidity_net。 - 收取自上次觸碰以來應付的手續費和獎勵,並記入
tokens_fees_owed_{0,1}/reward_amount_owed。這些金額僅在DecreaseLiquidity或CollectReward時支付,增加流動性時不會直接付出。
DecreaseLiquidityV2
從倉位移除流動性。
參數
IncreaseLiquidity 相同。
效果
- 依當前
sqrt_price_x64計算移除L所對應的(amount_0, amount_1)。 - 結算自上次觸碰以來累積的手續費/獎勵,方式與
IncreaseLiquidity相同。 - 將
amount_0 + fees_owed_0及amount_1 + fees_owed_1從保險庫轉給使用者。 - 遞減流動性計數器;若新的
personal_position.liquidity == 0,該倉位可執行ClosePosition。
amount_0_min 和 amount_1_min 是使用者在扣除輸出端 Token-2022 轉帳費用後可接受的最低金額。
ClosePosition
銷毀倉位 NFT 並關閉 PersonalPositionState。
前置條件
personal_position.liquidity == 0。tokens_fees_owed_{0,1} == 0。- 所有獎勵計數器
reward_amount_owed == 0。
- 銷毀 NFT。
- 關閉 NFT mint 帳戶及
personal_position帳戶,並將租金退還給payer。
SwapV2
沿流動性曲線行走;依 is_base_input 決定精確輸入或精確輸出模式。
參數
呼叫方傳入一組按優先順序排列、涵蓋預期交換範圍的 tick array 清單;程式按需取用。SDK 透過
PoolUtils.computeAmountOutFormat 或 API 報價端點計算此清單。
前置條件
pool_state.status允許交換。now >= open_time。sqrt_price_limit_x64位於當前sqrt_price_x64在該方向的正確一側。
ExceededSlippage、SqrtPriceLimitOverflow、TickArrayNotFound、LiquidityInsufficient。
呼叫方應了解的 SwapV2 內部行為(2025 年後版本):
- 動態費用附加 — 若
pool.dynamic_fee_info非零,程式依自上次交換以來穿越的 tick 距離更新波動性累加器(套用products/clmm/fees中的過濾/衰減規則),並在AmmConfig.trade_fee_rate之上加入dynamic_fee_component。總費率上限為 10%(MAX_FEE_RATE_NUMERATOR / 1_000_000)。 - 限價單撮合 — 當價格行走穿越持有開放限價單的 tick 時,程式先按
order_phaseFIFO 順序成交該 tick 的限價單流動性,再繼續沿 LP 流動性曲線行走。已成交金額更新tick.unfilled_ratio_x64及tick.part_filled_orders_remaining,供後續結算使用;訂單本身保持未動,直至擁有者呼叫SettleLimitOrder。 - 單側費用路由 — 當
pool.fee_on = Token0Only或Token1Only時,交換步驟仍計算相同的輸入輸出交易;費用隨後路由至設定的一側。若設定的費用側為輸出端,費用從交換輸出中扣除(使用者收到out − fee);若為輸入端,行為與FromInput相同。請參閱PoolState上的is_fee_on_input(zero_for_one)及is_fee_on_token0(zero_for_one)。
Swap(V1)實作與 SwapV2 相同的動態費用、單側費用路由及限價單撮合;唯一缺少的功能是 Token-2022 支援——兩個保險庫均須為傳統 SPL Token。任何含有 Token-2022 mint 的池必須透過 SwapV2 交換。聚合器與 SDK 已對所有 CLMM 路段優先選用 V2,呼叫方無需依 mint 類型分支處理。
OpenLimitOrder
在指定 tick 掛出賣單。訂單位於每個 tick 的 FIFO 批次中,在價格穿越時成交。
參數
前置條件
tick_index % pool.tick_spacing == 0,且在[MIN_TICK, MAX_TICK]範圍內。tick_index位於所選方向相對於pool.tick_current的正確一側(賣出 token0 → tick 必須在當前之上,反之亦然)。在已穿越的 tick 掛單會立即被撮合,因此會被拒絕。pool_state.status允許限價單操作(第 5 位元)。
limit_order已存在,快照開單時的tick.order_phase及tick.unfilled_ratio_x64。tick.orders_amount += amount(在當前批次中)。limit_order_nonce.order_nonce += 1。- 發出
OpenLimitOrderEvent。
InvalidLimitOrderAmount(金額為零或低於池的最低限額)、InvalidTickIndex(超出 [MIN_TICK, MAX_TICK] 範圍,或位於 tick_current 所選方向的錯誤一側)、TickAndSpacingNotMatch(tick_index % pool.tick_spacing != 0)、OrderPhaseSaturated。
IncreaseLimitOrder
增加現有掛單的數量。僅限訂單的 owner 呼叫。
參數
OpenLimitOrder 類似,但不需要 nonce 帳戶;直接傳入 limit_order PDA。
前置條件
limit_order.owner == signer。- 訂單仍在同一批次中(
tick.order_phase == limit_order.order_phase)。若批次已開始成交,訂單為部分結算狀態——呼叫方應先呼叫DecreaseLimitOrder或SettleLimitOrder以向前推進。
- 從擁有者 ATA 轉入
amount至input_vault。 limit_order.total_amount += amount;tick.orders_amount += amount。
DecreaseLimitOrder
減少或完全取消掛單。退回未成交餘額至擁有者,以及過去部分成交已結算的輸出代幣。
參數
效果
- 依批次的
unfilled_ratio_x64重新計算自開單以來的已成交金額。 - 將已成交的輸出代幣傳送至
output_token_account。 - 將
amount的未成交輸入退回至input_token_account。 - 相應更新
limit_order。若新的未成交餘額為零,程式關閉該帳戶並將租金退還給owner。
SettleLimitOrder
將已成交的輸出代幣推送給擁有者,而不改變訂單的未成交餘額。適用於 auto_withdraw keeper 對長期部分成交訂單進行分批支付的場景。
呼叫方 — 訂單的 owner,或程式的 limit_order_admin(一個執行自動 keeper 循環的鏈下操作熱錢包)。keeper 沒有其他權限——它只能將已成交的輸出代幣推送至訂單 owner 的 ATA,無法移動使用者其他資金。
帳戶
效果
- 使用
(limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64)計算累積應付輸出金額。 - 將差額轉至
output_token_account。 - 更新
limit_order.settled_output。 - 不關閉訂單;針對剩餘輸入的訂單仍保持開啟狀態。
CloseLimitOrder
關閉已完全成交的訂單帳戶。無論由誰簽署,租金始終退還給 limit_order.owner。
呼叫方 — owner 或 limit_order_admin。
前置條件
- 訂單未成交餘額為零(
amount == total_amount已成交並結算,或擁有者先前已將訂單減至零但忘記關閉)。
- 關閉
limit_order;租金傳送至limit_order.owner。
CreateDynamicFeeConfig(管理員)
以 u16 索引建立可重複使用的參數集。
參數
常見錯誤 — 若
decay_period <= filter_period 或任何值為 0 的欄位超出範圍,則回傳 InvalidDynamicFeeConfigParams。
UpdateDynamicFeeConfig(管理員)
修改現有的 DynamicFeeConfig。已在建立時快照該設定的池不會被追溯更新;只有後續建立並參照此設定的新池才會採用新值。
參數 — 與 CreateDynamicFeeConfig 相同的五個校準欄位(filter_period、decay_period、reduction_factor、dynamic_fee_control、max_volatility_accumulator);index 在建立時固定,此處不再傳入。
CollectProtocolFee / CollectFundFee
結構與 CPMM 的 CollectProtocolFee / CollectFundFee 完全相同。簽署者必須符合 AmmConfig.owner / AmmConfig.fund_owner。將池保險庫中累積的協議費/基金費轉至接收方,並將對應的 PoolState.protocol_fees_* / fund_fees_* 欄位歸零。
InitializeReward
為池附加新的獎勵流。每個池最多可同時啟用 3 個獎勵流。
參數
前置條件
- 池目前啟用的獎勵流少於 3 個。
- 資助方在此指令執行時向保險庫存入
total_emission = emissions_per_second × (end_time − open_time)數量的獎勵代幣。 - 獎勵 mint 已依
operation_state加入白名單。
SetRewardParams
延長、補充或修改現有獎勵流的發放速率。通常由池建立者或 Raydium 多簽呼叫。鏈上有相應限制:一般可以延長 end_time 或提高發放量,但不能追溯縮減。請查閱 operation_state 的擁有者清單。
UpdateRewardInfos
純帳務操作——透過 emissions_per_second × Δt / liquidity 將 reward_growth_global_x64 結算至當前時間。每個涉及流動性的指令內部均會呼叫此操作。也作為獨立指令對外開放,以便 UI 或 crank 等外部角色主動觸發。
CollectReward
倉位擁有者領取應得的獎勵代幣。
帳戶
效果
- 結算獎勵增長(方式與手續費相同)。
- 將應付金額轉至接收方 ATA,並將
reward_amount_owed[i]歸零。
狀態變更矩陣
下一步
products/clmm/code-demos— 可執行的 TypeScript 範例。products/clmm/fees— 手續費與獎勵累積詳情。reference/error-codes— 完整的 CLMM Anchor 錯誤代碼表。
raydium-io/raydium-clmm—programs/amm/src/instructions- Raydium SDK v2 —
@raydium-io/raydium-sdk-v2

