176 lines
7.4 KiB
Python
176 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import time
|
|
from decimal import Decimal
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
FUNDING = ROOT / "reports" / "extraction" / "promod-uniswap-v2-phase1-funding-readiness-latest.json"
|
|
CHECKLIST = ROOT / "reports" / "extraction" / "promod-uniswap-v2-phase1-execution-checklist-latest.json"
|
|
REPORT = ROOT / "reports" / "extraction" / "promod-uniswap-v2-phase1-funding-bundle-latest.json"
|
|
DOC = ROOT / "docs" / "03-deployment" / "PROMOD_UNISWAP_V2_PHASE1_FUNDING_BUNDLE.md"
|
|
|
|
|
|
def now() -> str:
|
|
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
|
|
|
|
def load(path: Path):
|
|
return json.loads(path.read_text())
|
|
|
|
|
|
def write_json(path: Path, payload) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps(payload, indent=2) + "\n")
|
|
|
|
|
|
def write_text(path: Path, text: str) -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(text.rstrip() + "\n")
|
|
|
|
|
|
def env_ref(name: str) -> str:
|
|
return "${" + name + "}"
|
|
|
|
|
|
def deploy_block(entry: dict, funding_entry: dict) -> str:
|
|
token_addresses = entry["token_addresses"]
|
|
cwusdt = token_addresses["cWUSDT"]
|
|
cwusdc = token_addresses["cWUSDC"]
|
|
envs = entry["required_uniswap_v2_env_vars"]
|
|
factory_var = next(name for name in envs if name.endswith("_FACTORY"))
|
|
router_var = next(name for name in envs if name.endswith("_ROUTER"))
|
|
rpc_var = entry["rpc_env_keys"][0]
|
|
amount_raw = min(
|
|
int(funding_entry["cwusdt"]["balance_raw"]),
|
|
int(funding_entry["cwusdc"]["balance_raw"]),
|
|
)
|
|
|
|
lines = [
|
|
"source smom-dbis-138/scripts/load-env.sh >/dev/null",
|
|
f'export RPC_URL="{env_ref(rpc_var)}"',
|
|
f'export FACTORY="{env_ref(factory_var)}"',
|
|
f'export ROUTER="{env_ref(router_var)}"',
|
|
f'export CWUSDT="{cwusdt}"',
|
|
f'export CWUSDC="{cwusdc}"',
|
|
'export SIGNER="$(cast wallet address --private-key "$PRIVATE_KEY")"',
|
|
f'export AMOUNT_RAW="{amount_raw}"',
|
|
'export DEADLINE="$(( $(date +%s) + 3600 ))"',
|
|
"",
|
|
'PAIR="$(cast call "$FACTORY" \'getPair(address,address)(address)\' "$CWUSDT" "$CWUSDC" --rpc-url "$RPC_URL")"',
|
|
'if [[ "$PAIR" == "0x0000000000000000000000000000000000000000" ]]; then',
|
|
' cast send "$FACTORY" \'createPair(address,address)(address)\' "$CWUSDT" "$CWUSDC" \\',
|
|
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
|
|
"fi",
|
|
"",
|
|
'cast send "$CWUSDT" \'approve(address,uint256)(bool)\' "$ROUTER" "$AMOUNT_RAW" \\',
|
|
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
|
|
"",
|
|
'cast send "$CWUSDC" \'approve(address,uint256)(bool)\' "$ROUTER" "$AMOUNT_RAW" \\',
|
|
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
|
|
"",
|
|
'cast send "$ROUTER" \\',
|
|
" 'addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256)' \\",
|
|
' "$CWUSDT" "$CWUSDC" "$AMOUNT_RAW" "$AMOUNT_RAW" "$AMOUNT_RAW" "$AMOUNT_RAW" "$SIGNER" "$DEADLINE" \\',
|
|
' --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL"',
|
|
"",
|
|
"python3 scripts/lib/promod_uniswap_v2_live_pair_discovery.py --write-discovered",
|
|
"bash scripts/verify/build-promod-uniswap-v2-promotion-gates.sh",
|
|
"node cross-chain-pmm-lps/scripts/validate-deployment-status.cjs cross-chain-pmm-lps/config/deployment-status.json",
|
|
]
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main() -> None:
|
|
funding = load(FUNDING)
|
|
checklist = load(CHECKLIST)
|
|
funding_by_chain = {entry["chain_id"]: entry for entry in funding["entries"]}
|
|
checklist_by_chain = {entry["chain_id"]: entry for entry in checklist["entries"]}
|
|
|
|
entries = []
|
|
for chain_id in [1, 10, 25, 56, 100, 137, 8453, 42161, 42220, 43114]:
|
|
f = funding_by_chain[chain_id]
|
|
c = checklist_by_chain[chain_id]
|
|
missing_tokens = []
|
|
if Decimal(f["cwusdt"]["balance_human"]) <= 0:
|
|
missing_tokens.append("cWUSDT")
|
|
if Decimal(f["cwusdc"]["balance_human"]) <= 0:
|
|
missing_tokens.append("cWUSDC")
|
|
gas_issue = not f["native_balance_ok_for_ops"]
|
|
exact_block = deploy_block(c, f) if f["funding_ready_now"] else None
|
|
entries.append(
|
|
{
|
|
"chain_id": chain_id,
|
|
"network": f["network"],
|
|
"phase_1_pair": f["phase_1_pair"],
|
|
"tokens_missing": missing_tokens,
|
|
"minimum_gas_issue": gas_issue,
|
|
"native_balance": f["native_balance"],
|
|
"max_equal_seed_human": f["max_equal_seed_human"],
|
|
"funding_ready_now": f["funding_ready_now"],
|
|
"exact_post_funding_deploy_block": exact_block,
|
|
"rpc_env_key": f["rpc_env_key"],
|
|
"router": f["router"],
|
|
"factory": f["factory"],
|
|
"token_addresses": c["token_addresses"],
|
|
}
|
|
)
|
|
|
|
payload = {
|
|
"generated_at": now(),
|
|
"program_name": "Mr. Promod Uniswap V2 phase 1 funding bundle",
|
|
"purpose": "Strict per-chain funding bundle: missing tokens, gas issue, and exact deploy block to run once each chain is funded.",
|
|
"signer": funding["signer"],
|
|
"phase_1_pair": funding["phase_1_pair"],
|
|
"entries": entries,
|
|
"source_artifacts": [
|
|
"reports/extraction/promod-uniswap-v2-phase1-funding-readiness-latest.json",
|
|
"reports/extraction/promod-uniswap-v2-phase1-execution-checklist-latest.json",
|
|
],
|
|
}
|
|
write_json(REPORT, payload)
|
|
|
|
lines = [
|
|
"# Mr. Promod Uniswap V2 Phase 1 Funding Bundle",
|
|
"",
|
|
f"- Generated: `{payload['generated_at']}`",
|
|
f"- Signer: `{payload['signer']}`",
|
|
"- Purpose: strict per-chain funding bundle for `cWUSDT/cWUSDC` phase-1 rollout.",
|
|
"",
|
|
"| Chain | Network | Tokens Missing | Minimum Gas Issue | Max Equal Seed | Funding Ready Now |",
|
|
"|---|---|---|---|---:|---|",
|
|
]
|
|
for entry in entries:
|
|
missing = ", ".join(f"`{x}`" for x in entry["tokens_missing"]) or "`none`"
|
|
lines.append(
|
|
f"| `{entry['chain_id']}` | {entry['network']} | {missing} | "
|
|
f"`{str(entry['minimum_gas_issue']).lower()}` | "
|
|
f"`{entry['max_equal_seed_human']}` | "
|
|
f"`{str(entry['funding_ready_now']).lower()}` |"
|
|
)
|
|
lines.append("")
|
|
lines.append("## Exact Post-Funding Deploy Blocks")
|
|
lines.append("")
|
|
for entry in entries:
|
|
lines.append(f"### Chain `{entry['chain_id']}` — {entry['network']}")
|
|
lines.append("")
|
|
lines.append(f"- Tokens missing: {', '.join(f'`{x}`' for x in entry['tokens_missing']) or '`none`'}")
|
|
lines.append(f"- Minimum gas issue: `{str(entry['minimum_gas_issue']).lower()}`")
|
|
lines.append(f"- Max equal seed after funding snapshot: `{entry['max_equal_seed_human']}`")
|
|
lines.append("")
|
|
if entry["exact_post_funding_deploy_block"]:
|
|
lines.append("```bash")
|
|
lines.append(entry["exact_post_funding_deploy_block"])
|
|
lines.append("```")
|
|
else:
|
|
lines.append("Post-funding deploy block becomes executable once the missing token and gas blockers are cleared. Use the chain-specific execution checklist plus this chain's env and token addresses.")
|
|
lines.append("")
|
|
write_text(DOC, "\n".join(lines))
|
|
print(REPORT)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|