Skip to main content
Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →

Por que sqrt-price e não price

CLMMs da família Uniswap-v3 representam o preço como sua raiz quadrada, armazenada em ponto fixo Q64.64:
Três razões:
  1. Matemática de liquidez linear. A quantidade de token0 ou token1 em um intervalo de preço acaba sendo uma função linear de sqrt_price, não de price. Armazenar sqrt_price permite que a etapa de swap avalie essas fórmulas lineares sem calcular uma raiz quadrada.
  2. Controle de overflow. sqrt_price · L cabe em u256 para todos os parâmetros razoáveis; price · L pode fazer overflow muito mais cedo.
  3. Matemática de ticks é uniforme. Como ticks são definidos como 1.0001^i, sqrt(price) = 1.00005^i também é uma escada exata de potências de 1.00005. Cada cruzamento de tick se traduz em uma pequena multiplicação no espaço sqrt_price_x64.
Price e sqrt-price são um para um; a conversão é price = (sqrt_price_x64 / 2^64)^2.

Lattice de ticks

Os preços são discretizados em uma grade:
tick_i é um i32. O intervalo ativo é [MIN_TICK, MAX_TICK] = [−443636, 443636], fornecendo um intervalo de preço de aproximadamente [2^−128, 2^128]. O tick_spacing de cada pool é definido por seu nível de taxa: espaçamentos menores para pares justos (por exemplo, stablecoin com taxa de 0.01% usa espaçamento 1), espaçamentos maiores para pares voláteis (taxa de 0.25% usa 60, taxa de 1% usa 120). Posições devem ter tick_lower e tick_upper alinhados a tick_spacing. Os ticks ativos de um pool (aqueles com liquidez começando ou terminando lá) são os únicos ticks que a etapa de swap se importa.

Liquidez para quantidade

Para uma posição com liquidez L e intervalo de preço [sqrt_lo, sqrt_hi] (todos os valores de sqrt_price): Derivação: diferenciar localmente o invariante CPMM. Dentro de qualquer intervalo de tick único, a posição se comporta como um CPMM com reservas virtuais (x_v, y_v) escolhidas de modo que o (sqrt_p, L) atual do pool seja consistente com L = sqrt(x_v · y_v). Integrando de sqrt_p até o limite do intervalo, obtemos as quantidades acima. Fórmulas inversas (usadas ao cunhar uma posição para um amount0 ou amount1 determinado):

Etapa de swap de um único tick

Dentro de um intervalo de tick único, o pool se comporta como um CPMM. Dado o sqrt_p atual e sqrt_target:

Etapa de entrada exata

Dado Δin_remaining:
O swap 0→1 reduz sqrt_p (o preço cai quando vendemos token0). Um swap 1→0 o eleva. As fórmulas são simétricas com sqrt_p e sqrt_target trocados.

Etapa de saída exata

Mesma estrutura, resolvendo para Δin em vez disso.

Loop de swap multi-tick

Um swap itera sobre ticks até que a entrada se esgote ou o limite de preço seja atingido:
Cada single_step usa o L atual do pool. L muda apenas ao cruzar um tick inicializado. A liquidez entre ticks é constante, o que torna a matemática da etapa em forma fechada. liquidity_net em um tick é a soma assinada das liquidez de posições que começam naquele tick menos as que terminam lá. Cruzar para cima adiciona liquidity_net; cruzar para baixo subtrai. Quando o pool tem ordens limite abertas em um tick, a etapa de cruzamento de tick também consome oportunisticamente parte da entrada de swap para preencher essas ordens (FIFO entre coortes). O algoritmo de correspondência e a sobretaxa de taxa dinâmica que pode se aplicar sobre a etapa base são documentados em products/clmm/math; eles não alteram as fórmulas de etapa única em forma fechada acima.

Acumuladores de crescimento de taxa

CLMM rastreia taxas por unidade de liquidez ativa, por lado, globalmente e por tick:
Em cada single_step:
(O fee_growth_global do outro lado não se move nesta etapa, pois nenhum token desse lado foi pago como entrada.) Ao cruzar um tick, o programa inverte fee_growth_outside:
“Fora” é relativo a tick_current. Quando tick_current está acima do tick, fora significa “abaixo”. Quando tick_current está abaixo, fora significa “acima”. A inversão troca a interpretação.

fee_growth_inside para uma posição

Dada uma posição [tick_lower, tick_upper] e o tick_current atual:
As taxas não coletadas de uma posição para o lado do token s são:
Esta atualização é executada em cada interação com a posição (IncreaseLiquidity, DecreaseLiquidity, CollectFees).

Exemplo trabalhado — cruzando um tick

Pool (simplificado):
  • sqrt_p_x64 = 2^64 · 1.0 = 2^64 (preço = 1.0)
  • L = 1_000_000
  • tick_current = 0
  • Próximo tick inicializado abaixo: tick = −60, sqrt_price = 1.0001^(−30) ≈ 0.99700, liquidity_net = −400_000 (este tick termina uma posição, então um cruzamento descendente remove 400k)
  • Taxa de taxa: 0.25%
Swap: Δin = 10_000 token0, direção = 0→1. Etapa 1 — até sqrt_target = 0.99700 · 2^64:
3.009 < 10.000, então preenchemos esta etapa completamente:
Etapa 2 — com novo L = 600_000: O próximo tick inicializado (digamos tick = −120) está em sqrt = 0.99402. Recalcule amount_in_to_target:
Ainda menos que Δin_remaining. Cruze novamente. Continue até Δin_remaining atingir zero. A sequência completa de Δout acumula para a saída final do swap.

Inicialização e proteções contra overflow

  • MIN_SQRT_PRICE_X64 e MAX_SQRT_PRICE_X64 correspondem a tick = ±443636. Qualquer swap que empurraria sqrt_p fora deste intervalo reverte.
  • O parâmetro sqrt_price_limit do usuário deve estar no mesmo intervalo; o programa verifica.
  • Produtos de L · Δsqrt são calculados em u256 e depois deslocados de volta para u128 para evitar overflow.

Diferenças vs Uniswap v3

  • Oracle. O ObservationState da Raydium armazena buffer ring (block_timestamp, tick_cumulative, seconds_per_liquidity_cumulative); formato de fio ligeiramente diferente do Uniswap, mas a mesma matemática TWAP.
  • Token-2022. CLMM da Raydium suporta mints Token-2022; a variante com taxa de transferência requer ajustes adicionais de quantidade pré/pós-swap. Veja algorithms/token-2022-transfer-fees.
  • Bitmap de ticks. Raydium empacota o bitmap de ticks inicializados em [u64; 16] por pool para find_next_initialized_tick rápido; Uniswap usa um mapeamento on-chain por palavra. A compensação é aluguel vs custo de busca.
  • Slots de recompensa. Raydium suporta 3 fluxos de recompensa por pool com contadores reward_growth_global_x64 separados; mesma estrutura que o acumulador de crescimento de taxa.

Ponteiros

Fontes:
  • Whitepaper Uniswap v3 (derivação canônica de matemática sqrt-price).
  • Código fonte do programa CLMM da Raydium.