Saltar para o conteúdo principal
Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →

A curva da tabela de consulta

O Stable AMM substitui a fórmula x·y=k por uma tabela de consulta esparsa de tuplas (x, y, price). Ao precificar um swap, o programa:
  1. Calcula a razão atual do pool a partir das reservas.
  2. Busca binariamente na tabela para encontrar as duas entradas que delimitam essa razão.
  3. Interpola linearmente entre elas para obter um preço intermediário.
  4. Aplica taxas e retorna a cotação.
Essa abordagem troca o determinismo de uma fórmula pela flexibilidade do administrador na modelagem de preços, e é eficiente o suficiente para caber no orçamento de computação da Solana.

Layout da tabela e busca binária

O ModelDataInfo contém até 50.000 entradas DataElement, indexadas pelo administrador. Apenas as primeiras valid_data_count estão ativas. Cada entrada:
DataElement {
  x: u64,      // Coordenada X (quantidade do lado da moeda, escalada)
  y: u64,      // Coordenada Y (quantidade do lado do PC, escalada)
  price: u64,  // price = x/y, escalado pelo multiplicador
}
Para encontrar um preço nas reservas atuais do pool (x_real, y_real):
  1. Calcule a razão: target_ratio = (x_real * multiplier) / y_real.
  2. Busque binariamente por entradas onde (element.x * multiplier) / element.y delimita target_ratio.
  3. Quando um intervalo [min_idx, max_idx] é encontrado, interpole.
O código de busca binária do programa ocupa ~150 linhas em state.rs::ModelDataInfo::get_mininum_range_by_xy_real. O invariante chave: as entradas devem estar ordenadas (x ascendente, y descendente, price ascendente) para que a busca funcione.

Interpolação linear

Quando dois pontos da tabela delimitam a razão, a interpolação calcula um preço intermediário e um par de reservas:
target = (x_real * multiplier) / y_real

[x1, y1, p1] = table[min_idx]
[x2, y2, p2] = table[max_idx]

// Interpolar preço
p = p1 + (p2 - p1) * (target - ratio1) / (ratio2 - ratio1)

// Interpolar reserva
x = x1 + (x2 - x1) * (target - ratio1) / (ratio2 - ratio1)
y = y1 + (y2 - y1) * (target - ratio1) / (ratio2 - ratio1)
O resultado é uma curva linear por partes que conecta suavemente os pontos da tabela.

Escala: o multiplicador

As reservas do pool e os preços são armazenados em escalas diferentes. O campo multiplier em ModelDataInfo lida com isso. Um padrão comum:
  • Moeda tem 6 decimais, PC tem 18 decimais.
  • Multiplicador = 10^6 (ou similar).
  • As entradas da tabela são armazenadas em uma escala reduzida para caber nos limites de u64.
O programa reescala na leitura/escrita via:
real_value = table_value * ratio / multiplier
table_value = real_value * multiplier / ratio

Precificação de swap: SwapBaseIn e SwapBaseOut

SwapBaseIn (entrada exata)

Dado o valor de entrada amount_in:
  1. Obtenha a razão atual de (coin_vault, pc_vault).
  2. Encontre as entradas da tabela que delimitam e interpole para obter a razão no espaço da tabela.
  3. Converta a entrada para o espaço da tabela: dx_table = amount_in * multiplier / ratio.
  4. Consulte a tabela na nova coordenada X para encontrar o novo Y.
  5. dy_table = y_old - y_new.
  6. Converta de volta: dy_real = dy_table * ratio / multiplier.
  7. Aplique a taxa de negociação: dy_output = dy_real - (dy_real * trade_fee_numerator / trade_fee_denominator).
  8. Retorne dy_output.

SwapBaseOut (saída exata)

Simétrico: dado o amount_out desejado, resolva para o amount_in necessário. Ambos os caminhos leem as reservas efetivas diretamente dos vaults do pool. O pool não mantém ordens abertas do OpenBook há anos, portanto não há nada para liquidar primeiro — os saldos dos vaults são a história completa. (A atualização de 2026-06-22 removeu o código de mercado restante.)

Aplicação de taxas

Idêntica ao AMM v4: veja products/amm-v4/math para a derivação completa.
gross_fee = amount_in * (swap_fee_numerator / swap_fee_denominator)    // ex: 0,25%
lp_portion = gross_fee - (gross_fee * pnl_numerator / pnl_denominator) // ex: 0,22%
pnl_portion = gross_fee * (pnl_numerator / pnl_denominator)            // ex: 0,03%
A pnl_portion vai para need_take_pnl_* e é retirada pelo administrador via WithdrawPnl. A lp_portion permanece no vault, inflacionando k e beneficiando os detentores de tokens LP.

Contabilidade de ativos do pool

A fórmula historicamente adicionava os fundos que o pool mantinha como ordens abertas em sua conta OpenOrders do OpenBook. Esse termo tem sido zero na prática desde que o pool parou de postar ordens, e a atualização de 2026-06-22 o removeu completamente da fórmula, deixando apenas o cálculo baseado em vaults:
Antigo: total assets = saldos de vault + fundos de ordens abertas (native_coin_total / native_pc_total) − PnL pendente (need_take_pnl)
Novo: total assets = saldos de vault − PnL pendente (need_take_pnl)
Este é o valor que a matemática da curva trata como reservas efetivas (a porção need_take_pnl acumulada mas não retirada fica fisicamente no vault mas é excluída da precificação). O código de cotação e indexadores que anteriormente liam saldos de OpenOrders devem descartar esse termo.

MonitorStep (removido)

MonitorStep era a instrução de crank que liquidava preenchimentos pendentes do OpenBook, recomputava AmmInfo.target_orders e repostava a grade de ordens limitadas derivada da tabela de consulta. O pool parou de postar ordens no OpenBook há anos, então o crank não tinha mais nada a fazer; foi removido na atualização de 2026-06-22. Integradores não precisam fazer crank em pools Stable.

Resumo: por que isso funciona

O design de tabela de consulta + interpolação é eficiente e flexível:
  • Eficiência: A busca binária é O(log 50.000) ≈ 16 iterações, cada uma ~ 300–500 CU. A interpolação é algumas multiplicações/divisões. O custo total de cotação é ~5k–15k CU, muito mais barato do que recomputar uma fórmula a cada swap.
  • Flexibilidade: O administrador pode codificar qualquer curva linear por partes. Pares de stablecoin obtêm alta densidade em torno de 1:1; pares colateralizados obtêm curvas personalizadas.
  • Liquidez autossuficiente: Todos os fundos vivem nos vaults do pool e a precificação os lê diretamente — sem crank, sem livro de ordens externo, menos contas por transação.
Para análises profundas da lógica de interpolação, veja raydium-stable/program/src/state.rs, métodos get_data_by_x, get_data_by_y, get_dy_by_dx_base_in, etc.

Próximos passos

  • Contas — referência de campos ModelDataInfo e DataElement.
  • Instruções — o conjunto chamável (swap, deposit, withdraw, WithdrawPnl) e as instruções removidas.
  • Taxas — aplicação de taxas e WithdrawPnl.
  • products/amm-v4/math — para a lógica de precificação de ordens inclusiva de taxas do OpenBook.
Fontes:
  • raydium-stable/program/src/state.rs (implementações de interpolação e busca binária)
  • raydium-stable/program/src/math.rs (utilitários de calculadora)