-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreplay-tx.sh
250 lines (231 loc) · 4.52 KB
/
replay-tx.sh
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#!/usr/bin/env bash
set -euo pipefail
fail() {
local msg="$1"
echo "ERROR: $1" 1>&2
exit 1
}
if ! command -v jq &>/dev/null; then
fail "'jq' command is missing"
fi
if ! command -v curl &>/dev/null; then
fail "'curl' command is missing"
fi
addr=
nonce=
output=
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
cat <<EOF
Replay Safe transaction.
USAGE:
$0 [-o|--output FILE] ADDR NONCE
OPTIONS:
-h|--help Display this output message
-o|--output FILE The file to output the transaction builder JSON to.
If left unset, will output to standard out.
ARGUMENTS:
ADDR The Safe with the transaction to replay.
NONCE The nonce to replay
EXAMPLES:
Generate Safe transaction builder JSON document and print it.
$0 eth:0xcA771eda0c70aA7d053aB1B25004559B918FE662 42
Generate Safe transaction builder JSON document and save it to 'tx.json'.
$0 eth:0xcA771eda0c70aA7d053aB1B25004559B918FE662 42
EOF
;;
-o|--output)
if [[ $# -lt 2 ]]; then
fail "missing argument for '-o|--output' option"
fi
shift
output="$1"
;;
*)
if [[ -z "$addr" ]]; then
addr="$1"
elif [[ -z "$nonce" ]]; then
nonce="$1"
else
fail "unexpected argument '$1'"
fi
;;
esac
shift
done
if [[ -z "$addr" ]] || [[ -z "$nonce" ]]; then
fail "missing Safe address and nonce arguments"
fi
if ! [[ "$addr" =~ ^[a-z]+:0x[0-9a-fA-F]{40}$ ]]; then
fail "invalid Safe address"
fi
if ! [[ "$nonce" =~ [0-9]+ ]]; then
fail "invalid nonce"
fi
case "$(echo "$addr" | cut -d ':' -f1)" in
eth)
network=mainnet
chain_id=1
;;
oeth)
network=optimism
chain_id=10
;;
bnb)
network=bsc
chain_id=56
;;
gno)
network=gnosis-chain
chain_id=100
;;
pol)
network=polygon
chain_id=137
;;
okb)
network=xlayer
chain_id=196
;;
zksync)
network=zksync
chain_id=324
;;
wc)
network=worldchain
chain_id=480
;;
zkevm)
network=zkevm
chain_id=1101
;;
mnt)
network=mantle
chain_id=5000
;;
base)
network=base
chain_id=8453
;;
chiado)
network=chiado
chain_id=10200
;;
arb1)
network=arbitrum
chain_id=42161
;;
celo)
network=celo
chain_id=42220
;;
avax)
network=avalanche
chain_id=43114
;;
linea)
network=linea
chain_id=59144
;;
blast)
network=blast
chain_id=81457
;;
basesep)
network=base-sepolia
chain_id=84532
;;
scr)
network=scroll
chain_id=534352
;;
sep)
network=sepolia
chain_id=11155111
;;
aurora)
network=aurora
chain_id=1313161554
;;
*) fail "unknown network" ;;
esac
safe="$(echo "$addr" | cut -d ':' -f2)"
txs="$(
curl -s --fail \
-H "Accept: application/json" \
"https://safe-transaction-$network.safe.global/api/v1/safes/$safe/multisig-transactions/?nonce=$nonce"
)"
if [[ "$(echo "$txs" | jq .count)" -ne 1 ]]; then
fail "could not find Safe transaction"
fi
tx="$(echo "$txs" | jq '.results[0]')"
is_multisend="$(
echo "$tx" | jq '
.to == "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D" and
.operation == 1 and
.dataDecoded.method == "multiSend" and
(.dataDecoded.parameters | length) == 1 and
.dataDecoded.parameters[0].type == "bytes" and
(.dataDecoded.parameters[0].valueDecoded | type) == "array"
'
)"
if [[ "$is_multisend" == "true" ]]; then
calls="$(echo "$tx" | jq '.dataDecoded.parameters[0].valueDecoded')"
else
calls="$(echo "$tx" | jq '[{ to, operation, value, data, dataDecoded }]')"
fi
has_delegatecall="$(echo "$calls" | jq 'any(.operation == 1)')"
if [[ "$has_delegatecall" == "true" ]]; then
fail "delegate calls not supported"
fi
builder="$(
echo "$calls" | jq '{
version: "1.0",
chainId: "'$chain_id'",
createdAt: 0,
meta: {
name: "Replay transaction nonce '$nonce'",
description: "",
txBuilderVersion: "",
createdFromSafeAddress: "'$safe'",
createdFromOwnerAddress: "",
checksum: "0x0000000000000000000000000000000000000000000000000000000000000000"
},
transactions: [
.[] | if .dataDecoded then {
to,
value,
data: null,
contractMethod: {
inputs: [
.dataDecoded.parameters[] | {
internalType: .type,
name,
type,
}
],
name: .dataDecoded.method,
paybale: (.value != "0")
},
contractInputsValues: ([
.dataDecoded.parameters[] | {
key: .name,
value,
}
] | from_entries),
} else {
to,
value,
data,
contractMethod: null,
contractInputsValues: null,
} end
],
}'
)"
if [[ -z "$output" ]]; then
echo "$builder" | jq .
else
echo "$builder" | jq . > "$output"
fi