Bu sayfa yapay zekâ tarafından otomatik olarak çevrilmiştir. İngilizce sürüm esas alınır.İngilizce sürümü görüntüle →
Bu sayfa işlevseldir: CLMM programı tarafından kullanılan formülleri, sabit-nokta kurallarını ve adım-adım işlemleri verir. Yoğunlaştırılmış likidite eğrisinin arkasındaki mantık — neden
L = sqrt(x · y) önemli — için bkz. algorithms/clmm-math. Bu sayfa, o sayfayı okuduğunuzu varsayar.Sqrt-fiyat gösterimi
CLMM, fiyatısqrt_price_x64 olarak depolar — token1-başına-token0 fiyatının karekökü, Q64.64 sabit-nokta sayısı olarak:
burada p = token1_amount / token0_amount. sqrt yerine p ile çalışmak swap matematiğini doğrusallaştırır (token-miktar deltaları Δsqrt_price içinde doğrusal hale gelir) ve x64 sabit-nokta, çok-tick swaplar boyunca kesinliği korur.
Tick ↔ sqrt-fiyat dönüşümü, bit-by-bit log-yaklaşımı aracılığıyla önceden hesaplanır:
tick_math::get_sqrt_price_at_tick içinde arama tabanlı üstel alma olarak uygulanır.
Likidite kanonik bir birim olarak
[sqrt_a, sqrt_b] aralığında (sqrt_a < sqrt_b ile) likidite L konumu, token miktarlarına aşağıdaki gibi eşlenir. sqrt_c = sqrt_price_x64 havuzun mevcut fiyatı olsun.
Üç kimlik de yoğunlaştırılmış likiditenin bir aralık içinde sağladığı
x = L / sqrt_p, y = L · sqrt_p değişmezinden gelir.
Entegratörler tipik olarak tersi isterler: amount0 / amount1 yatırımı verildiğinde, aralığa sığan maksimum L hesaplayın. SDK’nın LiquidityMath.getLiquidityFromTokenAmounts bunu yapar. Aralık içi durum için formül:
Hangi taraf bağlı olursa, gerçekten tüketilen oranı belirler; diğer taraf artabilir.
Tek-tick swap adımı
Bir swap adımlar halinde ilerler. Her adım ya (a) mevcut tick aralığında tüm mevcut girişi tick geçmeden tüketir, ya da (b) fiyatı tam olarak sonraki başlatılmış tike taşır. Mevcut durum(sqrt_c, L) ve aşağı swap (token0 giriş, token1 çıkış, sqrt_price azalır — fiyat token1/token0 olarak kote edilir, bu nedenle token0 eklemek onu düşürür) verildiğinde, aşağıdaki sonraki başlatılmış tick sqrt_t < sqrt_c konumunda oturur. Bu mikro-aralık içinde giriş ve fiyat arasındaki ilişki:
ve
Bir token1-giriş swapi ayna görüntüsüdür: sqrt_price sonraki üst tike doğru yükselir ve iki formül hangi uç noktanın çıkarıldığını değiştirir. Program yönü zero_for_one olarak kodlar (true giriş mint’i token_mint_0 olduğunda) ve bir zero_for_one swapi MIN_SQRT_PRICE_X64 doğru sınırlar.
Program iki şeyden birini yapar:
-
Tüm giriş sığar mı? Kalan giriş (ücret sonrası)
sqrt_tulaşmak içinΔamount0değerinden azsa, yenisqrt_c'tam olarak çözün: (tam-giriştoken0 → token1swapi için). Swap bu adımda tick geçmeden tamamlanır. -
Giriş
Δamount0aşar mı?sqrt_c' = sqrt_tayarlayın, tiki geçin (liquidity_netuygulayın), kalan girişiΔamount0kadar azaltın, çıkışıΔamount1kadar artırın ve tekrarlayın.
token1 → token0, fiyat düşüyor), formüllerin sqrt_c ve sqrt_t değiştirilmiş ve ters diğer yuvada.
Tam Rust uygulaması raydium-clmm/programs/amm/src/libraries/swap_math.rs içinde yaşar. Oradaki mantık Uniswap v3’ün SwapMath.computeSwapStep ile bire bir eşleşir.
Her adımda ücretler
İşlem ücretleri her adımda giriş miktarından alınır, CPMM ile aynı kural:L_i boyutundaki bir konum daha sonra L_i · Δfee_growth_global / 2^{64} borçlu token okuyacaktır.
Protocol ve fund kısımları sırasıyla PoolState.protocol_fees_token_{0,1} ve PoolState.fund_fees_token_{0,1} birikir, CPMM ile aynı. CollectProtocolFee / CollectFundFee tarafından temizlenir.
Aralık dışında ve içinde ücret büyümesi
CLMM ücret muhasebesi zor kısım: bir konum yalnızca havuzun fiyatı aralığı içinde olduğu sürece ücret kazanır. Havuz kümülatif ücretleri genel olarak izler; konum, kümülatif ücretleri belirli aralığı içinde bilmesi gerekir. Çözüm bir tick tabanlı biriktiricdir. Her tick depolar:- Havuzun fiyatı bu tik üstünde ise (
tick_current >= this_tick),fee_growth_outside = fee_growth_global. (Şimdiye kadar kazanılan her şey bu tike göre “dışında” — yani aşağıda — mevcut fiyata göre.) - Aksi takdirde
fee_growth_outside = 0.
fee_growth_outside değerini çevirir:
Bu korunan değişmez: herhangi bir tick t için, fee_growth_outside(t) tick_current t nin ters tarafında olduğu sürece tahakkuk eden ücretlere eşittir.
[tick_lower, tick_upper] aralığında ücret büyümesi daha sonra türetilir:
Bir konum ne depolar ve ne okur
BirPersonalPositionState fee_growth_inside_0_last_x64 ve fee_growth_inside_1_last_x64 depolar: konumun son dokunuşunun zamanındaki fee_growth_inside değerleri.
Sonraki herhangi bir dokunuşta (artırma, azaltma, toplama), program:
- Yukarıdaki formülü kullanarak mevcut
fee_growth_inside_{0,1}_x64hesaplar. Δ = fee_growth_inside_now − fee_growth_inside_lasthesaplar (u128 üzerinde modüler-çıkarma).Δ × position.liquidity / 2^{64}değerinitokens_fees_owed_{0,1}öğesine ekler.fee_growth_inside_lastöğesini yeni değere günceller.
CollectFees / DecreaseLiquidity üzerinde tokens_fees_owed karşılığında çıkar.
Ödüller
Havuzun 3’e kadar ödül akışının her biri, kendireward_growth_global_x64 biriktiricisinde aynı büyüme-içi mekanikasını kullanır. Emisyon zamanında:
— emisyonlar aktif likidite ile ters orantılı ölçeklenir, bu nedenle daha yoğun bir havuz her konuma saniye başına orantılı olarak daha az öder, ancak toplamda daha fazla konuma. Konum başına ödül borçlu
ve DecreaseLiquidity / DecreaseLiquidityV2 tarafından ödenir — bağımsız bir toplama-ödül talimatı yoktur. Bkz. products/clmm/fees.
Çalışılmış örnek: tam-giriş swapi
Varsayalım:tick_spacing = 60sqrt_price_x64 = 1 × 2^{64}— fiyat = 1.0, bu nedenletick_current = 0.- Aktif likidite
L = 1_000_000 × 2^{64}. - Aşağıdaki sonraki başlatılmış tick:
t = −60(sqrt_price_b ≈0.997005 × 2^{64}). Bir token0-giriş swapi aşağı hareket eder, bu nedenle üst tick burada ilgisizdir. - İşlem ücreti oranı: 500 (0.05%).
SwapBaseInput tam-giriş 1.000 token0.
Adım 1 — ücretler:
999 < 3004.4, bu nedenle tüm giriş tiki geçmeden sığar.
Adım 3 — yeni fiyat:
sqrt_c' sqrt_c altında iner, bu doğru yöndür: bir token0 → token1 swapi havuza token0 ekler ve bu nedenle token1/token0 fiyatını düşürür.
Adım 4 — çıkış miktarı:
trade_fee_rate × protocol_fee_rate / 1e6 tarafından LP, protocol ve fund arasında bölünür (fund için de benzer); LP kısmı fee_growth_global_0_x64 içine akar.
Swap sırasında limit-order eşleştirmesi
Bir swap adımı açık limit emirleri tutan bir tiki geçtiğinde, bu emirler swap girişini LP eğrisinden önce tik’in tam fiyatında tüketir. Eşleştirme, tik içindeorder_phase kohortuna göre FIFO’dur.
TickState üzerinde kohort başına durum
orders_amount öğesine katılır ve sonraki order_phase öğesini devralır; önceki kohort tam olarak tüketilene kadar dolduramaz.
Eşleştirme adımı
Swap sırasında her tick geçişinde gerçekleşen eşleştirme için sözde kod:SettleLimitOrder (veya DecreaseLimitOrder) çağırana kadar havuzun çıkış kasasında neredeyse oturur. Havuz, unfilled_ratio_x64 aracılığıyla kohortun ne kadarının doldurulduğunu izler. Her LimitOrderState açılış zamanında kendi (order_phase, unfilled_ratio_x64) anlık görüntüsünü depolar, bu nedenle yerleşim şu şekilde azalır:
LP eğrisi ile etkileşim
Bir swap adımında, limit-order eşleştirmesi tik konumunda (sıfırΔsqrt_price) gerçekleşir; LP eğrisi tüketimi tiklerin arasında gerçekleşir. Sıra bu nedenle:
- Tiki
t_crossgeçin (LPliquidity_netdeğişikliğini ilk olarak uygulayın, çünkü Uniswap-V3 bunu yapar). t_crosskonumunda oturan herhangi bir limit emrini doldurun.- LP eğrisi boyunca sonraki başlatılmış tike veya
swap_inputtükenişine devam edin.
Dinamik ücret türetmesi
PoolState.dynamic_fee_info volatilite durumunu taşır. Her swap adımı, adım başına ücret oranını şu şekilde hesaplar:
burada:
- —
DYNAMIC_FEE_CONTROL_DENOMINATOR - —
VOLATILITY_ACCUMULATOR_SCALE vol_accaşağıdaki güncelleme kuralından sonra swap başına biriktiricdirtick_spacingPoolState.tick_spacingöğesinden gelir
Biriktiricinin güncellenmesi
İki kural her swap’ta sırayla uygulanır: Bozunma. Referans taban, son güncelleme zamanından bu yana geçen zamana göre bozunur: Birikme. Yeni biriktiriciler referans artı önceki referans dizininden bu yana geçilen tick-mesafesidir:tick_spacing_index_reference () ham tiklerde değil, tick-aralığı birimlerindedir: .
Neden tick mesafesinde parabolik
Biriktiricinin karesini almak, ücretin fiyatın referans noktasından ne kadar uzağa yürüdüğünün karesi olarak yükseldiği anlamına gelir. Ampirik olarak bu, rastgele yürüyüş basıncı altında fiyatın varyans ölçeklemesiyle eşleşir: 2× tick sapması 4× ima edilen volatilite anlamına gelir, bu nedenle 4× ek ücret alır.dynamic_fee_control parametresi mutlak seviyeyi kalibre eder.
filter_period penceresi, küçük alt-saniye salınımlarının (örn. MEV botları sandviç yapması) biriktiricisini şişirmesini engeller. decay_period penceresi, tek bir geçmiş artışın pazar sakinleştikten sonra ücretleri süresiz olarak almasını engeller.
Sayısal sağlamlık
- Tüm ara ürünler
u128veyau256şeklindeki aritmetik aracılığıyla gider. CLMM,U128Sqrtyardımcılarını veFullMath::mulDivkalıplarını doğrudan Uniswap v3’ten taşır. - Bölme yuvarlama, değişmez
k' ≥ kyerel olarak uygulamak için adım başına seçilir.SwapBaseInputçıkışı aşağı yuvarlar;SwapBaseOutputgirişi yukarı yuvarlar. PoolState.liquidityöğesini sıfıra düşüren tick geçişlerine izin verilir (fiyat bir “likidite deliği” arasında geçebilir) ancak swap basitçe giriş tüketmeden sonraki başlatılmış tike ilerler, ücret almaz.- Taşma koruması:
sqrt_price_x64[MIN_TICK, MAX_TICK]öğesine karşılık gelen[MIN_SQRT_PRICE_X64, MAX_SQRT_PRICE_X64]kapsayıcı aralığında tutulur. Her iki sınırı da geçecek bir swapSqrtPriceLimitOverflowile geri döner.
Sonra nereye gitmeli
products/clmm/ticks-and-positionstick haritasının yürüyüşe nasıl katıldığı için.products/clmm/feesücret/ödül tarafının matematiği ayrıntılı olarak.algorithms/clmm-mathL = sqrt(x · y)ve aralık-vs-likidite formülleri arkasındaki türetmeler için.
raydium-io/raydium-clmm—libraries/swap_math.rs,libraries/tick_math.rs- “Uniswap v3 Core” teknik raporu, §6–7

