本頁內容由 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](每對一個規範池)。非零值表示池是透過CreatePermissionedPool建立的,索引是池 PDA seeds 的一部分,讓多個池可以為相同的(config, mint0, mint1)共存。要重新衍生這樣的池的地址,你必須知道其seed_index。dynamic_fee_info攜帶動態費用附加費的波動性狀態。啟用時,每次交換都會在AmmConfig.trade_fee_rate之上重新計算dynamic_fee_component。佈局在下面的DynamicFeeInfo中記錄;沒有動態費用的池將整個結構保留為零。
AmmConfig
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 中,該狀態在首次使用時延遲建立。
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 的組合:Position NFT mint
一個 SPL Token 或 Token-2022 mint,供應量為 1。擁有者錢包中的位置 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 帳戶清單上,作為 ABI 相容性的 UncheckedAccount,但程式不會寫入它。鏈上現有帳戶是遺留的;管理員可以呼叫 CloseProtocolPosition 來回收它們的租金。聚合範圍簿記現在直接從兩個端點 tick(liquidity_gross、liquidity_net 和每個 tick 的 fee_growth_outside_* / reward_growths_outside_x64)在 TickArrayState 中衍生。費用增長內部公式 fee_growth_inside = global − outside_lower − outside_upper 繼續在沒有聚合位置帳戶的情況下工作。觀察
(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0) 計算區間上的幾何平均價格,然後 price = 1.0001 ** tick。參見 algorithms/clmm-math。
DynamicFeeConfig 和 DynamicFeeInfo
動態費用參數位於兩個地方。可重用的範本——DynamicFeeConfig——由管理員管理,並在選擇加入的池之間共享。每個池的執行時狀態——DynamicFeeInfo——嵌入在 PoolState 中,由每次交換更新。
DynamicFeeConfig
["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
每個開放限價單一個帳戶。
- 開啟——使用者呼叫
open_limit_order,存入輸入代幣的total_amount,訂單綁定到TickState群組。 - (可選)增加/減少——
increase_limit_order添加到total_amount;decrease_limit_order返回未填充的代幣(以及到該點為止的任何已結算輸出)。 - 結算——當群組被完全或部分填充時,擁有者或操作保管人呼叫
settle_limit_order將輸出代幣推送到擁有者的 ATA。 - 關閉——一旦
unfilled_amount == 0,帳戶就可以關閉。租金始終返回給owner。
[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 上發生衝突。
[user_wallet.as_ref(), &[nonce_index]]。大多數客戶端使用 nonce_index = 0 並讓 order_nonce 進行基數計算。
Permission
一個能力帳戶,其存在就是授權:如果為給定的權限衍生 Permission PDA,該權限可能呼叫 CreatePermissionedPool。它除了建立它的權限外不儲存任何內容。
["permission", authority.as_ref()]。由管理員透過 CreatePermissionPda 建立,透過 ClosePermissionPda 拆除(租金退款給呼叫者)。兩個管理員指令都接受程式 admin 或專用 permission_pda_admin 金鑰。關閉 PDA 會撤銷授權——權限不再能建立額外的池,但它已建立的池不受影響。
衍生關鍵帳戶
reference/program-addresses 進行雙重檢查。
生命週期快速參考
TickArrayState 帳戶永遠不會被程式關閉——它們在池的整個生命週期內持續存在。一旦 tick 陣列被初始化,即使其中的每個 tick 都回到 liquidity_gross == 0,它也會保留在鏈上。重用現有 tick 陣列是免費的;只有首次接觸從未初始化陣列的位置才需支付其租金。
在哪裡閱讀什麼
- Tick 數學和範圍機制:
products/clmm/ticks-and-positions。 - 交換遍歷和費用增長數學:
products/clmm/math。 - 指令帳戶清單:
products/clmm/instructions。 - 費用和獎勵應計:
products/clmm/fees。 - 規範程式 ID 和 seeds:
reference/program-addresses。

