mirror of
https://github.com/luxfi/migration.git
synced 2026-10-30 15:25:07 +00:00
The migration EXECUTED on mainnet 2026-07-05 (V4 PoolManager 0x2e317c5ce2c3e3aa720a3bb7f366f5959d940d4c, LiquidityDeployer 0x9888015bd7cda1905bbebf560f800731772957fd handed to the DAO Safe). Logic is proven — this only removes cruft, unifies one way to do each thing, and rewrites the docs. No proven behavior changed; verified by re-running the full pipeline. Deleted / simplified: - execute.py: dead `_await_pending_nonce` (never called); dead `ZERO` const; dead `Q96` import; inline `from v4math import liquidity_for_amount0` hoisted to the top import. - Env surface trimmed to the genuinely operator-tuned knobs. Dropped never-set overrides: PLAN/STATE (now HERE-relative), READ_POD (= RPC_PODS[1], removing a vacuous len>1 guard), V4CORE_ART/LD_ART (now derived via the contracts/lib/v4-core symlink — no ~/work absolute path to keep in sync), snapshot OUT/RPC/TRANSPORT, investigate hardcoded ctx. Kept: DRY_RUN/EXECUTE, LUX_PRIVATE_KEY, GAS_PRICE_GWEI, SLIPPAGE_BPS, ORACLE_TICK_BAND, ONESIDED_MAX_WLUX, ONESIDED_BAND_TICKS, FINALIZE, ORACLE, KCTX/KNS, RPC_PODS. - snapshot.py: collapsed the dual http/kubectl transport to kubectl-exec only, matching execute.py + investigate_all.py (one transport, one way); dropped the urllib path and the redundant `except (DecodingError, Exception)`. - investigate_all.py: honor KCTX/KNS/KPOD from env (the Makefile already passes them). - v4math.py: hoist `import decimal, math` to module top. - Makefile: drop the now-dead TRANSPORT=kubectl from the snapshot target. Load-bearing live fixes LEFT INTACT (why the run worked, do not weaken): no-gossip nonce reconcile (_our_tx_mined), latest-based drift detection (not pending), checksummed tx `to`, 5-validator broadcast at ≥250 gwei. Docs: - RUNBOOK.md rewritten as the single canonical, deterministic replay guide: EXECUTED status + live addresses, chain-heartbeat suspend requirement, the one-way pipeline (snapshot→plan→test→migrate dry-run→migrate→finalize), post-reboot re-run, surviving-env table, one-sided oracle dual-control. - v3v4/LLM.md refreshed (concise agent guide, CLAUDE.md symlinks to it). - top-level LLM.md: added a pointer/status line for v3v4 (distinct from Quasar). Verified after cleanup: make test 16/16, python3 tools/test_red_oracle.py PASS, and make snapshot && make plan && make migrate (dry-run) reconciles clean against live chain (deploys + all steps report already-done, no broadcast). Co-authored-by: Hanzo Dev <[email protected]>
2.8 KiB
2.8 KiB
v3v4 — Lux mainnet V3 → V4 LP migration (AI guide)
DEX liquidity move on C-Chain 96369. NOT the Quasar network migration (../CLAUDE.md).
Read RUNBOOK.md first — it is the canonical, deterministic replay guide.
Status — EXECUTED 2026-07-05 on mainnet
- V4 PoolManager
0x2e317c5ce2c3e3aa720a3bb7f366f5959d940d4c(owner = treasury). - LiquidityDeployer
0x9888015bd7cda1905bbebf560f800731772957fd, ownership → DAO Safe0x51284dc2133e8d3a8e213dca6a6fa768cfdfcce2; residual approvals zeroed. - Migrated 50% of 5 pools (~71M WLUX + 1.434B LZOO); LAVAX/LUSD dust-skipped.
- Re-running reconciles against live chain: every step precheck reports "already done → skip".
One and only one way
make snapshot → make plan → make test → make migrate (dry-run) → make migrate DRY_RUN=0 (broadcast) → … FINALIZE=1 (hand LD to DAO).
Everything derives from live chain; nothing hardcoded. Idempotent; resumable via on-chain extsload/NPM.positions reads. Suspend the chain-heartbeat cronjob (ns lux-mainnet) before any broadcast run — it signs the treasury 0x9011 every 5 min and would race the nonce (RUNBOOK §1).
Layout
contracts/— foundry.src/LiquidityDeployer.sol(minimal owner-gatedIUnlockCallback:add/remove/initAndAdd/rescue/transferOwnership).test/16 tests incl. 256-run fuzz + mirror-rounding invariant.lib/v4-core→ symlink to~/work/lux-amm/v4-core.tools/snapshot.py— enumerate treasury V3 positions (read-only,kubectl exectransport).tools/investigate_all.py— full NPM ownership map (the LETH resolution).tools/v4math.py— bit-exact TickMath + LiquidityAmounts (validated 0-wei vs on-chain).tools/build_plan.py— classify + accounting →plan.json; freezesbaseline.json.tools/execute.py— staged executor (dry-run default; 5-RPC broadcast @250 gwei).scripts/setup.sh— pin v4-core deps for reproducible bytecode.
Non-negotiables
- V4 needs EIP-1153 (TSTORE). Live on 96369 (Cancun). If a reboot changes that, STOP.
- Treasury
0x9011…owns the live positions (NOT the DAO Safe). Migrate 50%. - One-sided WLUX pools (LBTC, LAVAX) are honeypots at their V3 edge — init V4 at oracle
price, place WLUX as a resting bid below oracle. Never clone the edge. Dual-control
oracle (
price+ independentexpected_tick); out-of-band aborts before touching V3. - No mempool gossip: broadcast every tx to all 5 validators at ≥250 gwei; nonce drift is
detected on the latest (mined) nonce, and a
nonce too lowafter our own txhash mined is SUCCESS, not a conflict (RUNBOOK §3 — load-bearing, do not weaken). - Contracts: solc 0.8.26, cancun, via_ir, optimizer 44444444, bytecode_hash=none (reproducible).
- No broadcast without
DRY_RUN=0(EXECUTE=1) +LUX_PRIVATE_KEY.