Files
precompile/dex/swap_amm_pool.go
zeekayandHanzo Dev af68fed375 dex: decomplect to canonical settle-only 0x9999 (remove embedded matcher)
ONE money path: D-Chain matches, C-Chain 0x9999 SETTLES, C never matches.

- 0x9999 swap() routes ONLY to SettleSwap (native C<->D atomic seam): untagged/
  DI01 => Phase A intent (lock input, write C->D object, return intent id); DS01
  => Phase B settlement (consume a real D->C atomic object once, credit RECORDED
  amount). No-receipt-no-settle: absent a real object, Phase B reverts
  ErrNativeNoSettlement (TestDecomplect_NoReceiptNoSettle).
- Deleted the embedded matcher: swap_sync*.go, swap_custody.go (maker order book),
  buildRouter/evmAMMPool in swap_amm_pool.go, and the swapDeposit/withdraw/place/
  cancel selectors. A live in-trie matcher forks consensus; deterministic
  atomic-object consumption is fork-safe inline.
- 0x9010 already non-dispatched. 0x9012 (LXRouter) value selectors exactInput*/
  exactOutput* now revert ErrPrecompileMoved (PRECOMPILE_MOVED); read-only quote/
  route views kept.
- Cleanups (dead code removal, all unreachable via any dispatched selector):
  deleted the legacy engine PoolManager.Swap + LXRouter.Exact*/executeV4Swap*;
  deleted the vestigial makerLockedVault ledger (0 callers, always 0); deleted the
  unwired Block-STM scaffolding (AssertWriteSetWithin/AccessCommitment/Predict*).
- Activation rides the EXISTING canonical gate 1766708400 (Dec 25 2025 16:20 PST);
  no new timestamp. Build CGO_ENABLED=0 (pure-Go luxfi/dex path); go.sum zap
  re-tag checksum refreshed.

327 dex tests PASS / 0 FAIL, go vet clean. RED-reviewed (0 critical, all drain
vectors safe, fund-strand cleared, negative invariant falsified-then-restored).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-04 12:52:44 -07:00

77 lines
3.4 KiB
Go

// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package dex
import (
"encoding/binary"
dexcore "github.com/luxfi/dex/pkg/dex"
)
// swap_amm_pool.go binds the router's V2/V3 AMM fallthrough to a pool's reserve
// state in the SAME cEVM. The constant-product MATH + routing live in dexcore (one
// place, both homes); this file is ONLY the precompile-specific reserve binding/read/
// write, expressed over the dexcore Store (which IS 0x9999 storage), so there is ONE
// binding and it is consensus-shared and reorg-safe.
//
// FIRST CUT — swap-only, AMM-fallthrough-by-binding: the AMM source is active for a
// market ONLY when a real pool's reserves are bound (BindAMMPool). Until then the
// router uses the CLOB alone. This ships the fallthrough WITHOUT ever fabricating a
// pool: an unbound market routes CLOB-only, a bound market routes CLOB+AMM. The bound
// reserves are synced from the real V2/V3 pool by the operator/maker seed path, so a
// validator replays the identical reserves from committed state — never a live query.
// ammRowKey is the ONE dexcore Store key for a market's AMM binding:
//
// ammrow:<poolID:32> -> baseReserve(8) | quoteReserve(8) | feeBps(4) | bound(1)
//
// The row lives in 0x9999 storage via the evmStore adapter, so it is committed by the
// block root and reverted by snapshots alongside the CLOB and EVM-balance effects.
const ammRowPrefix = "ammrow:"
func ammRowKey(poolID [32]byte) []byte {
k := make([]byte, 0, len(ammRowPrefix)+32)
k = append(k, []byte(ammRowPrefix)...)
k = append(k, poolID[:]...)
return k
}
const ammRowLen = 8 + 8 + 4 + 1 // base | quote | fee | bound
// readAMMRow returns a market's bound (base, quote, feeBps), ok=false if unbound.
func readAMMRow(store dexcore.Store, poolID [32]byte) (base, quote uint64, feeBps uint32, ok bool) {
v, err := store.Get(ammRowKey(poolID))
if err != nil || len(v) != ammRowLen || v[20] != 1 {
return 0, 0, 0, false
}
base = binary.BigEndian.Uint64(v[0:8])
quote = binary.BigEndian.Uint64(v[8:16])
feeBps = binary.BigEndian.Uint32(v[16:20])
return base, quote, feeBps, true
}
// writeAMMRow persists a market's (base, quote, feeBps) binding (bound=1).
func writeAMMRow(store dexcore.Store, poolID [32]byte, base, quote uint64, feeBps uint32) error {
v := make([]byte, ammRowLen)
binary.BigEndian.PutUint64(v[0:8], base)
binary.BigEndian.PutUint64(v[8:16], quote)
binary.BigEndian.PutUint32(v[16:20], feeBps)
v[20] = 1
return store.Put(ammRowKey(poolID), v)
}
// BindAMMPool activates the AMM fallthrough for a market with a reserve snapshot
// synced from a real V2/V3 pool and the pool fee (bps). The analog of OpenMarket for
// the AMM side: a market gains an AMM route only when an operator binds a real pool's
// reserves. Idempotent (re-bind updates the snapshot).
func BindAMMPool(store dexcore.Store, poolID [32]byte, baseReserve, quoteReserve uint64, feeBps uint32) error {
return writeAMMRow(store, poolID, baseReserve, quoteReserve, feeBps)
}
// The CLOB+AMM in-trie router (buildRouter / evmAMMPool) was REMOVED with the embedded
// matcher: 0x9999 no longer matches on C. The reserve-row read/write helpers above remain
// ONLY to back the read-only quote views (0x9998 Quoter, 0x9012 router quote selectors)
// and the operator seed (BindAMMPool). No value path reads or crosses this row any longer —
// a swap settles solely by consuming a real D-Chain-committed atomic object (settle9999.go).