@matterlabs/zksync-js 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/ethers/client.cjs +1705 -259
- package/dist/adapters/ethers/client.cjs.map +1 -1
- package/dist/adapters/ethers/client.d.ts +11 -0
- package/dist/adapters/ethers/client.js +6 -6
- package/dist/adapters/ethers/index.cjs +5254 -2335
- package/dist/adapters/ethers/index.cjs.map +1 -1
- package/dist/adapters/ethers/index.d.ts +4 -0
- package/dist/adapters/ethers/index.js +9 -9
- package/dist/adapters/ethers/resources/contracts/types.d.ts +15 -0
- package/dist/adapters/ethers/resources/deposits/context.d.ts +3 -3
- package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +2 -2
- package/dist/adapters/ethers/resources/deposits/services/verification.d.ts +1 -1
- package/dist/adapters/ethers/resources/interop/address.d.ts +18 -0
- package/dist/adapters/ethers/resources/interop/attributes/resource.d.ts +9 -0
- package/dist/adapters/ethers/resources/interop/context.d.ts +36 -0
- package/dist/adapters/ethers/resources/interop/index.d.ts +63 -0
- package/dist/adapters/ethers/resources/interop/resolvers.d.ts +9 -0
- package/dist/adapters/ethers/resources/interop/routes/direct.d.ts +2 -0
- package/dist/adapters/ethers/resources/interop/routes/indirect.d.ts +2 -0
- package/dist/adapters/ethers/resources/interop/routes/types.d.ts +13 -0
- package/dist/adapters/ethers/resources/interop/services/erc20.d.ts +15 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/bundle.d.ts +15 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/data-fetchers.d.ts +17 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/decoders.d.ts +12 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/index.d.ts +13 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/polling.d.ts +7 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/status.d.ts +5 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/topics.d.ts +6 -0
- package/dist/adapters/ethers/resources/interop/services/starter-data.d.ts +6 -0
- package/dist/adapters/ethers/resources/interop/types.d.ts +16 -0
- package/dist/adapters/ethers/resources/withdrawals/context.d.ts +2 -2
- package/dist/adapters/ethers/sdk.cjs +3384 -931
- package/dist/adapters/ethers/sdk.cjs.map +1 -1
- package/dist/adapters/ethers/sdk.d.ts +10 -8
- package/dist/adapters/ethers/sdk.js +7 -7
- package/dist/adapters/viem/client.cjs +760 -64
- package/dist/adapters/viem/client.cjs.map +1 -1
- package/dist/adapters/viem/client.js +6 -4
- package/dist/adapters/viem/index.cjs +404 -276
- package/dist/adapters/viem/index.cjs.map +1 -1
- package/dist/adapters/viem/index.d.ts +1 -0
- package/dist/adapters/viem/index.js +9 -8
- package/dist/adapters/viem/resources/deposits/context.d.ts +3 -3
- package/dist/adapters/viem/resources/deposits/services/gas.d.ts +2 -2
- package/dist/adapters/viem/resources/deposits/services/verification.d.ts +1 -1
- package/dist/adapters/viem/resources/withdrawals/context.d.ts +2 -2
- package/dist/adapters/viem/sdk.cjs +84 -92
- package/dist/adapters/viem/sdk.cjs.map +1 -1
- package/dist/adapters/viem/sdk.js +6 -6
- package/dist/{chunk-KRIRXY74.js → chunk-5AG6B7UX.js} +38 -63
- package/dist/{chunk-NNFWIAVG.js → chunk-AIFHAPJC.js} +9 -3
- package/dist/{chunk-NCR42O6O.js → chunk-C3AGOEHR.js} +11 -1
- package/dist/{chunk-GIXLOHLK.js → chunk-FBKBF7YM.js} +1534 -12
- package/dist/{chunk-VRL6Y4YJ.js → chunk-IYEDEUXG.js} +1 -1
- package/dist/chunk-JNWHQJU3.js +209 -0
- package/dist/{chunk-7VP6742W.js → chunk-KLNFDFLA.js} +43 -32
- package/dist/{chunk-GNERKUWO.js → chunk-QDJOEVGJ.js} +2 -2
- package/dist/{chunk-EWLA4NUE.js → chunk-RRKVUW3G.js} +1377 -78
- package/dist/{chunk-KAMEGD6I.js → chunk-SRPKTXIF.js} +1 -1
- package/dist/{chunk-WY36Z6YB.js → chunk-UIXU35ZU.js} +57 -19
- package/dist/{chunk-P5PIWVEO.js → chunk-ZVHFVUDE.js} +14 -26
- package/dist/core/abi.d.ts +5 -0
- package/dist/core/constants.cjs +10 -0
- package/dist/core/constants.cjs.map +1 -1
- package/dist/core/constants.d.ts +10 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/index.cjs +1676 -186
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +5 -5
- package/dist/core/internal/abis/IERC7786Attributes.d.ts +42 -0
- package/dist/core/internal/abis/IInteropCenter.d.ts +211 -0
- package/dist/core/internal/abis/IInteropHandler.d.ts +166 -0
- package/dist/core/internal/abis/InteropCenter.d.ts +578 -0
- package/dist/core/internal/abis/InteropRootStorage.d.ts +20 -0
- package/dist/core/internal/abis/L2MessageVerification.d.ts +277 -0
- package/dist/core/resources/interop/attributes/bundle.d.ts +6 -0
- package/dist/core/resources/interop/attributes/call.d.ts +6 -0
- package/dist/core/resources/interop/attributes/index.d.ts +4 -0
- package/dist/core/resources/interop/attributes/resource.d.ts +12 -0
- package/dist/core/resources/interop/attributes/types.d.ts +4 -0
- package/dist/core/resources/interop/events.d.ts +7 -0
- package/dist/core/resources/interop/finalization.d.ts +60 -0
- package/dist/core/resources/interop/plan.d.ts +39 -0
- package/dist/core/resources/interop/route.d.ts +15 -0
- package/dist/core/rpc/types.d.ts +9 -0
- package/dist/core/types/errors.d.ts +56 -5
- package/dist/core/types/fees.d.ts +9 -0
- package/dist/core/types/flows/base.d.ts +1 -1
- package/dist/core/types/flows/interop.d.ts +207 -0
- package/dist/core/types/flows/withdrawals.d.ts +0 -8
- package/dist/core/types/primitives.d.ts +1 -0
- package/dist/core/types/transactions.d.ts +10 -0
- package/dist/core/utils/addr.d.ts +2 -2
- package/dist/core/utils/events.d.ts +12 -0
- package/dist/core/utils/hash.d.ts +5 -0
- package/dist/core/utils/index.d.ts +5 -0
- package/dist/core/utils/number.d.ts +2 -0
- package/dist/index.cjs +1686 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -5
- package/package.json +6 -2
- package/dist/chunk-NGXRO2ZX.js +0 -142
- package/dist/core/resources/withdrawals/events.d.ts +0 -9
|
@@ -5,6 +5,19 @@ var sha3 = require('@noble/hashes/sha3');
|
|
|
5
5
|
var utils = require('@noble/hashes/utils');
|
|
6
6
|
|
|
7
7
|
// src/adapters/ethers/resources/deposits/services/verification.ts
|
|
8
|
+
|
|
9
|
+
// src/core/utils/hash.ts
|
|
10
|
+
var RegExpHex = /^0x[0-9a-fA-F]*$/;
|
|
11
|
+
var isHash = (x, length) => {
|
|
12
|
+
if (!x || typeof x !== "string") return false;
|
|
13
|
+
return (length === void 0 || x.length === length) && RegExpHex.test(x);
|
|
14
|
+
};
|
|
15
|
+
var isHashArray = (x, length) => {
|
|
16
|
+
if (!Array.isArray(x)) return false;
|
|
17
|
+
return x.every((item) => isHash(item, length));
|
|
18
|
+
};
|
|
19
|
+
var isHash66 = (x) => isHash(x, 66);
|
|
20
|
+
var isHash66Array = (x) => isHashArray(x, 66);
|
|
8
21
|
var k256hex = (s) => `0x${utils.bytesToHex(sha3.keccak_256(utils.utf8ToBytes(s)))}`.toLowerCase();
|
|
9
22
|
var FORMAL_ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
10
23
|
var ETH_ADDRESS = "0x0000000000000000000000000000000000000001";
|
|
@@ -12,6 +25,9 @@ var L2_ASSET_ROUTER_ADDRESS = "0x0000000000000000000000000000000000010003";
|
|
|
12
25
|
var L2_NATIVE_TOKEN_VAULT_ADDRESS = "0x0000000000000000000000000000000000010004";
|
|
13
26
|
var L1_MESSENGER_ADDRESS = "0x0000000000000000000000000000000000008008";
|
|
14
27
|
var L2_BASE_TOKEN_ADDRESS = "0x000000000000000000000000000000000000800A";
|
|
28
|
+
var L2_INTEROP_CENTER_ADDRESS = "0x000000000000000000000000000000000001000d";
|
|
29
|
+
var L2_INTEROP_ROOT_STORAGE_ADDRESS = "0x0000000000000000000000000000000000010008";
|
|
30
|
+
var BUNDLE_IDENTIFIER = "0x01";
|
|
15
31
|
var TOPIC_L1_MESSAGE_SENT_NEW = k256hex("L1MessageSent(uint256,bytes32,bytes)");
|
|
16
32
|
var TOPIC_L1_MESSAGE_SENT_LEG = k256hex("L1MessageSent(address,bytes32,bytes)");
|
|
17
33
|
var TOPIC_CANONICAL_ASSIGNED = "0x779f441679936c5441b671969f37400b8c3ed0071cb47444431bf985754560df";
|
|
@@ -23,8 +39,14 @@ var DEFAULT_PUBDATA_BYTES = 155n;
|
|
|
23
39
|
var DEFAULT_ABI_BYTES = 400n;
|
|
24
40
|
var SAFE_L1_BRIDGE_GAS = 700000n;
|
|
25
41
|
|
|
42
|
+
// src/core/utils/number.ts
|
|
43
|
+
var isNumber = (x) => typeof x === "number" && Number.isFinite(x);
|
|
44
|
+
var isBigint = (x) => typeof x === "bigint";
|
|
45
|
+
|
|
26
46
|
// src/core/utils/addr.ts
|
|
27
|
-
|
|
47
|
+
function isAddress(x) {
|
|
48
|
+
return isHash(x, 42);
|
|
49
|
+
}
|
|
28
50
|
function isAddressEq(a, b) {
|
|
29
51
|
return a.toLowerCase() === b.toLowerCase();
|
|
30
52
|
}
|
|
@@ -43,6 +65,14 @@ function normalizeAddrEq(a, b) {
|
|
|
43
65
|
var hexEq = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
44
66
|
var normalizeL1Token = (token) => isAddressEq(token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : token;
|
|
45
67
|
|
|
68
|
+
// src/core/utils/index.ts
|
|
69
|
+
function sleep(ms) {
|
|
70
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
71
|
+
}
|
|
72
|
+
function assertNever(x) {
|
|
73
|
+
throw new Error("Unexpected action type: " + String(x));
|
|
74
|
+
}
|
|
75
|
+
|
|
46
76
|
// src/core/errors/formatter.ts
|
|
47
77
|
function elideMiddle(s, max = 96) {
|
|
48
78
|
if (s.length <= max) return s;
|
|
@@ -53,7 +83,7 @@ function shortJSON(v, max = 240) {
|
|
|
53
83
|
try {
|
|
54
84
|
const s = JSON.stringify(
|
|
55
85
|
v,
|
|
56
|
-
(_k, val) =>
|
|
86
|
+
(_k, val) => isBigint(val) ? `${val.toString()}n` : val
|
|
57
87
|
);
|
|
58
88
|
return s.length > max ? elideMiddle(s, max) : s;
|
|
59
89
|
} catch {
|
|
@@ -73,7 +103,7 @@ function formatContextLine(ctx) {
|
|
|
73
103
|
if (txHash !== void 0)
|
|
74
104
|
parts.push(`txHash=${typeof txHash === "string" ? txHash : shortJSON(txHash, 96)}`);
|
|
75
105
|
if (nonce !== void 0) {
|
|
76
|
-
const nonceStr = typeof nonce === "string" ||
|
|
106
|
+
const nonceStr = typeof nonce === "string" || isNumber(nonce) || isBigint(nonce) ? String(nonce) : shortJSON(nonce, 48);
|
|
77
107
|
parts.push(`nonce=${nonceStr}`);
|
|
78
108
|
}
|
|
79
109
|
return parts.length ? ` ${kv("Context", parts.join(" \u2022 "))}` : void 0;
|
|
@@ -103,17 +133,17 @@ function formatCause(c) {
|
|
|
103
133
|
const head = [];
|
|
104
134
|
if (obj.name !== void 0) {
|
|
105
135
|
const nameVal = obj.name;
|
|
106
|
-
const nameStr = typeof nameVal === "string" ||
|
|
136
|
+
const nameStr = typeof nameVal === "string" || isNumber(nameVal) || isBigint(nameVal) || typeof nameVal === "boolean" ? String(nameVal) : shortJSON(nameVal, 120);
|
|
107
137
|
head.push(`name=${nameStr}`);
|
|
108
138
|
}
|
|
109
139
|
if (obj.code !== void 0) {
|
|
110
140
|
const codeVal = obj.code;
|
|
111
|
-
const codeStr = typeof codeVal === "string" ||
|
|
141
|
+
const codeStr = typeof codeVal === "string" || isNumber(codeVal) || isBigint(codeVal) || typeof codeVal === "boolean" ? String(codeVal) : shortJSON(codeVal, 120);
|
|
112
142
|
head.push(`code=${codeStr}`);
|
|
113
143
|
}
|
|
114
144
|
if (head.length) out.push(` ${kv("Cause", head.join(" "))}`);
|
|
115
145
|
if (obj.message) {
|
|
116
|
-
const messageStr = typeof obj.message === "string" ||
|
|
146
|
+
const messageStr = typeof obj.message === "string" || isNumber(obj.message) || isBigint(obj.message) || typeof obj.message === "boolean" ? String(obj.message) : shortJSON(obj.message, 600);
|
|
117
147
|
out.push(` message=${elideMiddle(messageStr, 600)}`);
|
|
118
148
|
}
|
|
119
149
|
if (obj.data) {
|
|
@@ -188,12 +218,18 @@ if (kInspect) {
|
|
|
188
218
|
enumerable: false
|
|
189
219
|
});
|
|
190
220
|
}
|
|
191
|
-
function isZKsyncError(e) {
|
|
221
|
+
function isZKsyncError(e, opts) {
|
|
192
222
|
if (!e || typeof e !== "object") return false;
|
|
193
223
|
const maybe = e;
|
|
194
224
|
if (!("envelope" in maybe)) return false;
|
|
195
225
|
const envelope = maybe.envelope;
|
|
196
|
-
|
|
226
|
+
if (typeof envelope?.type !== "string" || typeof envelope?.message !== "string") return false;
|
|
227
|
+
if (opts?.type && envelope.type !== opts.type) return false;
|
|
228
|
+
if (opts?.resource && envelope.resource !== opts.resource) return false;
|
|
229
|
+
if (opts?.operation && envelope.operation !== opts.operation) return false;
|
|
230
|
+
if (opts?.messageIncludes && !envelope.message.toLowerCase().includes(opts.messageIncludes.toLowerCase()))
|
|
231
|
+
return false;
|
|
232
|
+
return true;
|
|
197
233
|
}
|
|
198
234
|
function isReceiptNotFound(e) {
|
|
199
235
|
const chain = [];
|
|
@@ -308,11 +344,9 @@ var OP_WITHDRAWALS = {
|
|
|
308
344
|
rawReceipt: "withdrawals.finalize.fetchParams:rawReceipt",
|
|
309
345
|
messengerIndex: "withdrawals.finalize.fetchParams:messengerIndex",
|
|
310
346
|
proof: "withdrawals.finalize.fetchParams:proof",
|
|
311
|
-
network: "withdrawals.finalize.fetchParams:network"
|
|
312
|
-
ensureAddresses: "withdrawals.finalize.fetchParams:ensureAddresses"
|
|
347
|
+
network: "withdrawals.finalize.fetchParams:network"
|
|
313
348
|
},
|
|
314
349
|
readiness: {
|
|
315
|
-
ensureAddresses: "withdrawals.finalize.readiness:ensureAddresses",
|
|
316
350
|
isFinalized: "withdrawals.finalize.readiness:isWithdrawalFinalized",
|
|
317
351
|
simulate: "withdrawals.finalize.readiness:simulate"
|
|
318
352
|
},
|
|
@@ -322,6 +356,54 @@ var OP_WITHDRAWALS = {
|
|
|
322
356
|
estimate: "withdrawals.finalize.estimateFinalizationFees"
|
|
323
357
|
}
|
|
324
358
|
};
|
|
359
|
+
var OP_INTEROP = {
|
|
360
|
+
// high-level flow ops (match resource methods)
|
|
361
|
+
quote: "interop.quote",
|
|
362
|
+
tryQuote: "interop.tryQuote",
|
|
363
|
+
prepare: "interop.prepare",
|
|
364
|
+
tryPrepare: "interop.tryPrepare",
|
|
365
|
+
create: "interop.create",
|
|
366
|
+
tryCreate: "interop.tryCreate",
|
|
367
|
+
status: "interop.status",
|
|
368
|
+
wait: "interop.wait",
|
|
369
|
+
tryWait: "interop.tryWait",
|
|
370
|
+
finalize: "interop.finalize",
|
|
371
|
+
tryFinalize: "interop.tryFinalize",
|
|
372
|
+
context: {
|
|
373
|
+
chainTypeManager: "interop.chainTypeManager",
|
|
374
|
+
protocolVersion: "interop.protocolVersion"
|
|
375
|
+
},
|
|
376
|
+
// route-specific ops (keep names aligned with files)
|
|
377
|
+
routes: {
|
|
378
|
+
direct: {
|
|
379
|
+
preflight: "interop.routes.direct:preflight",
|
|
380
|
+
build: "interop.routes.direct:build"
|
|
381
|
+
},
|
|
382
|
+
indirect: {
|
|
383
|
+
preflight: "interop.routes.indirect:preflight",
|
|
384
|
+
build: "interop.routes.indirect:build"
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
// execution path (nonce, gas, send, wait) – mirrors deposits’ style
|
|
388
|
+
exec: {
|
|
389
|
+
sendStep: "interop.exec:sendStep",
|
|
390
|
+
waitStep: "interop.exec:waitStep"
|
|
391
|
+
},
|
|
392
|
+
// status service (logs & derivation)
|
|
393
|
+
svc: {
|
|
394
|
+
status: {
|
|
395
|
+
sourceReceipt: "interop.svc.status:sourceReceipt",
|
|
396
|
+
parseSentLog: "interop.svc.status:parseSentLog",
|
|
397
|
+
dstLogs: "interop.svc.status:dstLogs",
|
|
398
|
+
derive: "interop.svc.status:derive",
|
|
399
|
+
getRoot: "interop.svc.status:getRoot"
|
|
400
|
+
},
|
|
401
|
+
wait: {
|
|
402
|
+
poll: "interop.svc.wait:poll",
|
|
403
|
+
timeout: "interop.svc.wait:timeout"
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
};
|
|
325
407
|
|
|
326
408
|
// src/core/errors/factory.ts
|
|
327
409
|
function createError(type, input) {
|
|
@@ -358,7 +440,7 @@ var I_BRIDGEHUB = new ethers.Interface([
|
|
|
358
440
|
"event NewPriorityRequest(uint256 indexed chainId, address indexed sender, bytes32 txHash, uint256 txId, bytes data)"
|
|
359
441
|
]);
|
|
360
442
|
var TOPIC_BRIDGEHUB_NPR = I_BRIDGEHUB.getEvent("NewPriorityRequest").topicHash;
|
|
361
|
-
function
|
|
443
|
+
function getL2TransactionHashFromLogs(logs) {
|
|
362
444
|
for (const lg of logs) {
|
|
363
445
|
if ((lg.topics?.[0] ?? "").toLowerCase() === TOPIC_BRIDGEHUB_NPR.toLowerCase()) {
|
|
364
446
|
try {
|
|
@@ -385,7 +467,7 @@ function extractL2TxHashFromL1Logs(logs) {
|
|
|
385
467
|
async function waitForL2ExecutionFromL1Tx(l1, l2, l1TxHash) {
|
|
386
468
|
const l1Receipt = await l1.waitForTransaction(l1TxHash);
|
|
387
469
|
if (!l1Receipt) throw new Error("No L1 receipt found");
|
|
388
|
-
const l2TxHash =
|
|
470
|
+
const l2TxHash = getL2TransactionHashFromLogs(l1Receipt.logs);
|
|
389
471
|
if (!l2TxHash) {
|
|
390
472
|
throw createError("VERIFICATION", {
|
|
391
473
|
message: "Failed to extract L2 transaction hash from L1 logs",
|
|
@@ -3182,6 +3264,63 @@ var IERC20ABI = [
|
|
|
3182
3264
|
];
|
|
3183
3265
|
var IERC20_default = IERC20ABI;
|
|
3184
3266
|
|
|
3267
|
+
// src/core/internal/abis/IERC7786Attributes.ts
|
|
3268
|
+
var IERC7786AttributesABI = [
|
|
3269
|
+
{
|
|
3270
|
+
inputs: [
|
|
3271
|
+
{
|
|
3272
|
+
internalType: "bytes",
|
|
3273
|
+
name: "_executionAddress",
|
|
3274
|
+
type: "bytes"
|
|
3275
|
+
}
|
|
3276
|
+
],
|
|
3277
|
+
name: "executionAddress",
|
|
3278
|
+
outputs: [],
|
|
3279
|
+
stateMutability: "pure",
|
|
3280
|
+
type: "function"
|
|
3281
|
+
},
|
|
3282
|
+
{
|
|
3283
|
+
inputs: [
|
|
3284
|
+
{
|
|
3285
|
+
internalType: "uint256",
|
|
3286
|
+
name: "_indirectCallMessageValue",
|
|
3287
|
+
type: "uint256"
|
|
3288
|
+
}
|
|
3289
|
+
],
|
|
3290
|
+
name: "indirectCall",
|
|
3291
|
+
outputs: [],
|
|
3292
|
+
stateMutability: "pure",
|
|
3293
|
+
type: "function"
|
|
3294
|
+
},
|
|
3295
|
+
{
|
|
3296
|
+
inputs: [
|
|
3297
|
+
{
|
|
3298
|
+
internalType: "uint256",
|
|
3299
|
+
name: "_interopCallValue",
|
|
3300
|
+
type: "uint256"
|
|
3301
|
+
}
|
|
3302
|
+
],
|
|
3303
|
+
name: "interopCallValue",
|
|
3304
|
+
outputs: [],
|
|
3305
|
+
stateMutability: "pure",
|
|
3306
|
+
type: "function"
|
|
3307
|
+
},
|
|
3308
|
+
{
|
|
3309
|
+
inputs: [
|
|
3310
|
+
{
|
|
3311
|
+
internalType: "bytes",
|
|
3312
|
+
name: "_unbundlerAddress",
|
|
3313
|
+
type: "bytes"
|
|
3314
|
+
}
|
|
3315
|
+
],
|
|
3316
|
+
name: "unbundlerAddress",
|
|
3317
|
+
outputs: [],
|
|
3318
|
+
stateMutability: "pure",
|
|
3319
|
+
type: "function"
|
|
3320
|
+
}
|
|
3321
|
+
];
|
|
3322
|
+
var IERC7786Attributes_default = IERC7786AttributesABI;
|
|
3323
|
+
|
|
3185
3324
|
// src/core/internal/abis/Mailbox.ts
|
|
3186
3325
|
var MailboxABI = [
|
|
3187
3326
|
{
|
|
@@ -3558,206 +3697,1213 @@ var MailboxABI = [
|
|
|
3558
3697
|
];
|
|
3559
3698
|
var Mailbox_default = MailboxABI;
|
|
3560
3699
|
|
|
3561
|
-
// src/
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
}
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
[
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
}
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3700
|
+
// src/core/internal/abis/InteropCenter.ts
|
|
3701
|
+
var InteropCenterABI = [
|
|
3702
|
+
{
|
|
3703
|
+
inputs: [
|
|
3704
|
+
{
|
|
3705
|
+
internalType: "bytes4",
|
|
3706
|
+
name: "selector",
|
|
3707
|
+
type: "bytes4"
|
|
3708
|
+
}
|
|
3709
|
+
],
|
|
3710
|
+
name: "AttributeAlreadySet",
|
|
3711
|
+
type: "error"
|
|
3712
|
+
},
|
|
3713
|
+
{
|
|
3714
|
+
inputs: [
|
|
3715
|
+
{
|
|
3716
|
+
internalType: "bytes4",
|
|
3717
|
+
name: "selector",
|
|
3718
|
+
type: "bytes4"
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
internalType: "uint256",
|
|
3722
|
+
name: "restriction",
|
|
3723
|
+
type: "uint256"
|
|
3724
|
+
}
|
|
3725
|
+
],
|
|
3726
|
+
name: "AttributeViolatesRestriction",
|
|
3727
|
+
type: "error"
|
|
3728
|
+
},
|
|
3729
|
+
{
|
|
3730
|
+
inputs: [
|
|
3731
|
+
{
|
|
3732
|
+
internalType: "uint256",
|
|
3733
|
+
name: "expected",
|
|
3734
|
+
type: "uint256"
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
internalType: "uint256",
|
|
3738
|
+
name: "actual",
|
|
3739
|
+
type: "uint256"
|
|
3740
|
+
}
|
|
3741
|
+
],
|
|
3742
|
+
name: "IndirectCallValueMismatch",
|
|
3743
|
+
type: "error"
|
|
3744
|
+
},
|
|
3745
|
+
{
|
|
3746
|
+
inputs: [
|
|
3747
|
+
{
|
|
3748
|
+
internalType: "bytes",
|
|
3749
|
+
name: "interoperableAddress",
|
|
3750
|
+
type: "bytes"
|
|
3751
|
+
}
|
|
3752
|
+
],
|
|
3753
|
+
name: "InteroperableAddressChainReferenceNotEmpty",
|
|
3754
|
+
type: "error"
|
|
3755
|
+
},
|
|
3756
|
+
{
|
|
3757
|
+
inputs: [
|
|
3758
|
+
{
|
|
3759
|
+
internalType: "bytes",
|
|
3760
|
+
name: "interoperableAddress",
|
|
3761
|
+
type: "bytes"
|
|
3762
|
+
}
|
|
3763
|
+
],
|
|
3764
|
+
name: "InteroperableAddressNotEmpty",
|
|
3765
|
+
type: "error"
|
|
3766
|
+
},
|
|
3767
|
+
{
|
|
3768
|
+
inputs: [
|
|
3769
|
+
{
|
|
3770
|
+
internalType: "bytes",
|
|
3771
|
+
name: "",
|
|
3772
|
+
type: "bytes"
|
|
3773
|
+
}
|
|
3774
|
+
],
|
|
3775
|
+
name: "InteroperableAddressParsingError",
|
|
3776
|
+
type: "error"
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
inputs: [
|
|
3780
|
+
{
|
|
3781
|
+
internalType: "uint256",
|
|
3782
|
+
name: "expectedMsgValue",
|
|
3783
|
+
type: "uint256"
|
|
3784
|
+
},
|
|
3785
|
+
{
|
|
3786
|
+
internalType: "uint256",
|
|
3787
|
+
name: "providedMsgValue",
|
|
3788
|
+
type: "uint256"
|
|
3789
|
+
}
|
|
3790
|
+
],
|
|
3791
|
+
name: "MsgValueMismatch",
|
|
3792
|
+
type: "error"
|
|
3793
|
+
},
|
|
3794
|
+
{
|
|
3795
|
+
inputs: [],
|
|
3796
|
+
name: "NotInGatewayMode",
|
|
3797
|
+
type: "error"
|
|
3798
|
+
},
|
|
3799
|
+
{
|
|
3800
|
+
inputs: [
|
|
3801
|
+
{
|
|
3802
|
+
internalType: "uint256",
|
|
3803
|
+
name: "sourceChainId",
|
|
3804
|
+
type: "uint256"
|
|
3805
|
+
},
|
|
3806
|
+
{
|
|
3807
|
+
internalType: "uint256",
|
|
3808
|
+
name: "destinationChainId",
|
|
3809
|
+
type: "uint256"
|
|
3810
|
+
}
|
|
3811
|
+
],
|
|
3812
|
+
name: "NotL2ToL2",
|
|
3813
|
+
type: "error"
|
|
3814
|
+
},
|
|
3815
|
+
{
|
|
3816
|
+
inputs: [],
|
|
3817
|
+
name: "SlotOccupied",
|
|
3818
|
+
type: "error"
|
|
3819
|
+
},
|
|
3820
|
+
{
|
|
3821
|
+
inputs: [
|
|
3822
|
+
{
|
|
3823
|
+
internalType: "address",
|
|
3824
|
+
name: "caller",
|
|
3825
|
+
type: "address"
|
|
3826
|
+
}
|
|
3827
|
+
],
|
|
3828
|
+
name: "Unauthorized",
|
|
3829
|
+
type: "error"
|
|
3830
|
+
},
|
|
3831
|
+
{
|
|
3832
|
+
inputs: [
|
|
3833
|
+
{
|
|
3834
|
+
internalType: "bytes4",
|
|
3835
|
+
name: "selector",
|
|
3836
|
+
type: "bytes4"
|
|
3837
|
+
}
|
|
3838
|
+
],
|
|
3839
|
+
name: "UnsupportedAttribute",
|
|
3840
|
+
type: "error"
|
|
3841
|
+
},
|
|
3842
|
+
{
|
|
3843
|
+
anonymous: false,
|
|
3844
|
+
inputs: [
|
|
3845
|
+
{
|
|
3846
|
+
indexed: false,
|
|
3847
|
+
internalType: "uint8",
|
|
3848
|
+
name: "version",
|
|
3849
|
+
type: "uint8"
|
|
3850
|
+
}
|
|
3851
|
+
],
|
|
3852
|
+
name: "Initialized",
|
|
3853
|
+
type: "event"
|
|
3854
|
+
},
|
|
3855
|
+
{
|
|
3856
|
+
anonymous: false,
|
|
3857
|
+
inputs: [
|
|
3858
|
+
{
|
|
3859
|
+
indexed: false,
|
|
3860
|
+
internalType: "bytes32",
|
|
3861
|
+
name: "l2l1MsgHash",
|
|
3862
|
+
type: "bytes32"
|
|
3863
|
+
},
|
|
3864
|
+
{
|
|
3865
|
+
indexed: false,
|
|
3866
|
+
internalType: "bytes32",
|
|
3867
|
+
name: "interopBundleHash",
|
|
3868
|
+
type: "bytes32"
|
|
3869
|
+
},
|
|
3870
|
+
{
|
|
3871
|
+
components: [
|
|
3872
|
+
{
|
|
3873
|
+
internalType: "bytes1",
|
|
3874
|
+
name: "version",
|
|
3875
|
+
type: "bytes1"
|
|
3876
|
+
},
|
|
3877
|
+
{
|
|
3878
|
+
internalType: "uint256",
|
|
3879
|
+
name: "sourceChainId",
|
|
3880
|
+
type: "uint256"
|
|
3881
|
+
},
|
|
3882
|
+
{
|
|
3883
|
+
internalType: "uint256",
|
|
3884
|
+
name: "destinationChainId",
|
|
3885
|
+
type: "uint256"
|
|
3886
|
+
},
|
|
3887
|
+
{
|
|
3888
|
+
internalType: "bytes32",
|
|
3889
|
+
name: "interopBundleSalt",
|
|
3890
|
+
type: "bytes32"
|
|
3891
|
+
},
|
|
3892
|
+
{
|
|
3893
|
+
components: [
|
|
3894
|
+
{
|
|
3895
|
+
internalType: "bytes1",
|
|
3896
|
+
name: "version",
|
|
3897
|
+
type: "bytes1"
|
|
3898
|
+
},
|
|
3899
|
+
{
|
|
3900
|
+
internalType: "bool",
|
|
3901
|
+
name: "shadowAccount",
|
|
3902
|
+
type: "bool"
|
|
3903
|
+
},
|
|
3904
|
+
{
|
|
3905
|
+
internalType: "address",
|
|
3906
|
+
name: "to",
|
|
3907
|
+
type: "address"
|
|
3908
|
+
},
|
|
3909
|
+
{
|
|
3910
|
+
internalType: "address",
|
|
3911
|
+
name: "from",
|
|
3912
|
+
type: "address"
|
|
3913
|
+
},
|
|
3914
|
+
{
|
|
3915
|
+
internalType: "uint256",
|
|
3916
|
+
name: "value",
|
|
3917
|
+
type: "uint256"
|
|
3918
|
+
},
|
|
3919
|
+
{
|
|
3920
|
+
internalType: "bytes",
|
|
3921
|
+
name: "data",
|
|
3922
|
+
type: "bytes"
|
|
3923
|
+
}
|
|
3924
|
+
],
|
|
3925
|
+
internalType: "struct InteropCall[]",
|
|
3926
|
+
name: "calls",
|
|
3927
|
+
type: "tuple[]"
|
|
3928
|
+
},
|
|
3929
|
+
{
|
|
3930
|
+
components: [
|
|
3931
|
+
{
|
|
3932
|
+
internalType: "bytes",
|
|
3933
|
+
name: "executionAddress",
|
|
3934
|
+
type: "bytes"
|
|
3935
|
+
},
|
|
3936
|
+
{
|
|
3937
|
+
internalType: "bytes",
|
|
3938
|
+
name: "unbundlerAddress",
|
|
3939
|
+
type: "bytes"
|
|
3940
|
+
}
|
|
3941
|
+
],
|
|
3942
|
+
internalType: "struct BundleAttributes",
|
|
3943
|
+
name: "bundleAttributes",
|
|
3944
|
+
type: "tuple"
|
|
3945
|
+
}
|
|
3946
|
+
],
|
|
3947
|
+
indexed: false,
|
|
3948
|
+
internalType: "struct InteropBundle",
|
|
3949
|
+
name: "interopBundle",
|
|
3950
|
+
type: "tuple"
|
|
3951
|
+
}
|
|
3952
|
+
],
|
|
3953
|
+
name: "InteropBundleSent",
|
|
3954
|
+
type: "event"
|
|
3955
|
+
},
|
|
3956
|
+
{
|
|
3957
|
+
anonymous: false,
|
|
3958
|
+
inputs: [
|
|
3959
|
+
{
|
|
3960
|
+
indexed: true,
|
|
3961
|
+
internalType: "bytes32",
|
|
3962
|
+
name: "sendId",
|
|
3963
|
+
type: "bytes32"
|
|
3964
|
+
},
|
|
3965
|
+
{
|
|
3966
|
+
indexed: false,
|
|
3967
|
+
internalType: "bytes",
|
|
3968
|
+
name: "sender",
|
|
3969
|
+
type: "bytes"
|
|
3970
|
+
},
|
|
3971
|
+
{
|
|
3972
|
+
indexed: false,
|
|
3973
|
+
internalType: "bytes",
|
|
3974
|
+
name: "recipient",
|
|
3975
|
+
type: "bytes"
|
|
3976
|
+
},
|
|
3977
|
+
{
|
|
3978
|
+
indexed: false,
|
|
3979
|
+
internalType: "bytes",
|
|
3980
|
+
name: "payload",
|
|
3981
|
+
type: "bytes"
|
|
3982
|
+
},
|
|
3983
|
+
{
|
|
3984
|
+
indexed: false,
|
|
3985
|
+
internalType: "uint256",
|
|
3986
|
+
name: "value",
|
|
3987
|
+
type: "uint256"
|
|
3988
|
+
},
|
|
3989
|
+
{
|
|
3990
|
+
indexed: false,
|
|
3991
|
+
internalType: "bytes[]",
|
|
3992
|
+
name: "attributes",
|
|
3993
|
+
type: "bytes[]"
|
|
3994
|
+
}
|
|
3995
|
+
],
|
|
3996
|
+
name: "MessageSent",
|
|
3997
|
+
type: "event"
|
|
3998
|
+
},
|
|
3999
|
+
{
|
|
4000
|
+
anonymous: false,
|
|
4001
|
+
inputs: [
|
|
4002
|
+
{
|
|
4003
|
+
indexed: true,
|
|
4004
|
+
internalType: "address",
|
|
4005
|
+
name: "oldAssetRouter",
|
|
4006
|
+
type: "address"
|
|
4007
|
+
},
|
|
4008
|
+
{
|
|
4009
|
+
indexed: true,
|
|
4010
|
+
internalType: "address",
|
|
4011
|
+
name: "newAssetRouter",
|
|
4012
|
+
type: "address"
|
|
4013
|
+
}
|
|
4014
|
+
],
|
|
4015
|
+
name: "NewAssetRouter",
|
|
4016
|
+
type: "event"
|
|
4017
|
+
},
|
|
4018
|
+
{
|
|
4019
|
+
anonymous: false,
|
|
4020
|
+
inputs: [
|
|
4021
|
+
{
|
|
4022
|
+
indexed: true,
|
|
4023
|
+
internalType: "address",
|
|
4024
|
+
name: "oldAssetTracker",
|
|
4025
|
+
type: "address"
|
|
4026
|
+
},
|
|
4027
|
+
{
|
|
4028
|
+
indexed: true,
|
|
4029
|
+
internalType: "address",
|
|
4030
|
+
name: "newAssetTracker",
|
|
4031
|
+
type: "address"
|
|
4032
|
+
}
|
|
4033
|
+
],
|
|
4034
|
+
name: "NewAssetTracker",
|
|
4035
|
+
type: "event"
|
|
4036
|
+
},
|
|
4037
|
+
{
|
|
4038
|
+
anonymous: false,
|
|
4039
|
+
inputs: [
|
|
4040
|
+
{
|
|
4041
|
+
indexed: true,
|
|
4042
|
+
internalType: "address",
|
|
4043
|
+
name: "previousOwner",
|
|
4044
|
+
type: "address"
|
|
4045
|
+
},
|
|
4046
|
+
{
|
|
4047
|
+
indexed: true,
|
|
4048
|
+
internalType: "address",
|
|
4049
|
+
name: "newOwner",
|
|
4050
|
+
type: "address"
|
|
4051
|
+
}
|
|
4052
|
+
],
|
|
4053
|
+
name: "OwnershipTransferStarted",
|
|
4054
|
+
type: "event"
|
|
4055
|
+
},
|
|
4056
|
+
{
|
|
4057
|
+
anonymous: false,
|
|
4058
|
+
inputs: [
|
|
4059
|
+
{
|
|
4060
|
+
indexed: true,
|
|
4061
|
+
internalType: "address",
|
|
4062
|
+
name: "previousOwner",
|
|
4063
|
+
type: "address"
|
|
4064
|
+
},
|
|
4065
|
+
{
|
|
4066
|
+
indexed: true,
|
|
4067
|
+
internalType: "address",
|
|
4068
|
+
name: "newOwner",
|
|
4069
|
+
type: "address"
|
|
4070
|
+
}
|
|
4071
|
+
],
|
|
4072
|
+
name: "OwnershipTransferred",
|
|
4073
|
+
type: "event"
|
|
4074
|
+
},
|
|
4075
|
+
{
|
|
4076
|
+
anonymous: false,
|
|
4077
|
+
inputs: [
|
|
4078
|
+
{
|
|
4079
|
+
indexed: false,
|
|
4080
|
+
internalType: "address",
|
|
4081
|
+
name: "account",
|
|
4082
|
+
type: "address"
|
|
4083
|
+
}
|
|
4084
|
+
],
|
|
4085
|
+
name: "Paused",
|
|
4086
|
+
type: "event"
|
|
4087
|
+
},
|
|
4088
|
+
{
|
|
4089
|
+
anonymous: false,
|
|
4090
|
+
inputs: [
|
|
4091
|
+
{
|
|
4092
|
+
indexed: false,
|
|
4093
|
+
internalType: "address",
|
|
4094
|
+
name: "account",
|
|
4095
|
+
type: "address"
|
|
4096
|
+
}
|
|
4097
|
+
],
|
|
4098
|
+
name: "Unpaused",
|
|
4099
|
+
type: "event"
|
|
4100
|
+
},
|
|
4101
|
+
{
|
|
4102
|
+
inputs: [],
|
|
4103
|
+
name: "L1_CHAIN_ID",
|
|
4104
|
+
outputs: [
|
|
4105
|
+
{
|
|
4106
|
+
internalType: "uint256",
|
|
4107
|
+
name: "",
|
|
4108
|
+
type: "uint256"
|
|
4109
|
+
}
|
|
4110
|
+
],
|
|
4111
|
+
stateMutability: "view",
|
|
4112
|
+
type: "function"
|
|
4113
|
+
},
|
|
4114
|
+
{
|
|
4115
|
+
inputs: [],
|
|
4116
|
+
name: "acceptOwnership",
|
|
4117
|
+
outputs: [],
|
|
4118
|
+
stateMutability: "nonpayable",
|
|
4119
|
+
type: "function"
|
|
4120
|
+
},
|
|
4121
|
+
{
|
|
4122
|
+
inputs: [
|
|
4123
|
+
{
|
|
4124
|
+
internalType: "uint256",
|
|
4125
|
+
name: "_chainId",
|
|
4126
|
+
type: "uint256"
|
|
4127
|
+
},
|
|
4128
|
+
{
|
|
4129
|
+
internalType: "bytes32",
|
|
4130
|
+
name: "_canonicalTxHash",
|
|
4131
|
+
type: "bytes32"
|
|
4132
|
+
},
|
|
4133
|
+
{
|
|
4134
|
+
internalType: "uint64",
|
|
4135
|
+
name: "_expirationTimestamp",
|
|
4136
|
+
type: "uint64"
|
|
4137
|
+
},
|
|
4138
|
+
{
|
|
4139
|
+
components: [
|
|
4140
|
+
{
|
|
4141
|
+
internalType: "bytes1",
|
|
4142
|
+
name: "version",
|
|
4143
|
+
type: "bytes1"
|
|
4144
|
+
},
|
|
4145
|
+
{
|
|
4146
|
+
internalType: "address",
|
|
4147
|
+
name: "originToken",
|
|
4148
|
+
type: "address"
|
|
4149
|
+
},
|
|
4150
|
+
{
|
|
4151
|
+
internalType: "bytes32",
|
|
4152
|
+
name: "baseTokenAssetId",
|
|
4153
|
+
type: "bytes32"
|
|
4154
|
+
},
|
|
4155
|
+
{
|
|
4156
|
+
internalType: "uint256",
|
|
4157
|
+
name: "baseTokenAmount",
|
|
4158
|
+
type: "uint256"
|
|
4159
|
+
},
|
|
4160
|
+
{
|
|
4161
|
+
internalType: "bytes32",
|
|
4162
|
+
name: "assetId",
|
|
4163
|
+
type: "bytes32"
|
|
4164
|
+
},
|
|
4165
|
+
{
|
|
4166
|
+
internalType: "uint256",
|
|
4167
|
+
name: "amount",
|
|
4168
|
+
type: "uint256"
|
|
4169
|
+
},
|
|
4170
|
+
{
|
|
4171
|
+
internalType: "uint256",
|
|
4172
|
+
name: "tokenOriginChainId",
|
|
4173
|
+
type: "uint256"
|
|
4174
|
+
}
|
|
4175
|
+
],
|
|
4176
|
+
internalType: "struct BalanceChange",
|
|
4177
|
+
name: "_balanceChange",
|
|
4178
|
+
type: "tuple"
|
|
4179
|
+
}
|
|
4180
|
+
],
|
|
4181
|
+
name: "forwardTransactionOnGatewayWithBalanceChange",
|
|
4182
|
+
outputs: [],
|
|
4183
|
+
stateMutability: "nonpayable",
|
|
4184
|
+
type: "function"
|
|
4185
|
+
},
|
|
4186
|
+
{
|
|
4187
|
+
inputs: [
|
|
4188
|
+
{
|
|
4189
|
+
internalType: "uint256",
|
|
4190
|
+
name: "_l1ChainId",
|
|
4191
|
+
type: "uint256"
|
|
4192
|
+
},
|
|
4193
|
+
{
|
|
4194
|
+
internalType: "address",
|
|
4195
|
+
name: "_owner",
|
|
4196
|
+
type: "address"
|
|
4197
|
+
}
|
|
4198
|
+
],
|
|
4199
|
+
name: "initL2",
|
|
4200
|
+
outputs: [],
|
|
4201
|
+
stateMutability: "nonpayable",
|
|
4202
|
+
type: "function"
|
|
4203
|
+
},
|
|
4204
|
+
{
|
|
4205
|
+
inputs: [
|
|
4206
|
+
{
|
|
4207
|
+
internalType: "address",
|
|
4208
|
+
name: "sender",
|
|
4209
|
+
type: "address"
|
|
4210
|
+
}
|
|
4211
|
+
],
|
|
4212
|
+
name: "interopBundleNonce",
|
|
4213
|
+
outputs: [
|
|
4214
|
+
{
|
|
4215
|
+
internalType: "uint256",
|
|
4216
|
+
name: "numberOfBundlesSent",
|
|
4217
|
+
type: "uint256"
|
|
4218
|
+
}
|
|
4219
|
+
],
|
|
4220
|
+
stateMutability: "view",
|
|
4221
|
+
type: "function"
|
|
4222
|
+
},
|
|
4223
|
+
{
|
|
4224
|
+
inputs: [],
|
|
4225
|
+
name: "owner",
|
|
4226
|
+
outputs: [
|
|
4227
|
+
{
|
|
4228
|
+
internalType: "address",
|
|
4229
|
+
name: "",
|
|
4230
|
+
type: "address"
|
|
4231
|
+
}
|
|
4232
|
+
],
|
|
4233
|
+
stateMutability: "view",
|
|
4234
|
+
type: "function"
|
|
4235
|
+
},
|
|
4236
|
+
{
|
|
4237
|
+
inputs: [
|
|
4238
|
+
{
|
|
4239
|
+
internalType: "bytes[]",
|
|
4240
|
+
name: "_attributes",
|
|
4241
|
+
type: "bytes[]"
|
|
4242
|
+
},
|
|
4243
|
+
{
|
|
4244
|
+
internalType: "enum IInteropCenter.AttributeParsingRestrictions",
|
|
4245
|
+
name: "_restriction",
|
|
4246
|
+
type: "uint8"
|
|
4247
|
+
}
|
|
4248
|
+
],
|
|
4249
|
+
name: "parseAttributes",
|
|
4250
|
+
outputs: [
|
|
4251
|
+
{
|
|
4252
|
+
components: [
|
|
4253
|
+
{
|
|
4254
|
+
internalType: "uint256",
|
|
4255
|
+
name: "interopCallValue",
|
|
4256
|
+
type: "uint256"
|
|
4257
|
+
},
|
|
4258
|
+
{
|
|
4259
|
+
internalType: "bool",
|
|
4260
|
+
name: "indirectCall",
|
|
4261
|
+
type: "bool"
|
|
4262
|
+
},
|
|
4263
|
+
{
|
|
4264
|
+
internalType: "uint256",
|
|
4265
|
+
name: "indirectCallMessageValue",
|
|
4266
|
+
type: "uint256"
|
|
4267
|
+
}
|
|
4268
|
+
],
|
|
4269
|
+
internalType: "struct CallAttributes",
|
|
4270
|
+
name: "callAttributes",
|
|
4271
|
+
type: "tuple"
|
|
4272
|
+
},
|
|
4273
|
+
{
|
|
4274
|
+
components: [
|
|
4275
|
+
{
|
|
4276
|
+
internalType: "bytes",
|
|
4277
|
+
name: "executionAddress",
|
|
4278
|
+
type: "bytes"
|
|
4279
|
+
},
|
|
4280
|
+
{
|
|
4281
|
+
internalType: "bytes",
|
|
4282
|
+
name: "unbundlerAddress",
|
|
4283
|
+
type: "bytes"
|
|
4284
|
+
}
|
|
4285
|
+
],
|
|
4286
|
+
internalType: "struct BundleAttributes",
|
|
4287
|
+
name: "bundleAttributes",
|
|
4288
|
+
type: "tuple"
|
|
4289
|
+
}
|
|
4290
|
+
],
|
|
4291
|
+
stateMutability: "pure",
|
|
4292
|
+
type: "function"
|
|
4293
|
+
},
|
|
4294
|
+
{
|
|
4295
|
+
inputs: [],
|
|
4296
|
+
name: "pause",
|
|
4297
|
+
outputs: [],
|
|
4298
|
+
stateMutability: "nonpayable",
|
|
4299
|
+
type: "function"
|
|
4300
|
+
},
|
|
4301
|
+
{
|
|
4302
|
+
inputs: [],
|
|
4303
|
+
name: "paused",
|
|
4304
|
+
outputs: [
|
|
4305
|
+
{
|
|
4306
|
+
internalType: "bool",
|
|
4307
|
+
name: "",
|
|
4308
|
+
type: "bool"
|
|
4309
|
+
}
|
|
4310
|
+
],
|
|
4311
|
+
stateMutability: "view",
|
|
4312
|
+
type: "function"
|
|
4313
|
+
},
|
|
4314
|
+
{
|
|
4315
|
+
inputs: [],
|
|
4316
|
+
name: "pendingOwner",
|
|
4317
|
+
outputs: [
|
|
4318
|
+
{
|
|
4319
|
+
internalType: "address",
|
|
4320
|
+
name: "",
|
|
4321
|
+
type: "address"
|
|
4322
|
+
}
|
|
4323
|
+
],
|
|
4324
|
+
stateMutability: "view",
|
|
4325
|
+
type: "function"
|
|
4326
|
+
},
|
|
4327
|
+
{
|
|
4328
|
+
inputs: [],
|
|
4329
|
+
name: "renounceOwnership",
|
|
4330
|
+
outputs: [],
|
|
4331
|
+
stateMutability: "nonpayable",
|
|
4332
|
+
type: "function"
|
|
4333
|
+
},
|
|
4334
|
+
{
|
|
4335
|
+
inputs: [
|
|
4336
|
+
{
|
|
4337
|
+
internalType: "bytes",
|
|
4338
|
+
name: "_destinationChainId",
|
|
4339
|
+
type: "bytes"
|
|
4340
|
+
},
|
|
4341
|
+
{
|
|
4342
|
+
components: [
|
|
4343
|
+
{
|
|
4344
|
+
internalType: "bytes",
|
|
4345
|
+
name: "to",
|
|
4346
|
+
type: "bytes"
|
|
4347
|
+
},
|
|
4348
|
+
{
|
|
4349
|
+
internalType: "bytes",
|
|
4350
|
+
name: "data",
|
|
4351
|
+
type: "bytes"
|
|
4352
|
+
},
|
|
4353
|
+
{
|
|
4354
|
+
internalType: "bytes[]",
|
|
4355
|
+
name: "callAttributes",
|
|
4356
|
+
type: "bytes[]"
|
|
4357
|
+
}
|
|
4358
|
+
],
|
|
4359
|
+
internalType: "struct InteropCallStarter[]",
|
|
4360
|
+
name: "_callStarters",
|
|
4361
|
+
type: "tuple[]"
|
|
4362
|
+
},
|
|
4363
|
+
{
|
|
4364
|
+
internalType: "bytes[]",
|
|
4365
|
+
name: "_bundleAttributes",
|
|
4366
|
+
type: "bytes[]"
|
|
4367
|
+
}
|
|
4368
|
+
],
|
|
4369
|
+
name: "sendBundle",
|
|
4370
|
+
outputs: [
|
|
4371
|
+
{
|
|
4372
|
+
internalType: "bytes32",
|
|
4373
|
+
name: "bundleHash",
|
|
4374
|
+
type: "bytes32"
|
|
4375
|
+
}
|
|
4376
|
+
],
|
|
4377
|
+
stateMutability: "payable",
|
|
4378
|
+
type: "function"
|
|
4379
|
+
},
|
|
4380
|
+
{
|
|
4381
|
+
inputs: [
|
|
4382
|
+
{
|
|
4383
|
+
internalType: "bytes",
|
|
4384
|
+
name: "recipient",
|
|
4385
|
+
type: "bytes"
|
|
4386
|
+
},
|
|
4387
|
+
{
|
|
4388
|
+
internalType: "bytes",
|
|
4389
|
+
name: "payload",
|
|
4390
|
+
type: "bytes"
|
|
4391
|
+
},
|
|
4392
|
+
{
|
|
4393
|
+
internalType: "bytes[]",
|
|
4394
|
+
name: "attributes",
|
|
4395
|
+
type: "bytes[]"
|
|
4396
|
+
}
|
|
4397
|
+
],
|
|
4398
|
+
name: "sendMessage",
|
|
4399
|
+
outputs: [
|
|
4400
|
+
{
|
|
4401
|
+
internalType: "bytes32",
|
|
4402
|
+
name: "sendId",
|
|
4403
|
+
type: "bytes32"
|
|
4404
|
+
}
|
|
4405
|
+
],
|
|
4406
|
+
stateMutability: "payable",
|
|
4407
|
+
type: "function"
|
|
4408
|
+
},
|
|
4409
|
+
{
|
|
4410
|
+
inputs: [
|
|
4411
|
+
{
|
|
4412
|
+
internalType: "bytes4",
|
|
4413
|
+
name: "_attributeSelector",
|
|
4414
|
+
type: "bytes4"
|
|
4415
|
+
}
|
|
4416
|
+
],
|
|
4417
|
+
name: "supportsAttribute",
|
|
4418
|
+
outputs: [
|
|
4419
|
+
{
|
|
4420
|
+
internalType: "bool",
|
|
4421
|
+
name: "",
|
|
4422
|
+
type: "bool"
|
|
4423
|
+
}
|
|
4424
|
+
],
|
|
4425
|
+
stateMutability: "pure",
|
|
4426
|
+
type: "function"
|
|
4427
|
+
},
|
|
4428
|
+
{
|
|
4429
|
+
inputs: [
|
|
4430
|
+
{
|
|
4431
|
+
internalType: "address",
|
|
4432
|
+
name: "newOwner",
|
|
4433
|
+
type: "address"
|
|
4434
|
+
}
|
|
4435
|
+
],
|
|
4436
|
+
name: "transferOwnership",
|
|
4437
|
+
outputs: [],
|
|
4438
|
+
stateMutability: "nonpayable",
|
|
4439
|
+
type: "function"
|
|
4440
|
+
},
|
|
4441
|
+
{
|
|
4442
|
+
inputs: [],
|
|
4443
|
+
name: "unpause",
|
|
4444
|
+
outputs: [],
|
|
4445
|
+
stateMutability: "nonpayable",
|
|
4446
|
+
type: "function"
|
|
4447
|
+
}
|
|
4448
|
+
];
|
|
4449
|
+
var InteropCenter_default = InteropCenterABI;
|
|
4450
|
+
|
|
4451
|
+
// src/core/internal/abis/IInteropHandler.ts
|
|
4452
|
+
var IInteropHandlerABI = [
|
|
4453
|
+
{
|
|
4454
|
+
anonymous: false,
|
|
4455
|
+
inputs: [
|
|
4456
|
+
{
|
|
4457
|
+
indexed: true,
|
|
4458
|
+
internalType: "bytes32",
|
|
4459
|
+
name: "bundleHash",
|
|
4460
|
+
type: "bytes32"
|
|
4461
|
+
}
|
|
4462
|
+
],
|
|
4463
|
+
name: "BundleExecuted",
|
|
4464
|
+
type: "event"
|
|
4465
|
+
},
|
|
4466
|
+
{
|
|
4467
|
+
anonymous: false,
|
|
4468
|
+
inputs: [
|
|
4469
|
+
{
|
|
4470
|
+
indexed: true,
|
|
4471
|
+
internalType: "bytes32",
|
|
4472
|
+
name: "bundleHash",
|
|
4473
|
+
type: "bytes32"
|
|
4474
|
+
}
|
|
4475
|
+
],
|
|
4476
|
+
name: "BundleUnbundled",
|
|
4477
|
+
type: "event"
|
|
4478
|
+
},
|
|
4479
|
+
{
|
|
4480
|
+
anonymous: false,
|
|
4481
|
+
inputs: [
|
|
4482
|
+
{
|
|
4483
|
+
indexed: true,
|
|
4484
|
+
internalType: "bytes32",
|
|
4485
|
+
name: "bundleHash",
|
|
4486
|
+
type: "bytes32"
|
|
4487
|
+
}
|
|
4488
|
+
],
|
|
4489
|
+
name: "BundleVerified",
|
|
4490
|
+
type: "event"
|
|
4491
|
+
},
|
|
4492
|
+
{
|
|
4493
|
+
anonymous: false,
|
|
4494
|
+
inputs: [
|
|
4495
|
+
{
|
|
4496
|
+
indexed: true,
|
|
4497
|
+
internalType: "bytes32",
|
|
4498
|
+
name: "bundleHash",
|
|
4499
|
+
type: "bytes32"
|
|
4500
|
+
},
|
|
4501
|
+
{
|
|
4502
|
+
indexed: true,
|
|
4503
|
+
internalType: "uint256",
|
|
4504
|
+
name: "callIndex",
|
|
4505
|
+
type: "uint256"
|
|
4506
|
+
},
|
|
4507
|
+
{
|
|
4508
|
+
indexed: false,
|
|
4509
|
+
internalType: "enum CallStatus",
|
|
4510
|
+
name: "status",
|
|
4511
|
+
type: "uint8"
|
|
4512
|
+
}
|
|
4513
|
+
],
|
|
4514
|
+
name: "CallProcessed",
|
|
4515
|
+
type: "event"
|
|
4516
|
+
},
|
|
4517
|
+
{
|
|
4518
|
+
inputs: [
|
|
4519
|
+
{
|
|
4520
|
+
internalType: "bytes",
|
|
4521
|
+
name: "_bundle",
|
|
4522
|
+
type: "bytes"
|
|
4523
|
+
},
|
|
4524
|
+
{
|
|
4525
|
+
components: [
|
|
4526
|
+
{
|
|
4527
|
+
internalType: "uint256",
|
|
4528
|
+
name: "chainId",
|
|
4529
|
+
type: "uint256"
|
|
4530
|
+
},
|
|
4531
|
+
{
|
|
4532
|
+
internalType: "uint256",
|
|
4533
|
+
name: "l1BatchNumber",
|
|
4534
|
+
type: "uint256"
|
|
4535
|
+
},
|
|
4536
|
+
{
|
|
4537
|
+
internalType: "uint256",
|
|
4538
|
+
name: "l2MessageIndex",
|
|
4539
|
+
type: "uint256"
|
|
4540
|
+
},
|
|
4541
|
+
{
|
|
4542
|
+
components: [
|
|
4543
|
+
{
|
|
4544
|
+
internalType: "uint16",
|
|
4545
|
+
name: "txNumberInBatch",
|
|
4546
|
+
type: "uint16"
|
|
4547
|
+
},
|
|
4548
|
+
{
|
|
4549
|
+
internalType: "address",
|
|
4550
|
+
name: "sender",
|
|
4551
|
+
type: "address"
|
|
4552
|
+
},
|
|
4553
|
+
{
|
|
4554
|
+
internalType: "bytes",
|
|
4555
|
+
name: "data",
|
|
4556
|
+
type: "bytes"
|
|
4557
|
+
}
|
|
4558
|
+
],
|
|
4559
|
+
internalType: "struct L2Message",
|
|
4560
|
+
name: "message",
|
|
4561
|
+
type: "tuple"
|
|
4562
|
+
},
|
|
4563
|
+
{
|
|
4564
|
+
internalType: "bytes32[]",
|
|
4565
|
+
name: "proof",
|
|
4566
|
+
type: "bytes32[]"
|
|
4567
|
+
}
|
|
4568
|
+
],
|
|
4569
|
+
internalType: "struct MessageInclusionProof",
|
|
4570
|
+
name: "_proof",
|
|
4571
|
+
type: "tuple"
|
|
4572
|
+
}
|
|
4573
|
+
],
|
|
4574
|
+
name: "executeBundle",
|
|
4575
|
+
outputs: [],
|
|
4576
|
+
stateMutability: "nonpayable",
|
|
4577
|
+
type: "function"
|
|
4578
|
+
},
|
|
4579
|
+
{
|
|
4580
|
+
inputs: [
|
|
4581
|
+
{
|
|
4582
|
+
internalType: "uint256",
|
|
4583
|
+
name: "_sourceChainId",
|
|
4584
|
+
type: "uint256"
|
|
4585
|
+
},
|
|
4586
|
+
{
|
|
4587
|
+
internalType: "bytes",
|
|
4588
|
+
name: "_bundle",
|
|
4589
|
+
type: "bytes"
|
|
4590
|
+
},
|
|
4591
|
+
{
|
|
4592
|
+
internalType: "enum CallStatus[]",
|
|
4593
|
+
name: "_callStatus",
|
|
4594
|
+
type: "uint8[]"
|
|
4595
|
+
}
|
|
4596
|
+
],
|
|
4597
|
+
name: "unbundleBundle",
|
|
4598
|
+
outputs: [],
|
|
4599
|
+
stateMutability: "nonpayable",
|
|
4600
|
+
type: "function"
|
|
4601
|
+
},
|
|
4602
|
+
{
|
|
4603
|
+
inputs: [
|
|
4604
|
+
{
|
|
4605
|
+
internalType: "bytes",
|
|
4606
|
+
name: "_bundle",
|
|
4607
|
+
type: "bytes"
|
|
4608
|
+
},
|
|
4609
|
+
{
|
|
4610
|
+
components: [
|
|
4611
|
+
{
|
|
4612
|
+
internalType: "uint256",
|
|
4613
|
+
name: "chainId",
|
|
4614
|
+
type: "uint256"
|
|
4615
|
+
},
|
|
4616
|
+
{
|
|
4617
|
+
internalType: "uint256",
|
|
4618
|
+
name: "l1BatchNumber",
|
|
4619
|
+
type: "uint256"
|
|
4620
|
+
},
|
|
4621
|
+
{
|
|
4622
|
+
internalType: "uint256",
|
|
4623
|
+
name: "l2MessageIndex",
|
|
4624
|
+
type: "uint256"
|
|
4625
|
+
},
|
|
4626
|
+
{
|
|
4627
|
+
components: [
|
|
4628
|
+
{
|
|
4629
|
+
internalType: "uint16",
|
|
4630
|
+
name: "txNumberInBatch",
|
|
4631
|
+
type: "uint16"
|
|
4632
|
+
},
|
|
4633
|
+
{
|
|
4634
|
+
internalType: "address",
|
|
4635
|
+
name: "sender",
|
|
4636
|
+
type: "address"
|
|
4637
|
+
},
|
|
4638
|
+
{
|
|
4639
|
+
internalType: "bytes",
|
|
4640
|
+
name: "data",
|
|
4641
|
+
type: "bytes"
|
|
4642
|
+
}
|
|
4643
|
+
],
|
|
4644
|
+
internalType: "struct L2Message",
|
|
4645
|
+
name: "message",
|
|
4646
|
+
type: "tuple"
|
|
4647
|
+
},
|
|
4648
|
+
{
|
|
4649
|
+
internalType: "bytes32[]",
|
|
4650
|
+
name: "proof",
|
|
4651
|
+
type: "bytes32[]"
|
|
4652
|
+
}
|
|
4653
|
+
],
|
|
4654
|
+
internalType: "struct MessageInclusionProof",
|
|
4655
|
+
name: "_proof",
|
|
4656
|
+
type: "tuple"
|
|
4657
|
+
}
|
|
4658
|
+
],
|
|
4659
|
+
name: "verifyBundle",
|
|
4660
|
+
outputs: [],
|
|
4661
|
+
stateMutability: "nonpayable",
|
|
4662
|
+
type: "function"
|
|
4663
|
+
}
|
|
4664
|
+
];
|
|
4665
|
+
var IInteropHandler_default = IInteropHandlerABI;
|
|
4666
|
+
|
|
4667
|
+
// src/core/internal/abis/InteropRootStorage.ts
|
|
4668
|
+
var InteropRootStorageABI = [
|
|
4669
|
+
{
|
|
4670
|
+
inputs: [
|
|
4671
|
+
{
|
|
4672
|
+
internalType: "uint256",
|
|
4673
|
+
name: "chainId",
|
|
4674
|
+
type: "uint256"
|
|
4675
|
+
},
|
|
4676
|
+
{
|
|
4677
|
+
internalType: "uint256",
|
|
4678
|
+
name: "batchNumber",
|
|
4679
|
+
type: "uint256"
|
|
4680
|
+
}
|
|
4681
|
+
],
|
|
4682
|
+
name: "interopRoots",
|
|
4683
|
+
outputs: [
|
|
4684
|
+
{
|
|
4685
|
+
internalType: "bytes32",
|
|
4686
|
+
name: "",
|
|
4687
|
+
type: "bytes32"
|
|
4688
|
+
}
|
|
4689
|
+
],
|
|
4690
|
+
stateMutability: "view",
|
|
4691
|
+
type: "function"
|
|
4692
|
+
}
|
|
4693
|
+
];
|
|
4694
|
+
var InteropRootStorage_default = InteropRootStorageABI;
|
|
4695
|
+
|
|
4696
|
+
// src/core/types/fees.ts
|
|
4697
|
+
function toGasOverrides(overrides) {
|
|
4698
|
+
const { nonce: _, ...gas } = overrides;
|
|
4699
|
+
return gas;
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4702
|
+
// src/adapters/ethers/resources/deposits/context.ts
|
|
4703
|
+
async function commonCtx(p, client, tokens, contracts) {
|
|
4704
|
+
const { bridgehub, l1AssetRouter } = await contracts.addresses();
|
|
4705
|
+
const { chainId } = await client.l2.getNetwork();
|
|
4706
|
+
const sender = await client.signer.getAddress();
|
|
4707
|
+
const gasPerPubdata = p.gasPerPubdata ?? 800n;
|
|
4708
|
+
const operatorTip = p.operatorTip ?? 0n;
|
|
4709
|
+
const refundRecipient = p.refundRecipient ?? sender;
|
|
4710
|
+
const resolvedToken = await tokens.resolve(p.token, { chain: "l1" });
|
|
4711
|
+
const baseTokenAssetId = resolvedToken.baseTokenAssetId;
|
|
4712
|
+
const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
|
|
4713
|
+
const baseIsEth = resolvedToken.isChainEthBased;
|
|
4714
|
+
const route = (() => {
|
|
4715
|
+
if (resolvedToken.kind === "eth") {
|
|
4716
|
+
return baseIsEth ? "eth-base" : "eth-nonbase";
|
|
4717
|
+
}
|
|
4718
|
+
if (resolvedToken.kind === "base") {
|
|
4719
|
+
return baseIsEth ? "eth-base" : "erc20-base";
|
|
4720
|
+
}
|
|
4721
|
+
return "erc20-nonbase";
|
|
4722
|
+
})();
|
|
4723
|
+
return {
|
|
4724
|
+
client,
|
|
4725
|
+
tokens,
|
|
4726
|
+
contracts,
|
|
4727
|
+
resolvedToken,
|
|
4728
|
+
baseTokenAssetId,
|
|
4729
|
+
baseTokenL1,
|
|
4730
|
+
baseIsEth,
|
|
4731
|
+
l1AssetRouter,
|
|
4732
|
+
route,
|
|
4733
|
+
bridgehub,
|
|
4734
|
+
chainIdL2: BigInt(chainId),
|
|
4735
|
+
sender,
|
|
4736
|
+
gasOverrides: p.l1TxOverrides ? toGasOverrides(p.l1TxOverrides) : void 0,
|
|
4737
|
+
l2GasLimit: p.l2GasLimit,
|
|
4738
|
+
gasPerPubdata,
|
|
4739
|
+
operatorTip,
|
|
4740
|
+
refundRecipient
|
|
4741
|
+
};
|
|
4742
|
+
}
|
|
4743
|
+
function encodeNativeTokenVaultTransferData(amount, receiver, token) {
|
|
4744
|
+
return new ethers.AbiCoder().encode(["uint256", "address", "address"], [amount, receiver, token]);
|
|
4745
|
+
}
|
|
4746
|
+
function encodeSecondBridgeDataV1(assetId, transferData) {
|
|
4747
|
+
const abi2 = new ethers.AbiCoder();
|
|
4748
|
+
const data = abi2.encode(["bytes32", "bytes"], [assetId, transferData]);
|
|
4749
|
+
return ethers.ethers.concat(["0x01", data]);
|
|
4750
|
+
}
|
|
4751
|
+
function encodeSecondBridgeArgs(token, amount, l2Receiver) {
|
|
4752
|
+
return ethers.AbiCoder.defaultAbiCoder().encode(
|
|
4753
|
+
["address", "uint256", "address"],
|
|
4754
|
+
[token, amount, l2Receiver]
|
|
4755
|
+
);
|
|
4756
|
+
}
|
|
4757
|
+
function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
|
|
4758
|
+
return encodeSecondBridgeArgs(token, amount, l2Receiver);
|
|
4759
|
+
}
|
|
4760
|
+
function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
|
|
4761
|
+
return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
|
|
4762
|
+
}
|
|
4763
|
+
function buildDirectRequestStruct(args) {
|
|
4764
|
+
return {
|
|
4765
|
+
chainId: args.chainId,
|
|
4766
|
+
l2Contract: args.l2Contract,
|
|
4767
|
+
mintValue: args.mintValue,
|
|
4768
|
+
l2Value: args.l2Value,
|
|
4769
|
+
l2Calldata: "0x",
|
|
4770
|
+
l2GasLimit: args.l2GasLimit,
|
|
4771
|
+
l2GasPerPubdataByteLimit: args.gasPerPubdata,
|
|
4772
|
+
factoryDeps: [],
|
|
4773
|
+
refundRecipient: args.refundRecipient
|
|
4774
|
+
};
|
|
4775
|
+
}
|
|
4776
|
+
|
|
4777
|
+
// src/core/resources/deposits/gas.ts
|
|
4778
|
+
function makeGasQuote(p) {
|
|
4779
|
+
const maxPriorityFeePerGas = p.maxPriorityFeePerGas ?? 0n;
|
|
4780
|
+
return {
|
|
4781
|
+
gasLimit: p.gasLimit,
|
|
4782
|
+
maxFeePerGas: p.maxFeePerGas,
|
|
4783
|
+
maxPriorityFeePerGas,
|
|
4784
|
+
gasPerPubdata: p.gasPerPubdata,
|
|
4785
|
+
maxCost: p.gasLimit * p.maxFeePerGas
|
|
4786
|
+
};
|
|
4787
|
+
}
|
|
4788
|
+
async function fetchFees(estimator) {
|
|
4789
|
+
try {
|
|
4790
|
+
const fees = await estimator.estimateFeesPerGas();
|
|
4791
|
+
if (fees.maxFeePerGas != null) {
|
|
4792
|
+
return {
|
|
4793
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
4794
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
4797
|
+
if (fees.gasPrice != null) {
|
|
4798
|
+
return {
|
|
4799
|
+
maxFeePerGas: fees.gasPrice,
|
|
4800
|
+
maxPriorityFeePerGas: 0n
|
|
4801
|
+
};
|
|
4802
|
+
}
|
|
4803
|
+
} catch {
|
|
4804
|
+
}
|
|
4805
|
+
try {
|
|
4806
|
+
const gp = await estimator.getGasPrice();
|
|
4807
|
+
return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
|
|
4808
|
+
} catch {
|
|
4809
|
+
return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
async function quoteL1Gas(input) {
|
|
4813
|
+
const { estimator, tx, overrides, fallbackGasLimit } = input;
|
|
4814
|
+
let market;
|
|
4815
|
+
const getMarket = async () => {
|
|
4816
|
+
if (market) return market;
|
|
4817
|
+
market = await fetchFees(estimator);
|
|
4818
|
+
return market;
|
|
4819
|
+
};
|
|
4820
|
+
const maxFeePerGas = overrides?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : (await getMarket()).maxFeePerGas);
|
|
4821
|
+
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : (await getMarket()).maxPriorityFeePerGas);
|
|
4822
|
+
const explicitGasLimit = overrides?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
|
|
4823
|
+
if (explicitGasLimit != null) {
|
|
4824
|
+
return makeGasQuote({ gasLimit: explicitGasLimit, maxFeePerGas, maxPriorityFeePerGas });
|
|
4825
|
+
}
|
|
4826
|
+
try {
|
|
4827
|
+
const est = await estimator.estimateGas(tx);
|
|
4828
|
+
const buffered = BigInt(est) * (100n + BUFFER) / 100n;
|
|
4829
|
+
return makeGasQuote({ gasLimit: buffered, maxFeePerGas, maxPriorityFeePerGas });
|
|
4830
|
+
} catch (err) {
|
|
4831
|
+
if (fallbackGasLimit != null) {
|
|
4832
|
+
return makeGasQuote({ gasLimit: fallbackGasLimit, maxFeePerGas, maxPriorityFeePerGas });
|
|
4833
|
+
}
|
|
4834
|
+
console.warn("L1 gas estimation failed", err);
|
|
4835
|
+
return void 0;
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
async function quoteL2Gas(input) {
|
|
4839
|
+
const { estimator, route, tx, gasPerPubdata, l2GasLimit, overrideGasLimit, stateOverrides } = input;
|
|
4840
|
+
const market = await fetchFees(estimator);
|
|
4841
|
+
const maxFeePerGas = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
|
|
4842
|
+
const txGasLimit = tx?.gasLimit != null ? BigInt(tx.gasLimit) : void 0;
|
|
4843
|
+
const explicit = overrideGasLimit ?? txGasLimit;
|
|
4844
|
+
if (explicit != null) {
|
|
4845
|
+
return makeGasQuote({
|
|
4846
|
+
gasLimit: explicit,
|
|
4847
|
+
maxFeePerGas,
|
|
4848
|
+
gasPerPubdata
|
|
4849
|
+
});
|
|
4850
|
+
}
|
|
4851
|
+
if (!tx) {
|
|
4852
|
+
return makeGasQuote({
|
|
4853
|
+
gasLimit: l2GasLimit ?? 0n,
|
|
4854
|
+
maxFeePerGas,
|
|
4855
|
+
gasPerPubdata
|
|
4856
|
+
});
|
|
4857
|
+
}
|
|
4858
|
+
try {
|
|
4859
|
+
const execEstimate = await estimator.estimateGas(tx, stateOverrides);
|
|
4860
|
+
const memoryBytes = route === "erc20-nonbase" ? 500n : DEFAULT_ABI_BYTES;
|
|
4861
|
+
const pubdataBytes = route === "erc20-nonbase" ? 200n : DEFAULT_PUBDATA_BYTES;
|
|
4862
|
+
const pp = gasPerPubdata ?? 800n;
|
|
4863
|
+
const memoryOverhead = memoryBytes * TX_MEMORY_OVERHEAD_GAS;
|
|
4864
|
+
const pubdataOverhead = pubdataBytes * pp;
|
|
4865
|
+
let total = BigInt(execEstimate) + TX_OVERHEAD_GAS + memoryOverhead + pubdataOverhead;
|
|
4866
|
+
total = total * (100n + BUFFER) / 100n;
|
|
4867
|
+
return makeGasQuote({
|
|
4868
|
+
gasLimit: total,
|
|
4869
|
+
maxFeePerGas,
|
|
4870
|
+
gasPerPubdata: pp
|
|
4871
|
+
});
|
|
4872
|
+
} catch (err) {
|
|
4873
|
+
console.warn("L2 gas estimation failed", err);
|
|
4874
|
+
return makeGasQuote({
|
|
4875
|
+
gasLimit: l2GasLimit ?? 0n,
|
|
4876
|
+
maxFeePerGas,
|
|
4877
|
+
gasPerPubdata
|
|
4878
|
+
});
|
|
4879
|
+
}
|
|
4880
|
+
}
|
|
4881
|
+
async function quoteL2BaseCost(input) {
|
|
4882
|
+
const { estimator, encode: encode2, bridgehub, chainIdL2, l2GasLimit, gasPerPubdata } = input;
|
|
4883
|
+
const market = await fetchFees(estimator);
|
|
4884
|
+
const l1GasPrice = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
|
|
4885
|
+
if (l1GasPrice === 0n) {
|
|
4886
|
+
throw new Error("Could not fetch L1 gas price for Bridgehub base cost calculation.");
|
|
4887
|
+
}
|
|
4888
|
+
const data = encode2(IBridgehub_default, "l2TransactionBaseCost", [
|
|
4889
|
+
chainIdL2,
|
|
4890
|
+
l1GasPrice,
|
|
4891
|
+
l2GasLimit,
|
|
4892
|
+
gasPerPubdata
|
|
4893
|
+
]);
|
|
4894
|
+
const raw = await estimator.call({
|
|
4895
|
+
to: bridgehub,
|
|
4896
|
+
data
|
|
4897
|
+
});
|
|
4898
|
+
return BigInt(raw);
|
|
4899
|
+
}
|
|
4900
|
+
|
|
4901
|
+
// src/adapters/ethers/estimator.ts
|
|
4902
|
+
function toCoreTx(tx) {
|
|
4903
|
+
return {
|
|
4904
|
+
to: tx.to,
|
|
4905
|
+
from: tx.from,
|
|
4906
|
+
data: tx.data,
|
|
3761
4907
|
value: tx.value ? BigInt(tx.value) : void 0,
|
|
3762
4908
|
gasLimit: tx.gasLimit ? BigInt(tx.gasLimit) : void 0,
|
|
3763
4909
|
maxFeePerGas: tx.maxFeePerGas ? BigInt(tx.maxFeePerGas) : void 0,
|
|
@@ -3842,15 +4988,15 @@ function createErrorOps(decodeRevert2) {
|
|
|
3842
4988
|
throw toZKsyncError2(kind, { resource, operation, context: opts?.ctx ?? {}, message }, e);
|
|
3843
4989
|
}
|
|
3844
4990
|
}
|
|
3845
|
-
function
|
|
4991
|
+
function wrap6(operation, fn, opts) {
|
|
3846
4992
|
return run("INTERNAL", operation, fn, opts);
|
|
3847
4993
|
}
|
|
3848
4994
|
function wrapAs9(kind, operation, fn, opts) {
|
|
3849
4995
|
return run(kind, operation, fn, opts);
|
|
3850
4996
|
}
|
|
3851
|
-
async function
|
|
4997
|
+
async function toResult3(operation, fn, opts) {
|
|
3852
4998
|
try {
|
|
3853
|
-
const value = await
|
|
4999
|
+
const value = await wrap6(operation, fn, opts);
|
|
3854
5000
|
return { ok: true, value };
|
|
3855
5001
|
} catch (e) {
|
|
3856
5002
|
const shaped = isZKsyncError(e) ? e : toZKsyncError2(
|
|
@@ -3866,7 +5012,7 @@ function createErrorOps(decodeRevert2) {
|
|
|
3866
5012
|
return { ok: false, error: shaped };
|
|
3867
5013
|
}
|
|
3868
5014
|
}
|
|
3869
|
-
return { wrap:
|
|
5015
|
+
return { wrap: wrap6, wrapAs: wrapAs9, toResult: toResult3 };
|
|
3870
5016
|
}
|
|
3871
5017
|
return { toZKsyncError: toZKsyncError2, createErrorHandlers: createErrorHandlers2 };
|
|
3872
5018
|
}
|
|
@@ -4197,6 +5343,11 @@ function routeEthDirect() {
|
|
|
4197
5343
|
}
|
|
4198
5344
|
};
|
|
4199
5345
|
}
|
|
5346
|
+
|
|
5347
|
+
// src/core/types/primitives.ts
|
|
5348
|
+
var ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
5349
|
+
|
|
5350
|
+
// src/adapters/ethers/resources/deposits/routes/erc20-nonbase.ts
|
|
4200
5351
|
var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
|
|
4201
5352
|
function routeErc20NonBase() {
|
|
4202
5353
|
return {
|
|
@@ -4899,6 +6050,18 @@ function createContractsResource(client) {
|
|
|
4899
6050
|
const { l2BaseTokenSystem: l2BaseTokenSystem2 } = await instances();
|
|
4900
6051
|
return l2BaseTokenSystem2;
|
|
4901
6052
|
}
|
|
6053
|
+
async function interopCenter() {
|
|
6054
|
+
const { interopCenter: interopCenter2 } = await instances();
|
|
6055
|
+
return interopCenter2;
|
|
6056
|
+
}
|
|
6057
|
+
async function interopHandler() {
|
|
6058
|
+
const { interopHandler: interopHandler2 } = await instances();
|
|
6059
|
+
return interopHandler2;
|
|
6060
|
+
}
|
|
6061
|
+
async function l2MessageVerification() {
|
|
6062
|
+
const { l2MessageVerification: l2MessageVerification2 } = await instances();
|
|
6063
|
+
return l2MessageVerification2;
|
|
6064
|
+
}
|
|
4902
6065
|
return {
|
|
4903
6066
|
addresses,
|
|
4904
6067
|
instances,
|
|
@@ -4908,7 +6071,10 @@ function createContractsResource(client) {
|
|
|
4908
6071
|
l1Nullifier,
|
|
4909
6072
|
l2AssetRouter,
|
|
4910
6073
|
l2NativeTokenVault,
|
|
4911
|
-
l2BaseTokenSystem
|
|
6074
|
+
l2BaseTokenSystem,
|
|
6075
|
+
interopCenter,
|
|
6076
|
+
interopHandler,
|
|
6077
|
+
l2MessageVerification
|
|
4912
6078
|
};
|
|
4913
6079
|
}
|
|
4914
6080
|
|
|
@@ -4973,7 +6139,13 @@ function createDepositsResource(client, tokens, contracts) {
|
|
|
4973
6139
|
const stepHashes = {};
|
|
4974
6140
|
const managed = new ethers.NonceManager(client.signer);
|
|
4975
6141
|
const from = await managed.getAddress();
|
|
4976
|
-
let next
|
|
6142
|
+
let next;
|
|
6143
|
+
if (typeof p.l1TxOverrides?.nonce === "number") {
|
|
6144
|
+
next = p.l1TxOverrides.nonce;
|
|
6145
|
+
} else {
|
|
6146
|
+
const blockTag = p.l1TxOverrides?.nonce ?? "latest";
|
|
6147
|
+
next = await client.l1.getTransactionCount(from, blockTag);
|
|
6148
|
+
}
|
|
4977
6149
|
for (const step of plan.steps) {
|
|
4978
6150
|
if (step.kind === "approve") {
|
|
4979
6151
|
try {
|
|
@@ -5081,14 +6253,14 @@ function createDepositsResource(client, tokens, contracts) {
|
|
|
5081
6253
|
if (!l1Rcpt) return { phase: "L1_PENDING", l1TxHash };
|
|
5082
6254
|
let l2TxHash;
|
|
5083
6255
|
try {
|
|
5084
|
-
l2TxHash =
|
|
6256
|
+
l2TxHash = getL2TransactionHashFromLogs(l1Rcpt.logs) ?? void 0;
|
|
5085
6257
|
} catch (e) {
|
|
5086
6258
|
throw toZKsyncError(
|
|
5087
6259
|
"INTERNAL",
|
|
5088
6260
|
{
|
|
5089
6261
|
resource: "deposits",
|
|
5090
|
-
operation: "deposits.status.
|
|
5091
|
-
context: { where: "
|
|
6262
|
+
operation: "deposits.status.getL2TransactionHashFromLogs",
|
|
6263
|
+
context: { where: "getL2TransactionHashFromLogs", l1TxHash },
|
|
5092
6264
|
message: "Failed to derive L2 transaction hash from L1 logs."
|
|
5093
6265
|
},
|
|
5094
6266
|
e
|
|
@@ -5238,7 +6410,7 @@ async function commonCtx2(p, client, tokens, contracts) {
|
|
|
5238
6410
|
l2NativeTokenVault,
|
|
5239
6411
|
l2BaseTokenSystem,
|
|
5240
6412
|
baseIsEth,
|
|
5241
|
-
gasOverrides: p.l2TxOverrides
|
|
6413
|
+
gasOverrides: p.l2TxOverrides ? toGasOverrides(p.l2TxOverrides) : void 0
|
|
5242
6414
|
};
|
|
5243
6415
|
}
|
|
5244
6416
|
|
|
@@ -5314,820 +6486,2099 @@ async function quoteL2Gas4(input) {
|
|
|
5314
6486
|
});
|
|
5315
6487
|
}
|
|
5316
6488
|
|
|
5317
|
-
// src/adapters/ethers/resources/withdrawals/services/fees.ts
|
|
5318
|
-
function buildFeeBreakdown2(p) {
|
|
5319
|
-
const l2Total = p.l2Gas?.maxCost ?? 0n;
|
|
5320
|
-
const l2 = {
|
|
5321
|
-
total: l2Total,
|
|
5322
|
-
gasLimit: p.l2Gas?.gasLimit ?? 0n,
|
|
5323
|
-
maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
|
|
5324
|
-
maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
|
|
5325
|
-
};
|
|
5326
|
-
return {
|
|
5327
|
-
token: p.feeToken,
|
|
5328
|
-
maxTotal: l2Total,
|
|
5329
|
-
l2
|
|
5330
|
-
};
|
|
6489
|
+
// src/adapters/ethers/resources/withdrawals/services/fees.ts
|
|
6490
|
+
function buildFeeBreakdown2(p) {
|
|
6491
|
+
const l2Total = p.l2Gas?.maxCost ?? 0n;
|
|
6492
|
+
const l2 = {
|
|
6493
|
+
total: l2Total,
|
|
6494
|
+
gasLimit: p.l2Gas?.gasLimit ?? 0n,
|
|
6495
|
+
maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
|
|
6496
|
+
maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
|
|
6497
|
+
};
|
|
6498
|
+
return {
|
|
6499
|
+
token: p.feeToken,
|
|
6500
|
+
maxTotal: l2Total,
|
|
6501
|
+
l2
|
|
6502
|
+
};
|
|
6503
|
+
}
|
|
6504
|
+
|
|
6505
|
+
// src/adapters/ethers/resources/withdrawals/routes/eth.ts
|
|
6506
|
+
var { wrapAs: wrapAs6 } = createErrorHandlers("withdrawals");
|
|
6507
|
+
function routeEthBase() {
|
|
6508
|
+
return {
|
|
6509
|
+
async build(p, ctx) {
|
|
6510
|
+
const steps = [];
|
|
6511
|
+
const base = await ctx.contracts.l2BaseTokenSystem();
|
|
6512
|
+
const data = await wrapAs6(
|
|
6513
|
+
"INTERNAL",
|
|
6514
|
+
OP_WITHDRAWALS.eth.encodeWithdraw,
|
|
6515
|
+
() => Promise.resolve(base.interface.encodeFunctionData("withdraw", [p.to ?? ctx.sender])),
|
|
6516
|
+
{
|
|
6517
|
+
ctx: { where: "L2BaseToken.withdraw", to: p.to ?? ctx.sender },
|
|
6518
|
+
message: "Failed to encode ETH withdraw calldata."
|
|
6519
|
+
}
|
|
6520
|
+
);
|
|
6521
|
+
const tx = {
|
|
6522
|
+
to: L2_BASE_TOKEN_ADDRESS,
|
|
6523
|
+
data,
|
|
6524
|
+
from: ctx.sender,
|
|
6525
|
+
value: p.amount
|
|
6526
|
+
};
|
|
6527
|
+
const gas = await quoteL2Gas4({ ctx, tx });
|
|
6528
|
+
if (gas) {
|
|
6529
|
+
tx.gasLimit = gas.gasLimit;
|
|
6530
|
+
tx.maxFeePerGas = gas.maxFeePerGas;
|
|
6531
|
+
tx.maxPriorityFeePerGas = gas.maxPriorityFeePerGas;
|
|
6532
|
+
}
|
|
6533
|
+
const fees = buildFeeBreakdown2({
|
|
6534
|
+
feeToken: L2_BASE_TOKEN_ADDRESS,
|
|
6535
|
+
l2Gas: gas
|
|
6536
|
+
});
|
|
6537
|
+
steps.push({
|
|
6538
|
+
key: "l2-base-token:withdraw",
|
|
6539
|
+
kind: "l2-base-token:withdraw",
|
|
6540
|
+
description: "Withdraw ETH via L2 Base Token System",
|
|
6541
|
+
tx
|
|
6542
|
+
});
|
|
6543
|
+
return { steps, approvals: [], fees };
|
|
6544
|
+
}
|
|
6545
|
+
};
|
|
6546
|
+
}
|
|
6547
|
+
var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
|
|
6548
|
+
var SIG = {
|
|
6549
|
+
withdraw: "withdraw(bytes32,bytes)"
|
|
6550
|
+
};
|
|
6551
|
+
function routeErc20NonBase2() {
|
|
6552
|
+
return {
|
|
6553
|
+
async build(p, ctx) {
|
|
6554
|
+
const steps = [];
|
|
6555
|
+
const approvals = [];
|
|
6556
|
+
const erc20 = new ethers.Contract(p.token, IERC20_default, ctx.client.getL2Signer());
|
|
6557
|
+
const current = await wrapAs7(
|
|
6558
|
+
"CONTRACT",
|
|
6559
|
+
OP_WITHDRAWALS.erc20.allowance,
|
|
6560
|
+
() => erc20.allowance(ctx.sender, ctx.l2NativeTokenVault),
|
|
6561
|
+
{
|
|
6562
|
+
ctx: {
|
|
6563
|
+
where: "erc20.allowance",
|
|
6564
|
+
chain: "L2",
|
|
6565
|
+
token: p.token,
|
|
6566
|
+
spender: ctx.l2NativeTokenVault
|
|
6567
|
+
},
|
|
6568
|
+
message: "Failed to read L2 ERC-20 allowance."
|
|
6569
|
+
}
|
|
6570
|
+
);
|
|
6571
|
+
if (current < p.amount) {
|
|
6572
|
+
approvals.push({ token: p.token, spender: ctx.l2NativeTokenVault, amount: p.amount });
|
|
6573
|
+
const data = erc20.interface.encodeFunctionData("approve", [
|
|
6574
|
+
ctx.l2NativeTokenVault,
|
|
6575
|
+
p.amount
|
|
6576
|
+
]);
|
|
6577
|
+
const approveTx = {
|
|
6578
|
+
to: p.token,
|
|
6579
|
+
data,
|
|
6580
|
+
from: ctx.sender
|
|
6581
|
+
};
|
|
6582
|
+
const approveGas = await quoteL2Gas4({ ctx, tx: approveTx });
|
|
6583
|
+
if (approveGas) {
|
|
6584
|
+
approveTx.gasLimit = approveGas.gasLimit;
|
|
6585
|
+
approveTx.maxFeePerGas = approveGas.maxFeePerGas;
|
|
6586
|
+
approveTx.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
|
|
6587
|
+
}
|
|
6588
|
+
steps.push({
|
|
6589
|
+
key: `approve:l2:${p.token}:${ctx.l2NativeTokenVault}`,
|
|
6590
|
+
kind: "approve:l2",
|
|
6591
|
+
description: `Approve ${p.amount} to NativeTokenVault`,
|
|
6592
|
+
tx: approveTx
|
|
6593
|
+
});
|
|
6594
|
+
}
|
|
6595
|
+
const assetId = await wrapAs7(
|
|
6596
|
+
"CONTRACT",
|
|
6597
|
+
OP_WITHDRAWALS.erc20.ensureRegistered,
|
|
6598
|
+
async () => {
|
|
6599
|
+
const ntv = await ctx.contracts.l2NativeTokenVault();
|
|
6600
|
+
const ensured = await ntv.getFunction("ensureTokenIsRegistered").staticCall(p.token);
|
|
6601
|
+
return ensured;
|
|
6602
|
+
},
|
|
6603
|
+
{
|
|
6604
|
+
ctx: { where: "L2NativeTokenVault.ensureTokenIsRegistered", token: p.token },
|
|
6605
|
+
message: "Failed to ensure token is registered in L2NativeTokenVault."
|
|
6606
|
+
}
|
|
6607
|
+
);
|
|
6608
|
+
const assetData = await wrapAs7(
|
|
6609
|
+
"INTERNAL",
|
|
6610
|
+
OP_WITHDRAWALS.erc20.encodeAssetData,
|
|
6611
|
+
() => Promise.resolve(
|
|
6612
|
+
encodeNativeTokenVaultTransferData(p.amount, p.to ?? ctx.sender, p.token)
|
|
6613
|
+
),
|
|
6614
|
+
{
|
|
6615
|
+
ctx: { where: "AbiCoder.encode", token: p.token, to: p.to ?? ctx.sender },
|
|
6616
|
+
message: "Failed to encode burn/withdraw asset data."
|
|
6617
|
+
}
|
|
6618
|
+
);
|
|
6619
|
+
const l2ar = await ctx.contracts.l2AssetRouter();
|
|
6620
|
+
const dataWithdraw = await wrapAs7(
|
|
6621
|
+
"INTERNAL",
|
|
6622
|
+
OP_WITHDRAWALS.erc20.encodeWithdraw,
|
|
6623
|
+
() => Promise.resolve(l2ar.interface.encodeFunctionData(SIG.withdraw, [assetId, assetData])),
|
|
6624
|
+
{
|
|
6625
|
+
ctx: { where: "L2AssetRouter.withdraw", assetId },
|
|
6626
|
+
message: "Failed to encode withdraw calldata."
|
|
6627
|
+
}
|
|
6628
|
+
);
|
|
6629
|
+
const withdrawTx = {
|
|
6630
|
+
to: ctx.l2AssetRouter,
|
|
6631
|
+
data: dataWithdraw,
|
|
6632
|
+
from: ctx.sender
|
|
6633
|
+
};
|
|
6634
|
+
const withdrawGas = current >= p.amount ? await quoteL2Gas4({ ctx, tx: withdrawTx }) : void 0;
|
|
6635
|
+
if (withdrawGas) {
|
|
6636
|
+
withdrawTx.gasLimit = withdrawGas.gasLimit;
|
|
6637
|
+
withdrawTx.maxFeePerGas = withdrawGas.maxFeePerGas;
|
|
6638
|
+
withdrawTx.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
|
|
6639
|
+
}
|
|
6640
|
+
steps.push({
|
|
6641
|
+
key: "l2-asset-router:withdraw",
|
|
6642
|
+
kind: "l2-asset-router:withdraw",
|
|
6643
|
+
description: "Burn on L2 & send L2\u2192L1 message",
|
|
6644
|
+
tx: withdrawTx
|
|
6645
|
+
});
|
|
6646
|
+
const fees = buildFeeBreakdown2({
|
|
6647
|
+
feeToken: ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2),
|
|
6648
|
+
l2Gas: withdrawGas
|
|
6649
|
+
});
|
|
6650
|
+
return { steps, approvals, fees };
|
|
6651
|
+
}
|
|
6652
|
+
};
|
|
6653
|
+
}
|
|
6654
|
+
|
|
6655
|
+
// src/core/utils/events.ts
|
|
6656
|
+
function extractPreferAddress(opts) {
|
|
6657
|
+
const preferAddr = typeof opts?.prefer === "object" ? opts.prefer.address : opts?.prefer === "assetRouter" ? L2_ASSET_ROUTER_ADDRESS : L1_MESSENGER_ADDRESS;
|
|
6658
|
+
return (preferAddr || L1_MESSENGER_ADDRESS).toLowerCase();
|
|
6659
|
+
}
|
|
6660
|
+
function findL1MessageSentLog(receipt, opts) {
|
|
6661
|
+
const index = opts?.index ?? 0;
|
|
6662
|
+
const preferAddr = extractPreferAddress(opts);
|
|
6663
|
+
const matches = receipt.logs.filter((lg) => {
|
|
6664
|
+
const t0 = (lg.topics?.[0] ?? "").toLowerCase();
|
|
6665
|
+
return t0 === TOPIC_L1_MESSAGE_SENT_NEW || t0 === TOPIC_L1_MESSAGE_SENT_LEG;
|
|
6666
|
+
});
|
|
6667
|
+
if (!matches.length) {
|
|
6668
|
+
throw new Error("No L1MessageSent event found in L2 receipt logs.");
|
|
6669
|
+
}
|
|
6670
|
+
const preferred = matches.find((lg) => (lg.address ?? "").toLowerCase() === preferAddr);
|
|
6671
|
+
const chosen = preferred ?? matches[index] ?? matches[0];
|
|
6672
|
+
if (!chosen) {
|
|
6673
|
+
throw new Error("No suitable L1MessageSent event found.");
|
|
6674
|
+
}
|
|
6675
|
+
return chosen;
|
|
6676
|
+
}
|
|
6677
|
+
function isL1MessageSentLog(log, opts) {
|
|
6678
|
+
const topic = log.topics[0].toLowerCase();
|
|
6679
|
+
const preferAddr = extractPreferAddress(opts);
|
|
6680
|
+
return log.address.toLowerCase() === preferAddr && (topic === TOPIC_L1_MESSAGE_SENT_LEG.toLowerCase() || topic === TOPIC_L1_MESSAGE_SENT_NEW.toLowerCase());
|
|
6681
|
+
}
|
|
6682
|
+
|
|
6683
|
+
// src/core/resources/withdrawals/logs.ts
|
|
6684
|
+
function messengerLogIndex(raw, opts) {
|
|
6685
|
+
const index = opts?.index;
|
|
6686
|
+
const messenger = (opts?.messenger).toLowerCase();
|
|
6687
|
+
const arr = Array.isArray(raw?.l2ToL1Logs) ? raw.l2ToL1Logs : [];
|
|
6688
|
+
const hits = arr.map((lg, i) => ({ i, lg })).filter(({ lg }) => (lg?.sender ?? "").toLowerCase() === messenger);
|
|
6689
|
+
if (!hits.length) {
|
|
6690
|
+
throw new Error("No L2->L1 messenger logs found in receipt.");
|
|
6691
|
+
}
|
|
6692
|
+
return (hits[index] ?? hits[0]).i;
|
|
5331
6693
|
}
|
|
5332
6694
|
|
|
5333
|
-
// src/adapters/ethers/resources/withdrawals/
|
|
5334
|
-
var { wrapAs:
|
|
5335
|
-
|
|
6695
|
+
// src/adapters/ethers/resources/withdrawals/services/finalization.ts
|
|
6696
|
+
var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
|
|
6697
|
+
var IL1NullifierMini = [
|
|
6698
|
+
"function isWithdrawalFinalized(uint256,uint256,uint256) view returns (bool)"
|
|
6699
|
+
];
|
|
6700
|
+
function createFinalizationServices(client) {
|
|
6701
|
+
const { l1, l2, signer } = client;
|
|
5336
6702
|
return {
|
|
5337
|
-
async
|
|
5338
|
-
const
|
|
5339
|
-
|
|
5340
|
-
|
|
6703
|
+
async fetchFinalizeDepositParams(l2TxHash) {
|
|
6704
|
+
const parsed = await wrapAs8(
|
|
6705
|
+
"RPC",
|
|
6706
|
+
OP_WITHDRAWALS.finalize.fetchParams.receipt,
|
|
6707
|
+
() => client.zks.getReceiptWithL2ToL1(l2TxHash),
|
|
6708
|
+
{
|
|
6709
|
+
ctx: { where: "getReceiptWithL2ToL1", l2TxHash },
|
|
6710
|
+
message: "Failed to fetch L2 receipt (with L2\u2192L1 logs)."
|
|
6711
|
+
}
|
|
6712
|
+
);
|
|
6713
|
+
if (!parsed) {
|
|
6714
|
+
throw createError("STATE", {
|
|
6715
|
+
resource: "withdrawals",
|
|
6716
|
+
operation: OP_WITHDRAWALS.finalize.fetchParams.receipt,
|
|
6717
|
+
message: "L2 receipt not found.",
|
|
6718
|
+
context: { l2TxHash }
|
|
6719
|
+
});
|
|
6720
|
+
}
|
|
6721
|
+
const ev = await wrapAs8(
|
|
5341
6722
|
"INTERNAL",
|
|
5342
|
-
OP_WITHDRAWALS.
|
|
5343
|
-
|
|
6723
|
+
OP_WITHDRAWALS.finalize.fetchParams.findMessage,
|
|
6724
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
|
6725
|
+
() => Promise.resolve(findL1MessageSentLog(parsed, { index: 0 })),
|
|
5344
6726
|
{
|
|
5345
|
-
ctx: {
|
|
5346
|
-
message: "Failed to
|
|
6727
|
+
ctx: { l2TxHash, index: 0 },
|
|
6728
|
+
message: "Failed to locate L1MessageSent event in L2 receipt."
|
|
5347
6729
|
}
|
|
5348
6730
|
);
|
|
5349
|
-
const
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
6731
|
+
const message = await wrapAs8(
|
|
6732
|
+
"INTERNAL",
|
|
6733
|
+
OP_WITHDRAWALS.finalize.fetchParams.decodeMessage,
|
|
6734
|
+
() => Promise.resolve(ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], ev.data)[0]),
|
|
6735
|
+
{
|
|
6736
|
+
ctx: { where: "decode L1MessageSent", data: ev.data },
|
|
6737
|
+
message: "Failed to decode withdrawal message."
|
|
6738
|
+
}
|
|
6739
|
+
);
|
|
6740
|
+
const raw = await wrapAs8(
|
|
6741
|
+
"RPC",
|
|
6742
|
+
OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
|
|
6743
|
+
() => client.zks.getReceiptWithL2ToL1(l2TxHash),
|
|
6744
|
+
{
|
|
6745
|
+
ctx: { where: "getReceiptWithL2ToL1 (raw)", l2TxHash },
|
|
6746
|
+
message: "Failed to fetch raw L2 receipt."
|
|
6747
|
+
}
|
|
6748
|
+
);
|
|
6749
|
+
if (!raw) {
|
|
6750
|
+
throw createError("STATE", {
|
|
6751
|
+
resource: "withdrawals",
|
|
6752
|
+
operation: OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
|
|
6753
|
+
message: "Raw L2 receipt not found.",
|
|
6754
|
+
context: { l2TxHash }
|
|
6755
|
+
});
|
|
6756
|
+
}
|
|
6757
|
+
const idx = await wrapAs8(
|
|
6758
|
+
"INTERNAL",
|
|
6759
|
+
OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
|
|
6760
|
+
() => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
|
|
6761
|
+
{
|
|
6762
|
+
ctx: { where: "derive messenger log index", l2TxHash, receipt: raw },
|
|
6763
|
+
message: "Failed to derive messenger log index."
|
|
6764
|
+
}
|
|
6765
|
+
);
|
|
6766
|
+
const proof = await wrapAs8(
|
|
6767
|
+
"RPC",
|
|
6768
|
+
OP_WITHDRAWALS.finalize.fetchParams.proof,
|
|
6769
|
+
() => client.zks.getL2ToL1LogProof(l2TxHash, idx),
|
|
6770
|
+
{
|
|
6771
|
+
ctx: { where: "get L2\u2192L1 log proof", l2TxHash, messengerLogIndex: idx },
|
|
6772
|
+
message: "Failed to fetch L2\u2192L1 log proof."
|
|
6773
|
+
}
|
|
6774
|
+
);
|
|
6775
|
+
const { chainId } = await wrapAs8(
|
|
6776
|
+
"RPC",
|
|
6777
|
+
OP_WITHDRAWALS.finalize.fetchParams.network,
|
|
6778
|
+
() => l2.getNetwork(),
|
|
6779
|
+
{
|
|
6780
|
+
ctx: { where: "l2.getNetwork" },
|
|
6781
|
+
message: "Failed to read L2 network."
|
|
6782
|
+
}
|
|
6783
|
+
);
|
|
6784
|
+
const txIndex = Number(parsed.transactionIndex ?? 0);
|
|
6785
|
+
const params = {
|
|
6786
|
+
chainId: BigInt(chainId),
|
|
6787
|
+
l2BatchNumber: proof.batchNumber,
|
|
6788
|
+
l2MessageIndex: proof.id,
|
|
6789
|
+
l2Sender: L2_ASSET_ROUTER_ADDRESS,
|
|
6790
|
+
l2TxNumberInBatch: txIndex,
|
|
6791
|
+
message,
|
|
6792
|
+
merkleProof: proof.proof
|
|
5354
6793
|
};
|
|
5355
|
-
const
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
6794
|
+
const { l1Nullifier } = await client.ensureAddresses();
|
|
6795
|
+
return { params, nullifier: l1Nullifier };
|
|
6796
|
+
},
|
|
6797
|
+
async simulateFinalizeReadiness(params) {
|
|
6798
|
+
const { l1Nullifier } = await client.ensureAddresses();
|
|
6799
|
+
const done = await (async () => {
|
|
6800
|
+
try {
|
|
6801
|
+
const cMini = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
|
|
6802
|
+
const isFinalized = await wrapAs8(
|
|
6803
|
+
"RPC",
|
|
6804
|
+
OP_WITHDRAWALS.finalize.readiness.isFinalized,
|
|
6805
|
+
() => cMini.isWithdrawalFinalized(
|
|
6806
|
+
params.chainId,
|
|
6807
|
+
params.l2BatchNumber,
|
|
6808
|
+
params.l2MessageIndex
|
|
6809
|
+
),
|
|
6810
|
+
{
|
|
6811
|
+
ctx: { where: "isWithdrawalFinalized", params },
|
|
6812
|
+
message: "Failed to read finalization status."
|
|
6813
|
+
}
|
|
6814
|
+
);
|
|
6815
|
+
return Boolean(isFinalized);
|
|
6816
|
+
} catch {
|
|
6817
|
+
return false;
|
|
6818
|
+
}
|
|
6819
|
+
})();
|
|
6820
|
+
if (done) return { kind: "FINALIZED" };
|
|
6821
|
+
const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, l1);
|
|
6822
|
+
try {
|
|
6823
|
+
await c.finalizeDeposit.staticCall(params);
|
|
6824
|
+
return { kind: "READY" };
|
|
6825
|
+
} catch (e) {
|
|
6826
|
+
return classifyReadinessFromRevert(e);
|
|
6827
|
+
}
|
|
6828
|
+
},
|
|
6829
|
+
async isWithdrawalFinalized(key) {
|
|
6830
|
+
const { l1Nullifier } = await client.ensureAddresses();
|
|
6831
|
+
const c = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
|
|
6832
|
+
return await wrapAs8(
|
|
6833
|
+
"RPC",
|
|
6834
|
+
OP_WITHDRAWALS.finalize.isFinalized,
|
|
6835
|
+
() => c.isWithdrawalFinalized(key.chainIdL2, key.l2BatchNumber, key.l2MessageIndex),
|
|
6836
|
+
{
|
|
6837
|
+
ctx: { where: "isWithdrawalFinalized", key },
|
|
6838
|
+
message: "Failed to read finalization status."
|
|
6839
|
+
}
|
|
6840
|
+
);
|
|
6841
|
+
},
|
|
6842
|
+
async estimateFinalization(params) {
|
|
6843
|
+
const { l1Nullifier } = await client.ensureAddresses();
|
|
6844
|
+
const signer2 = client.getL1Signer();
|
|
6845
|
+
const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, signer2);
|
|
6846
|
+
const gasLimit = await wrapAs8(
|
|
6847
|
+
"RPC",
|
|
6848
|
+
OP_WITHDRAWALS.finalize.estimate,
|
|
6849
|
+
() => c.finalizeDeposit.estimateGas(params),
|
|
6850
|
+
{
|
|
6851
|
+
ctx: {
|
|
6852
|
+
where: "estimateGas(finalizeDeposit)",
|
|
6853
|
+
chainIdL2: params.chainId,
|
|
6854
|
+
l2BatchNumber: params.l2BatchNumber,
|
|
6855
|
+
l2MessageIndex: params.l2MessageIndex,
|
|
6856
|
+
l1Nullifier
|
|
6857
|
+
},
|
|
6858
|
+
message: "Failed to estimate gas for finalizeDeposit."
|
|
6859
|
+
}
|
|
6860
|
+
);
|
|
6861
|
+
const feeData = await wrapAs8("RPC", OP_WITHDRAWALS.finalize.estimate, () => l1.getFeeData(), {
|
|
6862
|
+
ctx: { where: "l1.getFeeData" },
|
|
6863
|
+
message: "Failed to estimate fee data for finalizeDeposit."
|
|
6864
|
+
});
|
|
6865
|
+
const maxFeePerGas = feeData.maxFeePerGas ?? feeData.gasPrice ?? // legacy-style gas price if present
|
|
6866
|
+
(() => {
|
|
6867
|
+
throw createError("RPC", {
|
|
6868
|
+
resource: "withdrawals",
|
|
6869
|
+
operation: OP_WITHDRAWALS.finalize.estimate,
|
|
6870
|
+
message: "Provider did not return gas price or EIP-1559 fields.",
|
|
6871
|
+
context: { feeData }
|
|
6872
|
+
});
|
|
6873
|
+
})();
|
|
6874
|
+
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? 0n;
|
|
6875
|
+
return {
|
|
6876
|
+
gasLimit,
|
|
6877
|
+
maxFeePerGas,
|
|
6878
|
+
maxPriorityFeePerGas
|
|
6879
|
+
};
|
|
6880
|
+
},
|
|
6881
|
+
async finalizeDeposit(params) {
|
|
6882
|
+
const { l1Nullifier } = await client.ensureAddresses();
|
|
6883
|
+
const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, signer);
|
|
6884
|
+
try {
|
|
6885
|
+
const receipt = await c.finalizeDeposit(params);
|
|
6886
|
+
const hash = receipt.hash;
|
|
6887
|
+
return {
|
|
6888
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
6889
|
+
hash,
|
|
6890
|
+
wait: async () => {
|
|
6891
|
+
try {
|
|
6892
|
+
return await receipt.wait();
|
|
6893
|
+
} catch (e) {
|
|
6894
|
+
throw toZKsyncError(
|
|
6895
|
+
"EXECUTION",
|
|
6896
|
+
{
|
|
6897
|
+
resource: "withdrawals",
|
|
6898
|
+
operation: OP_WITHDRAWALS.finalize.wait,
|
|
6899
|
+
message: "Failed while waiting for finalizeDeposit transaction.",
|
|
6900
|
+
context: { txHash: hash }
|
|
6901
|
+
},
|
|
6902
|
+
e
|
|
6903
|
+
);
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6906
|
+
};
|
|
6907
|
+
} catch (e) {
|
|
6908
|
+
throw toZKsyncError(
|
|
6909
|
+
"EXECUTION",
|
|
6910
|
+
{
|
|
6911
|
+
resource: "withdrawals",
|
|
6912
|
+
operation: OP_WITHDRAWALS.finalize.send,
|
|
6913
|
+
message: "Failed to send finalizeDeposit transaction.",
|
|
6914
|
+
context: {
|
|
6915
|
+
chainIdL2: params.chainId,
|
|
6916
|
+
l2BatchNumber: params.l2BatchNumber,
|
|
6917
|
+
l2MessageIndex: params.l2MessageIndex,
|
|
6918
|
+
l1Nullifier
|
|
6919
|
+
}
|
|
6920
|
+
},
|
|
6921
|
+
e
|
|
6922
|
+
);
|
|
5360
6923
|
}
|
|
5361
|
-
const fees = buildFeeBreakdown2({
|
|
5362
|
-
feeToken: L2_BASE_TOKEN_ADDRESS,
|
|
5363
|
-
l2Gas: gas
|
|
5364
|
-
});
|
|
5365
|
-
steps.push({
|
|
5366
|
-
key: "l2-base-token:withdraw",
|
|
5367
|
-
kind: "l2-base-token:withdraw",
|
|
5368
|
-
description: "Withdraw ETH via L2 Base Token System",
|
|
5369
|
-
tx
|
|
5370
|
-
});
|
|
5371
|
-
return { steps, approvals: [], fees };
|
|
5372
6924
|
}
|
|
5373
6925
|
};
|
|
5374
6926
|
}
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
6927
|
+
|
|
6928
|
+
// src/adapters/ethers/resources/withdrawals/index.ts
|
|
6929
|
+
var ROUTES2 = {
|
|
6930
|
+
base: routeEthBase(),
|
|
6931
|
+
// BaseTokenSystem.withdraw, chain base = ETH
|
|
6932
|
+
"erc20-nonbase": routeErc20NonBase2()
|
|
6933
|
+
// AssetRouter.withdraw for non-base ERC-20s
|
|
5378
6934
|
};
|
|
5379
|
-
function
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
6935
|
+
function createWithdrawalsResource(client, tokens, contracts) {
|
|
6936
|
+
const svc = createFinalizationServices(client);
|
|
6937
|
+
const { wrap: wrap6, toResult: toResult3 } = createErrorHandlers("withdrawals");
|
|
6938
|
+
const tokensResource = tokens ?? createTokensResource(client);
|
|
6939
|
+
const contractsResource = contracts ?? createContractsResource(client);
|
|
6940
|
+
async function buildPlan(p) {
|
|
6941
|
+
const ctx = await commonCtx2(p, client, tokensResource, contractsResource);
|
|
6942
|
+
await ROUTES2[ctx.route].preflight?.(p, ctx);
|
|
6943
|
+
const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
|
|
6944
|
+
return {
|
|
6945
|
+
route: ctx.route,
|
|
6946
|
+
summary: {
|
|
6947
|
+
route: ctx.route,
|
|
6948
|
+
approvalsNeeded: approvals,
|
|
6949
|
+
amounts: {
|
|
6950
|
+
transfer: { token: p.token, amount: p.amount }
|
|
6951
|
+
},
|
|
6952
|
+
fees
|
|
6953
|
+
},
|
|
6954
|
+
steps
|
|
6955
|
+
};
|
|
6956
|
+
}
|
|
6957
|
+
const finalizeCache = /* @__PURE__ */ new Map();
|
|
6958
|
+
const quote = (p) => wrap6(
|
|
6959
|
+
OP_WITHDRAWALS.quote,
|
|
6960
|
+
async () => {
|
|
6961
|
+
const plan = await buildPlan(p);
|
|
6962
|
+
return plan.summary;
|
|
6963
|
+
},
|
|
6964
|
+
{
|
|
6965
|
+
message: "Internal error while preparing a withdrawal quote.",
|
|
6966
|
+
ctx: { token: p.token, where: "withdrawals.quote" }
|
|
6967
|
+
}
|
|
6968
|
+
);
|
|
6969
|
+
const tryQuote = (p) => toResult3(
|
|
6970
|
+
OP_WITHDRAWALS.tryQuote,
|
|
6971
|
+
async () => {
|
|
6972
|
+
const plan = await buildPlan(p);
|
|
6973
|
+
return plan.summary;
|
|
6974
|
+
},
|
|
6975
|
+
{
|
|
6976
|
+
message: "Internal error while preparing a withdrawal quote.",
|
|
6977
|
+
ctx: { token: p.token, where: "withdrawals.tryQuote" }
|
|
6978
|
+
}
|
|
6979
|
+
);
|
|
6980
|
+
const prepare = (p) => wrap6(OP_WITHDRAWALS.prepare, () => buildPlan(p), {
|
|
6981
|
+
message: "Internal error while preparing a withdrawal plan.",
|
|
6982
|
+
ctx: { token: p.token, where: "withdrawals.prepare" }
|
|
6983
|
+
});
|
|
6984
|
+
const tryPrepare = (p) => toResult3(OP_WITHDRAWALS.tryPrepare, () => buildPlan(p), {
|
|
6985
|
+
message: "Internal error while preparing a withdrawal plan.",
|
|
6986
|
+
ctx: { token: p.token, where: "withdrawals.tryPrepare" }
|
|
6987
|
+
});
|
|
6988
|
+
const create = (p) => wrap6(
|
|
6989
|
+
OP_WITHDRAWALS.create,
|
|
6990
|
+
async () => {
|
|
6991
|
+
const plan = await prepare(p);
|
|
6992
|
+
const stepHashes = {};
|
|
6993
|
+
const managed = new ethers.NonceManager(client.getL2Signer());
|
|
6994
|
+
const from = await managed.getAddress();
|
|
6995
|
+
let next;
|
|
6996
|
+
if (typeof p.l2TxOverrides?.nonce === "number") {
|
|
6997
|
+
next = p.l2TxOverrides.nonce;
|
|
6998
|
+
} else {
|
|
6999
|
+
const blockTag = p.l2TxOverrides?.nonce ?? "pending";
|
|
7000
|
+
next = await client.l2.getTransactionCount(from, blockTag);
|
|
7001
|
+
}
|
|
7002
|
+
for (const step of plan.steps) {
|
|
7003
|
+
step.tx.nonce = next++;
|
|
7004
|
+
if (p.l2TxOverrides) {
|
|
7005
|
+
const overrides = p.l2TxOverrides;
|
|
7006
|
+
if (overrides.gasLimit != null) step.tx.gasLimit = overrides.gasLimit;
|
|
7007
|
+
if (overrides.maxFeePerGas != null) step.tx.maxFeePerGas = overrides.maxFeePerGas;
|
|
7008
|
+
if (overrides.maxPriorityFeePerGas != null) {
|
|
7009
|
+
step.tx.maxPriorityFeePerGas = overrides.maxPriorityFeePerGas;
|
|
7010
|
+
}
|
|
7011
|
+
}
|
|
7012
|
+
if (!step.tx.gasLimit) {
|
|
7013
|
+
try {
|
|
7014
|
+
const est = await client.l2.estimateGas(step.tx);
|
|
7015
|
+
step.tx.gasLimit = BigInt(est) * 115n / 100n;
|
|
7016
|
+
} catch {
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
let hash;
|
|
7020
|
+
try {
|
|
7021
|
+
const sent = await managed.sendTransaction(step.tx);
|
|
7022
|
+
hash = sent.hash;
|
|
7023
|
+
stepHashes[step.key] = hash;
|
|
7024
|
+
const rcpt = await sent.wait();
|
|
7025
|
+
if (rcpt?.status === 0) {
|
|
7026
|
+
throw createError("EXECUTION", {
|
|
7027
|
+
resource: "withdrawals",
|
|
7028
|
+
operation: "withdrawals.create.sendTransaction",
|
|
7029
|
+
message: "Withdrawal transaction reverted on L2 during a step.",
|
|
7030
|
+
context: { step: step.key, txHash: hash, nonce: Number(step.tx.nonce ?? -1) }
|
|
7031
|
+
});
|
|
7032
|
+
}
|
|
7033
|
+
} catch (e) {
|
|
7034
|
+
throw toZKsyncError(
|
|
7035
|
+
"EXECUTION",
|
|
7036
|
+
{
|
|
7037
|
+
resource: "withdrawals",
|
|
7038
|
+
operation: "withdrawals.create.sendTransaction",
|
|
7039
|
+
message: "Failed to send or confirm a withdrawal transaction step.",
|
|
7040
|
+
context: { step: step.key, txHash: hash, nonce: Number(step.tx.nonce ?? -1) }
|
|
7041
|
+
},
|
|
7042
|
+
e
|
|
7043
|
+
);
|
|
7044
|
+
}
|
|
7045
|
+
}
|
|
7046
|
+
const keys = Object.keys(stepHashes);
|
|
7047
|
+
const l2TxHash = stepHashes[keys[keys.length - 1]];
|
|
7048
|
+
return { kind: "withdrawal", l2TxHash, stepHashes, plan };
|
|
7049
|
+
},
|
|
7050
|
+
{
|
|
7051
|
+
message: "Internal error while creating withdrawal transactions.",
|
|
7052
|
+
ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.create" }
|
|
7053
|
+
}
|
|
7054
|
+
);
|
|
7055
|
+
const tryCreate = (p) => toResult3(OP_WITHDRAWALS.tryCreate, () => create(p), {
|
|
7056
|
+
message: "Internal error while creating withdrawal transactions.",
|
|
7057
|
+
ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.tryCreate" }
|
|
7058
|
+
});
|
|
7059
|
+
const status = (h) => wrap6(
|
|
7060
|
+
OP_WITHDRAWALS.status,
|
|
7061
|
+
async () => {
|
|
7062
|
+
const l2TxHash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
|
|
7063
|
+
if (!l2TxHash || l2TxHash === "0x") {
|
|
7064
|
+
return { phase: "UNKNOWN", l2TxHash: "0x" };
|
|
7065
|
+
}
|
|
7066
|
+
let l2Rcpt;
|
|
7067
|
+
try {
|
|
7068
|
+
l2Rcpt = await client.l2.getTransactionReceipt(l2TxHash);
|
|
7069
|
+
} catch (e) {
|
|
7070
|
+
if (isReceiptNotFound(e)) {
|
|
7071
|
+
return { phase: "L2_PENDING", l2TxHash };
|
|
7072
|
+
}
|
|
7073
|
+
throw toZKsyncError(
|
|
7074
|
+
"RPC",
|
|
7075
|
+
{
|
|
7076
|
+
resource: "withdrawals",
|
|
7077
|
+
operation: "withdrawals.status.getTransactionReceipt",
|
|
7078
|
+
message: "Failed to fetch L2 transaction receipt.",
|
|
7079
|
+
context: { l2TxHash, where: "l2.getTransactionReceipt" }
|
|
5395
7080
|
},
|
|
5396
|
-
|
|
7081
|
+
e
|
|
7082
|
+
);
|
|
7083
|
+
}
|
|
7084
|
+
if (!l2Rcpt) return { phase: "L2_PENDING", l2TxHash };
|
|
7085
|
+
let pack;
|
|
7086
|
+
try {
|
|
7087
|
+
pack = await svc.fetchFinalizeDepositParams(l2TxHash);
|
|
7088
|
+
} catch {
|
|
7089
|
+
return { phase: "PENDING", l2TxHash };
|
|
7090
|
+
}
|
|
7091
|
+
const key = {
|
|
7092
|
+
chainIdL2: pack.params.chainId,
|
|
7093
|
+
l2BatchNumber: pack.params.l2BatchNumber,
|
|
7094
|
+
l2MessageIndex: pack.params.l2MessageIndex
|
|
7095
|
+
};
|
|
7096
|
+
try {
|
|
7097
|
+
const done = await svc.isWithdrawalFinalized(key);
|
|
7098
|
+
if (done) return { phase: "FINALIZED", l2TxHash, key };
|
|
7099
|
+
} catch {
|
|
7100
|
+
}
|
|
7101
|
+
const readiness = await svc.simulateFinalizeReadiness(pack.params);
|
|
7102
|
+
if (readiness.kind === "FINALIZED") return { phase: "FINALIZED", l2TxHash, key };
|
|
7103
|
+
if (readiness.kind === "READY") return { phase: "READY_TO_FINALIZE", l2TxHash, key };
|
|
7104
|
+
return { phase: "PENDING", l2TxHash, key };
|
|
7105
|
+
},
|
|
7106
|
+
{
|
|
7107
|
+
message: "Internal error while checking withdrawal status.",
|
|
7108
|
+
ctx: { where: "withdrawals.status", l2TxHash: typeof h === "string" ? h : h.l2TxHash }
|
|
7109
|
+
}
|
|
7110
|
+
);
|
|
7111
|
+
const wait = (h, opts = {
|
|
7112
|
+
for: "l2",
|
|
7113
|
+
pollMs: 5500
|
|
7114
|
+
}) => wrap6(
|
|
7115
|
+
OP_WITHDRAWALS.wait,
|
|
7116
|
+
async () => {
|
|
7117
|
+
const l2Hash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
|
|
7118
|
+
if (!l2Hash || l2Hash === "0x") return null;
|
|
7119
|
+
if (opts.for === "l2") {
|
|
7120
|
+
let rcpt;
|
|
7121
|
+
try {
|
|
7122
|
+
rcpt = await client.l2.waitForTransaction(l2Hash);
|
|
7123
|
+
} catch (e) {
|
|
7124
|
+
throw toZKsyncError(
|
|
7125
|
+
"RPC",
|
|
7126
|
+
{
|
|
7127
|
+
resource: "withdrawals",
|
|
7128
|
+
operation: "withdrawals.wait.l2.waitForTransaction",
|
|
7129
|
+
message: "Failed while waiting for L2 transaction.",
|
|
7130
|
+
context: { l2TxHash: l2Hash }
|
|
7131
|
+
},
|
|
7132
|
+
e
|
|
7133
|
+
);
|
|
5397
7134
|
}
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
const
|
|
5411
|
-
if (
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
7135
|
+
if (!rcpt) return null;
|
|
7136
|
+
try {
|
|
7137
|
+
const raw = await client.zks.getReceiptWithL2ToL1(l2Hash);
|
|
7138
|
+
rcpt.l2ToL1Logs = raw?.l2ToL1Logs ?? [];
|
|
7139
|
+
} catch {
|
|
7140
|
+
rcpt.l2ToL1Logs = rcpt.l2ToL1Logs ?? [];
|
|
7141
|
+
}
|
|
7142
|
+
return rcpt;
|
|
7143
|
+
}
|
|
7144
|
+
const poll = Math.max(1e3, opts.pollMs ?? 2500);
|
|
7145
|
+
const deadline = opts.timeoutMs ? Date.now() + opts.timeoutMs : void 0;
|
|
7146
|
+
while (true) {
|
|
7147
|
+
const s = await status(l2Hash);
|
|
7148
|
+
if (opts.for === "ready") {
|
|
7149
|
+
if (s.phase === "READY_TO_FINALIZE" || s.phase === "FINALIZED") return null;
|
|
7150
|
+
} else {
|
|
7151
|
+
if (s.phase === "FINALIZED") {
|
|
7152
|
+
const l1Hash = finalizeCache.get(l2Hash);
|
|
7153
|
+
if (l1Hash) {
|
|
7154
|
+
try {
|
|
7155
|
+
const l1Rcpt = await client.l1.getTransactionReceipt(l1Hash);
|
|
7156
|
+
if (l1Rcpt) {
|
|
7157
|
+
finalizeCache.delete(l2Hash);
|
|
7158
|
+
return l1Rcpt;
|
|
7159
|
+
}
|
|
7160
|
+
} catch {
|
|
7161
|
+
}
|
|
7162
|
+
}
|
|
7163
|
+
return null;
|
|
7164
|
+
}
|
|
5415
7165
|
}
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
kind: "approve:l2",
|
|
5419
|
-
description: `Approve ${p.amount} to NativeTokenVault`,
|
|
5420
|
-
tx: approveTx
|
|
5421
|
-
});
|
|
7166
|
+
if (deadline && Date.now() > deadline) return null;
|
|
7167
|
+
await new Promise((r) => setTimeout(r, poll));
|
|
5422
7168
|
}
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
7169
|
+
},
|
|
7170
|
+
{
|
|
7171
|
+
message: "Internal error while waiting for withdrawal.",
|
|
7172
|
+
ctx: {
|
|
7173
|
+
where: "withdrawals.wait",
|
|
7174
|
+
l2TxHash: typeof h === "string" ? h : h.l2TxHash,
|
|
7175
|
+
for: opts.for
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
);
|
|
7179
|
+
const finalize = (l2TxHash) => wrap6(
|
|
7180
|
+
OP_WITHDRAWALS.finalize.send,
|
|
7181
|
+
async () => {
|
|
7182
|
+
const pack = await (async () => {
|
|
7183
|
+
try {
|
|
7184
|
+
return await svc.fetchFinalizeDepositParams(l2TxHash);
|
|
7185
|
+
} catch (e) {
|
|
7186
|
+
throw createError("STATE", {
|
|
7187
|
+
resource: "withdrawals",
|
|
7188
|
+
operation: OP_WITHDRAWALS.finalize.fetchParams.receipt,
|
|
7189
|
+
message: "Withdrawal not ready: finalize params unavailable.",
|
|
7190
|
+
context: { l2TxHash },
|
|
7191
|
+
cause: e
|
|
7192
|
+
});
|
|
5435
7193
|
}
|
|
5436
|
-
);
|
|
5437
|
-
const
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
7194
|
+
})();
|
|
7195
|
+
const { params } = pack;
|
|
7196
|
+
const key = {
|
|
7197
|
+
chainIdL2: params.chainId,
|
|
7198
|
+
l2BatchNumber: params.l2BatchNumber,
|
|
7199
|
+
l2MessageIndex: params.l2MessageIndex
|
|
7200
|
+
};
|
|
7201
|
+
try {
|
|
7202
|
+
const done = await svc.isWithdrawalFinalized(key);
|
|
7203
|
+
if (done) {
|
|
7204
|
+
const statusNow = await status(l2TxHash);
|
|
7205
|
+
return { status: statusNow };
|
|
5446
7206
|
}
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
const
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
7207
|
+
} catch {
|
|
7208
|
+
}
|
|
7209
|
+
const readiness = await svc.simulateFinalizeReadiness(params);
|
|
7210
|
+
if (readiness.kind === "FINALIZED") {
|
|
7211
|
+
const statusNow = await status(l2TxHash);
|
|
7212
|
+
return { status: statusNow };
|
|
7213
|
+
}
|
|
7214
|
+
if (readiness.kind === "NOT_READY") {
|
|
7215
|
+
throw createError("STATE", {
|
|
7216
|
+
resource: "withdrawals",
|
|
7217
|
+
operation: OP_WITHDRAWALS.finalize.readiness.simulate,
|
|
7218
|
+
message: "Withdrawal not ready to finalize.",
|
|
7219
|
+
context: readiness
|
|
7220
|
+
});
|
|
7221
|
+
}
|
|
7222
|
+
try {
|
|
7223
|
+
const tx = await svc.finalizeDeposit(params);
|
|
7224
|
+
finalizeCache.set(l2TxHash, tx.hash);
|
|
7225
|
+
const rcpt = await tx.wait();
|
|
7226
|
+
const statusNow = await status(l2TxHash);
|
|
7227
|
+
return { status: statusNow, receipt: rcpt };
|
|
7228
|
+
} catch (e) {
|
|
7229
|
+
const statusNow = await status(l2TxHash);
|
|
7230
|
+
if (statusNow.phase === "FINALIZED") return { status: statusNow };
|
|
7231
|
+
try {
|
|
7232
|
+
const again = await svc.simulateFinalizeReadiness(params);
|
|
7233
|
+
if (again.kind === "NOT_READY") {
|
|
7234
|
+
throw createError("STATE", {
|
|
7235
|
+
resource: "withdrawals",
|
|
7236
|
+
operation: OP_WITHDRAWALS.finalize.readiness.simulate,
|
|
7237
|
+
message: "Withdrawal not ready to finalize.",
|
|
7238
|
+
context: again
|
|
7239
|
+
});
|
|
7240
|
+
}
|
|
7241
|
+
} catch {
|
|
5456
7242
|
}
|
|
5457
|
-
|
|
5458
|
-
const withdrawTx = {
|
|
5459
|
-
to: ctx.l2AssetRouter,
|
|
5460
|
-
data: dataWithdraw,
|
|
5461
|
-
from: ctx.sender
|
|
5462
|
-
};
|
|
5463
|
-
const withdrawGas = await quoteL2Gas4({ ctx, tx: withdrawTx });
|
|
5464
|
-
if (withdrawGas) {
|
|
5465
|
-
withdrawTx.gasLimit = withdrawGas.gasLimit;
|
|
5466
|
-
withdrawTx.maxFeePerGas = withdrawGas.maxFeePerGas;
|
|
5467
|
-
withdrawTx.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
|
|
7243
|
+
throw e;
|
|
5468
7244
|
}
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
7245
|
+
},
|
|
7246
|
+
{
|
|
7247
|
+
message: "Internal error while attempting to finalize withdrawal.",
|
|
7248
|
+
ctx: { l2TxHash, where: "withdrawals.finalize" }
|
|
7249
|
+
}
|
|
7250
|
+
);
|
|
7251
|
+
const tryFinalize = (l2TxHash) => toResult3("withdrawals.tryFinalize", () => finalize(l2TxHash), {
|
|
7252
|
+
message: "Internal error while attempting to tryFinalize withdrawal.",
|
|
7253
|
+
ctx: { l2TxHash, where: "withdrawals.tryFinalize" }
|
|
7254
|
+
});
|
|
7255
|
+
const tryWait = (h, opts) => toResult3(
|
|
7256
|
+
OP_WITHDRAWALS.tryWait,
|
|
7257
|
+
async () => {
|
|
7258
|
+
const v = await wait(h, opts);
|
|
7259
|
+
if (v) return v;
|
|
7260
|
+
throw createError("STATE", {
|
|
7261
|
+
resource: "withdrawals",
|
|
7262
|
+
operation: "withdrawals.tryWait",
|
|
7263
|
+
message: opts.for === "l2" ? "No L2 receipt yet; the withdrawal has not executed on L2." : "No L1 receipt yet; the withdrawal has not been included on L1.",
|
|
7264
|
+
context: {
|
|
7265
|
+
for: opts.for,
|
|
7266
|
+
l2TxHash: typeof h === "string" ? h : "l2TxHash" in h ? h.l2TxHash : void 0,
|
|
7267
|
+
where: "withdrawals.tryWait"
|
|
7268
|
+
}
|
|
5478
7269
|
});
|
|
5479
|
-
|
|
7270
|
+
},
|
|
7271
|
+
{
|
|
7272
|
+
message: "Internal error while waiting for withdrawal.",
|
|
7273
|
+
ctx: { input: h, for: opts?.for, where: "withdrawals.tryWait" }
|
|
5480
7274
|
}
|
|
7275
|
+
);
|
|
7276
|
+
return {
|
|
7277
|
+
quote,
|
|
7278
|
+
tryQuote,
|
|
7279
|
+
prepare,
|
|
7280
|
+
tryPrepare,
|
|
7281
|
+
create,
|
|
7282
|
+
tryCreate,
|
|
7283
|
+
status,
|
|
7284
|
+
wait,
|
|
7285
|
+
finalize,
|
|
7286
|
+
tryFinalize,
|
|
7287
|
+
tryWait
|
|
5481
7288
|
};
|
|
5482
7289
|
}
|
|
5483
7290
|
|
|
5484
|
-
// src/core/resources/
|
|
5485
|
-
function
|
|
5486
|
-
const
|
|
5487
|
-
const
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
});
|
|
5493
|
-
if (!matches.length) {
|
|
5494
|
-
throw new Error("No L1MessageSent event found in L2 receipt logs.");
|
|
5495
|
-
}
|
|
5496
|
-
const preferred = matches.find((lg) => (lg.address ?? "").toLowerCase() === prefer);
|
|
5497
|
-
const chosen = preferred ?? matches[index] ?? matches[0];
|
|
5498
|
-
if (!chosen) {
|
|
5499
|
-
throw new Error("No suitable L1MessageSent event found.");
|
|
5500
|
-
}
|
|
5501
|
-
return chosen;
|
|
7291
|
+
// src/core/resources/interop/attributes/call.ts
|
|
7292
|
+
function createCallAttributes(codec) {
|
|
7293
|
+
const indirectCall = (messageValue) => codec.encode("indirectCall", [messageValue]);
|
|
7294
|
+
const interopCallValue = (bridgedAmount) => codec.encode("interopCallValue", [bridgedAmount]);
|
|
7295
|
+
return {
|
|
7296
|
+
indirectCall,
|
|
7297
|
+
interopCallValue
|
|
7298
|
+
};
|
|
5502
7299
|
}
|
|
5503
7300
|
|
|
5504
|
-
// src/core/resources/
|
|
5505
|
-
function
|
|
5506
|
-
const
|
|
5507
|
-
const
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
}
|
|
5513
|
-
return (hits[index] ?? hits[0]).i;
|
|
7301
|
+
// src/core/resources/interop/attributes/bundle.ts
|
|
7302
|
+
function createBundleAttributes(codec) {
|
|
7303
|
+
const executionAddress = (executor) => codec.encode("executionAddress", [executor]);
|
|
7304
|
+
const unbundlerAddress = (addr) => codec.encode("unbundlerAddress", [addr]);
|
|
7305
|
+
return {
|
|
7306
|
+
executionAddress,
|
|
7307
|
+
unbundlerAddress
|
|
7308
|
+
};
|
|
5514
7309
|
}
|
|
5515
7310
|
|
|
5516
|
-
// src/
|
|
5517
|
-
|
|
5518
|
-
var IL1NullifierMini = [
|
|
5519
|
-
"function isWithdrawalFinalized(uint256,uint256,uint256) view returns (bool)"
|
|
5520
|
-
];
|
|
5521
|
-
function createFinalizationServices(client) {
|
|
5522
|
-
const { l1, l2, signer } = client;
|
|
7311
|
+
// src/core/resources/interop/attributes/resource.ts
|
|
7312
|
+
function createAttributesResource(codec) {
|
|
5523
7313
|
return {
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
7314
|
+
call: createCallAttributes(codec),
|
|
7315
|
+
bundle: createBundleAttributes(codec)
|
|
7316
|
+
};
|
|
7317
|
+
}
|
|
7318
|
+
|
|
7319
|
+
// src/adapters/ethers/resources/interop/attributes/resource.ts
|
|
7320
|
+
function getInteropAttributes(params, ctx) {
|
|
7321
|
+
const bundleAttributes = [];
|
|
7322
|
+
if (params.execution?.only) {
|
|
7323
|
+
bundleAttributes.push(ctx.attributes.bundle.executionAddress(params.execution.only));
|
|
7324
|
+
}
|
|
7325
|
+
if (params.unbundling?.by) {
|
|
7326
|
+
bundleAttributes.push(ctx.attributes.bundle.unbundlerAddress(params.unbundling.by));
|
|
7327
|
+
}
|
|
7328
|
+
const callAttributes = params.actions.map((action) => {
|
|
7329
|
+
switch (action.type) {
|
|
7330
|
+
case "sendNative": {
|
|
7331
|
+
const baseMatches = ctx.baseTokens.src.toLowerCase() === ctx.baseTokens.dst.toLowerCase();
|
|
7332
|
+
if (baseMatches) {
|
|
7333
|
+
return [ctx.attributes.call.interopCallValue(action.amount)];
|
|
5532
7334
|
}
|
|
5533
|
-
|
|
5534
|
-
if (!parsed) {
|
|
5535
|
-
throw createError("STATE", {
|
|
5536
|
-
resource: "withdrawals",
|
|
5537
|
-
operation: OP_WITHDRAWALS.finalize.fetchParams.receipt,
|
|
5538
|
-
message: "L2 receipt not found.",
|
|
5539
|
-
context: { l2TxHash }
|
|
5540
|
-
});
|
|
7335
|
+
return [ctx.attributes.call.indirectCall(action.amount)];
|
|
5541
7336
|
}
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
7337
|
+
case "call":
|
|
7338
|
+
if (action.value && action.value > 0n) {
|
|
7339
|
+
return [ctx.attributes.call.interopCallValue(action.value)];
|
|
7340
|
+
}
|
|
7341
|
+
return [];
|
|
7342
|
+
case "sendErc20":
|
|
7343
|
+
return [ctx.attributes.call.indirectCall(0n)];
|
|
7344
|
+
default:
|
|
7345
|
+
assertNever(action);
|
|
7346
|
+
}
|
|
7347
|
+
});
|
|
7348
|
+
return { bundleAttributes, callAttributes };
|
|
7349
|
+
}
|
|
7350
|
+
function createEthersAttributesResource(opts = {}) {
|
|
7351
|
+
const iface = opts.iface ?? new ethers.Interface(IERC7786Attributes_default);
|
|
7352
|
+
const encode2 = (fn, args) => iface.encodeFunctionData(fn, args);
|
|
7353
|
+
return createAttributesResource({ encode: encode2 });
|
|
7354
|
+
}
|
|
7355
|
+
|
|
7356
|
+
// src/core/types/flows/interop.ts
|
|
7357
|
+
function isInteropExpectedRoot(obj) {
|
|
7358
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
7359
|
+
const root = obj;
|
|
7360
|
+
return isBigint(root.rootChainId) && isBigint(root.batchNumber) && isHash(root.expectedRoot);
|
|
7361
|
+
}
|
|
7362
|
+
function isInteropMessageProof(obj) {
|
|
7363
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
7364
|
+
const proof = obj;
|
|
7365
|
+
return isBigint(proof.chainId) && isBigint(proof.l1BatchNumber) && isBigint(proof.l2MessageIndex) && typeof proof.message === "object" && proof.message !== null && isNumber(proof.message.txNumberInBatch) && isAddress(proof.message.sender) && isHash(proof.message.data) && isHash66Array(proof.proof);
|
|
7366
|
+
}
|
|
7367
|
+
function isInteropFinalizationInfo(obj) {
|
|
7368
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
7369
|
+
const info = obj;
|
|
7370
|
+
return isHash66(info.l2SrcTxHash) && isHash66(info.bundleHash) && isBigint(info.dstChainId) && isHash(info.encodedData) && isInteropExpectedRoot(info.expectedRoot) && isInteropMessageProof(info.proof);
|
|
7371
|
+
}
|
|
7372
|
+
|
|
7373
|
+
// src/core/resources/interop/route.ts
|
|
7374
|
+
function sumActionMsgValue(actions) {
|
|
7375
|
+
let sum = 0n;
|
|
7376
|
+
for (const a of actions) {
|
|
7377
|
+
if (a.type === "sendNative") sum += a.amount;
|
|
7378
|
+
else if (a.type === "call" && a.value) sum += a.value;
|
|
7379
|
+
}
|
|
7380
|
+
return sum;
|
|
7381
|
+
}
|
|
7382
|
+
function sumErc20Amounts(actions) {
|
|
7383
|
+
let sum = 0n;
|
|
7384
|
+
for (const a of actions) if (a.type === "sendErc20") sum += a.amount;
|
|
7385
|
+
return sum;
|
|
7386
|
+
}
|
|
7387
|
+
function pickInteropRoute(args) {
|
|
7388
|
+
const hasErc20 = args.actions.some((a) => a.type === "sendErc20");
|
|
7389
|
+
const baseMatches = args.ctx.baseTokenSrc.toLowerCase() === args.ctx.baseTokenDst.toLowerCase();
|
|
7390
|
+
if (hasErc20) return "indirect";
|
|
7391
|
+
if (!baseMatches) return "indirect";
|
|
7392
|
+
return "direct";
|
|
7393
|
+
}
|
|
7394
|
+
|
|
7395
|
+
// src/core/resources/interop/plan.ts
|
|
7396
|
+
function preflightDirect(params, ctx) {
|
|
7397
|
+
if (!params.actions?.length) {
|
|
7398
|
+
throw new Error('route "direct" requires at least one action.');
|
|
7399
|
+
}
|
|
7400
|
+
const baseMatch = ctx.baseTokens.src.toLowerCase() === ctx.baseTokens.dst.toLowerCase();
|
|
7401
|
+
if (!baseMatch) {
|
|
7402
|
+
throw new Error('route "direct" requires matching base tokens between source and destination.');
|
|
7403
|
+
}
|
|
7404
|
+
for (const action of params.actions) {
|
|
7405
|
+
switch (action.type) {
|
|
7406
|
+
case "sendNative":
|
|
7407
|
+
if (action.amount < 0n) {
|
|
7408
|
+
throw new Error("sendNative.amount must be >= 0.");
|
|
5550
7409
|
}
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
() => Promise.resolve(ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], ev.data)[0]),
|
|
5556
|
-
{
|
|
5557
|
-
ctx: { where: "decode L1MessageSent", data: ev.data },
|
|
5558
|
-
message: "Failed to decode withdrawal message."
|
|
7410
|
+
break;
|
|
7411
|
+
case "call":
|
|
7412
|
+
if (action.value != null && action.value < 0n) {
|
|
7413
|
+
throw new Error("call.value must be >= 0 when provided.");
|
|
5559
7414
|
}
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
7415
|
+
break;
|
|
7416
|
+
default:
|
|
7417
|
+
throw new Error(
|
|
7418
|
+
`route "direct" does not support ${action.type} actions; use the indirect route.`
|
|
7419
|
+
);
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
function buildDirectBundle(params, ctx, attrs) {
|
|
7424
|
+
const totalActionValue = sumActionMsgValue(params.actions);
|
|
7425
|
+
const starters = params.actions.map((action, index) => {
|
|
7426
|
+
const to = ctx.codec.formatAddress(action.to);
|
|
7427
|
+
const callAttributes = attrs.callAttributes[index] ?? [];
|
|
7428
|
+
switch (action.type) {
|
|
7429
|
+
case "sendNative":
|
|
7430
|
+
return [to, "0x", callAttributes];
|
|
7431
|
+
case "call":
|
|
7432
|
+
return [to, action.data ?? "0x", callAttributes];
|
|
7433
|
+
default:
|
|
7434
|
+
throw new Error(`buildDirectBundle: unsupported action type "${action.type}".`);
|
|
7435
|
+
}
|
|
7436
|
+
});
|
|
7437
|
+
return {
|
|
7438
|
+
dstChain: ctx.codec.formatChain(ctx.dstChainId),
|
|
7439
|
+
starters,
|
|
7440
|
+
bundleAttributes: attrs.bundleAttributes,
|
|
7441
|
+
approvals: [],
|
|
7442
|
+
quoteExtras: {
|
|
7443
|
+
totalActionValue,
|
|
7444
|
+
bridgedTokenTotal: 0n
|
|
7445
|
+
}
|
|
7446
|
+
};
|
|
7447
|
+
}
|
|
7448
|
+
function preflightIndirect(params, ctx) {
|
|
7449
|
+
if (!params.actions?.length) {
|
|
7450
|
+
throw new Error('route "indirect" requires at least one action.');
|
|
7451
|
+
}
|
|
7452
|
+
const hasErc20 = params.actions.some((a) => a.type === "sendErc20");
|
|
7453
|
+
const baseMatches = ctx.baseTokens.src.toLowerCase() === ctx.baseTokens.dst.toLowerCase();
|
|
7454
|
+
if (!hasErc20 && baseMatches) {
|
|
7455
|
+
throw new Error(
|
|
7456
|
+
'route "indirect" requires ERC-20 actions or mismatched base tokens; use the direct route instead.'
|
|
7457
|
+
);
|
|
7458
|
+
}
|
|
7459
|
+
for (const action of params.actions) {
|
|
7460
|
+
switch (action.type) {
|
|
7461
|
+
case "sendNative":
|
|
7462
|
+
if (action.amount < 0n) {
|
|
7463
|
+
throw new Error("sendNative.amount must be >= 0.");
|
|
5568
7464
|
}
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
operation: OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
|
|
5574
|
-
message: "Raw L2 receipt not found.",
|
|
5575
|
-
context: { l2TxHash }
|
|
5576
|
-
});
|
|
5577
|
-
}
|
|
5578
|
-
const idx = await wrapAs8(
|
|
5579
|
-
"INTERNAL",
|
|
5580
|
-
OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
|
|
5581
|
-
() => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
|
|
5582
|
-
{
|
|
5583
|
-
ctx: { where: "derive messenger log index", l2TxHash, receipt: raw },
|
|
5584
|
-
message: "Failed to derive messenger log index."
|
|
7465
|
+
break;
|
|
7466
|
+
case "sendErc20":
|
|
7467
|
+
if (action.amount < 0n) {
|
|
7468
|
+
throw new Error("sendErc20.amount must be >= 0.");
|
|
5585
7469
|
}
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
7470
|
+
break;
|
|
7471
|
+
case "call":
|
|
7472
|
+
if (action.value != null) {
|
|
7473
|
+
if (action.value < 0n) {
|
|
7474
|
+
throw new Error("call.value must be >= 0 when provided.");
|
|
7475
|
+
}
|
|
7476
|
+
if (action.value > 0n && !baseMatches) {
|
|
7477
|
+
throw new Error("indirect route does not support call.value when base tokens differ.");
|
|
7478
|
+
}
|
|
5594
7479
|
}
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
7480
|
+
break;
|
|
7481
|
+
default:
|
|
7482
|
+
assertNever(action);
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
function buildIndirectBundle(params, ctx, attrs, starterData) {
|
|
7487
|
+
const totalActionValue = sumActionMsgValue(params.actions);
|
|
7488
|
+
const bridgedTokenTotal = sumErc20Amounts(params.actions);
|
|
7489
|
+
const approvalMap = /* @__PURE__ */ new Map();
|
|
7490
|
+
for (const action of params.actions) {
|
|
7491
|
+
if (action.type !== "sendErc20") continue;
|
|
7492
|
+
const key = action.token.toLowerCase();
|
|
7493
|
+
const existing = approvalMap.get(key);
|
|
7494
|
+
if (existing) {
|
|
7495
|
+
existing.amount += action.amount;
|
|
7496
|
+
} else {
|
|
7497
|
+
approvalMap.set(key, {
|
|
7498
|
+
token: action.token,
|
|
7499
|
+
spender: ctx.l2NativeTokenVault,
|
|
7500
|
+
amount: action.amount
|
|
7501
|
+
});
|
|
7502
|
+
}
|
|
7503
|
+
}
|
|
7504
|
+
const approvals = Array.from(approvalMap.values());
|
|
7505
|
+
const starters = params.actions.map((action, index) => {
|
|
7506
|
+
const callAttributes = attrs.callAttributes[index] ?? [];
|
|
7507
|
+
if (starterData[index]?.assetRouterPayload) {
|
|
7508
|
+
const l2AssetRouter = ctx.codec.formatAddress(ctx.l2AssetRouter);
|
|
7509
|
+
return [l2AssetRouter, starterData[index].assetRouterPayload, callAttributes];
|
|
7510
|
+
}
|
|
7511
|
+
const directTo = ctx.codec.formatAddress(action.to);
|
|
7512
|
+
switch (action.type) {
|
|
7513
|
+
case "sendNative":
|
|
7514
|
+
return [directTo, "0x", callAttributes];
|
|
7515
|
+
case "call":
|
|
7516
|
+
return [directTo, action.data ?? "0x", callAttributes];
|
|
7517
|
+
case "sendErc20":
|
|
7518
|
+
throw new Error("buildIndirectBundle: missing assetRouterPayload for sendErc20 action.");
|
|
7519
|
+
default:
|
|
7520
|
+
return assertNever(action);
|
|
7521
|
+
}
|
|
7522
|
+
});
|
|
7523
|
+
return {
|
|
7524
|
+
dstChain: ctx.codec.formatChain(ctx.dstChainId),
|
|
7525
|
+
starters,
|
|
7526
|
+
bundleAttributes: attrs.bundleAttributes,
|
|
7527
|
+
approvals,
|
|
7528
|
+
quoteExtras: {
|
|
7529
|
+
totalActionValue,
|
|
7530
|
+
bridgedTokenTotal
|
|
7531
|
+
}
|
|
7532
|
+
};
|
|
7533
|
+
}
|
|
7534
|
+
var PREFIX_EVM_CHAIN = ethers.getBytes("0x00010000");
|
|
7535
|
+
var PREFIX_EVM_ADDRESS = ethers.getBytes("0x000100000014");
|
|
7536
|
+
function formatInteropEvmChain(chainId) {
|
|
7537
|
+
const chainRef = ethers.toBeArray(chainId);
|
|
7538
|
+
const chainRefLength = ethers.getBytes(ethers.toBeHex(chainRef.length, 1));
|
|
7539
|
+
const payload = ethers.concat([PREFIX_EVM_CHAIN, chainRefLength, chainRef, new Uint8Array([0])]);
|
|
7540
|
+
return ethers.hexlify(payload);
|
|
7541
|
+
}
|
|
7542
|
+
function formatInteropEvmAddress(address) {
|
|
7543
|
+
const normalized = ethers.getAddress(address);
|
|
7544
|
+
const addrBytes = ethers.getBytes(normalized);
|
|
7545
|
+
const payload = ethers.concat([PREFIX_EVM_ADDRESS, addrBytes]);
|
|
7546
|
+
return ethers.hexlify(payload);
|
|
7547
|
+
}
|
|
7548
|
+
var interopCodec = {
|
|
7549
|
+
formatChain: formatInteropEvmChain,
|
|
7550
|
+
formatAddress: formatInteropEvmAddress
|
|
7551
|
+
};
|
|
7552
|
+
function getErc20Tokens(params) {
|
|
7553
|
+
const erc20Tokens = /* @__PURE__ */ new Map();
|
|
7554
|
+
for (const action of params.actions) {
|
|
7555
|
+
if (action.type !== "sendErc20") continue;
|
|
7556
|
+
erc20Tokens.set(action.token.toLowerCase(), action.token);
|
|
7557
|
+
}
|
|
7558
|
+
return Array.from(erc20Tokens.values());
|
|
7559
|
+
}
|
|
7560
|
+
function buildEnsureTokenSteps(erc20Tokens, ctx) {
|
|
7561
|
+
if (erc20Tokens.length === 0) return [];
|
|
7562
|
+
const ntv = new ethers.Contract(ctx.l2NativeTokenVault, L2NativeTokenVault_default, ctx.client.l2);
|
|
7563
|
+
return erc20Tokens.map((token) => ({
|
|
7564
|
+
key: `ensure-token:${token.toLowerCase()}`,
|
|
7565
|
+
kind: "interop.ntv.ensure-token",
|
|
7566
|
+
description: `Ensure ${token} is registered in the native token vault`,
|
|
7567
|
+
tx: {
|
|
7568
|
+
to: ctx.l2NativeTokenVault,
|
|
7569
|
+
data: ntv.interface.encodeFunctionData("ensureTokenIsRegistered", [token]),
|
|
7570
|
+
...ctx.gasOverrides
|
|
7571
|
+
}
|
|
7572
|
+
}));
|
|
7573
|
+
}
|
|
7574
|
+
async function resolveErc20AssetIds(erc20Tokens, ctx) {
|
|
7575
|
+
const assetIds = /* @__PURE__ */ new Map();
|
|
7576
|
+
if (erc20Tokens.length === 0) return assetIds;
|
|
7577
|
+
const ntv = new ethers.Contract(ctx.l2NativeTokenVault, L2NativeTokenVault_default, ctx.client.getL2Signer());
|
|
7578
|
+
for (const token of erc20Tokens) {
|
|
7579
|
+
const assetId = await ntv.getFunction("ensureTokenIsRegistered").staticCall(token);
|
|
7580
|
+
assetIds.set(token.toLowerCase(), assetId);
|
|
7581
|
+
}
|
|
7582
|
+
return assetIds;
|
|
7583
|
+
}
|
|
7584
|
+
|
|
7585
|
+
// src/adapters/ethers/resources/interop/services/starter-data.ts
|
|
7586
|
+
async function getStarterData(params, ctx, erc20AssetIds) {
|
|
7587
|
+
const starterData = [];
|
|
7588
|
+
for (const action of params.actions) {
|
|
7589
|
+
switch (action.type) {
|
|
7590
|
+
case "sendErc20": {
|
|
7591
|
+
const assetId = erc20AssetIds.get(action.token.toLowerCase());
|
|
7592
|
+
if (!assetId) {
|
|
7593
|
+
throw new Error(`Missing precomputed assetId for token ${action.token}.`);
|
|
5603
7594
|
}
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
7595
|
+
const transferData = encodeNativeTokenVaultTransferData(
|
|
7596
|
+
action.amount,
|
|
7597
|
+
action.to,
|
|
7598
|
+
action.token
|
|
7599
|
+
);
|
|
7600
|
+
const assetRouterPayload = encodeSecondBridgeDataV1(assetId, transferData);
|
|
7601
|
+
starterData.push({ assetRouterPayload });
|
|
7602
|
+
break;
|
|
7603
|
+
}
|
|
7604
|
+
case "sendNative":
|
|
7605
|
+
if (!ctx.baseTokens.matches) {
|
|
7606
|
+
const assetId = await ctx.tokens.baseTokenAssetId();
|
|
7607
|
+
const transferData = encodeNativeTokenVaultTransferData(
|
|
7608
|
+
action.amount,
|
|
7609
|
+
action.to,
|
|
7610
|
+
ctx.baseTokens.src
|
|
7611
|
+
);
|
|
7612
|
+
const assetRouterPayload = encodeSecondBridgeDataV1(assetId, transferData);
|
|
7613
|
+
starterData.push({ assetRouterPayload });
|
|
7614
|
+
} else {
|
|
7615
|
+
starterData.push({});
|
|
5622
7616
|
}
|
|
5623
|
-
|
|
5624
|
-
|
|
7617
|
+
break;
|
|
7618
|
+
case "call":
|
|
7619
|
+
starterData.push({});
|
|
7620
|
+
break;
|
|
7621
|
+
default:
|
|
7622
|
+
assertNever(action);
|
|
7623
|
+
}
|
|
7624
|
+
}
|
|
7625
|
+
return starterData;
|
|
7626
|
+
}
|
|
7627
|
+
|
|
7628
|
+
// src/adapters/ethers/resources/interop/routes/indirect.ts
|
|
7629
|
+
function routeIndirect() {
|
|
7630
|
+
return {
|
|
7631
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
7632
|
+
async preflight(params, ctx) {
|
|
7633
|
+
preflightIndirect(params, {
|
|
7634
|
+
dstChainId: ctx.dstChainId,
|
|
7635
|
+
baseTokens: ctx.baseTokens,
|
|
7636
|
+
l2AssetRouter: ctx.l2AssetRouter,
|
|
7637
|
+
l2NativeTokenVault: ctx.l2NativeTokenVault});
|
|
5625
7638
|
},
|
|
5626
|
-
async
|
|
5627
|
-
const
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
7639
|
+
async build(params, ctx) {
|
|
7640
|
+
const steps = [];
|
|
7641
|
+
const erc20Tokens = getErc20Tokens(params);
|
|
7642
|
+
const erc20AssetIds = await resolveErc20AssetIds(erc20Tokens, ctx);
|
|
7643
|
+
const attributes = getInteropAttributes(params, ctx);
|
|
7644
|
+
const starterData = await getStarterData(params, ctx, erc20AssetIds);
|
|
7645
|
+
const bundle = buildIndirectBundle(
|
|
7646
|
+
params,
|
|
5631
7647
|
{
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
7648
|
+
dstChainId: ctx.dstChainId,
|
|
7649
|
+
baseTokens: ctx.baseTokens,
|
|
7650
|
+
l2AssetRouter: ctx.l2AssetRouter,
|
|
7651
|
+
l2NativeTokenVault: ctx.l2NativeTokenVault,
|
|
7652
|
+
codec: interopCodec
|
|
7653
|
+
},
|
|
7654
|
+
attributes,
|
|
7655
|
+
starterData
|
|
5635
7656
|
);
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
7657
|
+
steps.push(...buildEnsureTokenSteps(erc20Tokens, ctx));
|
|
7658
|
+
for (const approval of bundle.approvals) {
|
|
7659
|
+
const erc20 = new ethers.Contract(approval.token, IERC20_default, ctx.client.l2);
|
|
7660
|
+
const currentAllowance = await erc20.allowance(
|
|
7661
|
+
ctx.sender,
|
|
7662
|
+
ctx.l2NativeTokenVault
|
|
7663
|
+
);
|
|
7664
|
+
if (currentAllowance < approval.amount) {
|
|
7665
|
+
const approveData = erc20.interface.encodeFunctionData("approve", [
|
|
7666
|
+
ctx.l2NativeTokenVault,
|
|
7667
|
+
approval.amount
|
|
7668
|
+
]);
|
|
7669
|
+
steps.push({
|
|
7670
|
+
key: `approve:${approval.token}:${ctx.l2NativeTokenVault}`,
|
|
7671
|
+
kind: "approve",
|
|
7672
|
+
description: `Approve ${ctx.l2NativeTokenVault} to spend ${approval.amount} of ${approval.token}`,
|
|
7673
|
+
tx: {
|
|
7674
|
+
to: approval.token,
|
|
7675
|
+
data: approveData,
|
|
7676
|
+
...ctx.gasOverrides
|
|
5650
7677
|
}
|
|
5651
|
-
);
|
|
5652
|
-
return Boolean(isFinalized);
|
|
5653
|
-
} catch {
|
|
5654
|
-
return false;
|
|
7678
|
+
});
|
|
5655
7679
|
}
|
|
5656
|
-
})();
|
|
5657
|
-
if (done) return { kind: "FINALIZED" };
|
|
5658
|
-
const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, l1);
|
|
5659
|
-
try {
|
|
5660
|
-
await c.finalizeDeposit.staticCall(params);
|
|
5661
|
-
return { kind: "READY" };
|
|
5662
|
-
} catch (e) {
|
|
5663
|
-
return classifyReadinessFromRevert(e);
|
|
5664
7680
|
}
|
|
7681
|
+
const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
|
|
7682
|
+
bundle.dstChain,
|
|
7683
|
+
bundle.starters,
|
|
7684
|
+
bundle.bundleAttributes
|
|
7685
|
+
]);
|
|
7686
|
+
steps.push({
|
|
7687
|
+
key: "sendBundle",
|
|
7688
|
+
kind: "interop.center",
|
|
7689
|
+
description: "Send interop bundle (indirect route)",
|
|
7690
|
+
tx: {
|
|
7691
|
+
to: ctx.interopCenter,
|
|
7692
|
+
data,
|
|
7693
|
+
value: bundle.quoteExtras.totalActionValue,
|
|
7694
|
+
...ctx.gasOverrides
|
|
7695
|
+
}
|
|
7696
|
+
});
|
|
7697
|
+
return {
|
|
7698
|
+
steps,
|
|
7699
|
+
approvals: bundle.approvals,
|
|
7700
|
+
quoteExtras: bundle.quoteExtras
|
|
7701
|
+
};
|
|
7702
|
+
}
|
|
7703
|
+
};
|
|
7704
|
+
}
|
|
7705
|
+
|
|
7706
|
+
// src/adapters/ethers/resources/interop/routes/direct.ts
|
|
7707
|
+
function routeDirect() {
|
|
7708
|
+
return {
|
|
7709
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
7710
|
+
async preflight(params, ctx) {
|
|
7711
|
+
preflightDirect(params, {
|
|
7712
|
+
dstChainId: ctx.dstChainId,
|
|
7713
|
+
baseTokens: ctx.baseTokens,
|
|
7714
|
+
l2AssetRouter: ctx.l2AssetRouter,
|
|
7715
|
+
l2NativeTokenVault: ctx.l2NativeTokenVault});
|
|
5665
7716
|
},
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
7717
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
7718
|
+
async build(params, ctx) {
|
|
7719
|
+
const steps = [];
|
|
7720
|
+
const attrs = getInteropAttributes(params, ctx);
|
|
7721
|
+
const built = buildDirectBundle(
|
|
7722
|
+
params,
|
|
5671
7723
|
{
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
7724
|
+
dstChainId: ctx.dstChainId,
|
|
7725
|
+
baseTokens: ctx.baseTokens,
|
|
7726
|
+
l2AssetRouter: ctx.l2AssetRouter,
|
|
7727
|
+
l2NativeTokenVault: ctx.l2NativeTokenVault,
|
|
7728
|
+
codec: interopCodec
|
|
7729
|
+
},
|
|
7730
|
+
attrs
|
|
5675
7731
|
);
|
|
5676
|
-
const
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
7732
|
+
const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
|
|
7733
|
+
built.dstChain,
|
|
7734
|
+
built.starters,
|
|
7735
|
+
built.bundleAttributes
|
|
7736
|
+
]);
|
|
7737
|
+
steps.push({
|
|
7738
|
+
key: "sendBundle",
|
|
7739
|
+
kind: "interop.center",
|
|
7740
|
+
description: `Send interop bundle (direct route; ${params.actions.length} actions)`,
|
|
7741
|
+
// In direct route, msg.value equals the total forwarded value across
|
|
7742
|
+
// all calls (sendNative.amount + call.value).
|
|
7743
|
+
tx: {
|
|
7744
|
+
to: ctx.interopCenter,
|
|
7745
|
+
data,
|
|
7746
|
+
value: built.quoteExtras.totalActionValue,
|
|
7747
|
+
...ctx.gasOverrides
|
|
5684
7748
|
}
|
|
5685
|
-
);
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
7749
|
+
});
|
|
7750
|
+
return {
|
|
7751
|
+
steps,
|
|
7752
|
+
approvals: built.approvals,
|
|
7753
|
+
quoteExtras: built.quoteExtras
|
|
7754
|
+
};
|
|
7755
|
+
}
|
|
7756
|
+
};
|
|
7757
|
+
}
|
|
7758
|
+
var MIN_INTEROP_PROTOCOL = 31;
|
|
7759
|
+
async function assertInteropProtocolVersion(client, srcChainId, dstChainId) {
|
|
7760
|
+
const [srcProtocolVersion, dstProtocolVersion] = await Promise.all([
|
|
7761
|
+
client.getProtocolVersion(srcChainId),
|
|
7762
|
+
client.getProtocolVersion(dstChainId)
|
|
7763
|
+
]);
|
|
7764
|
+
const assertProtocolVersion = (chainId, protocolVersion) => {
|
|
7765
|
+
if (protocolVersion[1] < MIN_INTEROP_PROTOCOL) {
|
|
7766
|
+
throw createError("VALIDATION", {
|
|
7767
|
+
resource: "interop",
|
|
7768
|
+
operation: OP_INTEROP.context.protocolVersion,
|
|
7769
|
+
message: `Interop requires protocol version 31.0+. Found: ${protocolVersion[1]}.${protocolVersion[2]} for chain: ${chainId}.`,
|
|
7770
|
+
context: {
|
|
7771
|
+
chainId,
|
|
7772
|
+
requiredMinor: MIN_INTEROP_PROTOCOL,
|
|
7773
|
+
semver: protocolVersion
|
|
5695
7774
|
}
|
|
5696
|
-
);
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
7775
|
+
});
|
|
7776
|
+
}
|
|
7777
|
+
};
|
|
7778
|
+
assertProtocolVersion(srcChainId, srcProtocolVersion);
|
|
7779
|
+
assertProtocolVersion(dstChainId, dstProtocolVersion);
|
|
7780
|
+
}
|
|
7781
|
+
async function commonCtx3(dstProvider, params, client, tokens, contracts, attributes) {
|
|
7782
|
+
const sender = await client.signer.getAddress();
|
|
7783
|
+
const chainId = (await client.l2.getNetwork()).chainId;
|
|
7784
|
+
const dstChainId = (await dstProvider.getNetwork()).chainId;
|
|
7785
|
+
const {
|
|
7786
|
+
bridgehub,
|
|
7787
|
+
l2AssetRouter,
|
|
7788
|
+
l2NativeTokenVault,
|
|
7789
|
+
interopCenter,
|
|
7790
|
+
interopHandler,
|
|
7791
|
+
l2MessageVerification
|
|
7792
|
+
} = await contracts.addresses();
|
|
7793
|
+
await assertInteropProtocolVersion(client, chainId, dstChainId);
|
|
7794
|
+
const [srcBaseToken, dstBaseToken] = await Promise.all([
|
|
7795
|
+
client.baseToken(chainId),
|
|
7796
|
+
client.baseToken(dstChainId)
|
|
7797
|
+
]);
|
|
7798
|
+
const interopCenterIface = new ethers.Interface(InteropCenter_default);
|
|
7799
|
+
const interopHandlerIface = new ethers.Interface(IInteropHandler_default);
|
|
7800
|
+
const baseMatches = srcBaseToken.toLowerCase() === dstBaseToken.toLowerCase();
|
|
7801
|
+
return {
|
|
7802
|
+
client,
|
|
7803
|
+
tokens,
|
|
7804
|
+
contracts,
|
|
7805
|
+
sender,
|
|
7806
|
+
chainIdL2: chainId,
|
|
7807
|
+
chainId,
|
|
7808
|
+
bridgehub,
|
|
7809
|
+
dstChainId,
|
|
7810
|
+
dstProvider,
|
|
7811
|
+
interopCenter,
|
|
7812
|
+
interopHandler,
|
|
7813
|
+
l2MessageVerification,
|
|
7814
|
+
l2AssetRouter,
|
|
7815
|
+
l2NativeTokenVault,
|
|
7816
|
+
baseTokens: { src: srcBaseToken, dst: dstBaseToken, matches: baseMatches },
|
|
7817
|
+
ifaces: { interopCenter: interopCenterIface, interopHandler: interopHandlerIface },
|
|
7818
|
+
attributes,
|
|
7819
|
+
gasOverrides: params.txOverrides ? toGasOverrides(params.txOverrides) : void 0
|
|
7820
|
+
};
|
|
7821
|
+
}
|
|
7822
|
+
function getTopics() {
|
|
7823
|
+
const centerIface = new ethers.Interface(InteropCenter_default);
|
|
7824
|
+
const handlerIface = new ethers.Interface(IInteropHandler_default);
|
|
7825
|
+
const topics = {
|
|
7826
|
+
interopBundleSent: centerIface.getEvent("InteropBundleSent").topicHash,
|
|
7827
|
+
bundleVerified: handlerIface.getEvent("BundleVerified").topicHash,
|
|
7828
|
+
bundleExecuted: handlerIface.getEvent("BundleExecuted").topicHash,
|
|
7829
|
+
bundleUnbundled: handlerIface.getEvent("BundleUnbundled").topicHash
|
|
7830
|
+
};
|
|
7831
|
+
return { topics, centerIface };
|
|
7832
|
+
}
|
|
7833
|
+
var { wrap: wrap2 } = createErrorHandlers("interop");
|
|
7834
|
+
var DEFAULT_BLOCKS_RANGE_SIZE = 1e4;
|
|
7835
|
+
var DEFAULT_MAX_BLOCKS_BACK = 2e4;
|
|
7836
|
+
var SAFE_BLOCKS_RANGE_SIZE = 1e3;
|
|
7837
|
+
function parseMaxBlockRangeLimit(error) {
|
|
7838
|
+
if (!ethers.isError(error, "UNKNOWN_ERROR")) return null;
|
|
7839
|
+
if (!error.error || typeof error.error !== "object") return null;
|
|
7840
|
+
const match = /query exceeds max block range\s+(\d+)/i.exec(error.error?.message);
|
|
7841
|
+
if (!match) return null;
|
|
7842
|
+
const limit = Number.parseInt(match[1], 10);
|
|
7843
|
+
return Number.isInteger(limit) && limit > 0 ? limit : null;
|
|
7844
|
+
}
|
|
7845
|
+
async function getTxReceipt(provider, txHash) {
|
|
7846
|
+
const receipt = await wrap2(
|
|
7847
|
+
OP_INTEROP.svc.status.sourceReceipt,
|
|
7848
|
+
() => provider.getTransactionReceipt(txHash),
|
|
7849
|
+
{
|
|
7850
|
+
ctx: { where: "l2.getTransactionReceipt", l2SrcTxHash: txHash },
|
|
7851
|
+
message: "Failed to fetch source L2 receipt for interop tx."
|
|
7852
|
+
}
|
|
7853
|
+
);
|
|
7854
|
+
if (!receipt) return null;
|
|
7855
|
+
return {
|
|
7856
|
+
logs: receipt.logs.map((log) => ({
|
|
7857
|
+
address: log.address,
|
|
7858
|
+
topics: log.topics,
|
|
7859
|
+
data: log.data,
|
|
7860
|
+
transactionHash: log.transactionHash
|
|
7861
|
+
}))
|
|
7862
|
+
};
|
|
7863
|
+
}
|
|
7864
|
+
async function getLogs(provider, address, topics, opts) {
|
|
7865
|
+
const maxBlocksBack = opts?.maxBlocksBack ?? DEFAULT_MAX_BLOCKS_BACK;
|
|
7866
|
+
const initialChunkSize = opts?.logChunkSize ?? DEFAULT_BLOCKS_RANGE_SIZE;
|
|
7867
|
+
return await wrap2(
|
|
7868
|
+
OP_INTEROP.svc.status.dstLogs,
|
|
7869
|
+
async () => {
|
|
7870
|
+
const currentBlock = await provider.getBlockNumber();
|
|
7871
|
+
const minBlock = Math.max(0, currentBlock - maxBlocksBack);
|
|
7872
|
+
let toBlock = currentBlock;
|
|
7873
|
+
let chunkSize = initialChunkSize;
|
|
7874
|
+
while (toBlock >= minBlock) {
|
|
7875
|
+
const fromBlock = Math.max(minBlock, toBlock - chunkSize + 1);
|
|
7876
|
+
try {
|
|
7877
|
+
const rawLogs = await provider.getLogs({
|
|
7878
|
+
address,
|
|
7879
|
+
topics,
|
|
7880
|
+
fromBlock,
|
|
7881
|
+
toBlock
|
|
7882
|
+
});
|
|
7883
|
+
if (rawLogs.length > 0) {
|
|
7884
|
+
return rawLogs.map((log) => ({
|
|
7885
|
+
address: log.address,
|
|
7886
|
+
topics: log.topics,
|
|
7887
|
+
data: log.data,
|
|
7888
|
+
transactionHash: log.transactionHash
|
|
7889
|
+
}));
|
|
7890
|
+
}
|
|
7891
|
+
toBlock = fromBlock - 1;
|
|
7892
|
+
} catch (error) {
|
|
7893
|
+
const serverLimit = parseMaxBlockRangeLimit(error);
|
|
7894
|
+
if (serverLimit == null) {
|
|
7895
|
+
if (chunkSize > SAFE_BLOCKS_RANGE_SIZE) {
|
|
7896
|
+
chunkSize = SAFE_BLOCKS_RANGE_SIZE;
|
|
7897
|
+
} else {
|
|
7898
|
+
throw error;
|
|
7899
|
+
}
|
|
7900
|
+
} else {
|
|
7901
|
+
chunkSize = Math.min(chunkSize, serverLimit);
|
|
7902
|
+
}
|
|
5712
7903
|
}
|
|
7904
|
+
}
|
|
7905
|
+
return [];
|
|
7906
|
+
},
|
|
7907
|
+
{
|
|
7908
|
+
ctx: { address, maxBlocksBack, logChunkSize: initialChunkSize },
|
|
7909
|
+
message: "Failed to query destination bundle lifecycle logs."
|
|
7910
|
+
}
|
|
7911
|
+
);
|
|
7912
|
+
}
|
|
7913
|
+
async function getInteropRoot(provider, rootChainId, batchNumber) {
|
|
7914
|
+
return await wrap2(
|
|
7915
|
+
OP_INTEROP.svc.status.getRoot,
|
|
7916
|
+
async () => {
|
|
7917
|
+
const rootStorage = new ethers.Contract(
|
|
7918
|
+
L2_INTEROP_ROOT_STORAGE_ADDRESS,
|
|
7919
|
+
InteropRootStorage_default,
|
|
7920
|
+
provider
|
|
5713
7921
|
);
|
|
5714
|
-
|
|
5715
|
-
ctx: { where: "l1.getFeeData" },
|
|
5716
|
-
message: "Failed to estimate fee data for finalizeDeposit."
|
|
5717
|
-
});
|
|
5718
|
-
const maxFeePerGas = feeData.maxFeePerGas ?? feeData.gasPrice ?? // legacy-style gas price if present
|
|
5719
|
-
(() => {
|
|
5720
|
-
throw createError("RPC", {
|
|
5721
|
-
resource: "withdrawals",
|
|
5722
|
-
operation: OP_WITHDRAWALS.finalize.estimate,
|
|
5723
|
-
message: "Provider did not return gas price or EIP-1559 fields.",
|
|
5724
|
-
context: { feeData }
|
|
5725
|
-
});
|
|
5726
|
-
})();
|
|
5727
|
-
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? 0n;
|
|
5728
|
-
return {
|
|
5729
|
-
gasLimit,
|
|
5730
|
-
maxFeePerGas,
|
|
5731
|
-
maxPriorityFeePerGas
|
|
5732
|
-
};
|
|
7922
|
+
return await rootStorage.interopRoots(rootChainId, batchNumber);
|
|
5733
7923
|
},
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
7924
|
+
{
|
|
7925
|
+
ctx: { rootChainId, batchNumber },
|
|
7926
|
+
message: "Failed to get interop root from the destination chain."
|
|
7927
|
+
}
|
|
7928
|
+
);
|
|
7929
|
+
}
|
|
7930
|
+
|
|
7931
|
+
// src/adapters/ethers/resources/interop/services/finalization/bundle.ts
|
|
7932
|
+
var { wrap: wrap3 } = createErrorHandlers("interop");
|
|
7933
|
+
async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
|
|
7934
|
+
const { interopHandler } = await client.ensureAddresses();
|
|
7935
|
+
const bundleLogs = await getLogs(dstProvider, interopHandler, [null, bundleHash], opts);
|
|
7936
|
+
const findLastByTopic = (eventTopic) => bundleLogs.findLast((log) => log.topics[0].toLowerCase() === eventTopic.toLowerCase());
|
|
7937
|
+
const lifecycleChecks = [
|
|
7938
|
+
{ phase: "UNBUNDLED", topic: topics.bundleUnbundled, includeTxHash: true },
|
|
7939
|
+
{ phase: "EXECUTED", topic: topics.bundleExecuted, includeTxHash: true },
|
|
7940
|
+
{ phase: "VERIFIED", topic: topics.bundleVerified }
|
|
7941
|
+
];
|
|
7942
|
+
for (const check of lifecycleChecks) {
|
|
7943
|
+
const match = findLastByTopic(check.topic);
|
|
7944
|
+
if (!match) continue;
|
|
7945
|
+
if (check.includeTxHash) {
|
|
7946
|
+
return { phase: check.phase, dstExecTxHash: match.transactionHash };
|
|
7947
|
+
}
|
|
7948
|
+
return { phase: check.phase };
|
|
7949
|
+
}
|
|
7950
|
+
return { phase: "SENT" };
|
|
7951
|
+
}
|
|
7952
|
+
async function executeBundle(client, dstProvider, info, opts) {
|
|
7953
|
+
const { topics } = getTopics();
|
|
7954
|
+
const { bundleHash, encodedData, proof } = info;
|
|
7955
|
+
const dstStatus = await getBundleStatus(client, dstProvider, topics, bundleHash, opts);
|
|
7956
|
+
if (["EXECUTED", "UNBUNDLED"].includes(dstStatus.phase)) {
|
|
7957
|
+
throw createError("STATE", {
|
|
7958
|
+
resource: "interop",
|
|
7959
|
+
operation: OP_INTEROP.finalize,
|
|
7960
|
+
message: `Interop bundle has already been ${dstStatus.phase.toLowerCase()}.`,
|
|
7961
|
+
context: { bundleHash }
|
|
7962
|
+
});
|
|
7963
|
+
}
|
|
7964
|
+
const signer = await wrap3(OP_INTEROP.exec.sendStep, () => client.signerFor(dstProvider), {
|
|
7965
|
+
message: "Failed to resolve destination signer."
|
|
7966
|
+
});
|
|
7967
|
+
const { interopHandler } = await client.ensureAddresses();
|
|
7968
|
+
const handler = new ethers.Contract(interopHandler, IInteropHandler_default, signer);
|
|
7969
|
+
try {
|
|
7970
|
+
const txResponse = await handler.executeBundle(encodedData, proof);
|
|
7971
|
+
const hash = txResponse.hash;
|
|
7972
|
+
return {
|
|
7973
|
+
hash,
|
|
7974
|
+
wait: async () => {
|
|
7975
|
+
try {
|
|
7976
|
+
const receipt = await txResponse.wait();
|
|
7977
|
+
if (!receipt || receipt.status !== 1) {
|
|
7978
|
+
throw createError("EXECUTION", {
|
|
7979
|
+
resource: "interop",
|
|
7980
|
+
operation: OP_INTEROP.exec.waitStep,
|
|
7981
|
+
message: "Interop bundle execution reverted on destination.",
|
|
7982
|
+
context: { txHash: hash }
|
|
7983
|
+
});
|
|
7984
|
+
}
|
|
7985
|
+
return receipt;
|
|
7986
|
+
} catch (e) {
|
|
7987
|
+
if (isZKsyncError(e)) throw e;
|
|
7988
|
+
throw toZKsyncError(
|
|
7989
|
+
"EXECUTION",
|
|
7990
|
+
{
|
|
7991
|
+
resource: "interop",
|
|
7992
|
+
operation: OP_INTEROP.exec.waitStep,
|
|
7993
|
+
message: "Failed while waiting for executeBundle transaction on destination.",
|
|
7994
|
+
context: { txHash: hash }
|
|
7995
|
+
},
|
|
7996
|
+
e
|
|
7997
|
+
);
|
|
5742
7998
|
}
|
|
5743
|
-
|
|
5744
|
-
|
|
7999
|
+
}
|
|
8000
|
+
};
|
|
8001
|
+
} catch (e) {
|
|
8002
|
+
throw toZKsyncError(
|
|
8003
|
+
"EXECUTION",
|
|
8004
|
+
{
|
|
8005
|
+
resource: "interop",
|
|
8006
|
+
operation: OP_INTEROP.exec.sendStep,
|
|
8007
|
+
message: "Failed to send executeBundle transaction on destination chain."
|
|
8008
|
+
},
|
|
8009
|
+
e
|
|
8010
|
+
);
|
|
8011
|
+
}
|
|
8012
|
+
}
|
|
8013
|
+
|
|
8014
|
+
// src/core/resources/interop/finalization.ts
|
|
8015
|
+
var DEFAULT_POLL_MS = 1e3;
|
|
8016
|
+
var DEFAULT_TIMEOUT_MS = 3e5;
|
|
8017
|
+
function resolveIdsFromWaitable(input) {
|
|
8018
|
+
if (typeof input === "string") {
|
|
8019
|
+
return { l2SrcTxHash: input };
|
|
8020
|
+
}
|
|
8021
|
+
return {
|
|
8022
|
+
l2SrcTxHash: input.l2SrcTxHash,
|
|
8023
|
+
bundleHash: input.bundleHash,
|
|
8024
|
+
dstExecTxHash: input.dstExecTxHash
|
|
8025
|
+
};
|
|
8026
|
+
}
|
|
8027
|
+
function parseBundleSentFromReceipt(input) {
|
|
8028
|
+
const { receipt, interopCenter, interopBundleSentTopic, decodeInteropBundleSent: decodeInteropBundleSent2 } = input;
|
|
8029
|
+
const bundleSentLog = receipt.logs.find(
|
|
8030
|
+
(log) => log.address.toLowerCase() === interopCenter.toLowerCase() && log.topics[0].toLowerCase() === interopBundleSentTopic.toLowerCase()
|
|
8031
|
+
);
|
|
8032
|
+
if (!bundleSentLog) {
|
|
8033
|
+
throw createError("STATE", {
|
|
8034
|
+
resource: "interop",
|
|
8035
|
+
operation: OP_INTEROP.svc.status.parseSentLog,
|
|
8036
|
+
message: "Failed to locate InteropBundleSent event in source receipt.",
|
|
8037
|
+
context: { receipt, interopCenter }
|
|
8038
|
+
});
|
|
8039
|
+
}
|
|
8040
|
+
const decoded = decodeInteropBundleSent2({
|
|
8041
|
+
data: bundleSentLog.data,
|
|
8042
|
+
topics: bundleSentLog.topics
|
|
8043
|
+
});
|
|
8044
|
+
return { bundleHash: decoded.bundleHash, dstChainId: decoded.destinationChainId };
|
|
8045
|
+
}
|
|
8046
|
+
function parseBundleReceiptInfo(params) {
|
|
8047
|
+
const {
|
|
8048
|
+
rawReceipt,
|
|
8049
|
+
interopCenter,
|
|
8050
|
+
interopBundleSentTopic,
|
|
8051
|
+
decodeInteropBundleSent: decodeInteropBundleSent2,
|
|
8052
|
+
decodeL1MessageData: decodeL1MessageData2,
|
|
8053
|
+
l2SrcTxHash
|
|
8054
|
+
} = params;
|
|
8055
|
+
let l2ToL1LogIndex = -1;
|
|
8056
|
+
let l1MessageData = null;
|
|
8057
|
+
let found;
|
|
8058
|
+
for (const log of rawReceipt.logs) {
|
|
8059
|
+
if (isL1MessageSentLog(log)) {
|
|
8060
|
+
l2ToL1LogIndex += 1;
|
|
5745
8061
|
try {
|
|
5746
|
-
|
|
5747
|
-
const hash = receipt.hash;
|
|
5748
|
-
return {
|
|
5749
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
5750
|
-
hash,
|
|
5751
|
-
wait: async () => {
|
|
5752
|
-
try {
|
|
5753
|
-
return await receipt.wait();
|
|
5754
|
-
} catch (e) {
|
|
5755
|
-
throw toZKsyncError(
|
|
5756
|
-
"EXECUTION",
|
|
5757
|
-
{
|
|
5758
|
-
resource: "withdrawals",
|
|
5759
|
-
operation: OP_WITHDRAWALS.finalize.wait,
|
|
5760
|
-
message: "Failed while waiting for finalizeDeposit transaction.",
|
|
5761
|
-
context: { txHash: hash }
|
|
5762
|
-
},
|
|
5763
|
-
e
|
|
5764
|
-
);
|
|
5765
|
-
}
|
|
5766
|
-
}
|
|
5767
|
-
};
|
|
8062
|
+
l1MessageData = decodeL1MessageData2(log);
|
|
5768
8063
|
} catch (e) {
|
|
5769
|
-
throw
|
|
5770
|
-
"
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
chainIdL2: params.chainId,
|
|
5777
|
-
l2BatchNumber: params.l2BatchNumber,
|
|
5778
|
-
l2MessageIndex: params.l2MessageIndex,
|
|
5779
|
-
l1Nullifier
|
|
5780
|
-
}
|
|
5781
|
-
},
|
|
5782
|
-
e
|
|
5783
|
-
);
|
|
8064
|
+
throw createError("STATE", {
|
|
8065
|
+
resource: "interop",
|
|
8066
|
+
operation: OP_INTEROP.svc.status.parseSentLog,
|
|
8067
|
+
message: "Failed to decode L1MessageSent log data for interop bundle.",
|
|
8068
|
+
context: { l2SrcTxHash, l2ToL1LogIndex },
|
|
8069
|
+
cause: e
|
|
8070
|
+
});
|
|
5784
8071
|
}
|
|
8072
|
+
continue;
|
|
5785
8073
|
}
|
|
8074
|
+
if (log.address.toLowerCase() !== interopCenter.toLowerCase() || log.topics[0].toLowerCase() !== interopBundleSentTopic.toLowerCase())
|
|
8075
|
+
continue;
|
|
8076
|
+
const decoded = decodeInteropBundleSent2({
|
|
8077
|
+
data: log.data,
|
|
8078
|
+
topics: log.topics
|
|
8079
|
+
});
|
|
8080
|
+
found = {
|
|
8081
|
+
bundleHash: decoded.bundleHash,
|
|
8082
|
+
dstChainId: decoded.destinationChainId,
|
|
8083
|
+
sourceChainId: decoded.sourceChainId
|
|
8084
|
+
};
|
|
8085
|
+
break;
|
|
8086
|
+
}
|
|
8087
|
+
if (!found) {
|
|
8088
|
+
throw createError("STATE", {
|
|
8089
|
+
resource: "interop",
|
|
8090
|
+
operation: OP_INTEROP.svc.status.parseSentLog,
|
|
8091
|
+
message: "Failed to locate InteropBundleSent event in source receipt.",
|
|
8092
|
+
context: { l2SrcTxHash, interopCenter }
|
|
8093
|
+
});
|
|
8094
|
+
}
|
|
8095
|
+
if (!l1MessageData) {
|
|
8096
|
+
throw createError("STATE", {
|
|
8097
|
+
resource: "interop",
|
|
8098
|
+
operation: OP_INTEROP.svc.status.parseSentLog,
|
|
8099
|
+
message: "Failed to locate L1MessageSent log data for interop bundle.",
|
|
8100
|
+
context: { l2SrcTxHash, interopCenter }
|
|
8101
|
+
});
|
|
8102
|
+
}
|
|
8103
|
+
return {
|
|
8104
|
+
bundleHash: found.bundleHash,
|
|
8105
|
+
dstChainId: found.dstChainId,
|
|
8106
|
+
sourceChainId: found.sourceChainId,
|
|
8107
|
+
l1MessageData,
|
|
8108
|
+
l2ToL1LogIndex,
|
|
8109
|
+
txNumberInBatch: Number(rawReceipt.transactionIndex),
|
|
8110
|
+
rawReceipt
|
|
8111
|
+
};
|
|
8112
|
+
}
|
|
8113
|
+
function getBundleEncodedData(messageData) {
|
|
8114
|
+
const prefix = `0x${messageData.slice(2, 4)}`;
|
|
8115
|
+
if (prefix !== BUNDLE_IDENTIFIER) {
|
|
8116
|
+
throw createError("STATE", {
|
|
8117
|
+
resource: "interop",
|
|
8118
|
+
operation: OP_INTEROP.wait,
|
|
8119
|
+
message: "Unexpected bundle prefix in L1MessageSent data.",
|
|
8120
|
+
context: { prefix, expected: BUNDLE_IDENTIFIER }
|
|
8121
|
+
});
|
|
8122
|
+
}
|
|
8123
|
+
return `0x${messageData.slice(4)}`;
|
|
8124
|
+
}
|
|
8125
|
+
function buildFinalizationInfo(ids, bundleInfo, proof, messageData) {
|
|
8126
|
+
const expectedRoot = {
|
|
8127
|
+
rootChainId: bundleInfo.sourceChainId,
|
|
8128
|
+
batchNumber: proof.batchNumber,
|
|
8129
|
+
expectedRoot: proof.root
|
|
8130
|
+
};
|
|
8131
|
+
const messageProof = {
|
|
8132
|
+
chainId: bundleInfo.sourceChainId,
|
|
8133
|
+
l1BatchNumber: proof.batchNumber,
|
|
8134
|
+
l2MessageIndex: proof.id,
|
|
8135
|
+
message: {
|
|
8136
|
+
txNumberInBatch: bundleInfo.txNumberInBatch,
|
|
8137
|
+
sender: L2_INTEROP_CENTER_ADDRESS,
|
|
8138
|
+
data: messageData
|
|
8139
|
+
},
|
|
8140
|
+
proof: proof.proof
|
|
8141
|
+
};
|
|
8142
|
+
return {
|
|
8143
|
+
l2SrcTxHash: ids.l2SrcTxHash,
|
|
8144
|
+
bundleHash: bundleInfo.bundleHash,
|
|
8145
|
+
dstChainId: bundleInfo.dstChainId,
|
|
8146
|
+
expectedRoot,
|
|
8147
|
+
proof: messageProof,
|
|
8148
|
+
encodedData: getBundleEncodedData(messageData)
|
|
8149
|
+
};
|
|
8150
|
+
}
|
|
8151
|
+
function decodeInteropBundleSent(centerIface, log) {
|
|
8152
|
+
const decoded = centerIface.decodeEventLog(
|
|
8153
|
+
"InteropBundleSent",
|
|
8154
|
+
log.data,
|
|
8155
|
+
log.topics
|
|
8156
|
+
);
|
|
8157
|
+
return {
|
|
8158
|
+
bundleHash: decoded.interopBundleHash,
|
|
8159
|
+
sourceChainId: decoded.interopBundle.sourceChainId,
|
|
8160
|
+
destinationChainId: decoded.interopBundle.destinationChainId
|
|
5786
8161
|
};
|
|
5787
8162
|
}
|
|
8163
|
+
function decodeL1MessageData(log) {
|
|
8164
|
+
const decoded = ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], log.data);
|
|
8165
|
+
return decoded[0];
|
|
8166
|
+
}
|
|
5788
8167
|
|
|
5789
|
-
// src/adapters/ethers/resources/
|
|
5790
|
-
var
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
};
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
8168
|
+
// src/adapters/ethers/resources/interop/services/finalization/polling.ts
|
|
8169
|
+
var { wrap: wrap4 } = createErrorHandlers("interop");
|
|
8170
|
+
function isProofNotReadyError(error) {
|
|
8171
|
+
return isZKsyncError(error, {
|
|
8172
|
+
operation: "zksrpc.getL2ToL1LogProof",
|
|
8173
|
+
messageIncludes: "proof not yet available"
|
|
8174
|
+
});
|
|
8175
|
+
}
|
|
8176
|
+
function shouldRetryRootFetch(error) {
|
|
8177
|
+
if (!isZKsyncError(error)) return false;
|
|
8178
|
+
return error.envelope.operation === OP_INTEROP.svc.status.getRoot;
|
|
8179
|
+
}
|
|
8180
|
+
async function waitForProof(client, l2SrcTxHash, logIndex, blockNumber, pollMs, deadline) {
|
|
8181
|
+
while (true) {
|
|
8182
|
+
if (Date.now() > deadline) {
|
|
8183
|
+
throw createError("TIMEOUT", {
|
|
8184
|
+
resource: "interop",
|
|
8185
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
8186
|
+
message: "Timed out waiting for block to be finalized.",
|
|
8187
|
+
context: { l2SrcTxHash, logIndex, blockNumber }
|
|
8188
|
+
});
|
|
8189
|
+
}
|
|
8190
|
+
const finalizedBlock = await client.l2.getBlock("finalized");
|
|
8191
|
+
if (finalizedBlock && BigInt(finalizedBlock.number) >= blockNumber) {
|
|
8192
|
+
break;
|
|
8193
|
+
}
|
|
8194
|
+
await sleep(pollMs);
|
|
8195
|
+
}
|
|
8196
|
+
while (true) {
|
|
8197
|
+
if (Date.now() > deadline) {
|
|
8198
|
+
throw createError("TIMEOUT", {
|
|
8199
|
+
resource: "interop",
|
|
8200
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
8201
|
+
message: "Timed out waiting for L2->L1 log proof to become available.",
|
|
8202
|
+
context: { l2SrcTxHash, logIndex }
|
|
8203
|
+
});
|
|
8204
|
+
}
|
|
8205
|
+
try {
|
|
8206
|
+
return await client.zks.getL2ToL1LogProof(l2SrcTxHash, logIndex);
|
|
8207
|
+
} catch (error) {
|
|
8208
|
+
if (!isProofNotReadyError(error)) throw error;
|
|
8209
|
+
}
|
|
8210
|
+
await sleep(pollMs);
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
8213
|
+
async function waitForRoot(provider, expectedRoot, pollMs, deadline) {
|
|
8214
|
+
while (true) {
|
|
8215
|
+
if (Date.now() > deadline) {
|
|
8216
|
+
throw createError("TIMEOUT", {
|
|
8217
|
+
resource: "interop",
|
|
8218
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
8219
|
+
message: "Timed out waiting for interop root to become available.",
|
|
8220
|
+
context: { expectedRoot }
|
|
8221
|
+
});
|
|
8222
|
+
}
|
|
8223
|
+
let interopRoot = null;
|
|
8224
|
+
try {
|
|
8225
|
+
const root = await getInteropRoot(
|
|
8226
|
+
provider,
|
|
8227
|
+
expectedRoot.rootChainId,
|
|
8228
|
+
expectedRoot.batchNumber
|
|
8229
|
+
);
|
|
8230
|
+
if (root !== ZERO_HASH) {
|
|
8231
|
+
interopRoot = root;
|
|
8232
|
+
}
|
|
8233
|
+
} catch (error) {
|
|
8234
|
+
if (!shouldRetryRootFetch(error)) throw error;
|
|
8235
|
+
interopRoot = null;
|
|
8236
|
+
}
|
|
8237
|
+
if (interopRoot) {
|
|
8238
|
+
if (interopRoot.toLowerCase() === expectedRoot.expectedRoot.toLowerCase()) {
|
|
8239
|
+
return;
|
|
8240
|
+
}
|
|
8241
|
+
throw createError("STATE", {
|
|
8242
|
+
resource: "interop",
|
|
8243
|
+
operation: OP_INTEROP.wait,
|
|
8244
|
+
message: "Interop root mismatch.",
|
|
8245
|
+
context: {
|
|
8246
|
+
expected: expectedRoot.expectedRoot,
|
|
8247
|
+
got: interopRoot
|
|
8248
|
+
}
|
|
8249
|
+
});
|
|
8250
|
+
}
|
|
8251
|
+
await sleep(pollMs);
|
|
8252
|
+
}
|
|
8253
|
+
}
|
|
8254
|
+
async function waitForTxReceipt(client, txHash, pollMs, deadline) {
|
|
8255
|
+
while (true) {
|
|
8256
|
+
if (Date.now() > deadline) {
|
|
8257
|
+
throw createError("TIMEOUT", {
|
|
8258
|
+
resource: "interop",
|
|
8259
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
8260
|
+
message: "Timed out waiting for source receipt to be available.",
|
|
8261
|
+
context: { txHash }
|
|
8262
|
+
});
|
|
8263
|
+
}
|
|
8264
|
+
const receipt = await wrap4(
|
|
8265
|
+
OP_INTEROP.svc.status.sourceReceipt,
|
|
8266
|
+
() => client.zks.getReceiptWithL2ToL1(txHash),
|
|
8267
|
+
{
|
|
8268
|
+
ctx: { where: "zks.getReceiptWithL2ToL1", txHash },
|
|
8269
|
+
message: "Failed to fetch source L2 receipt (with L2->L1 logs) for interop tx."
|
|
8270
|
+
}
|
|
8271
|
+
);
|
|
8272
|
+
if (receipt) {
|
|
8273
|
+
return receipt;
|
|
8274
|
+
}
|
|
8275
|
+
await sleep(pollMs);
|
|
8276
|
+
}
|
|
8277
|
+
}
|
|
8278
|
+
async function waitForFinalization(client, dstProvider, input, opts) {
|
|
8279
|
+
const { topics, centerIface } = getTopics();
|
|
8280
|
+
const pollMs = opts?.pollMs ?? DEFAULT_POLL_MS;
|
|
8281
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8282
|
+
const deadline = Date.now() + timeoutMs;
|
|
8283
|
+
const ids = resolveIdsFromWaitable(input);
|
|
8284
|
+
if (!ids.l2SrcTxHash) {
|
|
8285
|
+
throw createError("STATE", {
|
|
8286
|
+
resource: "interop",
|
|
8287
|
+
operation: OP_INTEROP.svc.status.sourceReceipt,
|
|
8288
|
+
message: "Cannot wait for interop finalization: missing l2SrcTxHash.",
|
|
8289
|
+
context: { input }
|
|
8290
|
+
});
|
|
8291
|
+
}
|
|
8292
|
+
const { interopCenter } = await client.ensureAddresses();
|
|
8293
|
+
let bundleInfo = null;
|
|
8294
|
+
while (!bundleInfo) {
|
|
8295
|
+
if (Date.now() > deadline) {
|
|
8296
|
+
throw createError("TIMEOUT", {
|
|
8297
|
+
resource: "interop",
|
|
8298
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
8299
|
+
message: "Timed out waiting for source receipt to be available.",
|
|
8300
|
+
context: { l2SrcTxHash: ids.l2SrcTxHash }
|
|
8301
|
+
});
|
|
8302
|
+
}
|
|
8303
|
+
const txReceipt = await waitForTxReceipt(client, ids.l2SrcTxHash, pollMs, deadline);
|
|
8304
|
+
bundleInfo = parseBundleReceiptInfo({
|
|
8305
|
+
rawReceipt: txReceipt,
|
|
8306
|
+
interopCenter,
|
|
8307
|
+
interopBundleSentTopic: topics.interopBundleSent,
|
|
8308
|
+
decodeInteropBundleSent: (log) => decodeInteropBundleSent(centerIface, log),
|
|
8309
|
+
decodeL1MessageData,
|
|
8310
|
+
l2SrcTxHash: ids.l2SrcTxHash
|
|
8311
|
+
});
|
|
8312
|
+
}
|
|
8313
|
+
const proof = await waitForProof(
|
|
8314
|
+
client,
|
|
8315
|
+
ids.l2SrcTxHash,
|
|
8316
|
+
bundleInfo.l2ToL1LogIndex,
|
|
8317
|
+
BigInt(bundleInfo.rawReceipt.blockNumber),
|
|
8318
|
+
pollMs,
|
|
8319
|
+
deadline
|
|
8320
|
+
);
|
|
8321
|
+
const finalizationInfo = buildFinalizationInfo(
|
|
8322
|
+
{ l2SrcTxHash: ids.l2SrcTxHash, bundleHash: ids.bundleHash },
|
|
8323
|
+
bundleInfo,
|
|
8324
|
+
proof,
|
|
8325
|
+
bundleInfo.l1MessageData
|
|
8326
|
+
);
|
|
8327
|
+
await waitForRoot(dstProvider, finalizationInfo.expectedRoot, pollMs, deadline);
|
|
8328
|
+
return finalizationInfo;
|
|
8329
|
+
}
|
|
8330
|
+
|
|
8331
|
+
// src/adapters/ethers/resources/interop/services/finalization/status.ts
|
|
8332
|
+
async function getStatus(client, dstProvider, input, opts) {
|
|
8333
|
+
const { topics, centerIface } = getTopics();
|
|
8334
|
+
const baseIds = resolveIdsFromWaitable(input);
|
|
8335
|
+
const enrichedIds = await (async () => {
|
|
8336
|
+
if (baseIds.bundleHash) return baseIds;
|
|
8337
|
+
if (!baseIds.l2SrcTxHash) return baseIds;
|
|
8338
|
+
const { interopCenter } = await client.ensureAddresses();
|
|
8339
|
+
const receipt = await getTxReceipt(client.l2, baseIds.l2SrcTxHash);
|
|
8340
|
+
if (!receipt) return baseIds;
|
|
8341
|
+
const { bundleHash } = parseBundleSentFromReceipt({
|
|
8342
|
+
receipt: { logs: receipt.logs },
|
|
8343
|
+
interopCenter,
|
|
8344
|
+
interopBundleSentTopic: topics.interopBundleSent,
|
|
8345
|
+
decodeInteropBundleSent: (log) => decodeInteropBundleSent(centerIface, log)
|
|
8346
|
+
});
|
|
8347
|
+
return { ...baseIds, bundleHash };
|
|
8348
|
+
})();
|
|
8349
|
+
if (!enrichedIds.bundleHash) {
|
|
8350
|
+
const phase = enrichedIds.l2SrcTxHash ? "SENT" : "UNKNOWN";
|
|
5805
8351
|
return {
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
amounts: {
|
|
5811
|
-
transfer: { token: p.token, amount: p.amount }
|
|
5812
|
-
},
|
|
5813
|
-
fees
|
|
5814
|
-
},
|
|
5815
|
-
steps
|
|
8352
|
+
phase,
|
|
8353
|
+
l2SrcTxHash: enrichedIds.l2SrcTxHash,
|
|
8354
|
+
bundleHash: enrichedIds.bundleHash,
|
|
8355
|
+
dstExecTxHash: enrichedIds.dstExecTxHash
|
|
5816
8356
|
};
|
|
5817
8357
|
}
|
|
5818
|
-
const
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
8358
|
+
const dstInfo = await getBundleStatus(client, dstProvider, topics, enrichedIds.bundleHash, opts);
|
|
8359
|
+
return {
|
|
8360
|
+
phase: dstInfo.phase,
|
|
8361
|
+
l2SrcTxHash: enrichedIds.l2SrcTxHash,
|
|
8362
|
+
bundleHash: enrichedIds.bundleHash,
|
|
8363
|
+
dstExecTxHash: dstInfo.dstExecTxHash ?? enrichedIds.dstExecTxHash
|
|
8364
|
+
};
|
|
8365
|
+
}
|
|
8366
|
+
|
|
8367
|
+
// src/adapters/ethers/resources/interop/services/finalization/index.ts
|
|
8368
|
+
function createInteropFinalizationServices(client) {
|
|
8369
|
+
return {
|
|
8370
|
+
status(dstProvider, input, opts) {
|
|
8371
|
+
return getStatus(client, dstProvider, input, opts);
|
|
5824
8372
|
},
|
|
5825
|
-
{
|
|
5826
|
-
|
|
5827
|
-
ctx: { token: p.token, where: "withdrawals.quote" }
|
|
5828
|
-
}
|
|
5829
|
-
);
|
|
5830
|
-
const tryQuote = (p) => toResult2(
|
|
5831
|
-
OP_WITHDRAWALS.tryQuote,
|
|
5832
|
-
async () => {
|
|
5833
|
-
const plan = await buildPlan(p);
|
|
5834
|
-
return plan.summary;
|
|
8373
|
+
wait(dstProvider, input, opts) {
|
|
8374
|
+
return waitForFinalization(client, dstProvider, input, opts);
|
|
5835
8375
|
},
|
|
5836
|
-
{
|
|
5837
|
-
|
|
5838
|
-
|
|
8376
|
+
async finalize(dstProvider, info, opts) {
|
|
8377
|
+
const execResult = await executeBundle(client, dstProvider, info, opts);
|
|
8378
|
+
await execResult.wait();
|
|
8379
|
+
return {
|
|
8380
|
+
bundleHash: info.bundleHash,
|
|
8381
|
+
dstExecTxHash: execResult.hash
|
|
8382
|
+
};
|
|
5839
8383
|
}
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
8384
|
+
};
|
|
8385
|
+
}
|
|
8386
|
+
function resolveDstProvider(dstChain) {
|
|
8387
|
+
return typeof dstChain === "string" ? new ethers.JsonRpcProvider(dstChain) : dstChain;
|
|
8388
|
+
}
|
|
8389
|
+
function resolveWaitableInput(waitableInput) {
|
|
8390
|
+
const input = waitableInput;
|
|
8391
|
+
return {
|
|
8392
|
+
dstProvider: resolveDstProvider(waitableInput.dstChain),
|
|
8393
|
+
waitable: input.waitable ? input.waitable : waitableInput
|
|
8394
|
+
};
|
|
8395
|
+
}
|
|
8396
|
+
|
|
8397
|
+
// src/adapters/ethers/resources/interop/index.ts
|
|
8398
|
+
var { wrap: wrap5, toResult: toResult2 } = createErrorHandlers("interop");
|
|
8399
|
+
var ROUTES3 = {
|
|
8400
|
+
direct: routeDirect(),
|
|
8401
|
+
indirect: routeIndirect()
|
|
8402
|
+
};
|
|
8403
|
+
function createInteropResource(client, tokens, contracts, attributes) {
|
|
8404
|
+
const svc = createInteropFinalizationServices(client);
|
|
8405
|
+
const tokensResource = createTokensResource(client);
|
|
8406
|
+
const contractsResource = createContractsResource(client);
|
|
8407
|
+
const attributesResource = createEthersAttributesResource();
|
|
8408
|
+
async function buildPlanWithCtx(dstProvider, params) {
|
|
8409
|
+
const ctx = await commonCtx3(
|
|
8410
|
+
dstProvider,
|
|
8411
|
+
params,
|
|
8412
|
+
client,
|
|
8413
|
+
tokensResource,
|
|
8414
|
+
contractsResource,
|
|
8415
|
+
attributesResource
|
|
8416
|
+
);
|
|
8417
|
+
const route = pickInteropRoute({
|
|
8418
|
+
actions: params.actions,
|
|
8419
|
+
ctx: {
|
|
8420
|
+
sender: ctx.sender,
|
|
8421
|
+
srcChainId: ctx.chainId,
|
|
8422
|
+
dstChainId: ctx.dstChainId,
|
|
8423
|
+
baseTokenSrc: ctx.baseTokens.src,
|
|
8424
|
+
baseTokenDst: ctx.baseTokens.dst
|
|
8425
|
+
}
|
|
8426
|
+
});
|
|
8427
|
+
await wrap5(OP_INTEROP.routes[route].preflight, () => ROUTES3[route].preflight?.(params, ctx), {
|
|
8428
|
+
message: "Interop preflight failed.",
|
|
8429
|
+
ctx: { where: `routes.${route}.preflight` }
|
|
8430
|
+
});
|
|
8431
|
+
const { steps, approvals, quoteExtras } = await wrap5(
|
|
8432
|
+
OP_INTEROP.routes[route].build,
|
|
8433
|
+
() => ROUTES3[route].build(params, ctx),
|
|
8434
|
+
{
|
|
8435
|
+
message: "Failed to build interop route plan.",
|
|
8436
|
+
ctx: { where: `routes.${route}.build` }
|
|
8437
|
+
}
|
|
8438
|
+
);
|
|
8439
|
+
const summary = {
|
|
8440
|
+
route,
|
|
8441
|
+
approvalsNeeded: approvals,
|
|
8442
|
+
totalActionValue: quoteExtras.totalActionValue,
|
|
8443
|
+
bridgedTokenTotal: quoteExtras.bridgedTokenTotal
|
|
8444
|
+
};
|
|
8445
|
+
return { plan: { route, summary, steps }, ctx };
|
|
8446
|
+
}
|
|
8447
|
+
async function buildPlan(dstProvider, params) {
|
|
8448
|
+
const { plan } = await buildPlanWithCtx(dstProvider, params);
|
|
8449
|
+
return plan;
|
|
8450
|
+
}
|
|
8451
|
+
const quote = (params) => wrap5(OP_INTEROP.quote, async () => {
|
|
8452
|
+
const plan = await buildPlan(resolveDstProvider(params.dstChain), params);
|
|
8453
|
+
return plan.summary;
|
|
5844
8454
|
});
|
|
5845
|
-
const
|
|
5846
|
-
|
|
5847
|
-
|
|
8455
|
+
const tryQuote = (params) => toResult2(OP_INTEROP.tryQuote, () => quote(params));
|
|
8456
|
+
const prepare = (params) => wrap5(OP_INTEROP.prepare, () => buildPlan(resolveDstProvider(params.dstChain), params), {
|
|
8457
|
+
message: "Internal error while preparing an interop plan.",
|
|
8458
|
+
ctx: { where: "interop.prepare" }
|
|
5848
8459
|
});
|
|
5849
|
-
const
|
|
5850
|
-
|
|
8460
|
+
const tryPrepare = (params) => toResult2(OP_INTEROP.tryPrepare, () => prepare(params));
|
|
8461
|
+
const create = (params) => wrap5(
|
|
8462
|
+
OP_INTEROP.create,
|
|
5851
8463
|
async () => {
|
|
5852
|
-
const plan = await
|
|
8464
|
+
const { plan, ctx } = await buildPlanWithCtx(resolveDstProvider(params.dstChain), params);
|
|
8465
|
+
const signer = ctx.client.signerFor(ctx.client.l2);
|
|
8466
|
+
const srcProvider = ctx.client.l2;
|
|
8467
|
+
const from = await signer.getAddress();
|
|
8468
|
+
let next;
|
|
8469
|
+
if (typeof params.txOverrides?.nonce === "number") {
|
|
8470
|
+
next = params.txOverrides.nonce;
|
|
8471
|
+
} else {
|
|
8472
|
+
const blockTag = params.txOverrides?.nonce ?? "pending";
|
|
8473
|
+
next = await srcProvider.getTransactionCount(from, blockTag);
|
|
8474
|
+
}
|
|
5853
8475
|
const stepHashes = {};
|
|
5854
|
-
const managed = new ethers.NonceManager(client.getL2Signer());
|
|
5855
|
-
const from = await managed.getAddress();
|
|
5856
|
-
let next = await client.l2.getTransactionCount(from, "pending");
|
|
5857
8476
|
for (const step of plan.steps) {
|
|
5858
8477
|
step.tx.nonce = next++;
|
|
5859
|
-
if (
|
|
5860
|
-
|
|
5861
|
-
if (overrides.gasLimit != null) step.tx.gasLimit = overrides.gasLimit;
|
|
5862
|
-
if (overrides.maxFeePerGas != null) step.tx.maxFeePerGas = overrides.maxFeePerGas;
|
|
5863
|
-
if (overrides.maxPriorityFeePerGas != null) {
|
|
5864
|
-
step.tx.maxPriorityFeePerGas = overrides.maxPriorityFeePerGas;
|
|
5865
|
-
}
|
|
8478
|
+
if (!step.tx.chainId) {
|
|
8479
|
+
step.tx.chainId = Number(ctx.chainId);
|
|
5866
8480
|
}
|
|
5867
8481
|
if (!step.tx.gasLimit) {
|
|
5868
8482
|
try {
|
|
5869
|
-
const est = await
|
|
8483
|
+
const est = await srcProvider.estimateGas({
|
|
8484
|
+
...step.tx,
|
|
8485
|
+
from
|
|
8486
|
+
});
|
|
5870
8487
|
step.tx.gasLimit = BigInt(est) * 115n / 100n;
|
|
5871
8488
|
} catch {
|
|
5872
8489
|
}
|
|
5873
8490
|
}
|
|
5874
8491
|
let hash;
|
|
5875
8492
|
try {
|
|
5876
|
-
const sent = await
|
|
8493
|
+
const sent = await signer.sendTransaction(step.tx);
|
|
5877
8494
|
hash = sent.hash;
|
|
5878
8495
|
stepHashes[step.key] = hash;
|
|
5879
8496
|
const rcpt = await sent.wait();
|
|
5880
8497
|
if (rcpt?.status === 0) {
|
|
5881
8498
|
throw createError("EXECUTION", {
|
|
5882
|
-
resource: "
|
|
5883
|
-
operation: "
|
|
5884
|
-
message: "
|
|
5885
|
-
context: { step: step.key, txHash: hash
|
|
8499
|
+
resource: "interop",
|
|
8500
|
+
operation: "interop.create.sendTransaction",
|
|
8501
|
+
message: "Interop transaction reverted on source L2.",
|
|
8502
|
+
context: { step: step.key, txHash: hash }
|
|
5886
8503
|
});
|
|
5887
8504
|
}
|
|
5888
8505
|
} catch (e) {
|
|
5889
|
-
throw
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
8506
|
+
if (isZKsyncError(e)) throw e;
|
|
8507
|
+
throw createError("EXECUTION", {
|
|
8508
|
+
resource: "interop",
|
|
8509
|
+
operation: "interop.create.sendTransaction",
|
|
8510
|
+
message: "Failed to send or confirm an interop transaction step.",
|
|
8511
|
+
context: {
|
|
8512
|
+
step: step.key,
|
|
8513
|
+
txHash: hash,
|
|
8514
|
+
nonce: Number(step.tx.nonce ?? -1)
|
|
5896
8515
|
},
|
|
5897
|
-
e
|
|
5898
|
-
);
|
|
5899
|
-
}
|
|
5900
|
-
}
|
|
5901
|
-
const keys = Object.keys(stepHashes);
|
|
5902
|
-
const l2TxHash = stepHashes[keys[keys.length - 1]];
|
|
5903
|
-
return { kind: "withdrawal", l2TxHash, stepHashes, plan };
|
|
5904
|
-
},
|
|
5905
|
-
{
|
|
5906
|
-
message: "Internal error while creating withdrawal transactions.",
|
|
5907
|
-
ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.create" }
|
|
5908
|
-
}
|
|
5909
|
-
);
|
|
5910
|
-
const tryCreate = (p) => toResult2(OP_WITHDRAWALS.tryCreate, () => create(p), {
|
|
5911
|
-
message: "Internal error while creating withdrawal transactions.",
|
|
5912
|
-
ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.tryCreate" }
|
|
5913
|
-
});
|
|
5914
|
-
const status = (h) => wrap2(
|
|
5915
|
-
OP_WITHDRAWALS.status,
|
|
5916
|
-
async () => {
|
|
5917
|
-
const l2TxHash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
|
|
5918
|
-
if (!l2TxHash || l2TxHash === "0x") {
|
|
5919
|
-
return { phase: "UNKNOWN", l2TxHash: "0x" };
|
|
5920
|
-
}
|
|
5921
|
-
let l2Rcpt;
|
|
5922
|
-
try {
|
|
5923
|
-
l2Rcpt = await client.l2.getTransactionReceipt(l2TxHash);
|
|
5924
|
-
} catch (e) {
|
|
5925
|
-
if (isReceiptNotFound(e)) {
|
|
5926
|
-
return { phase: "L2_PENDING", l2TxHash };
|
|
8516
|
+
cause: e
|
|
8517
|
+
});
|
|
5927
8518
|
}
|
|
5928
|
-
throw toZKsyncError(
|
|
5929
|
-
"RPC",
|
|
5930
|
-
{
|
|
5931
|
-
resource: "withdrawals",
|
|
5932
|
-
operation: "withdrawals.status.getTransactionReceipt",
|
|
5933
|
-
message: "Failed to fetch L2 transaction receipt.",
|
|
5934
|
-
context: { l2TxHash, where: "l2.getTransactionReceipt" }
|
|
5935
|
-
},
|
|
5936
|
-
e
|
|
5937
|
-
);
|
|
5938
|
-
}
|
|
5939
|
-
if (!l2Rcpt) return { phase: "L2_PENDING", l2TxHash };
|
|
5940
|
-
let pack;
|
|
5941
|
-
try {
|
|
5942
|
-
pack = await svc.fetchFinalizeDepositParams(l2TxHash);
|
|
5943
|
-
} catch {
|
|
5944
|
-
return { phase: "PENDING", l2TxHash };
|
|
5945
8519
|
}
|
|
5946
|
-
const
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
8520
|
+
const last = Object.values(stepHashes).pop();
|
|
8521
|
+
return {
|
|
8522
|
+
kind: "interop",
|
|
8523
|
+
dstChain: params.dstChain,
|
|
8524
|
+
stepHashes,
|
|
8525
|
+
plan,
|
|
8526
|
+
l2SrcTxHash: last ?? "0x"
|
|
5950
8527
|
};
|
|
5951
|
-
try {
|
|
5952
|
-
const done = await svc.isWithdrawalFinalized(key);
|
|
5953
|
-
if (done) return { phase: "FINALIZED", l2TxHash, key };
|
|
5954
|
-
} catch {
|
|
5955
|
-
}
|
|
5956
|
-
const readiness = await svc.simulateFinalizeReadiness(pack.params);
|
|
5957
|
-
if (readiness.kind === "FINALIZED") return { phase: "FINALIZED", l2TxHash, key };
|
|
5958
|
-
if (readiness.kind === "READY") return { phase: "READY_TO_FINALIZE", l2TxHash, key };
|
|
5959
|
-
return { phase: "PENDING", l2TxHash, key };
|
|
5960
8528
|
},
|
|
5961
8529
|
{
|
|
5962
|
-
message: "Internal error while
|
|
5963
|
-
ctx: { where: "
|
|
8530
|
+
message: "Internal error while creating interop bundle.",
|
|
8531
|
+
ctx: { where: "interop.create" }
|
|
5964
8532
|
}
|
|
5965
8533
|
);
|
|
5966
|
-
const
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
context: { l2TxHash: l2Hash }
|
|
5986
|
-
},
|
|
5987
|
-
e
|
|
5988
|
-
);
|
|
5989
|
-
}
|
|
5990
|
-
if (!rcpt) return null;
|
|
5991
|
-
try {
|
|
5992
|
-
const raw = await client.zks.getReceiptWithL2ToL1(l2Hash);
|
|
5993
|
-
rcpt.l2ToL1Logs = raw?.l2ToL1Logs ?? [];
|
|
5994
|
-
} catch {
|
|
5995
|
-
rcpt.l2ToL1Logs = rcpt.l2ToL1Logs ?? [];
|
|
5996
|
-
}
|
|
5997
|
-
return rcpt;
|
|
5998
|
-
}
|
|
5999
|
-
const poll = Math.max(1e3, opts.pollMs ?? 2500);
|
|
6000
|
-
const deadline = opts.timeoutMs ? Date.now() + opts.timeoutMs : void 0;
|
|
6001
|
-
while (true) {
|
|
6002
|
-
const s = await status(l2Hash);
|
|
6003
|
-
if (opts.for === "ready") {
|
|
6004
|
-
if (s.phase === "READY_TO_FINALIZE" || s.phase === "FINALIZED") return null;
|
|
6005
|
-
} else {
|
|
6006
|
-
if (s.phase === "FINALIZED") {
|
|
6007
|
-
const l1Hash = finalizeCache.get(l2Hash);
|
|
6008
|
-
if (l1Hash) {
|
|
6009
|
-
try {
|
|
6010
|
-
const l1Rcpt = await client.l1.getTransactionReceipt(l1Hash);
|
|
6011
|
-
if (l1Rcpt) {
|
|
6012
|
-
finalizeCache.delete(l2Hash);
|
|
6013
|
-
return l1Rcpt;
|
|
6014
|
-
}
|
|
6015
|
-
} catch {
|
|
6016
|
-
}
|
|
6017
|
-
}
|
|
6018
|
-
return null;
|
|
6019
|
-
}
|
|
6020
|
-
}
|
|
6021
|
-
if (deadline && Date.now() > deadline) return null;
|
|
6022
|
-
await new Promise((r) => setTimeout(r, poll));
|
|
6023
|
-
}
|
|
6024
|
-
},
|
|
6025
|
-
{
|
|
6026
|
-
message: "Internal error while waiting for withdrawal.",
|
|
6027
|
-
ctx: {
|
|
6028
|
-
where: "withdrawals.wait",
|
|
6029
|
-
l2TxHash: typeof h === "string" ? h : h.l2TxHash,
|
|
6030
|
-
for: opts.for
|
|
8534
|
+
const tryCreate = (params) => toResult2(OP_INTEROP.tryCreate, () => create(params));
|
|
8535
|
+
const status = (h, opts) => {
|
|
8536
|
+
const { dstProvider, waitable } = resolveWaitableInput(h);
|
|
8537
|
+
return wrap5(OP_INTEROP.status, () => svc.status(dstProvider, waitable, opts), {
|
|
8538
|
+
message: "Internal error while checking interop status.",
|
|
8539
|
+
ctx: { where: "interop.status" }
|
|
8540
|
+
});
|
|
8541
|
+
};
|
|
8542
|
+
const wait = (h, opts) => {
|
|
8543
|
+
const { dstProvider, waitable } = resolveWaitableInput(h);
|
|
8544
|
+
return wrap5(
|
|
8545
|
+
OP_INTEROP.wait,
|
|
8546
|
+
async () => {
|
|
8547
|
+
const info = await svc.wait(dstProvider, waitable, opts);
|
|
8548
|
+
return { ...info, dstChain: h.dstChain };
|
|
8549
|
+
},
|
|
8550
|
+
{
|
|
8551
|
+
message: "Internal error while waiting for interop finalization.",
|
|
8552
|
+
ctx: { where: "interop.wait" }
|
|
6031
8553
|
}
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
const
|
|
6035
|
-
|
|
8554
|
+
);
|
|
8555
|
+
};
|
|
8556
|
+
const tryWait = (h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(h, opts));
|
|
8557
|
+
const finalize = (h, opts) => wrap5(
|
|
8558
|
+
OP_INTEROP.finalize,
|
|
6036
8559
|
async () => {
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
return await svc.fetchFinalizeDepositParams(l2TxHash);
|
|
6040
|
-
} catch (e) {
|
|
8560
|
+
if (isInteropFinalizationInfo(h)) {
|
|
8561
|
+
if (h.dstChain == null) {
|
|
6041
8562
|
throw createError("STATE", {
|
|
6042
|
-
resource: "
|
|
6043
|
-
operation:
|
|
6044
|
-
message: "
|
|
6045
|
-
context: {
|
|
6046
|
-
cause: e
|
|
8563
|
+
resource: "interop",
|
|
8564
|
+
operation: OP_INTEROP.finalize,
|
|
8565
|
+
message: "Missing dstChain in interop finalization info.",
|
|
8566
|
+
context: { input: h }
|
|
6047
8567
|
});
|
|
6048
8568
|
}
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
const key = {
|
|
6052
|
-
chainIdL2: params.chainId,
|
|
6053
|
-
l2BatchNumber: params.l2BatchNumber,
|
|
6054
|
-
l2MessageIndex: params.l2MessageIndex
|
|
6055
|
-
};
|
|
6056
|
-
try {
|
|
6057
|
-
const done = await svc.isWithdrawalFinalized(key);
|
|
6058
|
-
if (done) {
|
|
6059
|
-
const statusNow = await status(l2TxHash);
|
|
6060
|
-
return { status: statusNow };
|
|
6061
|
-
}
|
|
6062
|
-
} catch {
|
|
6063
|
-
}
|
|
6064
|
-
const readiness = await svc.simulateFinalizeReadiness(params);
|
|
6065
|
-
if (readiness.kind === "FINALIZED") {
|
|
6066
|
-
const statusNow = await status(l2TxHash);
|
|
6067
|
-
return { status: statusNow };
|
|
6068
|
-
}
|
|
6069
|
-
if (readiness.kind === "NOT_READY") {
|
|
6070
|
-
throw createError("STATE", {
|
|
6071
|
-
resource: "withdrawals",
|
|
6072
|
-
operation: OP_WITHDRAWALS.finalize.readiness.simulate,
|
|
6073
|
-
message: "Withdrawal not ready to finalize.",
|
|
6074
|
-
context: readiness
|
|
6075
|
-
});
|
|
6076
|
-
}
|
|
6077
|
-
try {
|
|
6078
|
-
const tx = await svc.finalizeDeposit(params);
|
|
6079
|
-
finalizeCache.set(l2TxHash, tx.hash);
|
|
6080
|
-
const rcpt = await tx.wait();
|
|
6081
|
-
const statusNow = await status(l2TxHash);
|
|
6082
|
-
return { status: statusNow, receipt: rcpt };
|
|
6083
|
-
} catch (e) {
|
|
6084
|
-
const statusNow = await status(l2TxHash);
|
|
6085
|
-
if (statusNow.phase === "FINALIZED") return { status: statusNow };
|
|
6086
|
-
try {
|
|
6087
|
-
const again = await svc.simulateFinalizeReadiness(params);
|
|
6088
|
-
if (again.kind === "NOT_READY") {
|
|
6089
|
-
throw createError("STATE", {
|
|
6090
|
-
resource: "withdrawals",
|
|
6091
|
-
operation: OP_WITHDRAWALS.finalize.readiness.simulate,
|
|
6092
|
-
message: "Withdrawal not ready to finalize.",
|
|
6093
|
-
context: again
|
|
6094
|
-
});
|
|
6095
|
-
}
|
|
6096
|
-
} catch {
|
|
6097
|
-
}
|
|
6098
|
-
throw e;
|
|
8569
|
+
const dstProvider2 = resolveDstProvider(h.dstChain);
|
|
8570
|
+
return svc.finalize(dstProvider2, h, opts);
|
|
6099
8571
|
}
|
|
8572
|
+
const { dstProvider, waitable } = resolveWaitableInput(h);
|
|
8573
|
+
const info = await svc.wait(dstProvider, waitable);
|
|
8574
|
+
return svc.finalize(dstProvider, info, opts);
|
|
6100
8575
|
},
|
|
6101
8576
|
{
|
|
6102
|
-
message: "
|
|
6103
|
-
ctx: {
|
|
6104
|
-
}
|
|
6105
|
-
);
|
|
6106
|
-
const tryFinalize = (l2TxHash) => toResult2("withdrawals.tryFinalize", () => finalize(l2TxHash), {
|
|
6107
|
-
message: "Internal error while attempting to tryFinalize withdrawal.",
|
|
6108
|
-
ctx: { l2TxHash, where: "withdrawals.tryFinalize" }
|
|
6109
|
-
});
|
|
6110
|
-
const tryWait = (h, opts) => toResult2(
|
|
6111
|
-
OP_WITHDRAWALS.tryWait,
|
|
6112
|
-
async () => {
|
|
6113
|
-
const v = await wait(h, opts);
|
|
6114
|
-
if (v) return v;
|
|
6115
|
-
throw createError("STATE", {
|
|
6116
|
-
resource: "withdrawals",
|
|
6117
|
-
operation: "withdrawals.tryWait",
|
|
6118
|
-
message: opts.for === "l2" ? "No L2 receipt yet; the withdrawal has not executed on L2." : "No L1 receipt yet; the withdrawal has not been included on L1.",
|
|
6119
|
-
context: {
|
|
6120
|
-
for: opts.for,
|
|
6121
|
-
l2TxHash: typeof h === "string" ? h : "l2TxHash" in h ? h.l2TxHash : void 0,
|
|
6122
|
-
where: "withdrawals.tryWait"
|
|
6123
|
-
}
|
|
6124
|
-
});
|
|
6125
|
-
},
|
|
6126
|
-
{
|
|
6127
|
-
message: "Internal error while waiting for withdrawal.",
|
|
6128
|
-
ctx: { input: h, for: opts?.for, where: "withdrawals.tryWait" }
|
|
8577
|
+
message: "Failed to finalize/execute interop bundle on destination.",
|
|
8578
|
+
ctx: { where: "interop.finalize" }
|
|
6129
8579
|
}
|
|
6130
8580
|
);
|
|
8581
|
+
const tryFinalize = (h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(h, opts));
|
|
6131
8582
|
return {
|
|
6132
8583
|
quote,
|
|
6133
8584
|
tryQuote,
|
|
@@ -6137,9 +8588,9 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
6137
8588
|
tryCreate,
|
|
6138
8589
|
status,
|
|
6139
8590
|
wait,
|
|
8591
|
+
tryWait,
|
|
6140
8592
|
finalize,
|
|
6141
|
-
tryFinalize
|
|
6142
|
-
tryWait
|
|
8593
|
+
tryFinalize
|
|
6143
8594
|
};
|
|
6144
8595
|
}
|
|
6145
8596
|
|
|
@@ -6147,11 +8598,13 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
6147
8598
|
function createEthersSdk(client) {
|
|
6148
8599
|
const tokens = createTokensResource(client);
|
|
6149
8600
|
const contracts = createContractsResource(client);
|
|
8601
|
+
const interop = createInteropResource(client);
|
|
6150
8602
|
return {
|
|
6151
8603
|
deposits: createDepositsResource(client, tokens, contracts),
|
|
6152
8604
|
withdrawals: createWithdrawalsResource(client, tokens, contracts),
|
|
6153
8605
|
tokens,
|
|
6154
|
-
contracts
|
|
8606
|
+
contracts,
|
|
8607
|
+
interop
|
|
6155
8608
|
};
|
|
6156
8609
|
}
|
|
6157
8610
|
|