Zum Hauptinhalt springen
Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.Englische Version ansehen →

Die Nachschlagetabellen-Kurve

Stable AMM ersetzt die Formel x·y=k durch eine spärliche Nachschlagetabelle von (x, y, price) Tupeln. Bei der Preisbestimmung eines Swaps führt das Programm folgende Schritte durch:
  1. Berechnet das aktuelle Verhältnis des Pools aus den Reserven.
  2. Durchsucht die Tabelle binär, um die beiden Einträge zu finden, die dieses Verhältnis einrahmen.
  3. Interpoliert linear zwischen ihnen, um einen Zwischenpreis zu erhalten.
  4. Wendet Gebühren an und gibt das Angebot zurück.
Dieser Ansatz tauscht die Determiniertheit einer Formel gegen Admin-Flexibilität bei der Preisgestaltung ein und ist effizient genug, um in Solanas Compute-Budget zu passen.

Tabellenlayout und binäre Suche

Die ModelDataInfo enthält bis zu 50.000 DataElement Einträge, indiziert durch den Admin. Nur die ersten valid_data_count sind aktiv. Jeder Eintrag:
DataElement {
  x: u64,      // X-Koordinate (Coin-seitige Menge, skaliert)
  y: u64,      // Y-Koordinate (PC-seitige Menge, skaliert)
  price: u64,  // price = x/y, skaliert durch Multiplikator
}
Um einen Preis bei den aktuellen Pool-Reserven (x_real, y_real) zu finden:
  1. Berechnen Sie das Verhältnis: target_ratio = (x_real * multiplier) / y_real.
  2. Binäre Suche nach Einträgen, bei denen (element.x * multiplier) / element.y das target_ratio einrahmt.
  3. Wenn eine Klammer [min_idx, max_idx] gefunden wird, interpolieren Sie.
Der binäre Suchcode des Programms erstreckt sich über etwa 150 Zeilen in state.rs::ModelDataInfo::get_mininum_range_by_xy_real. Die Schlüsselinvariante: Einträge müssen sortiert sein (x aufsteigend, y absteigend, price aufsteigend), damit die Suche funktioniert.

Lineare Interpolation

Sobald zwei Tabellenpunkte das Verhältnis einrahmen, berechnet die Interpolation einen Zwischenpreis und ein Reservepaar:
target = (x_real * multiplier) / y_real

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

// Preis interpolieren
p = p1 + (p2 - p1) * (target - ratio1) / (ratio2 - ratio1)

// Reserve interpolieren
x = x1 + (x2 - x1) * (target - ratio1) / (ratio2 - ratio1)
y = y1 + (y2 - y1) * (target - ratio1) / (ratio2 - ratio1)
Das Ergebnis ist eine stückweise lineare Kurve, die die Tabellenpunkte sanft verbindet.

Skalierung: der Multiplikator

Pool-Reserven und Preise werden in unterschiedlichen Maßstäben gespeichert. Das Feld multiplier auf ModelDataInfo berücksichtigt dies. Ein häufiges Muster:
  • Coin hat 6 Dezimalstellen, PC hat 18 Dezimalstellen.
  • Multiplikator = 10^6 (oder ähnlich).
  • Tabelleneinträge werden in reduziertem Maßstab gespeichert, um u64-Grenzen einzuhalten.
Das Programm skaliert beim Lesen/Schreiben über:
real_value = table_value * ratio / multiplier
table_value = real_value * multiplier / ratio

Swap-Preisbestimmung: SwapBaseIn und SwapBaseOut

SwapBaseIn (exakte Eingabe)

Gegeben eine Eingabemenge amount_in:
  1. Holen Sie sich das aktuelle Verhältnis von (coin_vault, pc_vault).
  2. Finden Sie einrahmende Tabelleneinträge und interpolieren Sie, um das Tabellen-Verhältnis zu erhalten.
  3. Konvertieren Sie die Eingabe in Tabellenraum: dx_table = amount_in * multiplier / ratio.
  4. Fragen Sie die Tabelle bei der neuen X-Koordinate ab, um das neue Y zu finden.
  5. dy_table = y_old - y_new.
  6. Konvertieren Sie zurück: dy_real = dy_table * ratio / multiplier.
  7. Wenden Sie die Handelsgebühr an: dy_output = dy_real - (dy_real * trade_fee_numerator / trade_fee_denominator).
  8. Geben Sie dy_output zurück.

SwapBaseOut (exakte Ausgabe)

Symmetrisch: Gegeben die gewünschte amount_out, lösen Sie die erforderliche amount_in auf. Beide Pfade lesen effektive Reserven direkt aus den Pool-Vaults. Der Pool hat seit Jahren keine OpenBook-offenen Aufträge gehalten, daher gibt es nichts zu begleichen — die Vault-Guthaben sind die ganze Geschichte. (Das Upgrade vom 2026-06-22 entfernte den verbleibenden Market-Code.)

Gebührenanwendung

Identisch mit AMM v4: siehe products/amm-v4/math für die vollständige Herleitung.
gross_fee = amount_in * (swap_fee_numerator / swap_fee_denominator)    // z.B. 0,25%
lp_portion = gross_fee - (gross_fee * pnl_numerator / pnl_denominator) // z.B. 0,22%
pnl_portion = gross_fee * (pnl_numerator / pnl_denominator)            // z.B. 0,03%
Der pnl_portion geht zu need_take_pnl_* und wird vom Admin über WithdrawPnl eingezogen. Der lp_portion bleibt im Vault und erhöht k, was LP-Token-Inhabern zugute kommt.

Pool-Vermögensabrechnung

Die Formel addierte historisch die Mittel, die der Pool als offene Aufträge in seinem OpenBook OpenOrders-Konto hielt. Dieser Term war praktisch seit dem Zeitpunkt, an dem der Pool aufhörte, Aufträge zu posten, null, und das Upgrade vom 2026-06-22 entfernte ihn vollständig aus der Formel, sodass nur noch die Vault-Berechnung übrig bleibt:
Alt: Gesamtvermögen = Vault-Guthaben + offene Auftragsmittel (native_coin_total / native_pc_total) − ausstehender PnL (need_take_pnl)
Neu: Gesamtvermögen = Vault-Guthaben − ausstehender PnL (need_take_pnl)
Dies ist der Wert, den die Kurvenmathe als effektive Reserven behandelt (der aufgelaufene, aber nicht eingezogene need_take_pnl Teil sitzt physisch im Vault, wird aber von der Preisbestimmung ausgeschlossen). Quoting-Code und Indexer, die zuvor OpenOrders-Guthaben lasen, müssen diesen Term streichen.

MonitorStep (entfernt)

MonitorStep war die Crank-Anweisung, die ausstehende OpenBook-Fills beglich, AmmInfo.target_orders neu berechnete und das aus der Nachschlagetabelle abgeleitete Limit-Order-Gitter neu postete. Der Pool postete seit Jahren keine Aufträge mehr zu OpenBook, daher hatte der Crank nichts mehr zu tun; er wurde im Upgrade vom 2026-06-22 entfernt. Integratoren müssen Stable-Pools nicht cranken.

Zusammenfassung: warum das funktioniert

Das Design mit Nachschlagetabelle + Interpolation ist effizient und flexibel:
  • Effizienz: Binäre Suche ist O(log 50.000) ≈ 16 Iterationen, jeweils ~ 300–500 CU. Interpolation ist ein paar Multiplikationen/Divisionen. Die gesamten Quoting-Kosten betragen ~5k–15k CU, viel günstiger als die Neuberechnung einer Formel bei jedem Swap.
  • Flexibilität: Der Admin kann jede stückweise lineare Kurve kodieren. Stablecoin-Paare erhalten hohe Dichte um 1:1; besicherte Paare erhalten benutzerdefinierte Kurven.
  • Eigenständige Liquidität: Alle Mittel leben in den Pool-Vaults und die Preisbestimmung liest sie direkt — kein Crank, kein externes Orderbuch, weniger Konten pro Transaktion.
Für tiefere Einblicke in die Interpolationslogik siehe raydium-stable/program/src/state.rs, Methoden get_data_by_x, get_data_by_y, get_dy_by_dx_base_in, usw.

Nächste Schritte

  • KontenModelDataInfo und DataElement Feldverweis.
  • Anweisungen — der aufrufbare Satz (Swap, Einzahlung, Auszahlung, WithdrawPnl) und die entfernten Anweisungen.
  • Gebühren — Gebührenanwendung und WithdrawPnl.
  • products/amm-v4/math — für die OpenBook-gebühreninklusive Order-Preislogik.
Quellen:
  • raydium-stable/program/src/state.rs (Interpolations- und binäre Suchimplementierungen)
  • raydium-stable/program/src/math.rs (Rechner-Dienstprogramme)