Skip to main content
本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
本頁說明每個帳戶的配置和角色。種子(Seeds)是規範的,列在 reference/program-addresses。CLMM 池比 CPMM 池需要更多帳戶,因為流動性分散儲存在整個 tick 範圍內;理解這種分散性是本頁的重點。

帳戶清單

一個運作中的 CLMM 池由以下帳戶族群組成。除了兩個 mint 及其金庫外,所有帳戶都由 CLMM 程式擁有。

PoolState

池的即時狀態,在每次交換和每次頭寸變更時讀取。
你實際會接觸的欄位:
  • sqrt_price_x64 和 tick_current 是池的價格狀態。它們在每次交換時一起更新。tick_current 是 log_{1.0001}(price) 的下限。
  • liquidity 是活躍流動性——所有範圍包含 tick_current 的頭寸的 L 值之和。每次交換跨越 tick 時以及每次頭寸開啟/關閉/調整大小時都會變更。
  • fee_growth_global_{0,1}_x64 是整個池歷史中每單位流動性累積的費用。頭寸讀取此值以計算欠他們的費用。
  • tick_spacing 在初始化時鎖定到 AmmConfig,永遠不會改變。它決定哪些 tick 索引可以作為頭寸端點。
  • tick_array_bitmap 是一個內聯位圖,涵蓋現貨價格周圍常用的 tick 範圍。對於頭寸延伸很遠的池,溢出追蹤位於單獨的 TickArrayBitmapExtension。
  • fee_on 在池建立時固定。0(FromInput)重現經典 Uniswap-V3 行為。1 和 2 將交換費路由到書籍的單一側——請參閱 products/clmm/fees 以了解權衡。
  • seed_index 對於透過 CreatePool / CreateCustomizablePool 建立的每個池都是 [0, 0](每對一個規範池)。非零值表示池是透過 CreateCustomizablePoolV2(2026-10-22 之前名為 CreatePermissionedPool)建立的,索引是池 PDA 種子的一部分,允許同一 (config, mint0, mint1) 存在多個池。要重新衍生這樣的池的地址,你必須知道其 seed_index。
  • dynamic_fee_info 攜帶動態費用加價的波動性狀態。啟用時,每次交換都會在 AmmConfig.trade_fee_rate 之上重新計算 dynamic_fee_component。配置在下面的 DynamicFeeInfo 下記錄;沒有動態費用的池將整個結構保留為零。

AmmConfig

自 2026-09 升級以來,CreateAmmConfig 將程式的硬編碼 protocol_fee_owner::ID 寫入 owner,將 fund_fee_owner::ID 寫入 fund_owner。在此之前,它將管理員簽署者的金鑰複製到兩者。現有配置保留它們建立或輪換到的任何內容,因此請從帳戶讀取兩個欄位。UpdateAmmConfig 參數 3 / 4 仍然輪換它們。地址在 reference/program-addresses。 一個典型的已發佈 CLMM 費用等級集合(確認對比 GET https://api-v3.raydium.io/main/clmm-config): protocol_fee_rate 和 fund_fee_rate 是交易費的分數;與 CPMM 相同的慣例。請參閱 products/clmm/fees。

TickArrayState

CLMM 不會為每個 tick 儲存單一記錄,那樣會產生數十億個帳戶。相反,它將 TICK_ARRAY_SIZE 個相鄰的已初始化或未初始化 tick(通常為 60 或 88,取決於程式版本)分組到一個 TickArrayState 中,該帳戶在首次使用時才被延遲建立。
四個限價單欄位在任何從未用於限價單的 tick 上都為零。當在某個 tick 上開啟訂單時,程式會將它們追蹤為一系列的批次:
  • order_phase 是批次 ID。每當批次從「全部未成交」轉變為「部分成交」時,它就會遞增。
  • orders_amount 是目前(最新)批次的輸入代幣總額。
  • part_filled_orders_remaining 追蹤目前正被進行中的交換填充的前一個批次。
  • unfilled_ratio_x64 是在批次上攜帶的 Q64.64 乘數:當交換填充批次的 X% 時,比率乘以 (1 − X)。每個開啟的訂單在開啟時儲存自己的 (order_phase, unfilled_ratio_x64) 快照,因此結算數學簡化為比較快照。
規則:
  • 位置端點 tick t 必須滿足 t % tick_spacing == 0。程式會拒絕不符合間距的位置。
  • tick 的陣列位於 floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing)。
  • tick 陣列是延遲初始化的:第一個接觸未初始化陣列的位置或交換會建立它,並支付租金。
  • tick 陣列永遠不會被程式關閉。一旦分配,它就會在資金池的整個生命週期內持續存在,即使其中的每個 tick 都回到 liquidity_gross == 0。後續的位置和交換會重複使用現有帳戶,無需額外租金。沒有由 ClosePosition 驅動的 tick 陣列清理路徑。

TickArrayBitmapExtension

PoolState.tick_array_bitmap(內聯)涵蓋「接近現貨」範圍 — ±512 個 tick 陣列(TICK_ARRAY_BITMAP_SIZE = 512;[u64; 16] 欄位是 1,024 位,在負數和正數起始索引之間均勻分割,因此陣列索引 −512 … +511)。超出該範圍(對於極端 tick 值),程式會維護一個擴展帳戶:
如果你的位置範圍是「正常的」,你永遠不需要考慮擴展帳戶。全範圍位置(例如 (MIN_TICK, MAX_TICK))需要它;SDK 會為你解決。

位置

CLMM 位置是三個帳戶加一個 mint 的組合:

位置 NFT mint

一個供應量為 1 的 SPL Token 或 Token-2022 mint。所有者錢包中的位置 NFT 是持有該單一代幣的 ATA。程式將授權金鑰設定為 NFT 的 ATA 餘額的目前持有者,而不是儲存在狀態中的 Pubkey。 新位置 NFT mint 在鑄造單一代幣並移除 mint 權限之前,將 pool_state 設定為其凍結權限。設定凍結權限本身不會凍結 NFT 帳戶。 除非同時滿足兩個條件,否則帳戶保持未凍結且可轉移:呼叫者使用 OpenPositionV2 或 OpenPositionWithToken22Nft,且至少一個基礎保管庫 mint 的凍結權限出現在 CLMM 的受限發行人清單上。只有這樣,CLMM 才會在鑄造後凍結 NFT 帳戶。這不會改變任何 PersonalPositionState 或 PoolState 位元組。

PersonalPositionState

每個開啟的位置一個。以 NFT mint 為鑰。

ProtocolPositionState(已棄用)

較舊的 CLMM 版本在 ProtocolPositionState PDA 中儲存每個 (pool, tick_lower, tick_upper) 的彙總簿記。較新的版本不再建立或讀取此帳戶。 該位置仍然出現在 OpenPosition / IncreaseLiquidity / DecreaseLiquidity 帳戶清單上,作為 UncheckedAccount 以保持 ABI 相容性,但程式不會寫入它。鏈上現有的帳戶是遺留的;管理員可以呼叫 CloseProtocolPosition 來回收它們的租金。彙總範圍簿記現在直接從兩個端點 tick(liquidity_gross、liquidity_net 和 TickArrayState 中的每個 tick fee_growth_outside_* / reward_growths_outside_x64)衍生。費用增長內部公式 fee_growth_inside = global − outside_lower − outside_upper 繼續在沒有彙總位置帳戶的情況下運作。

觀察

CLMM 的觀察緩衝區儲存累積 tick,而不是累積價格。外部消費者從 (tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0) 計算區間上的幾何平均價格,然後 price = 1.0001 ** tick。參見 algorithms/clmm-math。

DynamicFeeConfig 和 DynamicFeeInfo

動態費用參數存在於兩個地方。可重複使用的範本 — DynamicFeeConfig — 由管理員管理並在選擇加入的資金池之間共享。每個資金池的執行時狀態 — DynamicFeeInfo — 嵌入在 PoolState 中,並由每次交換更新。

DynamicFeeConfig

PDA 種子:["dynamic_fee_config", index.to_be_bytes()]。透過 create_dynamic_fee_config(管理員限制)建立,並透過 update_dynamic_fee_config 修改。使用 enable_dynamic_fee = true 建立的資金池會在建立時將設定的五個校準參數(filter_period、decay_period、reduction_factor、dynamic_fee_control、max_volatility_accumulator)快照到自己的 DynamicFeeInfo 中;稍後對 DynamicFeeConfig 的編輯不會追溯影響現有資金池。

DynamicFeeInfo(嵌入在 PoolState 中)

底部四個欄位是狀態;頂部五個是從 DynamicFeeConfig 複製的校準。費用數學和衰減規則記錄在 products/clmm/math 和 products/clmm/fees 下。 公式使用的常數:

LimitOrderState

每個開啟的限價單一個帳戶。
生命週期:
  1. 開啟 — 使用者呼叫 open_limit_order,存入 total_amount 的輸入代幣,訂單綁定到 TickState 批次。
  2. (可選)增加 / 減少 — increase_limit_order 增加 total_amount;decrease_limit_order 返回未成交代幣(以及到該點為止的任何已結算輸出)。
  3. 結算 — 當批次被完全或部分填充時,所有者或操作保管人呼叫 settle_limit_order 將輸出代幣推送到所有者的 ATA。
  4. 關閉 — 一旦 unfilled_amount == 0,帳戶就可以關閉。租金始終返回給 owner。
PDA 種子:[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]。訂單 PDA 因此對每個 (owner, nonce_index, order_nonce) 都是唯一的。

LimitOrderNonce

針對每個 (wallet, nonce_index) 組合的計數器,讓單一使用者能夠並行執行多條限價單管道,而不會在 PDA 上發生碰撞。
PDA 種子:[user_wallet.as_ref(), &[nonce_index]]。大多數客戶端使用 nonce_index = 0,並讓 order_nonce 承載基數。

Permission(已停用)

Permission 帳戶在 2026-10-22 升級中被移除。它曾經用於控制 CreatePermissionedPool,現在已改為無需許可的 CreateCustomizablePoolV2。程式不再讀取或關閉這些帳戶,CreatePermissionPda / ClosePermissionPda 指令也已移除。升級前建立的 PDA(["permission", authority],280 位元組)仍保留在鏈上作為惰性資料;掃描 CLMM 擁有的帳戶時請忽略它們。

推導關鍵帳戶

確切的種子字串應始終對照鏈上 IDL 和 reference/program-addresses 進行雙重檢查。

生命週期快速參考

TickArrayState 帳戶永遠不會被程式關閉 — 它們在池的整個生命週期內持續存在。一旦 tick 陣列被初始化,即使其中的每個 tick 都回到 liquidity_gross == 0,它仍會保留在鏈上。重複使用現有 tick 陣列是免費的;只有第一個接觸從未初始化陣列的頭寸才需支付其租金。

在何處閱讀什麼

來源: