Skip to main content
本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
本頁與 products/clmm/accounts(帳戶說明)和 products/clmm/math(數學說明)配套。本頁對參數和帳戶順序具有權威性;具體的位元組佈局來自 IDL。

指令清單

大多數管理員專用指令(CreateAmmConfigUpdateAmmConfigUpdatePoolStatusCreateSupportMintAssociatedCreateOperationAccountUpdateOperationAccountCloseProtocolPosition)由程序的硬編碼 admin 公鑰控制。CreatePermissionPda / ClosePermissionPda 接受 admin 公鑰專用的 permission_pda_admin 密鑰。獎勵流管理員指令(TransferRewardOwnerCollectRemainingRewards)由獎勵資金提供者控制,而不是程序管理員。 V2 後綴表示「在保管庫/NFT 上支持 Token-2022,需要位圖擴展槽」。SDK 預設為新池選擇 V2。

CreatePool

參數
帳戶(簡化) 前置條件
  • token_mint_0 < token_mint_1(按位元組順序)。
  • amm_config.disable_create_pool == false
  • 鑄幣未被 Token-2022 擴展允許列表拒絕。
後置條件
  • pool_state.sqrt_price_x64 = sqrt_price_x64tick_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 = falsedynamic_fee_config 被忽略。 後置條件
  • pool_state.fee_on 設置為選定的 CollectFeeOn 變體。
  • 如果啟用了動態費用:pool_state.dynamic_fee_info 從提供的 DynamicFeeConfig 初始化(複製五個校準參數;狀態欄位清零)。
  • 否則:pool_state.dynamic_fee_info 被清零(= 此池永遠不會啟用動態費用)。
fee_on 和動態費用啟用位在池創建時設置。沒有就地升級 — 通過舊版 CreatePool 創建的池無法追溯地獲得動態費用或單邊費用。新部署應預設為此指令。

CreatePermissionedPool

CreatePoolCreateCustomizablePool 都從 ["pool", amm_config, token_mint_0, token_mint_1] 派生池 PDA,因此每個 (config, mint0, mint1) 三元組恰好有一個規範池地址 — 在相同種子處的第二個 init 失敗。CreatePermissionedPool 通過將客戶端提供的 seed_index: u16 折疊到池 PDA 種子中來解除此限制,允許同一交易對和費用等級的多個池 — 每個在其自己的地址。因為任意池地址是特權功能,支付者必須持有授權它的 Permission PDA。 關於池的其他一切與 CreateCustomizablePool 相同:它採用相同的 CreateCustomizableParams 並支持單邊費用和動態費用選擇加入。 參數
帳戶(簡化) — 與 CreateCustomizablePool 相同,加上前面的: pool_state PDA 派生自 ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()] 前置條件
  • seed_index != 0seed_index0 保留給舊版池並在此被拒絕;[0, 0] 種子分量是使舊版池地址折疊為經典四種子形式的原因。
  • payerpermission PDA 存在(由管理員通過 CreatePermissionPda 創建)。
  • CreatePool 相同的鑄幣/允許列表規則。
後置條件
  • 新的 pool_state 存在於 seed_index 派生的地址,pool_state.seed_index = seed_index
  • 所有其他後狀態與 CreateCustomizablePool 匹配(費用模式、可選動態費用)。
此指令擴大一般池創建訪問 — 無權限創建繼續通過 CreatePool / CreateCustomizablePool,每對仍為一個池。CreatePermissionedPool 存在於白名單操作者需要同一交易對的多個池(例如不同的初始價格或啟動隊列)並持有由管理員授予的 Permission PDA 的特定情況。

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 陣列已傳遞並初始化(或在交易中通過 InitTickArray CPI 創建)。
  • 用戶在源 ATA 中至少有 amount_0_maxamount_1_max
後置條件
  • personal_position 存在,liquidity 設置,fee_growth_inside_last 快照。
  • Tick 陣列條目在 tick_lowertick_upper 處更新(liquidity_gross += Lliquidity_net ± L,費用增長快照維護)。
  • 如果頭寸在範圍內(tick_lower ≤ tick_current < tick_upper),pool_state.liquidity += L
  • 位置 NFT 鑄幣記錄 pool_state 作為凍結權限。鑄幣權限在單個 NFT 鑄造後被移除。記錄凍結權限不會改變 NFT 代幣帳戶的狀態。
  • NFT 代幣帳戶保持未凍結,除非指令是 OpenPositionV2OpenPositionWithToken22Nft 任一保管庫鑄幣的凍結權限與 CLMM 的受限發行人列表匹配。只有該匹配的 V2 路徑凍結帳戶。OpenPosition V1 不凍結。
常見錯誤InvalidTickIndexNotApprovedZeroAmountSpecifiedTransactionTooLarge(如果 tick 陣列過多)。
頭寸凍結不添加聲明的指令帳戶或參數。客戶端可以使用現有的 V2 佈局打開這些頭寸。行為在鏈上從 vault_0_mintvault_1_mint 選擇。

IncreaseLiquidityV2

向已開放的頭寸添加流動性。 參數
帳戶 — 如 OpenPosition 減去 NFT 鑄幣(頭寸已存在;NFT 作為持有 1 個代幣的所有者 ATA 傳遞)。 效果
  • 從用戶轉移 amount_0_actual / amount_1_actual → 保管庫。
  • 增加 personal_position.liquiditypool_state.liquidity(如果在範圍內),以及端點 tick 的 liquidity_gross / liquidity_net
  • 收集自上次觸及以來應付的費用和獎勵並將其記入 tokens_fees_owed_{0,1} / reward_amount_owed。這些僅在 DecreaseLiquidityCollectReward 時支付,而不是在增加時。

DecreaseLiquidityV2

從頭寸移除流動性。 參數
帳戶 — 與 IncreaseLiquidity 相同的形狀。 效果
  • 給定當前 sqrt_price_x64,計算移除的 L(amount_0, amount_1)
  • 結算自上次觸及以來累積的費用/獎勵,與 IncreaseLiquidity 相同。
  • 從保管庫轉移 amount_0 + fees_owed_0amount_1 + fees_owed_1 到用戶。
  • 遞減流動性計數器;如果新的 personal_position.liquidity == 0,頭寸符合 ClosePosition 的條件。
滑點amount_0_minamount_1_min 是用戶在輸出端 Token-2022 轉移費用淨額後接受的最小值。

ClosePosition

銷毀頭寸 NFT 並關閉 PersonalPositionState 聲明的帳戶 剩餘帳戶
  • 未凍結 NFT:不需要;額外的池帳戶無害,因為處理程序不讀取它。
  • 凍結 NFT:附加 personal_position.pool_id 作為第一個剩餘帳戶。程序將其加載為 PoolState 並使用其 PDA 種子簽署解凍。
前置條件
  • personal_position.liquidity == 0
  • tokens_fees_owed_{0,1} == 0
  • 所有獎勵計數器 reward_amount_owed == 0
(即,先收集所有內容並遞減到零。) 效果
  • 如果 NFT 代幣帳戶被凍結,驗證第一個剩餘帳戶等於 personal_position.pool_id,然後使用池 PDA 解凍。
  • 銷毀 NFT。
  • 關閉 NFT 代幣帳戶和 personal_position,將租金退款給 nft_owner。如果頭寸 NFT 使用 Token-2022,它也關閉 NFT 鑄幣;經典 SPL Token 鑄幣無法關閉,供應量保持為零。
解凍、銷毀和關閉是原子的。NFT 在這些步驟之間無法變為可轉移。 條件客戶端中斷 — 聲明的 IDL 佈局未更改,因此舊版客戶端繼續關閉現有和未凍結的頭寸。省略池剩餘帳戶的舊版構建器在關閉凍結頭寸時失敗,出現 AccountLack。為每次關閉傳遞池是最簡單的兼容策略。

SwapV2

沿流動性曲線行走;精確輸入精確輸出取決於 is_base_input 參數
帳戶(簡化) 調用者傳遞覆蓋預期交換行走的排序 tick 陣列列表;程序使用所需的數量。SDK 通過 PoolUtils.computeAmountOutFormat 或 API 的報價端點計算此列表。 前置條件
  • pool_state.status 允許交換。
  • now >= open_time
  • sqrt_price_limit_x64sqrt_price_x64 的正確一側用於方向。
常見錯誤ExceededSlippageSqrtPriceLimitOverflowTickArrayNotFoundLiquidityInsufficient SwapV2 在內部執行的調用者應該知道的內容(2025 年後發布):
  1. 動態費用附加費 — 如果 pool.dynamic_fee_info 非零,程序使用自上次交換以來遍歷的 tick 距離更新波動率累加器(使用 products/clmm/fees 中的過濾/衰減規則),並在 AmmConfig.trade_fee_rate 之上添加 dynamic_fee_component。總費用上限為 10%(MAX_FEE_RATE_NUMERATOR / 1_000_000)。
  2. 限價單匹配 — 當價格行走穿過持有開放限價單的 tick 時,程序首先填充該 tick 處可用的限價單流動性(按 order_phase 的 FIFO),然後沿著 LP 流動性曲線進行。已成交金額更新 tick.unfilled_ratio_x64tick.part_filled_orders_remaining 以供稍後結算;訂單本身保持未花費,直到其所有者調用 SettleLimitOrder
  3. 單邊費用路由 — 當 pool.fee_on = Token0OnlyToken1Only 時,交換步驟仍計算相同的輸入輸出交易;費用隨後被路由到配置的一側。對於配置費用側是輸出的方向,費用從交換輸出中扣除(用戶收到 out − fee);對於配置費用側是輸入的方向,行為與 FromInput 匹配。見 pool_state 上的 is_fee_on_input(zero_for_one)is_fee_on_token0(zero_for_one)
Swap(V1)實現與 SwapV2 相同的動態費用、單邊費用路由和限價單匹配;它缺少的唯一功能是 Token-2022 支持 — 兩個保管庫都必須是經典 SPL Token。任何 Token-2022 鑄幣的池必須通過 SwapV2 交換。聚合器和 SDK 已經為每個 CLMM 腿優先選擇 V2,因此調用者不必根據鑄幣類型進行分支。

OpenLimitOrder

在特定 tick 處下達賣單。訂單位於每 tick FIFO 隊列中,並在價格穿過時填充。 參數
帳戶(簡化)
帳戶列表變更(2026-07 發布)。 OpenLimitOrder 現在也採用輸出端帳戶 — output_token_accountoutput_vaultoutput_vault_mint — 除了輸入端。它們僅用於驗證:如果所有者的輸入輸出代幣帳戶被凍結,程序拒絕訂單。這保證填充實際上可以結算到所有者的輸出 ATA,這對於允許列表/預設凍結的 Token-2022 鑄幣(例如許可代幣)很重要,其中帳戶可能尚未解凍。針對舊版單邊帳戶列表構建的客戶端必須添加三個輸出帳戶。
前置條件
  • input_token_accountoutput_token_account 都未被凍結(否則 NotApproved)。
  • pool_state.status 允許交換(位 4)和限價單(位 5)操作(否則 NotApproved)。
  • tick_index % pool.tick_spacing == 0 並在 [MIN_TICK, MAX_TICK] 內。
  • tick_index 在所選方向的 pool.tick_current 的正確一側(出售 token0 → tick 必須在當前上方,反之亦然)。在已穿過的 tick 處出售會立即匹配並被拒絕。
後置條件
  • limit_order 存在,快照打開時的 tick.order_phasetick.unfilled_ratio_x64
  • tick.orders_amount += amount(在當前隊列中)。
  • limit_order_nonce.order_nonce += 1
  • 發出 OpenLimitOrderEvent
常見錯誤NotApproved(輸入或輸出代幣帳戶被凍結,或池禁用交換/限價單)、InvalidLimitOrderAmount(零或低於池的最小值)、InvalidTickIndex(超出 [MIN_TICK, MAX_TICK],或在所選方向的 tick_current 的錯誤一側)、TickAndSpacingNotMatchtick_index % pool.tick_spacing != 0)、OrderPhaseSaturated

IncreaseLimitOrder

添加到現有開放訂單。僅由訂單的 owner 調用。 參數
帳戶 — 如 OpenLimitOrder 減去 nonce 帳戶;limit_order PDA 直接傳遞。 前置條件
  • limit_order.owner == signer
  • 訂單仍在同一隊列中(tick.order_phase == limit_order.order_phase)。如果隊列已開始填充,訂單已部分結算 — 調用者應首先調用 DecreaseLimitOrderSettleLimitOrder 以向前推進。
效果
  • 從所有者 ATA 轉移 amountinput_vault
  • limit_order.total_amount += amounttick.orders_amount += amount

DecreaseLimitOrder

減少或完全取消開放訂單。將未成交的剩餘部分支付回所有者,加上過去部分成交已結算的任何輸出。 參數
帳戶 — 輸入和輸出代幣兩側: 效果
  • 從打開以來隊列的 unfilled_ratio_x64 重新計算訂單的已成交金額。
  • 將已成交輸出發送到 output_token_account
  • amount 的未成交輸入發送回 input_token_account
  • 相應地更新 limit_order。如果新的未成交剩餘為零,程序關閉帳戶並將租金退款給 owner

SettleLimitOrder

將已成交的輸出代幣推送給所有者,而不改變訂單的未成交剩餘。當 auto_withdraw 保管人想要滴灌支付長期運行的部分成交時很有用。 調用者 — 訂單的 owner,或程序的 limit_order_admin(運行自動保管人循環的離線操作熱錢包)。保管人沒有其他權限 — 它無法將用戶資金移出推送已成交輸出到訂單的 owner ATA 之外。 帳戶 效果
  • 使用 (limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64) 計算累積應付輸出。
  • 將增量轉移到 output_token_account
  • 更新 limit_order.settled_output
  • 關閉訂單;它對任何剩餘輸入仍然開放。

CloseLimitOrder

關閉完全消耗的訂單帳戶。租金始終返回給 limit_order.owner,無論誰簽署。 調用者ownerlimit_order_admin 前置條件
  • 訂單的未成交剩餘為零(amount == total_amount 已成交並結算,或所有者之前將訂單減少到零並忘記關閉)。
效果
  • 關閉 limit_order;租金發送到 limit_order.owner

CreateDynamicFeeConfig(管理員)

在 u16 索引下創建可重用的參數集。 參數
帳戶 常見錯誤 — 如果 decay_period <= filter_period 或任何 0 值欄位超出邊界,則 InvalidDynamicFeeConfigParams

UpdateDynamicFeeConfig(管理員)

修改現有 DynamicFeeConfig。在創建時已快照配置的池被追溯更新;只有引用此配置的新創建池才會選擇新值。 參數 — 與 CreateDynamicFeeConfig 相同的五個校準欄位(filter_perioddecay_periodreduction_factordynamic_fee_controlmax_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) 價值的獎勵代幣存入保管庫。
  • 根據 operation_state 白名單獎勵鑄幣。

SetRewardParams

延長、充值或更改現有獎勵流的發放速率。通常由池創建者或 Raydium 多簽調用。約束在鏈上:你通常可以延長 end_time 或增加發放,而不是追溯縮減。檢查 operation_state 的所有者列表。

UpdateRewardInfos

純粹的簿記 — 通過將 emissions_per_second × Δt / liquidity 相乘將 reward_growth_global_x64 結算到當前時間。由每個流動性觸及指令在內部調用。作為獨立指令公開,因為外部參與者(UI、cranks)有時想觸發它。

CollectReward

頭寸所有者聲稱應付的獎勵代幣。 帳戶 效果
  • 結算獎勵增長(與費用相同的模式)。
  • 將應付金額轉移到收件人 ATA,將 reward_amount_owed[i] 清零。

狀態變更矩陣

後續步驟

來源: