Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.Englische Version ansehen →
Diese Seite fasst die Herleitungen hinter CLMM zusammen. Für die On-Chain-Implementierung siehe
products/clmm/math (das diese Seite zitiert) und products/clmm/ticks-and-positions (das das Tick-Gitter motiviert).Warum sqrt-price statt price
CLMMs der Uniswap-v3-Familie stellen den Preis als Quadratwurzel dar, gespeichert in einem Fixed-Point-FormatQ64.64:
- Lineare Liquiditätsmathematik. Die Menge von Token0 oder Token1 in einem Preisbereich ist eine lineare Funktion von
sqrt_price, nicht vonprice. Die Speicherung vonsqrt_priceermöglicht es dem Swap-Schritt, diese linearen Formeln auszuwerten, ohne eine Quadratwurzel zu berechnen. - Overflow-Kontrolle.
sqrt_price · Lpasst inu256für alle vernünftigen Parameter;price · Lkann viel früher überlasten. - Tick-Mathematik ist einheitlich. Da Ticks als
1.0001^idefiniert sind, istsqrt(price) = (√1.0001)^i ≈ 1.00005^iauch eine exakte geometrische Leiter. (√1.0001 = 1.00004999875…, daher driftet die Behandlung als exakt1.00005um bis zu ~0,6% beiMAX_TICK.) Jeder Tick-Übergang entspricht einer kleinen Multiplikation imsqrt_price_x64-Raum.
price = (sqrt_price_x64 / 2^64)^2.
Tick-Gitter
Preise werden auf ein Gitter diskretisiert:tick_i ist ein i32. Der aktive Bereich ist [MIN_TICK, MAX_TICK] = [−443636, 443636], was einen Preisbereich von ungefähr [2^−64, 2^64] ergibt — etwa 5,4e-20 bis 1,8e19. Der tick_spacing jedes Pools wird durch seinen Fee-Tier festgelegt: kleinere Abstände für enge Paare (z. B. Stablecoin-0,01%-Tier verwendet Abstand 1), größere Abstände für volatile Paare (0,25%-Tier verwendet 60, 1%-Tier verwendet 120).
Positionen müssen tick_lower und tick_upper an tick_spacing ausgerichtet haben. Die aktiven Ticks eines Pools (diejenigen mit Liquidität, die dort beginnt oder endet) sind die einzigen Ticks, die der Swap-Schritt berücksichtigt.
Liquidität-zu-Betrag
Für eine Position mit LiquiditätL und Preisbereich [sqrt_lo, sqrt_hi] (alle sqrt_price-Werte):
Herleitung: Differenzieren Sie die CPMM-Invariante lokal. Innerhalb eines einzelnen Tick-Bereichs verhält sich die Position wie ein CPMM mit virtuellen Reserven
(x_v, y_v), die so gewählt sind, dass der aktuelle (sqrt_p, L) des Pools mit L = sqrt(x_v · y_v) konsistent ist. Die Integration von sqrt_p zur Bereichsgrenze ergibt die obigen Beträge.
Inverse Formeln (verwendet beim Prägen einer Position für einen gegebenen amount0 oder amount1):
Single-Tick-Swap-Schritt
Innerhalb eines einzelnen Tick-Bereichs verhält sich der Pool wie ein CPMM. Gegeben aktuellessqrt_p und Ziel sqrt_target:
Exact-Input-Schritt
GegebenΔin_remaining:
0→1-Swap senkt sqrt_p (der Preis sinkt, wenn wir Token0 verkaufen). Ein 1→0-Swap hebt ihn an. Die Formeln sind symmetrisch mit sqrt_p und sqrt_target vertauscht.
Exact-Output-Schritt
Gleiche Struktur, lösen Sie stattdessen fürΔin.
Multi-Tick-Swap-Schleife
Ein Swap iteriert über Ticks, bis die Eingabe erschöpft ist oder das Preislimit erreicht wird:single_step verwendet die aktuelle L des Pools. L ändert sich nur beim Überqueren eines initialisierten Ticks. Die Liquidität zwischen Ticks ist konstant, was die Schritt-Mathematik geschlossen macht.
liquidity_net bei einem Tick ist die vorzeichenbehaftete Summe der Positionsliquiditäten, die bei diesem Tick beginnen, minus denen, die dort enden. Das Überqueren nach oben addiert liquidity_net; das Überqueren nach unten subtrahiert es.
Wenn der Pool Limit-Orders bei einem Tick offen hat, verbraucht der Cross-Tick-Schritt auch opportunistisch einen Teil der Swap-Eingabe, um diese Orders zu erfüllen (FIFO über Kohorten). Der Matching-Algorithmus und der dynamische Fee-Zuschlag, der möglicherweise zusätzlich zum Basis-Schritt anfällt, sind in products/clmm/math dokumentiert; sie ändern die geschlossenen Single-Step-Formeln oben nicht.
Fee-Growth-Akkumulatoren
CLMM verfolgt Gebühren pro Einheit aktiver Liquidität, pro Seite, global und pro Tick:single_step:
fee_growth_global der anderen Seite bewegt sich bei diesem Schritt nicht, da kein Token auf dieser Seite als Eingabe bezahlt wurde.)
Beim Überqueren eines Ticks flippt das Programm fee_growth_outside:
tick_current. Wenn tick_current über dem Tick liegt, bedeutet außen „darunter”. Wenn tick_current darunter liegt, bedeutet außen „darüber”. Der Flip tauscht die Interpretation.
fee_growth_inside für eine Position
Gegeben eine Position [tick_lower, tick_upper] und das aktuelle tick_current:
s sind:
IncreaseLiquidity, DecreaseLiquidity, CollectFees).
Durchgerechnetes Beispiel — einen Tick überqueren
Pool (vereinfacht):sqrt_p_x64 = 2^64 · 1.0 = 2^64(Preis = 1,0)L = 1_000_000tick_current = 0- Nächster initialisierter Tick darunter:
tick = −60,sqrt_price = 1.0001^(−30) ≈ 0,99700,liquidity_net = −400_000(dieser Tick beendet eine Position, daher entfernt ein Abwärts-Übergang 400k) - Fee-Rate: 0,25%
Δin = 10_000 Token0, Richtung = 0→1.
Schritt 1 — bis sqrt_target = 0,99700 · 2^64:
L = 600_000:
Der nächste initialisierte Tick (sagen wir tick = −120) liegt bei sqrt = 0,99402. Berechnen Sie amount_in_to_target neu:
Δin_remaining. Überqueren Sie erneut. Fahren Sie fort, bis Δin_remaining null erreicht.
Die vollständige Abfolge von Δout akkumuliert zur endgültigen Swap-Ausgabe.
Initialisierung und Overflow-Schutz
MIN_SQRT_PRICE_X64undMAX_SQRT_PRICE_X64entsprechentick = ±443636. Jeder Swap, dersqrt_paußerhalb dieses Bereichs drücken würde, wird rückgängig gemacht.- Der
sqrt_price_limit-Parameter des Benutzers muss im gleichen Intervall liegen; das Programm prüft dies. - Produkte von
L · Δsqrtwerden inu256berechnet und dann aufu128verschoben, um Overflow zu vermeiden.
Unterschiede zu Uniswap v3
- Oracle. Raydiums
ObservationState-Ringpuffer speichert nur(block_timestamp: u32, tick_cumulative: i64)pro Slot plus[u64; 4]reserviertes Padding — es gibt keinseconds_per_liquidity_cumulative-Feld, daher sind Uniswaps liquiditätsgewichtete Ableitungen nicht on-chain verfügbar. - Token-2022. Raydium CLMM unterstützt Token-2022-Mints; die Transfer-Fee-Variante erfordert zusätzliche Pre/Post-Swap-Anpassungen. Siehe
algorithms/token-2022-transfer-fees. - Tick-Bitmap. Raydium packt die initialisierte-Tick-Bitmap in
[u64; 16]pro Pool für schnellefind_next_initialized_tick; Uniswap verwendet eine Pro-Wort-On-Chain-Zuordnung. Der Tradeoff ist Miete vs. Lookup-Kosten. - Reward-Slots. Raydium unterstützt 3 Pro-Pool-Reward-Streams mit separaten
reward_growth_global_x64-Zählern; gleiche Struktur wie der Fee-Growth-Akkumulator.
Verweise
products/clmm/math— die On-Chain-Implementierung und durchgerechnetes Beispiel mit tatsächlichen CLMM-Struct-Feldern.products/clmm/ticks-and-positions— Tick-Gitter,liquidity_net/gross, Semantik des aktiven Bereichs.products/clmm/fees— der Fee-Growth-Akkumulator in Aktion.
- Uniswap v3 Whitepaper (kanonische Herleitung der sqrt-price-Mathematik).
- Raydium CLMM Programmquelle.

