Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.Englische Version ansehen →
Diese Seite beschreibt das Layout und die Rolle jedes Accounts. Die Seeds sind kanonisch und unter
reference/program-addresses aufgeführt. Ein CLMM-Pool benötigt mehr Accounts als ein CPMM-Pool, da Liquidität dünn verteilt über den Tick-Bereich gespeichert wird — das Verstehen dieser Verteilung ist der Kerninhalt dieser Seite.Account-Übersicht
Ein aktiver CLMM-Pool wird durch folgende Account-Familien beschrieben. Alle gehören dem CLMM-Programm, mit Ausnahme der beiden Mints und ihrer Vaults.PoolState
Der Live-Zustand des Pools, der bei jedem Swap und jeder Positionsänderung gelesen wird.
sqrt_price_x64undtick_currentstellen den Preisstatus des Pools dar. Sie werden bei jedem Swap gemeinsam aktualisiert.tick_currentist der ganzzahlige Anteil vonlog_{1.0001}(price).liquidityist die aktive Liquidität — die Summe derL-Werte aller Positionen, deren Bereichtick_currententhält. Sie ändert sich, sobald ein Swap einen Tick kreuzt oder eine Position geöffnet, geschlossen oder angepasst wird.fee_growth_global_{0,1}_x64sind die kumulierten Gebühren pro Liquiditätseinheit über die gesamte Pool-Geschichte. Positionen lesen diesen Wert, um ihren ausstehenden Anteil zu berechnen.tick_spacingwird bei der Initialisierung an denAmmConfiggebunden und ändert sich nie. Es legt fest, welche Tick-Indizes als Positionsendpunkte zulässig sind.tick_array_bitmapist eine inline Bitmap, die den üblicherweise genutzten Tick-Bereich um den Spotpreis abdeckt. Für Pools, deren Positionen weiter außerhalb liegen, lebt die Overflow-Nachverfolgung im separatenTickArrayBitmapExtension-Account.fee_onwird bei der Pool-Erstellung festgelegt.0(FromInput) reproduziert das klassische Uniswap-V3-Verhalten.1und2leiten die Swap-Gebühr an eine einzelne Seite des Buches weiter — sieheproducts/clmm/feesfür die jeweiligen Abwägungen.dynamic_fee_infoenthält den Volatilitätsstatus für den dynamischen Gebührenzuschlag. Wenn aktiviert, berechnet jeder Swap einendynamic_fee_componentzusätzlich zuAmmConfig.trade_fee_rate. Das Layout ist unterDynamicFeeInfoweiter unten dokumentiert; Pools ohne dynamische Gebühr lassen die gesamte Struktur auf null.
AmmConfig
GET https://api-v3.raydium.io/main/clmm-config verifizieren):
protocol_fee_rate und fund_fee_rate sind Anteile der Handelsgebühr — gleiche Konvention wie bei CPMM. Siehe products/clmm/fees.
TickArrayState
CLMM speichert keinen einzelnen Eintrag pro Tick — das wären Milliarden von Accounts. Stattdessen fasst es TICK_ARRAY_SIZE benachbarte, initialisierte oder nicht initialisierte Ticks (typischerweise 60 oder 88, je nach Programmversion) in einem TickArrayState zusammen, der bei erster Verwendung lazily angelegt wird.
order_phaseist die Kohorten-ID. Sie wird jedes Mal erhöht, wenn eine Kohorte von „vollständig ungefüllt” auf „teilweise gefüllt” übergeht.orders_amountist der Input-Token-Gesamtbetrag der aktuellen (neuesten) Kohorte.part_filled_orders_remainingverfolgt die vorherige Kohorte, die gerade durch laufende Swaps gefüllt wird.unfilled_ratio_x64ist ein Q64.64-Multiplikator der Kohorte: Wenn ein Swap X % der Kohorte füllt, wird das Verhältnis mit(1 − X)multipliziert. Jede offene Order speichert ihren eigenen(order_phase, unfilled_ratio_x64)-Snapshot zum Eröffnungszeitpunkt, sodass die Abrechnungsrechnung auf einen Snapshot-Vergleich reduziert wird.
- Ein Positionsendpunkt-Tick t muss
t % tick_spacing == 0erfüllen. Das Programm lehnt Positionen mit ungültigem Spacing ab. - Das Array eines Ticks befindet sich bei
floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing). - Ein Tick-Array wird lazily initialisiert: Die erste Position oder der erste Swap, der ein nicht initialisiertes Array berührt, legt es an und übernimmt die Miete.
- Ein Tick-Array wird vom Programm nie geschlossen. Einmal angelegt, bleibt er für die Lebensdauer des Pools bestehen, auch wenn alle darin enthaltenen Ticks wieder
liquidity_gross == 0erreichen. Folgende Positionen und Swaps nutzen den bestehenden Account ohne zusätzliche Miete. Es gibt keinenClosePosition-gesteuerten Bereinigungspfad für Tick-Arrays.
TickArrayBitmapExtension
PoolState.tick_array_bitmap (inline) deckt den „nahe am Spotpreis”-Bereich ab — ±1.024 Tick-Arrays. Außerhalb dieses Bereichs (für extreme Tick-Werte) verwaltet das Programm einen Extension-Account:
(MIN_TICK, MAX_TICK)) benötigen ihn; das SDK löst ihn für Sie auf.
Positionen
Eine CLMM-Position ist ein Bündel aus drei Accounts plus einem Mint:Position-NFT-Mint
Ein SPL-Token-Mint mit Supply 1. Die Adresse des Mints ist ein deterministischer PDA; das Position-NFT im Wallet des Inhabers ist lediglich ein ATA, das dieses einzelne Token hält. Die Übertragung des NFTs ist der Mechanismus, über den eine Position den Besitzer wechselt — das Programm knüpft die Autorisierung an den aktuellen Inhaber des ATA-Guthabens des NFTs, nicht an einen in State gespeicherten Pubkey.PersonalPositionState
Einer pro offener Position. Abgeleitet vom NFT-Mint.
ProtocolPositionState (veraltet)
Ältere CLMM-Versionen speicherten aggregierte Buchführung pro
(pool, tick_lower, tick_upper) in einem ProtocolPositionState-PDA. Neuere Versionen erstellen oder lesen diesen Account nicht mehr. Der Slot erscheint in den Account-Listen von OpenPosition / IncreaseLiquidity / DecreaseLiquidity noch als UncheckedAccount für ABI-Kompatibilität, aber das Programm schreibt nicht mehr darin. Bestehende Accounts on-chain sind Relikte; der Admin kann CloseProtocolPosition aufrufen, um die Miete zurückzugewinnen.Die aggregierte Bereichsbuchführung wird jetzt direkt aus den beiden Endpunkt-Ticks (liquidity_gross, liquidity_net sowie die Tick-spezifischen fee_growth_outside_* / reward_growths_outside_x64) im TickArrayState abgeleitet. Die Fee-Growth-Inside-Formel fee_growth_inside = global − outside_lower − outside_upper funktioniert weiterhin ohne aggregierten Positions-Account.Observation
(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0) und anschließend price = 1.0001 ** tick. Siehe algorithms/clmm-math.
DynamicFeeConfig und DynamicFeeInfo
Dynamische Gebührenparameter befinden sich an zwei Stellen. Die wiederverwendbare Vorlage — DynamicFeeConfig — wird vom Admin verwaltet und von Pools geteilt, die sich anmelden. Der Pool-spezifische Laufzeitzustand — DynamicFeeInfo — ist in PoolState eingebettet und wird bei jedem Swap aktualisiert.
DynamicFeeConfig
["dynamic_fee_config", index.to_be_bytes()]. Wird über create_dynamic_fee_config (Admin-gesperrt) erstellt und über update_dynamic_fee_config geändert. Ein Pool, der mit enable_dynamic_fee = true erstellt wird, übernimmt die fünf Kalibrierungsparameter (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator) bei der Erstellung in seine eigene DynamicFeeInfo; spätere Änderungen am DynamicFeeConfig wirken sich nicht rückwirkend auf bestehende Pools aus.
DynamicFeeInfo (eingebettet in PoolState)
DynamicFeeConfig kopiert wurden. Die Gebührenberechnung und die Decay-Regeln sind unter products/clmm/math und products/clmm/fees dokumentiert.
Von der Formel verwendete Konstanten:
LimitOrderState
Einer pro offener Limit-Order.
- Eröffnen — Der Nutzer ruft
open_limit_orderauf, hinterlegttotal_amountdes Input-Tokens; die Order wird an eineTickState-Kohorte gebunden. - (optional) Erhöhen / Verringern —
increase_limit_ordererhöhttotal_amount;decrease_limit_ordergibt ungefüllte Token zurück (und jeden bis dahin abgerechneten Output). - Abrechnen — Wenn die Kohorte vollständig oder teilweise gefüllt ist, ruft der Inhaber oder der operationale Keeper
settle_limit_orderauf, um Output-Token an das ATA des Inhabers zu übertragen. - Schließen — Sobald
unfilled_amount == 0, kann der Account geschlossen werden. Die Miete geht immer anownerzurück.
[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]. Der Order-PDA ist daher eindeutig pro (owner, nonce_index, order_nonce).
LimitOrderNonce
Pro-(wallet, nonce_index)-Zähler, der es einem einzelnen Nutzer ermöglicht, mehrere parallele Pipelines von Limit-Orders zu betreiben, ohne PDA-Kollisionen zu verursachen.
[user_wallet.as_ref(), &[nonce_index]]. Die meisten Clients verwenden nonce_index = 0 und lassen order_nonce die Kardinalität tragen.
Ableitung der wichtigsten Accounts
reference/program-addresses gegengeprüft werden.
Kurzreferenz Lebenszyklus
TickArrayState-Accounts werden vom Programm nie geschlossen — sie bleiben für die gesamte Lebensdauer des Pools bestehen. Einmal initialisiert, verbleibt ein Tick-Array on-chain, auch wenn jeder darin enthaltene Tick wieder liquidity_gross == 0 erreicht. Die Wiederverwendung eines bestehenden Tick-Arrays ist kostenlos; nur die erste Position, die ein noch nie initialisiertes Array berührt, übernimmt dessen Miete.
Was wo nachzulesen ist
- Tick-Mathematik und Bereichsmechanik:
products/clmm/ticks-and-positions. - Swap-Walk und Fee-Growth-Mathematik:
products/clmm/math. - Instruction-Account-Listen:
products/clmm/instructions. - Gebühren und Reward-Ansammlung:
products/clmm/fees. - Kanonische Programm-IDs und Seeds:
reference/program-addresses.

