Files
zeekayandHanzo Dev 33b43f3682 v3v4: decomplect the V3→V4 migration tooling (Rob Pike pass) + canonical RUNBOOK
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]>
2026-07-05 10:16:32 -07:00

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 Safe 0x51284dc2133e8d3a8e213dca6a6fa768cfdfcce2; 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-gated IUnlockCallback: 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 exec transport).
  • 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; freezes baseline.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 + independent expected_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 low after 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.