Saltar al contenido principal
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 →

La curva de tabla de búsqueda

Stable AMM reemplaza la fórmula x·y=k con una tabla de búsqueda dispersa de tuplas (x, y, price). Cuando se cotiza un swap, el programa:
  1. Calcula la relación actual del pool a partir de las reservas.
  2. Busca binariamente en la tabla para encontrar las dos entradas que delimitan esa relación.
  3. Interpola linealmente entre ellas para obtener un precio intermedio.
  4. Aplica comisiones y devuelve la cotización.
Este enfoque intercambia el determinismo de una fórmula por flexibilidad administrativa en la configuración de precios, y es lo suficientemente eficiente para caber en el presupuesto de cómputo de Solana.

Diseño de tabla y búsqueda binaria

ModelDataInfo contiene hasta 50,000 entradas DataElement, indexadas por el administrador. Solo las primeras valid_data_count están activas. Cada entrada:
DataElement {
  x: u64,      // Coordenada X (cantidad del lado de la moneda, escalada)
  y: u64,      // Coordenada Y (cantidad del lado de PC, escalada)
  price: u64,  // price = x/y, escalado por multiplicador
}
Para encontrar un precio en las reservas actuales del pool (x_real, y_real):
  1. Calcula la relación: target_ratio = (x_real * multiplier) / y_real.
  2. Busca binariamente entradas donde (element.x * multiplier) / element.y delimite target_ratio.
  3. Cuando se encuentra un delimitador [min_idx, max_idx], interpola.
El código de búsqueda binaria del programa abarca ~150 líneas en state.rs::ModelDataInfo::get_mininum_range_by_xy_real. El invariante clave: las entradas deben estar ordenadas (x ascendente, y descendente, price ascendente) para que la búsqueda funcione.

Interpolación lineal

Una vez que dos puntos de tabla delimitan la relación, la interpolación calcula un precio intermedio y un par de reservas:
target = (x_real * multiplier) / y_real

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

// Interpola precio
p = p1 + (p2 - p1) * (target - ratio1) / (ratio2 - ratio1)

// Interpola reserva
x = x1 + (x2 - x1) * (target - ratio1) / (ratio2 - ratio1)
y = y1 + (y2 - y1) * (target - ratio1) / (ratio2 - ratio1)
El resultado es una curva lineal por tramos que conecta suavemente los puntos de la tabla.

Escalado: el multiplicador

Las reservas del pool y los precios se almacenan en escalas diferentes. El campo multiplier en ModelDataInfo explica esto. Un patrón común:
  • La moneda tiene 6 decimales, PC tiene 18 decimales.
  • Multiplicador = 10^6 (o similar).
  • Las entradas de la tabla se almacenan en una escala reducida para caber dentro de los límites de u64.
El programa reescala al leer/escribir mediante:
real_value = table_value * ratio / multiplier
table_value = real_value * multiplier / ratio

Cotización de swap: SwapBaseIn y SwapBaseOut

SwapBaseIn (entrada exacta)

Dado el monto de entrada amount_in:
  1. Obtén la relación actual de (coin_vault, pc_vault).
  2. Encuentra las entradas de tabla delimitadoras e interpola para obtener la relación en el espacio de la tabla.
  3. Convierte la entrada al espacio de tabla: dx_table = amount_in * multiplier / ratio.
  4. Consulta la tabla en la nueva coordenada X para encontrar la nueva Y.
  5. dy_table = y_old - y_new.
  6. Convierte de vuelta: dy_real = dy_table * ratio / multiplier.
  7. Aplica comisión de operación: dy_output = dy_real - (dy_real * trade_fee_numerator / trade_fee_denominator).
  8. Devuelve dy_output.

SwapBaseOut (salida exacta)

Simétrico: dado el amount_out deseado, resuelve el amount_in requerido. Ambas rutas leen reservas efectivas directamente de los vaults del pool. El pool no ha mantenido órdenes abiertas de OpenBook durante años, por lo que no hay nada que liquidar primero — los saldos de los vaults son toda la historia. (La actualización del 2026-06-22 eliminó el código de mercado restante.)

Aplicación de comisiones

Idéntica a AMM v4: consulta products/amm-v4/math para la derivación completa.
gross_fee = amount_in * (swap_fee_numerator / swap_fee_denominator)    // p. ej., 0.25%
lp_portion = gross_fee - (gross_fee * pnl_numerator / pnl_denominator) // p. ej., 0.22%
pnl_portion = gross_fee * (pnl_numerator / pnl_denominator)            // p. ej., 0.03%
La pnl_portion va a need_take_pnl_* y es retirada por el administrador mediante WithdrawPnl. La lp_portion permanece en el vault, inflando k y beneficiando a los poseedores de tokens LP.

Contabilidad de activos del pool

La fórmula históricamente sumaba los fondos que el pool mantenía como órdenes abiertas en su cuenta OpenOrders de OpenBook. Ese término ha sido cero en la práctica desde que el pool dejó de publicar órdenes, y la actualización del 2026-06-22 lo eliminó completamente de la fórmula, dejando el cálculo solo de vaults:
Anterior: total assets = saldos de vault + fondos de órdenes abiertas (native_coin_total / native_pc_total) − PnL pendiente (need_take_pnl)
Nuevo: total assets = saldos de vault − PnL pendiente (need_take_pnl)
Este es el valor que la matemática de la curva trata como reservas efectivas (la porción need_take_pnl acumulada pero no barrida se encuentra físicamente en el vault pero se excluye de la cotización). El código de cotización e indexadores que anteriormente leían saldos de OpenOrders deben eliminar ese término.

MonitorStep (eliminado)

MonitorStep era la instrucción de crank que liquidaba los rellenos pendientes de OpenBook, recalculaba AmmInfo.target_orders y volvía a publicar la cuadrícula de órdenes limitadas derivada de la tabla de búsqueda. El pool dejó de publicar órdenes en OpenBook hace años, por lo que el crank no tenía nada que hacer; fue eliminado en la actualización del 2026-06-22. Los integradores no necesitan hacer crank en pools Stable.

Resumen: por qué funciona

El diseño de tabla de búsqueda + interpolación es eficiente y flexible:
  • Eficiencia: La búsqueda binaria es O(log 50,000) ≈ 16 iteraciones, cada una ~ 300–500 CU. La interpolación es algunos multiplicaciones/divisiones. El costo total de cotización es ~5k–15k CU, mucho más barato que recomputar una fórmula en cada swap.
  • Flexibilidad: El administrador puede codificar cualquier curva lineal por tramos. Los pares de stablecoins obtienen alta densidad alrededor de 1:1; los pares colateralizados obtienen curvas personalizadas.
  • Liquidez autónoma: Todos los fondos viven en los vaults del pool y la cotización los lee directamente — sin crank, sin libro de órdenes externo, menos cuentas por transacción.
Para análisis profundos de la lógica de interpolación, consulta raydium-stable/program/src/state.rs, métodos get_data_by_x, get_data_by_y, get_dy_by_dx_base_in, etc.

Dónde ir a continuación

  • Cuentas — referencia de campos ModelDataInfo y DataElement.
  • Instrucciones — el conjunto invocable (swap, deposit, withdraw, WithdrawPnl) y las instrucciones eliminadas.
  • Comisiones — aplicación de comisiones y WithdrawPnl.
  • products/amm-v4/math — para la lógica de cotización de órdenes inclusiva de comisiones de OpenBook.
Fuentes:
  • raydium-stable/program/src/state.rs (implementaciones de interpolación y búsqueda binaria)
  • raydium-stable/program/src/math.rs (utilidades de calculadora)