Documentation Index
Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
Use this file to discover all available pages before exploring further.
Esta página fue traducida automáticamente por IA. La versión en inglés es la fuente autorizada.Ver versión en inglés →
Representación de precio raíz
CLMM almacena el precio comosqrt_price_x64 — la raíz cuadrada del precio de token1 por token0, como un número de punto fijo Q64.64:
donde p = token1_amount / token0_amount. Trabajar en sqrt en lugar de p linealiza las matemáticas de swap (los deltas de cantidad de tokens se vuelven lineales en Δsqrt_price), y el punto fijo x64 mantiene precisión a través de swaps multi-tick.
La conversión tick ↔ precio raíz se precomputa mediante una aproximación logarítmica bit-por-bit:
implementada como una exponenciación basada en búsqueda en tick_math::get_sqrt_price_at_tick.
Liquidity como unidad canónica
Dentro de un rango[sqrt_a, sqrt_b] (con sqrt_a < sqrt_b), una posición de liquidity L se mapea a cantidades de tokens de la siguiente manera. Sea sqrt_c = sqrt_price_x64 el precio actual del pool.
| Caso | amount0 | amount1 |
|---|---|---|
sqrt_c <= sqrt_a (precio del pool por debajo del rango) | L · (sqrt_b - sqrt_a) / (sqrt_a · sqrt_b) | 0 |
sqrt_a < sqrt_c < sqrt_b (dentro del rango) | L · (sqrt_b - sqrt_c) / (sqrt_c · sqrt_b) | L · (sqrt_c - sqrt_a) |
sqrt_c >= sqrt_b (precio del pool por encima del rango) | 0 | L · (sqrt_b - sqrt_a) |
x = L / sqrt_p, y = L · sqrt_p que la liquidity concentrada satisface dentro de un rango.
Los integradores típicamente quieren la inversa: dada una aportación de amount0 / amount1, calcular el máximo L que cabe en el rango. El método LiquidityMath.getLiquidityFromTokenAmounts del SDK hace esto. La fórmula para el caso dentro del rango:
Cualquiera que sea el lado que se limite determina la ratio realmente consumida; el otro lado puede tener sobrante.
Paso de swap de un tick
Un swap procede en pasos. Cada paso (a) consume toda la entrada disponible dentro del rango de tick actual sin cruzar un tick, o (b) mueve el precio exactamente al siguiente tick inicializado. Dado el estado actual(sqrt_c, L) y un swap hacia arriba (token0 entra, token1 sale, sqrt_price aumenta), la distancia al siguiente tick inicializado es sqrt_t. Dentro de este micro-intervalo, la relación entre entrada y precio es:
y
El programa hace una de dos cosas:
-
¿Cabe toda la entrada? Si la entrada restante (después de comisión) es menor que
Δamount0para llegar asqrt_t, resuelve el nuevosqrt_c'exactamente: (para un swap exacto de entradatoken0 → token1). El swap se completa en este paso sin cruzar un tick. -
¿La entrada excede
Δamount0? Establecesqrt_c' = sqrt_t, cruza el tick (aplicaliquidity_net), decrementa la entrada restante porΔamount0, incrementa la salida porΔamount1y repite.
token1 → token0, precio bajando), las fórmulas tienen sqrt_c y sqrt_t intercambiados e invertidos en el otro slot.
La implementación completa en Rust se encuentra en raydium-clmm/programs/amm/src/libraries/swap_math.rs. La lógica ahí coincide uno-a-uno con SwapMath.computeSwapStep de Uniswap v3.
Comisiones en cada paso
Las comisiones comerciales se toman de la cantidad de entrada en cada paso, con la misma convención que CPMM:L_i que permaneció dentro del rango durante este swap lea después L_i · Δfee_growth_global / 2^{64} tokens adeudados.
Las porciones de protocolo y fondo se acumulan en PoolState.protocol_fees_token_{0,1} y PoolState.fund_fees_token_{0,1} respectivamente, idéntico a CPMM. Se barren mediante CollectProtocolFee / CollectFundFee.
Crecimiento de comisiones fuera y dentro
La parte complicada de la contabilidad de comisiones en CLMM: una posición gana comisiones solo mientras el precio del pool está dentro de su rango. El pool rastrea comisiones cumulativas globalmente; la posición necesita conocer las comisiones cumulativas mientras está dentro de su rango específico. La solución es un acumulador basado en ticks. Cada tick almacena:- Si el precio del pool está por encima de este tick (
tick_current >= this_tick),fee_growth_outside = fee_growth_global. (Todo lo ganado hasta ahora está “afuera” — es decir, por debajo de — este tick, relativo al precio actual.) - En caso contrario
fee_growth_outside = 0.
fee_growth_outside de ese tick:
El invariante que esto preserva: para cualquier tick t, fee_growth_outside(t) es igual a las comisiones que se acumularon mientras tick_current estuvo en el lado opuesto de t.
Crecimiento de comisiones dentro de un rango [tick_lower, tick_upper] se deriva entonces:
Qué almacena una posición y qué lee
UnPersonalPositionState almacena fee_growth_inside_0_last_x64 y fee_growth_inside_1_last_x64: los valores de fee_growth_inside la última vez que se tocó la posición.
En cualquier toque posterior (aumentar, disminuir, recopilar), el programa:
- Calcula el
fee_growth_inside_{0,1}_x64actual usando la fórmula anterior. - Calcula
Δ = fee_growth_inside_now − fee_growth_inside_last(resta modular en u128). - Suma
Δ × position.liquidity / 2^{64}atokens_fees_owed_{0,1}. - Actualiza
fee_growth_inside_lastal nuevo valor.
CollectFees / DecreaseLiquidity, contra tokens_fees_owed.
Recompensas
Cada uno de los hasta 3 flujos de recompensa del pool usa la misma maquinaria de crecimiento dentro del rango, en su propio acumuladorreward_growth_global_x64. En el momento de emisión:
— las emisiones escalan inversamente con la liquidity activa, así que un pool más denso paga a cada posición proporcionalmente menos por segundo, pero en más posiciones totales. La recompensa por posición adeudada es
y se reclama mediante CollectReward. Ver products/clmm/fees.
Ejemplo práctico: swap de entrada exacta
Supongamos:tick_spacing = 60sqrt_price_x64 = 1 × 2^{64}— precio = 1.0, así quetick_current = 0.- Liquidity activa
L = 1_000_000 × 2^{64}. - Siguiente tick inicializado arriba:
t = 60(sqrt_price_b ≈1.003004 × 2^{64}). - Tasa de comisión comercial: 500 (0.05%).
SwapBaseInput entrada exacta de 1,000 token0.
Paso 1 — comisiones:
999 < 2995.5, así que toda la entrada cabe sin cruzar el tick.
Paso 3 — nuevo precio:
sqrt_c' ligeramente por debajo de sqrt_c. Nota que la fórmula anterior es para un swap token1 → token0. El ejemplo aquí es token0 → token1, que impulsa el precio hacia arriba, no hacia abajo — así que usamos la forma correspondiente para token0 dentro:
token0 → token1: sqrt_c sube junto con el precio.)
Paso 4 — cantidad de salida:
trade_fee_rate × protocol_fee_rate / 1e6 (y similar para fondo); la porción de LP fluye hacia fee_growth_global_0_x64.
Coincidencia de órdenes de límite durante swap
Cuando un paso de swap cruza un tick que contiene órdenes de límite abiertas, esas órdenes consumen la entrada del swap antes de que lo haga la curva de LP, al precio exacto del tick. La coincidencia es FIFO dentro del tick por cohorte deorder_phase.
Estado por cohorte en TickState
orders_amount y heredan el siguiente order_phase; no pueden completarse hasta que la cohorte anterior se consume completamente.
Paso de coincidencia
Pseudo-código para la coincidencia que ocurre en cada cruce de tick durante un swap:SettleLimitOrder (o DecreaseLimitOrder). El pool simplemente rastrea cuánto de la cohorte se llena ahora mediante unfilled_ratio_x64. Cada LimitOrderState almacena su propia instantánea de (order_phase, unfilled_ratio_x64) en el momento de apertura, así que la liquidación se reduce a:
Interacción con la curva de LP
En un paso de swap, la coincidencia de órdenes de límite ocurre en el tick (ceroΔsqrt_price); el consumo de la curva de LP ocurre entre ticks. El orden es por lo tanto:
- Cruza tick
t_cross(aplica el cambio de LPliquidity_netprimero, ya que así es como Uniswap-V3 lo hace). - Complete cualquier orden de límite que esté en
t_cross. - Continúa a lo largo de la curva de LP al siguiente tick inicializado o al agotamiento de
swap_input.
Derivación de comisión dinámica
PoolState.dynamic_fee_info lleva el estado de volatilidad. Cada paso de swap calcula la tasa de comisión por paso como:
donde:
- —
DYNAMIC_FEE_CONTROL_DENOMINATOR - —
VOLATILITY_ACCUMULATOR_SCALE vol_acces el acumulador por swap después de la regla de actualización abajotick_spacinges dePoolState.tick_spacing
Actualización del acumulador
Se aplican dos reglas cada swap, en orden: Decaimiento. El piso de referencia decae basado en el tiempo desde la última actualización: Acumular. El nuevo acumulador es la referencia más la distancia de tick recorrida desde el índice de referencia anterior:tick_spacing_index_reference () está en unidades de espaciamiento de tick, no ticks sin procesar: .
Por qué parabólica en distancia de tick
Elevar al cuadrado el acumulador significa que la comisión sube como el cuadrado de qué tan lejos el precio ha caminado desde su punto de referencia. Empíricamente esto coincide con el escalado de varianza del precio bajo presión de paseo aleatorio: una excursión de tick 2× implica 4× la volatilidad implícita, así que carga 4× el recargo. El parámetrodynamic_fee_control calibra el nivel absoluto.
La ventana filter_period evita que minúsculas oscilaciones sub-segundo (por ejemplo, bots de MEV haciendo sándwich) inflen el acumulador. La ventana decay_period evita que un pico pasado único cobre comisiones indefinidamente después de que el mercado se ha calmado.
Robustez numérica
- Todos los productos intermedios pasan por aritmética de forma
u128ou256. CLMM usa auxiliaresU128Sqrty patronesFullMath::mulDivdirectamente portados de Uniswap v3. - El redondeo de división se elige por paso para reforzar el invariante
k' ≥ klocalmente.SwapBaseInputredondea la salida hacia abajo;SwapBaseOutputredondea la entrada hacia arriba. - Los cruces de tick que reducen
PoolState.liquiditya cero se permiten (el precio puede atravesar un “agujero de liquidity”), pero el swap simplemente avanza al siguiente tick inicializado sin consumir entrada, sin cobrar comisión. - Guardia de desbordamiento:
sqrt_price_x64se mantiene en el rango inclusivo[MIN_SQRT_PRICE_X64, MAX_SQRT_PRICE_X64]correspondiente a[MIN_TICK, MAX_TICK]. Un swap que empujaría más allá de cualquiera de los límites revierte conSqrtPriceLimitOverflow.
Qué sigue
products/clmm/ticks-and-positionspara cómo el mapa de ticks participa en la caminata.products/clmm/feespara el lado de comisión/recompensa de las matemáticas en detalle.algorithms/clmm-mathpara las derivaciones detrás deL = sqrt(x · y)y las fórmulas de rango versus liquidity.
raydium-io/raydium-clmm—libraries/swap_math.rs,libraries/tick_math.rs- Documento técnico “Uniswap v3 Core”, §6–7


