Files
zeekayandHanzo Dev 91af9c85b5 v3v4: harden mainnet V3->V4 migration executor (Red FIX-THEN-SHIP)
DEX LP migration toolkit for Lux C-Chain 96369. Contract (LiquidityDeployer.sol)
unchanged and RED-approved (16/16 tests). All hardening is in the Python executor,
plan builder, Makefile, and RUNBOOK.

FIX 1 (HIGH #4) oracle sanity bound — BLOCKED BROADCAST.
  The old one-sided guard (tick_o < v3edge-1000) only fired at ~25,000x error; a 10x
  oracle typo cloned a honeypot and let an LBTC-seller drain 4.29M WLUX. oracle.json is
  now a dual-control object per base {price, expected_tick(, band_ticks)}: the executor
  recomputes the tick from `price` and ABORTS if it strays > ORACLE_TICK_BAND (2000
  ticks ~= +/-22%) from the SECOND operator's independent expected_tick. A hard
  ONESIDED_MAX_WLUX cap (5,000,000e18) bounds per-pool WLUX at risk. The honeypot-edge
  check is kept as a backstop. Oracle validation runs BEFORE any V3 decrease.
  tools/execute.py: onesided_band_ok(), compute_onesided_bid(); tools/oracle.example.json.

FIX 2 (HIGH #5b) freeze baseline — prevents double-decrease to 75%.
  Re-running `make snapshot && make plan` mid-migration used to read already-halved
  liquidity as the new baseline and remove 50% of the remainder. build_plan.py now
  freezes tools/baseline.json (original liquidity + one-shot 50% target per tokenId) on
  first plan and reads it thereafter; a position already <= its baseline target is a
  no-op via the executor's on-chain precheck. Regenerating the plan is idempotent.

FIX 3 (MED #6) per-tx nonce + stop masking nonce errors.
  Re-read the live pending nonce before every tx and ABORT on drift (concurrent signer
  on treasury 0x9011); preflight asserts nonce stable across two reads 3s apart. A
  nonce too low/high is now FATAL (abort before the 240s receipt wait) instead of being
  masked as "sent"; benign "already known" still counts as accepted; 0/5 acceptance
  aborts.

FIX 4 (LOW) finalize + gas gate.
  Opt-in FINALIZE=1: after all adds, zero residual LD approvals and transferOwnership
  LD -> DAO Safe (0x51284...). Execute-mode preflight aborts if baseFee > gasPrice.
  state.json pools deduped (upsert by v4PoolId).

Verify: make test 16/16; tools/test_red_oracle.py PASS (K>=1.5x REJECT, 10x aborts);
make migrate dry-run clean end-to-end; fat-finger oracle aborts before touching V3.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-04 21:33:24 -07:00

44 lines
1.8 KiB
Bash

#!/usr/bin/env bash
# Deterministic build inputs: ensure v4-core's dependency submodules are present
# at PINNED commits (the repo ships empty lib/ dirs). Idempotent. No network if
# already populated. Records the exact commits so bytecode is reproducible.
# POSIX/bash-3.2 compatible (macOS default shell) — no associative arrays.
set -eu
HERE="$(cd "$(dirname "$0")/.." && pwd)"
V4CORE="$(cd "$HERE/contracts/lib/v4-core" && pwd)" # resolves the symlink
# name|url|pin (pins matched to the deployable artifacts in this repo)
DEPS="
forge-std|https://github.com/foundry-rs/forge-std|bf647bd6046f2f7da30d0c2bf435e5c76a780c1b
solmate|https://github.com/transmissions11/solmate|89365b880c4f3c786bdd453d4b8e8fe410344a69
openzeppelin-contracts|https://github.com/OpenZeppelin/openzeppelin-contracts|a22c8862f3fd80cd2bd5fab703b4e93ef3830040
"
clone_pin() { # dir url pin
dir="$1"; url="$2"; pin="$3"
if [ -d "$dir/.git" ] || [ -f "$dir/.git" ]; then
echo " $dir present ($(git -C "$dir" rev-parse --short HEAD 2>/dev/null || echo '?'))"
return 0
fi
echo " cloning $url @ $pin"
rm -rf "$dir"; git clone --quiet "$url" "$dir"; git -C "$dir" checkout --quiet "$pin"
}
echo "v4-core deps -> $V4CORE/lib"
echo "$DEPS" | while IFS='|' read -r name url pin; do
[ -z "$name" ] && continue
clone_pin "$V4CORE/lib/$name" "$url" "$pin"
done
clone_pin "$V4CORE/lib/forge-std/lib/ds-test" "https://github.com/dapphub/ds-test" "e282159d5170298eb2455a6c05280ab5a73a4ef0"
echo "python deps:"
python3 - <<'PY'
import importlib
for m in ("eth_abi", "eth_account", "eth_utils"):
try:
importlib.import_module(m); print(f" {m} OK")
except ImportError:
print(f" {m} MISSING -> pip3 install {m}")
PY
echo "setup done. Build the PoolManager artifact once: (cd $V4CORE && forge build src/PoolManager.sol)"