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 foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
Representação de sqrt-price
O CLMM armazena o preço comosqrt_price_x64 — a raiz quadrada do preço de token1 por token0, como um número de ponto fixo Q64.64:
onde p = token1_amount / token0_amount. Trabalhar em sqrt em vez de p lineariza a matemática do swap (os deltas de quantidade de token se tornam lineares em Δsqrt_price), e o x64 de ponto fixo preserva a precisão ao longo de muitos ticks.
A conversão de tick para sqrt-price é pré-computada via uma aproximação de log bit-by-bit:
implementada como uma exponenciação baseada em lookup em tick_math::get_sqrt_price_at_tick.
Liquidity como unidade canônica
Dentro de um intervalo[sqrt_a, sqrt_b] (com sqrt_a < sqrt_b), uma posição de liquidity L mapeia para quantidades de token da seguinte forma. Seja sqrt_c = sqrt_price_x64 o preço atual do pool.
| Caso | amount0 | amount1 |
|---|---|---|
sqrt_c <= sqrt_a (preço do pool abaixo do intervalo) | L · (sqrt_b - sqrt_a) / (sqrt_a · sqrt_b) | 0 |
sqrt_a < sqrt_c < sqrt_b (no intervalo) | L · (sqrt_b - sqrt_c) / (sqrt_c · sqrt_b) | L · (sqrt_c - sqrt_a) |
sqrt_c >= sqrt_b (preço do pool acima do intervalo) | 0 | L · (sqrt_b - sqrt_a) |
x = L / sqrt_p, y = L · sqrt_p que a liquidity concentrada satisfaz dentro de um intervalo.
Integradores normalmente querem o inverso: dada uma deposição de amount0 / amount1, calcular o máximo L que cabe no intervalo. O método LiquidityMath.getLiquidityFromTokenAmounts do SDK faz isso. A fórmula para o caso no intervalo:
Qual lado se vincular determina a proporção realmente consumida; o outro lado pode ter sobra.
Etapa de swap de um único tick
Um swap segue em etapas. Cada etapa (a) consome toda a entrada disponível dentro do intervalo de tick atual sem cruzar um tick, ou (b) move o preço exatamente para o próximo tick inicializado. Dado o estado atual(sqrt_c, L) e um swap para cima (token0 entra, token1 sai, sqrt_price aumenta), a distância até o próximo tick inicializado é sqrt_t. Dentro deste micro-intervalo, a relação entre entrada e preço é:
e
O programa faz uma de duas coisas:
-
A entrada inteira cabe? Se a entrada restante (após taxa) for menor que
Δamount0para alcançarsqrt_t, resolva o novosqrt_c'exatamente: (para um swap exato de entradatoken0 → token1). O swap se completa nesta etapa sem cruzar um tick. -
A entrada excede
Δamount0? Definasqrt_c' = sqrt_t, cruze o tick (apliqueliquidity_net), decremente a entrada restante porΔamount0, incremente a saída porΔamount1e repita.
token1 → token0, preço descendo), as fórmulas têm sqrt_c e sqrt_t trocados com a inversão no outro slot.
A implementação completa em Rust está em raydium-clmm/programs/amm/src/libraries/swap_math.rs. A lógica lá corresponde um-a-um com o SwapMath.computeSwapStep da Uniswap v3.
Taxas em cada etapa
As taxas de negociação são extraídas do montante de entrada em cada etapa, mesma convenção do CPMM:L_i que permaneceu no intervalo durante este swap mais tarde lerá L_i · Δfee_growth_global / 2^{64} tokens devidos.
As porções de protocolo e fundo se acumulam em PoolState.protocol_fees_token_{0,1} e PoolState.fund_fees_token_{0,1} respectivamente, idêntico ao CPMM. Elas são limpas por CollectProtocolFee / CollectFundFee.
Crescimento de taxa fora e dentro
A parte complicada da contabilização de taxa do CLMM: uma posição ganha taxas apenas enquanto o preço do pool está dentro de seu intervalo. O pool rastreia as taxas cumulativas globalmente; a posição precisa saber as taxas cumulativas enquanto dentro de seu intervalo específico. A solução é um acumulador baseado em tick. Cada tick armazena:- Se o preço do pool está acima deste tick (
tick_current >= this_tick),fee_growth_outside = fee_growth_global. (Tudo ganho até agora é “fora” — ou seja, abaixo — este tick, relativo ao preço atual.) - Caso contrário,
fee_growth_outside = 0.
fee_growth_outside desse tick:
O invariante que isto preserva: para qualquer tick t, fee_growth_outside(t) é igual às taxas que se acumularam enquanto tick_current estava no lado oposto de t.
Crescimento de taxa dentro de um intervalo [tick_lower, tick_upper] é então derivado:
O que uma posição armazena e o que ela lê
UmPersonalPositionState armazena fee_growth_inside_0_last_x64 e fee_growth_inside_1_last_x64: os valores de fee_growth_inside da última vez que a posição foi tocada.
Em qualquer toque subsequente (aumentar, diminuir, coletar), o programa:
- Computa o
fee_growth_inside_{0,1}_x64atual usando a fórmula acima. - Computa
Δ = fee_growth_inside_now − fee_growth_inside_last(subtração modular em u128). - Adiciona
Δ × position.liquidity / 2^{64}atokens_fees_owed_{0,1}. - Atualiza
fee_growth_inside_lastpara o novo valor.
CollectFees / DecreaseLiquidity, contra tokens_fees_owed.
Recompensas
Cada um dos fluxos de recompensa do pool (até 3) usa a mesma maquinaria de crescimento dentro do intervalo, em seu próprio acumuladorreward_growth_global_x64. No momento de emissão:
— emissões escalam inversamente com a liquidity ativa, de modo que um pool mais denso paga a cada posição proporcionalmente menos por segundo, mas sobre mais posições no total. A recompensa devida por posição é
e é reivindicada via CollectReward. Veja /pt/products/clmm/fees.
Exemplo trabalhado: swap de entrada exata
Suponha:tick_spacing = 60sqrt_price_x64 = 1 × 2^{64}— preço = 1.0, entãotick_current = 0.- Liquidity ativa
L = 1_000_000 × 2^{64}. - Próximo tick inicializado acima:
t = 60(sqrt_price_b ≈1.003004 × 2^{64}). - Taxa de taxa de negociação: 500 (0.05%).
SwapBaseInput entrada exata 1.000 token0.
Etapa 1 — taxas:
999 < 2995.5, então a entrada inteira cabe sem cruzar o tick.
Etapa 3 — novo preço:
sqrt_c' ligeiramente abaixo de sqrt_c. Observe que a fórmula acima é para um swap token1 → token0. O exemplo aqui é token0 → token1, que impulsiona o preço para cima, não para baixo — então usamos a forma correspondente para token0 in:
token0 → token1: sqrt_c sobe junto com o preço.)
Etapa 4 — quantidade saída:
trade_fee_rate × protocol_fee_rate / 1e6 (e similar para fundo); a porção LP flui para fee_growth_global_0_x64.
Correspondência de ordem limite durante o swap
Quando uma etapa de swap cruza um tick que contém ordens limite abertas, essas ordens consomem entrada de swap antes da curva LP, ao preço exato do tick. A correspondência é FIFO dentro do tick por cohortorder_phase.
Estado por cohort em TickState
orders_amount e herdam o próximo order_phase; elas não podem preencher até o cohort anterior ser totalmente consumido.
Etapa de correspondência
Pseudo-código para a correspondência que acontece em cada cruzamento de tick durante um swap:SettleLimitOrder (ou DecreaseLimitOrder). O pool simplesmente rastreia quanto do cohort agora está preenchido via unfilled_ratio_x64. Cada LimitOrderState armazena seu próprio snapshot (order_phase, unfilled_ratio_x64) no tempo de abertura, então a liquidação se reduz a:
Interação com a curva LP
Em uma etapa de swap, a correspondência de ordem limite acontece no tick (zeroΔsqrt_price); o consumo da curva LP acontece entre ticks. A ordem é portanto:
- Cruze o tick
t_cross(aplique a mudança LPliquidity_netprimeiro, pois é assim que Uniswap-V3 faz). - Preencha qualquer ordem limite sentada em
t_cross. - Continue ao longo da curva LP para o próximo tick inicializado ou para a exaustão de
swap_input.
Derivação de taxa dinâmica
PoolState.dynamic_fee_info carrega o estado de volatilidade. Cada etapa de swap computa a taxa de taxa por etapa como:
onde:
- —
DYNAMIC_FEE_CONTROL_DENOMINATOR - —
VOLATILITY_ACCUMULATOR_SCALE vol_accé o acumulador por swap após a regra de atualização abaixotick_spacingé dePoolState.tick_spacing
Atualização do acumulador
Duas regras são aplicadas cada swap, em ordem: Decaimento. O piso de referência decai com base no tempo desde a última atualização: Acumular. O novo acumulador é a referência mais distância de tick percorrida desde o índice de referência anterior:tick_spacing_index_reference () está em unidades de espaçamento de tick, não ticks brutos: .
Por que parabólico em distância de tick
Elevar ao quadrado o acumulador significa que a taxa aumenta como o quadrado de quão longe o preço caminhou de seu ponto de referência. Empiricamente, isto corresponde ao dimensionamento de variância de preço sob pressão de passeio aleatório: uma excursão de tick 2× implica 4× a volatilidade implícita, então cobra 4× a sobretaxa. O parâmetrodynamic_fee_control calibra o nível absoluto.
A janela filter_period evita que minúsculas oscilações sub-segundo (ex., bots de MEV fazendo sandwich) inflem o acumulador. A janela decay_period evita que um pico passado único cobre taxas indefinidamente depois que o mercado tenha se acalmado.
Robustez numérica
- Todos os produtos intermediários passam por aritmética em forma de
u128ouu256. O CLMM usa helpersU128Sqrte padrõesFullMath::mulDivdiretamente portados da Uniswap v3. - O arredondamento de divisão é escolhido por etapa para reforçar o invariante
k' ≥ klocalmente.SwapBaseInputarredonda saída para baixo;SwapBaseOutputarredonda entrada para cima. - Cruzamentos de tick que deixam
PoolState.liquidityem zero são permitidos (o preço pode percorrer um “buraco de liquidity”), mas o swap simplesmente avança para o próximo tick inicializado sem consumir entrada, não cobrando taxa. - Guarda contra overflow:
sqrt_price_x64é mantido no intervalo inclusivo[MIN_SQRT_PRICE_X64, MAX_SQRT_PRICE_X64]correspondente a[MIN_TICK, MAX_TICK]. Um swap que empurrasse além de qualquer limite reverte comSqrtPriceLimitOverflow.
Próximos passos
/pt/products/clmm/ticks-and-positionspara como o mapa de tick participa da caminhada./pt/products/clmm/feespara o lado de taxa/recompensa da matemática em detalhe./pt/algorithms/clmm-mathpara as derivações por trás deL = sqrt(x · y)e as fórmulas de intervalo vs. liquidity.
raydium-io/raydium-clmm—libraries/swap_math.rs,libraries/tick_math.rs- Whitepaper “Uniswap v3 Core”, §6–7


