From bf07b59954de0d6f953d066f29c8a32d849956c2 Mon Sep 17 00:00:00 2001 From: david-uniswap <274080779+david-uniswap@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:40:53 -0700 Subject: [PATCH] fix(hyperevm): cast-version-independent field reads; fix run-latest restore in the registry trap Follow-up to #164 review (non-blocking comments left with the approval): - merge_extra_deploys.py read cast --json, whose shape changed in cast 1.8 (wrapped in schema_version/success/data). Use the plain field accessors (cast receipt contractAddress|blockNumber, cast tx to|input), which print bare values on every version. - hyperevm.sh registry: the ERR trap copied several run-1*.json files to /dev/null, which only errors. It now copies the newest broadcast to run-latest.json explicitly. Registry step re-run against main's committed deployments/json/999.json: byte-identical. Co-Authored-By: Claude Fable 5.1 --- script/hyperevm/hyperevm.sh | 2 +- script/hyperevm/merge_extra_deploys.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/script/hyperevm/hyperevm.sh b/script/hyperevm/hyperevm.sh index a8789bb9..2299d81a 100755 --- a/script/hyperevm/hyperevm.sh +++ b/script/hyperevm/hyperevm.sh @@ -72,7 +72,7 @@ case $STEP in forge build >/dev/null || exit 1 # never lose the committed registry if a step fails: work on a backup and restore on any error cp "$J" "$J.bak" 2>/dev/null || true - trap '[ -f "$J.bak" ] && { echo "registry step failed, restoring $J"; mv "$J.bak" "$J"; }; cp broadcast/Deploy-all.s.sol/'$CHAIN'/run-1*.json /dev/null 2>&1' ERR + trap '[ -f "$J.bak" ] && { echo "registry step failed, restoring $J"; mv "$J.bak" "$J"; }; cp "$(ls broadcast/Deploy-all.s.sol/'$CHAIN'/run-1*.json | sort | tail -1)" broadcast/Deploy-all.s.sol/'$CHAIN'/run-latest.json' ERR set -e rm -f "$J" for b in $(ls broadcast/Deploy-all.s.sol/$CHAIN/run-1*.json | sort); do diff --git a/script/hyperevm/merge_extra_deploys.py b/script/hyperevm/merge_extra_deploys.py index 7df534d3..2fde589b 100644 --- a/script/hyperevm/merge_extra_deploys.py +++ b/script/hyperevm/merge_extra_deploys.py @@ -49,19 +49,20 @@ def on_main(c): runs = {} for x in cfg["extra"]: addr, tx = x["address"], x["deploymentTxn"] - rc = json.loads(sh("cast", "receipt", tx, "--json", "--rpc-url", rpc)) - created = (rc.get("contractAddress") or "").lower() - if not created: # CREATE2 through the deterministic factory: derive keccak(0xff ++ factory ++ salt ++ keccak(initcode)) - txj = json.loads(sh("cast", "tx", tx, "--json", "--rpc-url", rpc)) - data = txj["input"] + # field accessors print plain values on every cast version; --json output changed shape in cast 1.8 + created = sh("cast", "receipt", tx, "contractAddress", "--rpc-url", rpc).lower() + block = int(sh("cast", "receipt", tx, "blockNumber", "--rpc-url", rpc)) + if not created.startswith("0x") or len(created) != 42: # CREATE2 through the deterministic factory + data = sh("cast", "tx", tx, "input", "--rpc-url", rpc) + factory = sh("cast", "tx", tx, "to", "--rpc-url", rpc) salt, initcode = "0x" + data[2:66], "0x" + data[66:] init_hash = sh("cast", "keccak", initcode)[2:] - created = "0x" + sh("cast", "keccak", "0xff" + txj["to"][2:] + salt[2:] + init_hash)[-40:].lower() + created = "0x" + sh("cast", "keccak", "0xff" + factory[2:] + salt[2:] + init_hash)[-40:].lower() if created != addr.lower(): sys.exit(f"{x['name']}: tx {tx} created {created}, not {addr}") if sh("cast", "code", addr, "--rpc-url", rpc) == "0x": sys.exit(f"{x['name']}: no code at {addr}") - ts = int(sh("cast", "block", str(int(rc["blockNumber"], 16)), "-f", "timestamp", "--rpc-url", rpc)) * 1000 + ts = int(sh("cast", "block", str(block), "-f", "timestamp", "--rpc-url", rpc)) * 1000 # chronicles hashes the implementation's creation input for proxies, the contract's own otherwise hash_tx = x.get("implementationTxn", tx) h = sh("cast", "keccak", sh("cast", "tx", hash_tx, "input", "--rpc-url", rpc))[2:]