1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#!/usr/bin/env bash
#
# Deploys Love on two local anvil nodes with different chain ids and checks
# that CREATE2 gives the token the same address on both. The address embeds the
# wETH address, so this only holds for chains sharing one wETH deployment —
# both nodes here are given the same WETH.
#
# Usage: ./script/multichain-check.sh
#
# Env overrides: PORT_A, PORT_B, CHAIN_ID_A, CHAIN_ID_B, SALT, WETH
set -euo pipefail
PORT_A=${PORT_A:-8545}
PORT_B=${PORT_B:-8546}
CHAIN_ID_A=${CHAIN_ID_A:-31337}
CHAIN_ID_B=${CHAIN_ID_B:-31338}
# First anvil dev account — local only, never use this key anywhere else.
ANVIL_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
CREATE2_FACTORY=0x4e59b44847b379578588920cA78FbF26c0B4956C
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
RPC_A="http://127.0.0.1:$PORT_A"
RPC_B="http://127.0.0.1:$PORT_B"
TMP=$(mktemp -d)
PIDS=()
cleanup() {
for pid in ${PIDS[@]+"${PIDS[@]}"}; do
kill "$pid" 2>/dev/null || true
done
rm -rf "$TMP"
rm -rf "$ROOT/broadcast/Love.s.sol/$CHAIN_ID_A" "$ROOT/broadcast/Love.s.sol/$CHAIN_ID_B"
rmdir "$ROOT/broadcast/Love.s.sol" "$ROOT/broadcast" 2>/dev/null || true
}
trap cleanup EXIT
start_node() {
local port=$1 chain_id=$2 rpc=$3
anvil --port "$port" --chain-id "$chain_id" --silent >"$TMP/anvil-$port.log" 2>&1 &
PIDS+=($!)
for _ in $(seq 1 50); do
if cast chain-id --rpc-url "$rpc" >/dev/null 2>&1; then
return 0
fi
sleep 0.2
done
echo "anvil on port $port never came up:" >&2
cat "$TMP/anvil-$port.log" >&2
exit 1
}
deploy() {
local rpc=$1 label=$2
forge script script/Love.s.sol:LoveScript \
--rpc-url "$rpc" \
--private-key "$ANVIL_KEY" \
--broadcast \
--skip-simulation >"$TMP/deploy-$label.log" 2>&1 ||
{
echo "deploy on $label failed:" >&2
cat "$TMP/deploy-$label.log" >&2
exit 1
}
grep -oE 'predicted +0x[0-9a-fA-F]{40}' "$TMP/deploy-$label.log" | tail -1 | grep -oE '0x[0-9a-fA-F]{40}'
}
report() {
local rpc=$1 addr=$2 label=$3
local code
code=$(cast code "$addr" --rpc-url "$rpc")
if [[ ${#code} -le 2 ]]; then
echo "$label: no code at $addr" >&2
exit 1
fi
printf '%s %s %s bytes %s / %s weth %s\n' \
"$label" "$addr" "$(((${#code} - 2) / 2))" \
"$(cast call "$addr" 'name()(string)' --rpc-url "$rpc")" \
"$(cast call "$addr" 'symbol()(string)' --rpc-url "$rpc")" \
"$(cast call "$addr" 'WETH()(address)' --rpc-url "$rpc")"
}
cd "$ROOT"
for cmd in anvil cast forge; do
command -v "$cmd" >/dev/null || {
echo "$cmd not found — install foundry" >&2
exit 1
}
done
start_node "$PORT_A" "$CHAIN_ID_A" "$RPC_A"
start_node "$PORT_B" "$CHAIN_ID_B" "$RPC_B"
for pair in "A|$RPC_A" "B|$RPC_B"; do
IFS='|' read -r label rpc <<<"$pair"
if [[ $(cast code "$CREATE2_FACTORY" --rpc-url "$rpc") == "0x" ]]; then
echo "$label: deterministic deployer missing at $CREATE2_FACTORY" >&2
exit 1
fi
done
forge build >/dev/null
ADDR_A=$(deploy "$RPC_A" A)
ADDR_B=$(deploy "$RPC_B" B)
echo "chain $CHAIN_ID_A"
report "$RPC_A" "$ADDR_A" " A"
echo "chain $CHAIN_ID_B"
report "$RPC_B" "$ADDR_B" " B"
if [[ "$ADDR_A" != "$ADDR_B" ]]; then
echo "FAIL: addresses differ" >&2
exit 1
fi
echo "OK: same address on both chains"
|