Files
smom-dbis-138/scripts/deployment/c138-cw-bridge-mainnet-pct.sh
defiQUG f3d2961b97
Some checks failed
CI/CD Pipeline / Lint and Format (push) Failing after 46s
CI/CD Pipeline / Terraform Validation (push) Failing after 35s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 37s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 1m50s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 2m19s
Validation / validate-genesis (push) Successful in 51s
Validation / validate-terraform (push) Failing after 39s
Validation / validate-kubernetes (push) Failing after 10s
CI/CD Pipeline / Solidity Contracts (push) Failing after 12m56s
Validation / validate-smart-contracts (push) Failing after 12s
CI/CD Pipeline / Security Scanning (push) Failing after 15m52s
Validation / validate-security (push) Failing after 10m59s
Validation / validate-documentation (push) Failing after 17s
Validate Token List / validate (push) Failing after 30s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 26s
Verify Deployment / Verify Deployment (push) Failing after 56s
feat: add hybx omnl stack and gas pmm tooling
2026-04-24 12:56:40 -07:00

233 lines
8.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Chain 138 → Ethereum Mainnet only: bridge PCT of each canonical c* balance via CWMultiTokenBridgeL1.
# Default PCT: 17.25% (= 1725 basis points of 10000; override with PCT_BP).
#
# Modes:
# --plan-only Write JSON + summary (default)
# --check-routes destinations(token, Mainnet selector) for each token
# --emit-cmds Print approve + lockAndSend cast lines (review before running)
#
# Env: PRIVATE_KEY (for --emit-cmds deployer address), RPC_URL_138, CW_L1_BRIDGE_CHAIN138,
# LINK_TOKEN_CHAIN138, RECIPIENT_ADDRESS (default: deployer)
# PCT_BP (default 1725 = 17.25%)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
PROXMOX_ROOT="$(cd "$SMOM_ROOT/.." && pwd)"
cd "$SMOM_ROOT"
MODE="plan"
while [[ $# -gt 0 ]]; do
case "$1" in
--plan-only) MODE="plan" ;;
--check-routes) MODE="check" ;;
--emit-cmds) MODE="emit" ;;
--help|-h)
grep '^#' "$0" | head -22
exit 0
;;
*) echo "Unknown: $1"; exit 1 ;;
esac
shift || true
done
if [[ -f "$PROXMOX_ROOT/scripts/lib/load-project-env.sh" ]]; then
# shellcheck disable=SC1090
PROJECT_ROOT="$PROXMOX_ROOT" source "$PROXMOX_ROOT/scripts/lib/load-project-env.sh"
elif [[ -f .env ]]; then
set -a && source .env && set +a
fi
PCT_BP="${PCT_BP:-1725}"
RPC="${RPC_URL_138:-${CHAIN138_RPC:-${RPC_URL:-http://192.168.11.211:8545}}}"
OUT_JSON="${OUT_JSON:-$SMOM_ROOT/reports/status/c138-bridge-mainnet-pct-latest.json}"
BRIDGE="${CW_L1_BRIDGE_CHAIN138:-}"
DEPLOYER=""
if [[ -n "${PRIVATE_KEY:-}" ]]; then
DEPLOYER="$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)"
fi
RECIPIENT="${RECIPIENT_ADDRESS:-$DEPLOYER}"
MAINNET_SEL=5009297550715157269
export RPC OUT_JSON DEPLOYER RECIPIENT BRIDGE PCT_BP MAINNET_SEL
# Canonical c* only (EXPLORER_TOKEN_LIST_CROSSCHECK §5)
read -r -d '' TOKEN_ROWS << 'EOF' || true
cUSDT:0x93E66202A11B1772E55407B32B44e5Cd8eda7f22
cUSDC:0xf22258f57794CC8E06237084b353Ab30fFfa640b
cEURC:0x8085961F9cF02b4d800A3c6d386D31da4B34266a
cEURT:0xdf4b71c61E5912712C1Bdd451416B9aC26949d72
cGBPC:0x003960f16D9d34F2e98d62723B6721Fb92074aD2
cGBPT:0x350f54e4D23795f86A9c03988c7135357CCaD97c
cAUDC:0xD51482e567c03899eecE3CAe8a058161FD56069D
cJPYC:0xEe269e1226a334182aace90056EE4ee5Cc8A6770
cCHFC:0x873990849DDa5117d7C644f0aF24370797C03885
cCADC:0x54dBd40cF05e15906A2C21f600937e96787f5679
cXAUC:0x290E52a8819A4fbD0714E517225429aA2B70EC6b
cXAUT:0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E
EOF
export TOKEN_ROWS
mkdir -p "$(dirname "$OUT_JSON")"
python3 << PY
import json, subprocess, os, re
rpc = os.environ.get("RPC", "http://192.168.11.211:8545")
deployer = os.environ.get("DEPLOYER", "")
recipient = os.environ.get("RECIPIENT", deployer)
bridge = os.environ.get("BRIDGE", "")
pct_bp = int(os.environ.get("PCT_BP", "1725"))
sel = int(os.environ.get("MAINNET_SEL", "5009297550715157269"))
rows = []
for line in os.environ.get("TOKEN_ROWS", "").strip().split("\n"):
if not line.strip():
continue
sym, addr = line.split(":", 1)
rows.append((sym.strip(), addr.strip()))
def balance_of(addr):
if not deployer:
return None
r = subprocess.run(
["cast", "call", addr, "balanceOf(address)(uint256)", deployer, "--rpc-url", rpc],
capture_output=True, text=True,
)
if r.returncode != 0:
return None
m = re.match(r"^\s*(\d+)", r.stdout.strip())
return int(m.group(1)) if m else None
plan = {
"schema": "c138-bridge-mainnet-pct/v1",
"rpc_url": rpc,
"deployer": deployer,
"recipient": recipient,
"cw_l1_bridge": bridge,
"destination": "Ethereum Mainnet",
"chain_selector": str(sel),
"pct_basis_points": pct_bp,
"pct_human": f"{pct_bp / 100:.2f}%",
"tokens": [],
}
for sym, addr in rows:
bal = balance_of(addr)
if bal is None:
plan["tokens"].append({"symbol": sym, "address": addr, "error": "balance_of_failed"})
continue
amt = bal * pct_bp // 10000
plan["tokens"].append({
"symbol": sym,
"address": addr,
"balance_wei": str(bal),
"amount_to_bridge_wei": str(amt),
})
path = os.environ.get("OUT_JSON", "")
with open(path, "w") as f:
json.dump(plan, f, indent=2)
print(json.dumps({"written": path, "tokens": len(plan["tokens"])}))
PY
python3 - <<'PY'
import json, os
with open(os.environ["OUT_JSON"]) as f:
p = json.load(f)
print("\n=== c* → Mainnet only:", p.get("pct_human"), "of balance (integer base units) ===\n")
print(f"Deployer: {p.get('deployer','?')}\nRecipient: {p.get('recipient','?')}\nBridge: {p.get('cw_l1_bridge') or '(unset)'}\n")
for t in p["tokens"]:
if "error" in t:
print(f"{t['symbol']}: {t['error']}")
continue
sym = t["symbol"]
amt = int(t["amount_to_bridge_wei"])
if sym.startswith("cXAU"):
print(f"{sym:<10} bridge: {amt / 1e6:,.6f} troy oz (wei={t['amount_to_bridge_wei']})")
else:
print(f"{sym:<10} bridge: {amt / 1e6:,.6f} tokens (wei={t['amount_to_bridge_wei']})")
print("\nJSON:", os.environ["OUT_JSON"])
PY
if [[ "$MODE" == "plan" ]]; then
exit 0
fi
[[ -n "$BRIDGE" ]] || { echo "Set CW_L1_BRIDGE_CHAIN138"; exit 1; }
code=$(cast code "$BRIDGE" --rpc-url "$RPC" 2>/dev/null || echo "0x")
[[ -n "$code" && "$code" != "0x" ]] || { echo "No contract at CW_L1_BRIDGE_CHAIN138=$BRIDGE"; exit 1; }
if [[ "$MODE" == "check" ]]; then
echo ""
echo "=== Mainnet route: $BRIDGE ==="
while IFS= read -r line; do
[[ -z "$line" ]] && continue
sym="${line%%:*}"
addr="${line#*:}"
dest=$(cast call "$BRIDGE" "destinations(address,uint64)(address,bool)" "$addr" "$MAINNET_SEL" --rpc-url "$RPC" 2>/dev/null || echo "ERR")
echo "$sym ($addr): destinations(Mainnet)=$dest"
done <<< "$TOKEN_ROWS"
exit 0
fi
if [[ "$MODE" == "emit" ]]; then
[[ -n "${PRIVATE_KEY:-}" ]] || { echo "PRIVATE_KEY required for --emit-cmds"; exit 1; }
[[ -n "$RECIPIENT" ]] || { echo "RECIPIENT_ADDRESS or deployer required"; exit 1; }
LINK_TOKEN="${LINK_TOKEN_CHAIN138:-${LINK_TOKEN:-}}"
[[ -n "$LINK_TOKEN" ]] || { echo "Set LINK_TOKEN or LINK_TOKEN_CHAIN138 for fee approval lines"; exit 1; }
export LINK_TOKEN
OUT_CAST="${OUT_CAST:-$SMOM_ROOT/reports/status/c138-bridge-mainnet-pct-cast-commands.sh}"
export OUT_CAST
{
echo "#!/usr/bin/env bash"
echo "# Generated: c138-cw-bridge-mainnet-pct.sh --emit-cmds"
echo "# Review fee + reserve verifier. Fund LINK on deployer for CCIP fees."
echo "set -euo pipefail"
python3 <<'PY'
import json, os, subprocess
rpc = os.environ["RPC"]
bridge = os.environ["BRIDGE"]
recipient = os.environ["RECIPIENT"]
link = os.environ["LINK_TOKEN"]
sel = int(os.environ["MAINNET_SEL"])
with open(os.environ["OUT_JSON"]) as f:
plan = json.load(f)
for t in plan["tokens"]:
if "error" in t:
continue
amt = t.get("amount_to_bridge_wei", "0")
if int(amt) == 0:
continue
sym, token = t["symbol"], t["address"]
chk = subprocess.run(
["cast", "call", bridge, "destinations(address,uint64)(address,bool)", token, str(sel), "--rpc-url", rpc],
capture_output=True, text=True,
)
if chk.returncode != 0 or "true" not in chk.stdout:
print(f"# SKIP {sym}: destination Mainnet not enabled or query failed")
print(f"# cast output: {chk.stdout.strip()}")
continue
fee = subprocess.run(
["cast", "call", bridge,
"calculateFee(address,uint64,address,uint256)(uint256)",
token, str(sel), recipient, amt,
"--rpc-url", rpc],
capture_output=True, text=True,
)
fq = fee.stdout.strip().split()[0] if fee.returncode == 0 else "0"
print("")
print(f"# {sym} -> Mainnet amount={amt} fee_wei={fq}")
print(f"cast send {link} \"approve(address,uint256)\" {bridge} {fq} --rpc-url {rpc} --private-key \"$PRIVATE_KEY\" --legacy --gas-limit 120000")
print(f"cast send {token} \"approve(address,uint256)\" {bridge} {amt} --rpc-url {rpc} --private-key \"$PRIVATE_KEY\" --legacy --gas-limit 400000")
print(f"cast send {bridge} \"lockAndSend(address,uint64,address,uint256)\" {token} {sel} {recipient} {amt} --rpc-url {rpc} --private-key \"$PRIVATE_KEY\" --legacy --gas-limit 4000000")
PY
} > "$OUT_CAST"
chmod +x "$OUT_CAST"
echo "Wrote: $OUT_CAST"
wc -l "$OUT_CAST"
exit 0
fi