@matterlabs/zksync-js 0.0.13 → 0.0.14
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 +13 -4
- package/dist/adapters/ethers/client.cjs.map +1 -1
- package/dist/adapters/ethers/client.js +7 -6
- package/dist/adapters/ethers/index.cjs +501 -242
- package/dist/adapters/ethers/index.cjs.map +1 -1
- package/dist/adapters/ethers/index.js +10 -9
- package/dist/adapters/ethers/resources/deposits/routes/priority.d.ts +12 -0
- package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +4 -0
- package/dist/adapters/ethers/resources/interop/index.d.ts +14 -14
- package/dist/adapters/ethers/resources/interop/resolvers.d.ts +3 -8
- package/dist/adapters/ethers/resources/interop/routes/types.d.ts +2 -1
- package/dist/adapters/ethers/resources/interop/services/erc20.d.ts +10 -0
- package/dist/adapters/ethers/resources/interop/services/fee.d.ts +12 -0
- package/dist/adapters/ethers/resources/interop/services/finalization/index.d.ts +1 -1
- package/dist/adapters/ethers/resources/interop/services/finalization/polling.d.ts +1 -1
- package/dist/adapters/ethers/resources/interop/types.d.ts +6 -14
- package/dist/adapters/ethers/sdk.cjs +912 -252
- package/dist/adapters/ethers/sdk.cjs.map +1 -1
- package/dist/adapters/ethers/sdk.d.ts +6 -1
- package/dist/adapters/ethers/sdk.js +8 -7
- package/dist/adapters/viem/client.cjs +8 -4
- package/dist/adapters/viem/client.cjs.map +1 -1
- package/dist/adapters/viem/client.js +7 -6
- package/dist/adapters/viem/index.cjs +315 -73
- package/dist/adapters/viem/index.cjs.map +1 -1
- package/dist/adapters/viem/index.js +10 -9
- package/dist/adapters/viem/resources/deposits/routes/priority.d.ts +13 -0
- package/dist/adapters/viem/resources/deposits/services/gas.d.ts +4 -0
- package/dist/adapters/viem/sdk.cjs +307 -69
- package/dist/adapters/viem/sdk.cjs.map +1 -1
- package/dist/adapters/viem/sdk.js +7 -7
- package/dist/{chunk-E3KP7XCG.js → chunk-3HHUZXSV.js} +1 -1
- package/dist/{chunk-UDBRUBEK.js → chunk-5RRJDPAJ.js} +2 -2
- package/dist/{chunk-EDWBCPO3.js → chunk-75IOOODG.js} +253 -53
- package/dist/{chunk-R5WRFPK2.js → chunk-7CAVFIMW.js} +5 -4
- package/dist/chunk-BWKWWLY4.js +9 -0
- package/dist/{chunk-4S4XDA4N.js → chunk-DYJKK5FW.js} +17 -15
- package/dist/{chunk-5L6EYUJB.js → chunk-EOBXYHTZ.js} +35 -7
- package/dist/{chunk-53MC5BR2.js → chunk-HP3EWKJL.js} +1 -1
- package/dist/{chunk-HI64OOAR.js → chunk-J47RI3G7.js} +1 -1
- package/dist/{chunk-RI73VJSH.js → chunk-JY62QO3W.js} +44 -21
- package/dist/{chunk-QQ2OR434.js → chunk-MT4X5FEO.js} +18 -2
- package/dist/{chunk-2RIARDXZ.js → chunk-OTXPSNNC.js} +5 -4
- package/dist/{chunk-5R7L5NM5.js → chunk-XDRCN4FC.js} +2 -2
- package/dist/{chunk-JHO2UQ5F.js → chunk-XKRNLFET.js} +394 -200
- package/dist/core/constants.cjs +17 -1
- package/dist/core/constants.cjs.map +1 -1
- package/dist/core/constants.d.ts +9 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/index.cjs +52 -24
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +6 -5
- package/dist/core/internal/abis/IERC7786Attributes.d.ts +21 -11
- package/dist/core/internal/abis/IInteropCenter.d.ts +4 -0
- package/dist/core/resources/deposits/priority.d.ts +37 -0
- package/dist/core/resources/interop/attributes/bundle.d.ts +1 -0
- package/dist/core/resources/interop/attributes/resource.d.ts +1 -0
- package/dist/core/resources/interop/plan.d.ts +11 -3
- package/dist/core/rpc/types.d.ts +1 -0
- package/dist/core/rpc/zks.d.ts +5 -1
- package/dist/core/types/errors.d.ts +5 -0
- package/dist/core/types/flows/interop.d.ts +11 -18
- package/dist/index.cjs +69 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -5
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-
|
|
2
|
-
import { createNTVCodec, toGasOverrides, buildFeeBreakdown, quoteL2Gas, quoteL2BaseCost, quoteL1Gas, quoteL2Gas2 } from './chunk-
|
|
3
|
-
import { findL1MessageSentLog, messengerLogIndex, isL1MessageSentLog, pickWithdrawRoute } from './chunk-
|
|
4
|
-
import { isHash66, IL1Nullifier_default, OP_WITHDRAWALS, createError, normalizeL1Token, isAddressEq, hexEq, OP_DEPOSITS, IERC20_default, isZKsyncError, isReceiptNotFound, OP_INTEROP, IInteropHandler_default, IERC7786Attributes_default, isBigint, isHash, IInteropCenter_default, sleep, isETH, normalizeAddrEq, isNumber, isAddress, isHash66Array, IInteropRootStorage_default, L2NativeTokenVault_default, assertNever } from './chunk-
|
|
5
|
-
import { ETH_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_INTEROP_CENTER_ADDRESS, BUNDLE_IDENTIFIER, L2_INTEROP_ROOT_STORAGE_ADDRESS, SAFE_L1_BRIDGE_GAS, FORMAL_ETH_ADDRESS } from './chunk-
|
|
6
|
-
import { Interface, AbiCoder, ethers, getBytes, Contract, NonceManager, JsonRpcProvider, isError, getAddress, concat, hexlify, toBeArray, toBeHex } from 'ethers';
|
|
1
|
+
import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-5RRJDPAJ.js';
|
|
2
|
+
import { createNTVCodec, toGasOverrides, buildFeeBreakdown, derivePriorityTxGasBreakdown, quoteL2Gas, quoteL2BaseCost, quoteL1Gas, derivePriorityBodyGasEstimateCap, quoteL2Gas2 } from './chunk-EOBXYHTZ.js';
|
|
3
|
+
import { findL1MessageSentLog, messengerLogIndex, isL1MessageSentLog, pickWithdrawRoute } from './chunk-3HHUZXSV.js';
|
|
4
|
+
import { isHash66, IL1Nullifier_default, OP_WITHDRAWALS, createError, normalizeL1Token, isAddressEq, hexEq, OP_DEPOSITS, IERC20_default, isZKsyncError, isReceiptNotFound, OP_INTEROP, IInteropHandler_default, IERC7786Attributes_default, isBigint, isHash, IInteropCenter_default, sleep, isETH, normalizeAddrEq, isNumber, isAddress, isHash66Array, IInteropRootStorage_default, IL2AssetRouter_default, L2NativeTokenVault_default, assertNever } from './chunk-JY62QO3W.js';
|
|
5
|
+
import { ETH_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_INTEROP_CENTER_ADDRESS, BUNDLE_IDENTIFIER, L2_INTEROP_ROOT_STORAGE_ADDRESS, SAFE_L1_BRIDGE_GAS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
|
|
6
|
+
import { Interface, keccak256, AbiCoder, ethers, getBytes, Contract, NonceManager, JsonRpcProvider, isError, getAddress, concat, hexlify, toBeArray, toBeHex } from 'ethers';
|
|
7
7
|
|
|
8
8
|
var I_BRIDGEHUB = new Interface([
|
|
9
9
|
"event NewPriorityRequest(uint256 indexed chainId, address indexed sender, bytes32 txHash, uint256 txId, bytes data)"
|
|
@@ -279,8 +279,22 @@ async function determineNonBaseL2Gas(input) {
|
|
|
279
279
|
try {
|
|
280
280
|
const l2TokenAddress = input.knownL2Token ?? (ctx.tokens ? await ctx.tokens.toL2Address(l1Token) : await (await ctx.contracts.l2NativeTokenVault()).l2TokenAddress(l1Token));
|
|
281
281
|
if (l2TokenAddress === ZERO_L2_TOKEN_ADDRESS) {
|
|
282
|
+
if (input.undeployedGasLimit != null) {
|
|
283
|
+
return quoteL2Gas3({
|
|
284
|
+
ctx,
|
|
285
|
+
route,
|
|
286
|
+
overrideGasLimit: input.undeployedGasLimit
|
|
287
|
+
});
|
|
288
|
+
}
|
|
282
289
|
return fallbackQuote();
|
|
283
290
|
}
|
|
291
|
+
if (input.priorityFloorGasLimit != null) {
|
|
292
|
+
return quoteL2Gas3({
|
|
293
|
+
ctx,
|
|
294
|
+
route,
|
|
295
|
+
overrideGasLimit: input.priorityFloorGasLimit
|
|
296
|
+
});
|
|
297
|
+
}
|
|
284
298
|
const modelTx = {
|
|
285
299
|
to: input.modelTx?.to ?? ctx.sender,
|
|
286
300
|
from: input.modelTx?.from ?? ctx.sender,
|
|
@@ -296,8 +310,7 @@ async function determineNonBaseL2Gas(input) {
|
|
|
296
310
|
return fallbackQuote();
|
|
297
311
|
}
|
|
298
312
|
return gas;
|
|
299
|
-
} catch
|
|
300
|
-
console.warn("Failed to determine non-base deposit L2 gas; defaulting to safe gas limit.", err);
|
|
313
|
+
} catch {
|
|
301
314
|
return fallbackQuote();
|
|
302
315
|
}
|
|
303
316
|
}
|
|
@@ -314,45 +327,86 @@ async function determineEthNonBaseL2Gas(input) {
|
|
|
314
327
|
route: "eth-nonbase",
|
|
315
328
|
l1Token: input.ctx.resolvedToken?.l1 ?? FORMAL_ETH_ADDRESS,
|
|
316
329
|
knownL2Token: input.ctx.resolvedToken?.l2,
|
|
317
|
-
modelTx: input.modelTx
|
|
330
|
+
modelTx: input.modelTx,
|
|
331
|
+
priorityFloorGasLimit: input.priorityFloorGasLimit,
|
|
332
|
+
undeployedGasLimit: input.undeployedGasLimit
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
var EMPTY_BYTES = "0x";
|
|
336
|
+
var ZERO_RESERVED_WORDS = [0n, 0n, 0n, 0n];
|
|
337
|
+
var L2_CANONICAL_TRANSACTION_TUPLE = "tuple(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 paymaster,uint256 nonce,uint256 value,uint256[4] reserved,bytes data,bytes signature,uint256[] factoryDeps,bytes paymasterInput,bytes reservedDynamic)";
|
|
338
|
+
function hexByteLength(hex) {
|
|
339
|
+
return BigInt(Math.max(hex.length - 2, 0) / 2);
|
|
340
|
+
}
|
|
341
|
+
function getPriorityTxEncodedLength(input) {
|
|
342
|
+
const encoded = AbiCoder.defaultAbiCoder().encode(
|
|
343
|
+
[L2_CANONICAL_TRANSACTION_TUPLE],
|
|
344
|
+
[
|
|
345
|
+
[
|
|
346
|
+
0n,
|
|
347
|
+
BigInt(input.sender),
|
|
348
|
+
BigInt(input.l2Contract),
|
|
349
|
+
0n,
|
|
350
|
+
input.gasPerPubdata,
|
|
351
|
+
0n,
|
|
352
|
+
0n,
|
|
353
|
+
0n,
|
|
354
|
+
0n,
|
|
355
|
+
input.l2Value,
|
|
356
|
+
ZERO_RESERVED_WORDS,
|
|
357
|
+
input.l2Calldata,
|
|
358
|
+
EMPTY_BYTES,
|
|
359
|
+
input.factoryDepsHashes ?? [],
|
|
360
|
+
EMPTY_BYTES,
|
|
361
|
+
EMPTY_BYTES
|
|
362
|
+
]
|
|
363
|
+
]
|
|
364
|
+
);
|
|
365
|
+
return hexByteLength(encoded);
|
|
366
|
+
}
|
|
367
|
+
function getPriorityTxGasBreakdown(input) {
|
|
368
|
+
return derivePriorityTxGasBreakdown({
|
|
369
|
+
encodedLength: getPriorityTxEncodedLength(input),
|
|
370
|
+
gasPerPubdata: input.gasPerPubdata,
|
|
371
|
+
factoryDepsCount: BigInt(input.factoryDepsHashes?.length ?? 0)
|
|
318
372
|
});
|
|
319
373
|
}
|
|
320
374
|
|
|
321
375
|
// src/adapters/ethers/resources/deposits/routes/eth.ts
|
|
376
|
+
var EMPTY_BYTES2 = "0x";
|
|
322
377
|
function routeEthDirect() {
|
|
323
378
|
return {
|
|
324
379
|
async build(p, ctx) {
|
|
325
380
|
const bh = await ctx.contracts.bridgehub();
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
381
|
+
const l2Contract = p.to ?? ctx.sender;
|
|
382
|
+
const l2Value = p.amount;
|
|
383
|
+
const l2Calldata = EMPTY_BYTES2;
|
|
384
|
+
const priorityFloorBreakdown = getPriorityTxGasBreakdown({
|
|
385
|
+
sender: ctx.sender,
|
|
386
|
+
l2Contract,
|
|
387
|
+
l2Value,
|
|
388
|
+
l2Calldata,
|
|
389
|
+
gasPerPubdata: ctx.gasPerPubdata
|
|
390
|
+
});
|
|
391
|
+
const quotedL2GasLimit = ctx.l2GasLimit ?? priorityFloorBreakdown.derivedL2GasLimit;
|
|
332
392
|
const l2GasParams = await quoteL2Gas3({
|
|
333
393
|
ctx,
|
|
334
394
|
route: "eth-base",
|
|
335
|
-
|
|
336
|
-
overrideGasLimit: ctx.l2GasLimit,
|
|
337
|
-
stateOverrides: {
|
|
338
|
-
[ctx.sender]: {
|
|
339
|
-
balance: "0xffffffffffffffffffff"
|
|
340
|
-
}
|
|
341
|
-
}
|
|
395
|
+
overrideGasLimit: quotedL2GasLimit
|
|
342
396
|
});
|
|
343
397
|
if (!l2GasParams) {
|
|
344
398
|
throw new Error("Failed to estimate L2 gas for deposit.");
|
|
345
399
|
}
|
|
346
400
|
const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
|
|
347
|
-
const mintValue = baseCost + ctx.operatorTip +
|
|
401
|
+
const mintValue = baseCost + ctx.operatorTip + l2Value;
|
|
348
402
|
const req = buildDirectRequestStruct({
|
|
349
403
|
chainId: ctx.chainIdL2,
|
|
350
404
|
mintValue,
|
|
351
405
|
l2GasLimit: l2GasParams.gasLimit,
|
|
352
406
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
353
407
|
refundRecipient: ctx.refundRecipient,
|
|
354
|
-
l2Contract
|
|
355
|
-
l2Value
|
|
408
|
+
l2Contract,
|
|
409
|
+
l2Value
|
|
356
410
|
});
|
|
357
411
|
const data = bh.interface.encodeFunctionData("requestL2TransactionDirect", [req]);
|
|
358
412
|
const l1TxCandidate = {
|
|
@@ -402,6 +456,53 @@ var ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000
|
|
|
402
456
|
|
|
403
457
|
// src/adapters/ethers/resources/deposits/routes/erc20-nonbase.ts
|
|
404
458
|
var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
|
|
459
|
+
var ZERO_L2_TOKEN_ADDRESS2 = "0x0000000000000000000000000000000000000000";
|
|
460
|
+
var ZERO_ASSET_ID = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
461
|
+
async function getPriorityGasModel(input) {
|
|
462
|
+
try {
|
|
463
|
+
const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
|
|
464
|
+
const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
|
|
465
|
+
const { chainId: l1ChainId } = await input.ctx.client.l1.getNetwork();
|
|
466
|
+
const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n;
|
|
467
|
+
const erc20MetadataOriginChainId = isFirstBridge ? BigInt(l1ChainId) : input.ctx.resolvedToken.originChainId;
|
|
468
|
+
const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
|
|
469
|
+
input.token,
|
|
470
|
+
erc20MetadataOriginChainId
|
|
471
|
+
);
|
|
472
|
+
const bridgeMintCalldata = AbiCoder.defaultAbiCoder().encode(
|
|
473
|
+
["address", "address", "address", "uint256", "bytes"],
|
|
474
|
+
[input.ctx.sender, input.receiver, input.token, input.amount, erc20Metadata]
|
|
475
|
+
);
|
|
476
|
+
const l2Calldata = isFirstBridge ? new Interface(IL2AssetRouter_default).encodeFunctionData(
|
|
477
|
+
"finalizeDeposit(address,address,address,uint256,bytes)",
|
|
478
|
+
[input.ctx.sender, input.receiver, input.token, input.amount, erc20Metadata]
|
|
479
|
+
) : await (() => {
|
|
480
|
+
return l1AssetRouter.getDepositCalldata(
|
|
481
|
+
input.ctx.sender,
|
|
482
|
+
input.ctx.resolvedToken.assetId,
|
|
483
|
+
bridgeMintCalldata
|
|
484
|
+
);
|
|
485
|
+
})();
|
|
486
|
+
const priorityFloorBreakdown = getPriorityTxGasBreakdown({
|
|
487
|
+
sender: input.ctx.l1AssetRouter,
|
|
488
|
+
l2Contract: L2_ASSET_ROUTER_ADDRESS,
|
|
489
|
+
l2Value: 0n,
|
|
490
|
+
l2Calldata,
|
|
491
|
+
gasPerPubdata: input.ctx.gasPerPubdata
|
|
492
|
+
});
|
|
493
|
+
const model = {
|
|
494
|
+
priorityFloorGasLimit: priorityFloorBreakdown.derivedL2GasLimit
|
|
495
|
+
};
|
|
496
|
+
if (isFirstBridge || input.ctx.resolvedToken.l2.toLowerCase() === ZERO_L2_TOKEN_ADDRESS2) {
|
|
497
|
+
model.undeployedGasLimit = derivePriorityBodyGasEstimateCap({
|
|
498
|
+
minBodyGas: priorityFloorBreakdown.minBodyGas
|
|
499
|
+
}) + priorityFloorBreakdown.overhead;
|
|
500
|
+
}
|
|
501
|
+
return model;
|
|
502
|
+
} catch {
|
|
503
|
+
return {};
|
|
504
|
+
}
|
|
505
|
+
}
|
|
405
506
|
function routeErc20NonBase() {
|
|
406
507
|
return {
|
|
407
508
|
async preflight(p, ctx) {
|
|
@@ -422,11 +523,29 @@ function routeErc20NonBase() {
|
|
|
422
523
|
const l1Signer = ctx.client.getL1Signer();
|
|
423
524
|
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
424
525
|
const baseIsEth = ctx.baseIsEth ?? isETH(baseToken);
|
|
526
|
+
const receiver = p.to ?? ctx.sender;
|
|
527
|
+
const secondBridgeCalldata = await wrapAs2(
|
|
528
|
+
"INTERNAL",
|
|
529
|
+
OP_DEPOSITS.nonbase.encodeCalldata,
|
|
530
|
+
() => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
|
|
531
|
+
{
|
|
532
|
+
ctx: { where: "encodeSecondBridgeErc20Args" },
|
|
533
|
+
message: "Failed to encode bridging calldata."
|
|
534
|
+
}
|
|
535
|
+
);
|
|
536
|
+
const priorityGasModel = await getPriorityGasModel({
|
|
537
|
+
ctx,
|
|
538
|
+
token: p.token,
|
|
539
|
+
amount: p.amount,
|
|
540
|
+
receiver
|
|
541
|
+
});
|
|
425
542
|
const l2GasParams = await determineErc20L2Gas({
|
|
426
543
|
ctx,
|
|
427
544
|
l1Token: p.token,
|
|
545
|
+
priorityFloorGasLimit: priorityGasModel.priorityFloorGasLimit,
|
|
546
|
+
undeployedGasLimit: priorityGasModel.undeployedGasLimit,
|
|
428
547
|
modelTx: {
|
|
429
|
-
to:
|
|
548
|
+
to: receiver,
|
|
430
549
|
from: ctx.sender,
|
|
431
550
|
data: "0x",
|
|
432
551
|
value: 0n
|
|
@@ -488,15 +607,6 @@ function routeErc20NonBase() {
|
|
|
488
607
|
});
|
|
489
608
|
}
|
|
490
609
|
}
|
|
491
|
-
const secondBridgeCalldata = await wrapAs2(
|
|
492
|
-
"INTERNAL",
|
|
493
|
-
OP_DEPOSITS.nonbase.encodeCalldata,
|
|
494
|
-
() => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, p.to ?? ctx.sender)),
|
|
495
|
-
{
|
|
496
|
-
ctx: { where: "encodeSecondBridgeErc20Args" },
|
|
497
|
-
message: "Failed to encode bridging calldata."
|
|
498
|
-
}
|
|
499
|
-
);
|
|
500
610
|
const requestStruct = {
|
|
501
611
|
chainId: ctx.chainIdL2,
|
|
502
612
|
mintValue,
|
|
@@ -554,6 +664,51 @@ function routeErc20NonBase() {
|
|
|
554
664
|
};
|
|
555
665
|
}
|
|
556
666
|
var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
|
|
667
|
+
var ZERO_L2_TOKEN_ADDRESS3 = "0x0000000000000000000000000000000000000000";
|
|
668
|
+
var ZERO_ASSET_ID2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
669
|
+
var ntvCodec = createNTVCodec({
|
|
670
|
+
encode: (types, values) => AbiCoder.defaultAbiCoder().encode(types, values),
|
|
671
|
+
keccak256: (data) => keccak256(data)
|
|
672
|
+
});
|
|
673
|
+
async function getPriorityGasModel2(input) {
|
|
674
|
+
try {
|
|
675
|
+
const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
|
|
676
|
+
const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
|
|
677
|
+
const originChainId = input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : BigInt((await input.ctx.client.l1.getNetwork()).chainId);
|
|
678
|
+
const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
|
|
679
|
+
const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
|
|
680
|
+
ETH_ADDRESS,
|
|
681
|
+
originChainId
|
|
682
|
+
);
|
|
683
|
+
const bridgeMintCalldata = AbiCoder.defaultAbiCoder().encode(
|
|
684
|
+
["address", "address", "address", "uint256", "bytes"],
|
|
685
|
+
[input.ctx.sender, input.receiver, ETH_ADDRESS, input.amount, erc20Metadata]
|
|
686
|
+
);
|
|
687
|
+
const l2Calldata = await l1AssetRouter.getDepositCalldata(
|
|
688
|
+
input.ctx.sender,
|
|
689
|
+
resolvedAssetId,
|
|
690
|
+
bridgeMintCalldata
|
|
691
|
+
);
|
|
692
|
+
const priorityFloorBreakdown = getPriorityTxGasBreakdown({
|
|
693
|
+
sender: input.ctx.l1AssetRouter,
|
|
694
|
+
l2Contract: L2_ASSET_ROUTER_ADDRESS,
|
|
695
|
+
l2Value: 0n,
|
|
696
|
+
l2Calldata,
|
|
697
|
+
gasPerPubdata: input.ctx.gasPerPubdata
|
|
698
|
+
});
|
|
699
|
+
const model = {
|
|
700
|
+
priorityFloorGasLimit: priorityFloorBreakdown.derivedL2GasLimit
|
|
701
|
+
};
|
|
702
|
+
if (input.ctx.resolvedToken.l2.toLowerCase() === ZERO_L2_TOKEN_ADDRESS3) {
|
|
703
|
+
model.undeployedGasLimit = derivePriorityBodyGasEstimateCap({
|
|
704
|
+
minBodyGas: priorityFloorBreakdown.minBodyGas
|
|
705
|
+
}) + priorityFloorBreakdown.overhead;
|
|
706
|
+
}
|
|
707
|
+
return model;
|
|
708
|
+
} catch {
|
|
709
|
+
return {};
|
|
710
|
+
}
|
|
711
|
+
}
|
|
557
712
|
function routeEthNonBase() {
|
|
558
713
|
return {
|
|
559
714
|
async preflight(p, ctx) {
|
|
@@ -602,15 +757,23 @@ function routeEthNonBase() {
|
|
|
602
757
|
async build(p, ctx) {
|
|
603
758
|
const l1Signer = ctx.client.getL1Signer();
|
|
604
759
|
const baseToken = ctx.baseTokenL1;
|
|
760
|
+
const receiver = p.to ?? ctx.sender;
|
|
761
|
+
const priorityGasModel = await getPriorityGasModel2({
|
|
762
|
+
ctx,
|
|
763
|
+
amount: p.amount,
|
|
764
|
+
receiver
|
|
765
|
+
});
|
|
605
766
|
const l2TxModel = {
|
|
606
|
-
to:
|
|
767
|
+
to: receiver,
|
|
607
768
|
from: ctx.sender,
|
|
608
769
|
data: "0x",
|
|
609
770
|
value: 0n
|
|
610
771
|
};
|
|
611
772
|
const l2GasParams = await determineEthNonBaseL2Gas({
|
|
612
773
|
ctx,
|
|
613
|
-
modelTx: l2TxModel
|
|
774
|
+
modelTx: l2TxModel,
|
|
775
|
+
priorityFloorGasLimit: priorityGasModel.priorityFloorGasLimit,
|
|
776
|
+
undeployedGasLimit: priorityGasModel.undeployedGasLimit
|
|
614
777
|
});
|
|
615
778
|
if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
|
|
616
779
|
const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
|
|
@@ -644,12 +807,12 @@ function routeEthNonBase() {
|
|
|
644
807
|
const secondBridgeCalldata = await wrapAs3(
|
|
645
808
|
"INTERNAL",
|
|
646
809
|
OP_DEPOSITS.ethNonBase.encodeCalldata,
|
|
647
|
-
() => Promise.resolve(encodeSecondBridgeEthArgs(p.amount,
|
|
810
|
+
() => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, receiver)),
|
|
648
811
|
{
|
|
649
812
|
ctx: {
|
|
650
813
|
where: "encodeSecondBridgeEthArgs",
|
|
651
814
|
amount: p.amount.toString(),
|
|
652
|
-
to:
|
|
815
|
+
to: receiver
|
|
653
816
|
}
|
|
654
817
|
}
|
|
655
818
|
);
|
|
@@ -710,6 +873,7 @@ function routeEthNonBase() {
|
|
|
710
873
|
};
|
|
711
874
|
}
|
|
712
875
|
var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
|
|
876
|
+
var EMPTY_BYTES3 = "0x";
|
|
713
877
|
function routeErc20Base() {
|
|
714
878
|
return {
|
|
715
879
|
async preflight(p, ctx) {
|
|
@@ -740,17 +904,21 @@ function routeErc20Base() {
|
|
|
740
904
|
async build(p, ctx) {
|
|
741
905
|
const l1Signer = ctx.client.getL1Signer();
|
|
742
906
|
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
907
|
+
const l2Contract = p.to ?? ctx.sender;
|
|
908
|
+
const l2Value = p.amount;
|
|
909
|
+
const l2Calldata = EMPTY_BYTES3;
|
|
910
|
+
const priorityFloorBreakdown = getPriorityTxGasBreakdown({
|
|
911
|
+
sender: ctx.sender,
|
|
912
|
+
l2Contract,
|
|
913
|
+
l2Value,
|
|
914
|
+
l2Calldata,
|
|
915
|
+
gasPerPubdata: ctx.gasPerPubdata
|
|
916
|
+
});
|
|
917
|
+
const quotedL2GasLimit = ctx.l2GasLimit ?? priorityFloorBreakdown.derivedL2GasLimit;
|
|
749
918
|
const l2GasParams = await quoteL2Gas3({
|
|
750
919
|
ctx,
|
|
751
920
|
route: "erc20-base",
|
|
752
|
-
|
|
753
|
-
overrideGasLimit: ctx.l2GasLimit
|
|
921
|
+
overrideGasLimit: quotedL2GasLimit
|
|
754
922
|
});
|
|
755
923
|
if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
|
|
756
924
|
const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
|
|
@@ -789,8 +957,8 @@ function routeErc20Base() {
|
|
|
789
957
|
l2GasLimit: l2GasParams.gasLimit,
|
|
790
958
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
791
959
|
refundRecipient: ctx.refundRecipient,
|
|
792
|
-
l2Contract
|
|
793
|
-
l2Value
|
|
960
|
+
l2Contract,
|
|
961
|
+
l2Value
|
|
794
962
|
});
|
|
795
963
|
const bridgehub = await ctx.contracts.bridgehub();
|
|
796
964
|
const data = bridgehub.interface.encodeFunctionData("requestL2TransactionDirect", [
|
|
@@ -839,7 +1007,7 @@ function routeErc20Base() {
|
|
|
839
1007
|
}
|
|
840
1008
|
var { wrapAs: wrapAs5 } = createErrorHandlers("tokens");
|
|
841
1009
|
var abi = AbiCoder.defaultAbiCoder();
|
|
842
|
-
var
|
|
1010
|
+
var ntvCodec2 = createNTVCodec({
|
|
843
1011
|
encode: (types, values) => abi.encode(types, values),
|
|
844
1012
|
keccak256: (data) => ethers.keccak256(data)
|
|
845
1013
|
});
|
|
@@ -958,7 +1126,7 @@ function createTokensResource(client) {
|
|
|
958
1126
|
return wrapAs5("CONTRACT", "tokens.isChainEthBased", async () => {
|
|
959
1127
|
const baseAssetId = await getBaseTokenAssetId();
|
|
960
1128
|
const l1ChainId = await getL1ChainId();
|
|
961
|
-
const ethAssetId =
|
|
1129
|
+
const ethAssetId = ntvCodec2.encodeAssetId(
|
|
962
1130
|
l1ChainId,
|
|
963
1131
|
L2_NATIVE_TOKEN_VAULT_ADDRESS,
|
|
964
1132
|
ETH_ADDRESS
|
|
@@ -1853,7 +2021,7 @@ var ROUTES2 = {
|
|
|
1853
2021
|
};
|
|
1854
2022
|
function createWithdrawalsResource(client, tokens, contracts) {
|
|
1855
2023
|
const svc = createFinalizationServices(client);
|
|
1856
|
-
const { wrap:
|
|
2024
|
+
const { wrap: wrap7, toResult: toResult3 } = createErrorHandlers("withdrawals");
|
|
1857
2025
|
const tokensResource = tokens ?? createTokensResource(client);
|
|
1858
2026
|
const contractsResource = contracts ?? createContractsResource(client);
|
|
1859
2027
|
async function buildPlan(p) {
|
|
@@ -1874,7 +2042,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
1874
2042
|
};
|
|
1875
2043
|
}
|
|
1876
2044
|
const finalizeCache = /* @__PURE__ */ new Map();
|
|
1877
|
-
const quote = (p) =>
|
|
2045
|
+
const quote = (p) => wrap7(
|
|
1878
2046
|
OP_WITHDRAWALS.quote,
|
|
1879
2047
|
async () => {
|
|
1880
2048
|
const plan = await buildPlan(p);
|
|
@@ -1896,7 +2064,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
1896
2064
|
ctx: { token: p.token, where: "withdrawals.tryQuote" }
|
|
1897
2065
|
}
|
|
1898
2066
|
);
|
|
1899
|
-
const prepare = (p) =>
|
|
2067
|
+
const prepare = (p) => wrap7(OP_WITHDRAWALS.prepare, () => buildPlan(p), {
|
|
1900
2068
|
message: "Internal error while preparing a withdrawal plan.",
|
|
1901
2069
|
ctx: { token: p.token, where: "withdrawals.prepare" }
|
|
1902
2070
|
});
|
|
@@ -1904,7 +2072,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
1904
2072
|
message: "Internal error while preparing a withdrawal plan.",
|
|
1905
2073
|
ctx: { token: p.token, where: "withdrawals.tryPrepare" }
|
|
1906
2074
|
});
|
|
1907
|
-
const create = (p) =>
|
|
2075
|
+
const create = (p) => wrap7(
|
|
1908
2076
|
OP_WITHDRAWALS.create,
|
|
1909
2077
|
async () => {
|
|
1910
2078
|
const plan = await prepare(p);
|
|
@@ -1975,7 +2143,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
1975
2143
|
message: "Internal error while creating withdrawal transactions.",
|
|
1976
2144
|
ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.tryCreate" }
|
|
1977
2145
|
});
|
|
1978
|
-
const status = (h) =>
|
|
2146
|
+
const status = (h) => wrap7(
|
|
1979
2147
|
OP_WITHDRAWALS.status,
|
|
1980
2148
|
async () => {
|
|
1981
2149
|
const l2TxHash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
|
|
@@ -2030,7 +2198,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
2030
2198
|
const wait = (h, opts = {
|
|
2031
2199
|
for: "l2",
|
|
2032
2200
|
pollMs: 5500
|
|
2033
|
-
}) =>
|
|
2201
|
+
}) => wrap7(
|
|
2034
2202
|
OP_WITHDRAWALS.wait,
|
|
2035
2203
|
async () => {
|
|
2036
2204
|
const l2Hash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
|
|
@@ -2095,7 +2263,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
|
|
|
2095
2263
|
}
|
|
2096
2264
|
}
|
|
2097
2265
|
);
|
|
2098
|
-
const finalize = (l2TxHash) =>
|
|
2266
|
+
const finalize = (l2TxHash) => wrap7(
|
|
2099
2267
|
OP_WITHDRAWALS.finalize.send,
|
|
2100
2268
|
async () => {
|
|
2101
2269
|
const pack = await (async () => {
|
|
@@ -2221,9 +2389,11 @@ function createCallAttributes(codec) {
|
|
|
2221
2389
|
function createBundleAttributes(codec) {
|
|
2222
2390
|
const executionAddress = (executor) => codec.encode("executionAddress", [executor]);
|
|
2223
2391
|
const unbundlerAddress = (addr) => codec.encode("unbundlerAddress", [addr]);
|
|
2392
|
+
const useFixedFee = (enabled) => codec.encode("useFixedFee", [enabled]);
|
|
2224
2393
|
return {
|
|
2225
2394
|
executionAddress,
|
|
2226
|
-
unbundlerAddress
|
|
2395
|
+
unbundlerAddress,
|
|
2396
|
+
useFixedFee
|
|
2227
2397
|
};
|
|
2228
2398
|
}
|
|
2229
2399
|
|
|
@@ -2244,6 +2414,7 @@ function getInteropAttributes(params, ctx) {
|
|
|
2244
2414
|
if (params.unbundling?.by) {
|
|
2245
2415
|
bundleAttributes.push(ctx.attributes.bundle.unbundlerAddress(params.unbundling.by));
|
|
2246
2416
|
}
|
|
2417
|
+
bundleAttributes.push(ctx.attributes.bundle.useFixedFee(params.fee?.useFixed ?? false));
|
|
2247
2418
|
const callAttributes = params.actions.map((action) => {
|
|
2248
2419
|
switch (action.type) {
|
|
2249
2420
|
case "sendNative": {
|
|
@@ -2273,11 +2444,6 @@ function createEthersAttributesResource(opts = {}) {
|
|
|
2273
2444
|
}
|
|
2274
2445
|
|
|
2275
2446
|
// src/core/types/flows/interop.ts
|
|
2276
|
-
function isInteropExpectedRoot(obj) {
|
|
2277
|
-
if (typeof obj !== "object" || obj === null) return false;
|
|
2278
|
-
const root = obj;
|
|
2279
|
-
return isBigint(root.rootChainId) && isBigint(root.batchNumber) && isHash(root.expectedRoot);
|
|
2280
|
-
}
|
|
2281
2447
|
function isInteropMessageProof(obj) {
|
|
2282
2448
|
if (typeof obj !== "object" || obj === null) return false;
|
|
2283
2449
|
const proof = obj;
|
|
@@ -2286,7 +2452,7 @@ function isInteropMessageProof(obj) {
|
|
|
2286
2452
|
function isInteropFinalizationInfo(obj) {
|
|
2287
2453
|
if (typeof obj !== "object" || obj === null) return false;
|
|
2288
2454
|
const info = obj;
|
|
2289
|
-
return isHash66(info.l2SrcTxHash) && isHash66(info.bundleHash) && isBigint(info.dstChainId) && isHash(info.encodedData) &&
|
|
2455
|
+
return isHash66(info.l2SrcTxHash) && isHash66(info.bundleHash) && isBigint(info.dstChainId) && isHash(info.encodedData) && isInteropMessageProof(info.proof);
|
|
2290
2456
|
}
|
|
2291
2457
|
|
|
2292
2458
|
// src/core/resources/interop/route.ts
|
|
@@ -2339,7 +2505,7 @@ function preflightDirect(params, ctx) {
|
|
|
2339
2505
|
}
|
|
2340
2506
|
}
|
|
2341
2507
|
}
|
|
2342
|
-
function buildDirectBundle(params, ctx, attrs) {
|
|
2508
|
+
function buildDirectBundle(params, ctx, attrs, interopFeeInfo) {
|
|
2343
2509
|
const totalActionValue = sumActionMsgValue(params.actions);
|
|
2344
2510
|
const starters = params.actions.map((action, index) => {
|
|
2345
2511
|
const to = ctx.codec.formatAddress(action.to);
|
|
@@ -2357,7 +2523,8 @@ function buildDirectBundle(params, ctx, attrs) {
|
|
|
2357
2523
|
dstChain: ctx.codec.formatChain(ctx.dstChainId),
|
|
2358
2524
|
starters,
|
|
2359
2525
|
bundleAttributes: attrs.bundleAttributes,
|
|
2360
|
-
approvals: [],
|
|
2526
|
+
approvals: interopFeeInfo.approval ? [interopFeeInfo.approval] : [],
|
|
2527
|
+
interopFee: interopFeeInfo.fee,
|
|
2361
2528
|
quoteExtras: {
|
|
2362
2529
|
totalActionValue,
|
|
2363
2530
|
bridgedTokenTotal: 0n
|
|
@@ -2402,7 +2569,7 @@ function preflightIndirect(params, ctx) {
|
|
|
2402
2569
|
}
|
|
2403
2570
|
}
|
|
2404
2571
|
}
|
|
2405
|
-
function buildIndirectBundle(params, ctx, attrs, starterData) {
|
|
2572
|
+
function buildIndirectBundle(params, ctx, attrs, starterData, interopFeeInfo) {
|
|
2406
2573
|
const totalActionValue = sumActionMsgValue(params.actions);
|
|
2407
2574
|
const bridgedTokenTotal = sumErc20Amounts(params.actions);
|
|
2408
2575
|
const approvalMap = /* @__PURE__ */ new Map();
|
|
@@ -2421,6 +2588,7 @@ function buildIndirectBundle(params, ctx, attrs, starterData) {
|
|
|
2421
2588
|
}
|
|
2422
2589
|
}
|
|
2423
2590
|
const approvals = Array.from(approvalMap.values());
|
|
2591
|
+
if (interopFeeInfo.approval) approvals.push(interopFeeInfo.approval);
|
|
2424
2592
|
const starters = params.actions.map((action, index) => {
|
|
2425
2593
|
const callAttributes = attrs.callAttributes[index] ?? [];
|
|
2426
2594
|
if (starterData[index]?.assetRouterPayload) {
|
|
@@ -2444,6 +2612,7 @@ function buildIndirectBundle(params, ctx, attrs, starterData) {
|
|
|
2444
2612
|
starters,
|
|
2445
2613
|
bundleAttributes: attrs.bundleAttributes,
|
|
2446
2614
|
approvals,
|
|
2615
|
+
interopFee: interopFeeInfo.fee,
|
|
2447
2616
|
quoteExtras: {
|
|
2448
2617
|
totalActionValue,
|
|
2449
2618
|
bridgedTokenTotal
|
|
@@ -2490,6 +2659,29 @@ function buildEnsureTokenSteps(erc20Tokens, ctx) {
|
|
|
2490
2659
|
}
|
|
2491
2660
|
}));
|
|
2492
2661
|
}
|
|
2662
|
+
async function buildApproveSteps(approvals, ctx) {
|
|
2663
|
+
const steps = [];
|
|
2664
|
+
for (const approval of approvals) {
|
|
2665
|
+
const erc20 = new Contract(approval.token, IERC20_default, ctx.client.l2);
|
|
2666
|
+
const currentAllowance = await erc20.allowance(ctx.sender, approval.spender);
|
|
2667
|
+
if (currentAllowance < approval.amount) {
|
|
2668
|
+
steps.push({
|
|
2669
|
+
key: `approve:${approval.token}:${approval.spender}`,
|
|
2670
|
+
kind: "approve",
|
|
2671
|
+
description: `Approve ${approval.spender} to spend ${approval.amount} of ${approval.token}`,
|
|
2672
|
+
tx: {
|
|
2673
|
+
to: approval.token,
|
|
2674
|
+
data: erc20.interface.encodeFunctionData("approve", [
|
|
2675
|
+
approval.spender,
|
|
2676
|
+
approval.amount
|
|
2677
|
+
]),
|
|
2678
|
+
...ctx.gasOverrides
|
|
2679
|
+
}
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
return steps;
|
|
2684
|
+
}
|
|
2493
2685
|
async function resolveErc20AssetIds(erc20Tokens, ctx) {
|
|
2494
2686
|
const assetIds = /* @__PURE__ */ new Map();
|
|
2495
2687
|
if (erc20Tokens.length === 0) return assetIds;
|
|
@@ -2543,6 +2735,44 @@ async function getStarterData(params, ctx, erc20AssetIds) {
|
|
|
2543
2735
|
}
|
|
2544
2736
|
return starterData;
|
|
2545
2737
|
}
|
|
2738
|
+
var { wrap: wrap2 } = createErrorHandlers("interop");
|
|
2739
|
+
async function buildFeeInfo(params, ctx, numStarters) {
|
|
2740
|
+
const useFixed = params.fee?.useFixed ?? false;
|
|
2741
|
+
const interopCenter = new Contract(ctx.interopCenter, IInteropCenter_default, ctx.client.l2);
|
|
2742
|
+
if (useFixed) {
|
|
2743
|
+
const zkFeePerCall = await wrap2(
|
|
2744
|
+
OP_INTEROP.svc.fees.zkInteropFee,
|
|
2745
|
+
() => interopCenter.ZK_INTEROP_FEE(),
|
|
2746
|
+
{ message: "Failed to fetch ZK interop fee from InteropCenter." }
|
|
2747
|
+
);
|
|
2748
|
+
const zkFeeTotal = zkFeePerCall * BigInt(numStarters);
|
|
2749
|
+
const zkTokenAddress = await wrap2(
|
|
2750
|
+
OP_INTEROP.svc.fees.zkToken,
|
|
2751
|
+
() => interopCenter.zkToken(),
|
|
2752
|
+
{ message: "Failed to fetch ZK token address from InteropCenter." }
|
|
2753
|
+
);
|
|
2754
|
+
const approval = {
|
|
2755
|
+
token: zkTokenAddress,
|
|
2756
|
+
spender: ctx.interopCenter,
|
|
2757
|
+
amount: zkFeeTotal
|
|
2758
|
+
};
|
|
2759
|
+
return {
|
|
2760
|
+
approval,
|
|
2761
|
+
fee: { token: zkTokenAddress, amount: zkFeeTotal }
|
|
2762
|
+
};
|
|
2763
|
+
} else {
|
|
2764
|
+
const protocolFeePerCall = await wrap2(
|
|
2765
|
+
OP_INTEROP.svc.fees.protocolFee,
|
|
2766
|
+
() => interopCenter.interopProtocolFee(),
|
|
2767
|
+
{ message: "Failed to fetch interop protocol fee from InteropCenter." }
|
|
2768
|
+
);
|
|
2769
|
+
const totalFee = protocolFeePerCall * BigInt(numStarters);
|
|
2770
|
+
return {
|
|
2771
|
+
approval: null,
|
|
2772
|
+
fee: { token: ctx.baseTokens.src, amount: totalFee }
|
|
2773
|
+
};
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2546
2776
|
|
|
2547
2777
|
// src/adapters/ethers/resources/interop/routes/indirect.ts
|
|
2548
2778
|
function routeIndirect() {
|
|
@@ -2558,7 +2788,10 @@ function routeIndirect() {
|
|
|
2558
2788
|
async build(params, ctx) {
|
|
2559
2789
|
const steps = [];
|
|
2560
2790
|
const erc20Tokens = getErc20Tokens(params);
|
|
2561
|
-
const erc20AssetIds = await
|
|
2791
|
+
const [erc20AssetIds, feeInfo] = await Promise.all([
|
|
2792
|
+
resolveErc20AssetIds(erc20Tokens, ctx),
|
|
2793
|
+
buildFeeInfo(params, ctx, params.actions.length)
|
|
2794
|
+
]);
|
|
2562
2795
|
const attributes = getInteropAttributes(params, ctx);
|
|
2563
2796
|
const starterData = await getStarterData(params, ctx, erc20AssetIds);
|
|
2564
2797
|
const bundle = buildIndirectBundle(
|
|
@@ -2571,32 +2804,11 @@ function routeIndirect() {
|
|
|
2571
2804
|
codec: interopCodec
|
|
2572
2805
|
},
|
|
2573
2806
|
attributes,
|
|
2574
|
-
starterData
|
|
2807
|
+
starterData,
|
|
2808
|
+
feeInfo
|
|
2575
2809
|
);
|
|
2576
2810
|
steps.push(...buildEnsureTokenSteps(erc20Tokens, ctx));
|
|
2577
|
-
|
|
2578
|
-
const erc20 = new Contract(approval.token, IERC20_default, ctx.client.l2);
|
|
2579
|
-
const currentAllowance = await erc20.allowance(
|
|
2580
|
-
ctx.sender,
|
|
2581
|
-
ctx.l2NativeTokenVault
|
|
2582
|
-
);
|
|
2583
|
-
if (currentAllowance < approval.amount) {
|
|
2584
|
-
const approveData = erc20.interface.encodeFunctionData("approve", [
|
|
2585
|
-
ctx.l2NativeTokenVault,
|
|
2586
|
-
approval.amount
|
|
2587
|
-
]);
|
|
2588
|
-
steps.push({
|
|
2589
|
-
key: `approve:${approval.token}:${ctx.l2NativeTokenVault}`,
|
|
2590
|
-
kind: "approve",
|
|
2591
|
-
description: `Approve ${ctx.l2NativeTokenVault} to spend ${approval.amount} of ${approval.token}`,
|
|
2592
|
-
tx: {
|
|
2593
|
-
to: approval.token,
|
|
2594
|
-
data: approveData,
|
|
2595
|
-
...ctx.gasOverrides
|
|
2596
|
-
}
|
|
2597
|
-
});
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2811
|
+
steps.push(...await buildApproveSteps(bundle.approvals, ctx));
|
|
2600
2812
|
const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
|
|
2601
2813
|
bundle.dstChain,
|
|
2602
2814
|
bundle.starters,
|
|
@@ -2609,14 +2821,15 @@ function routeIndirect() {
|
|
|
2609
2821
|
tx: {
|
|
2610
2822
|
to: ctx.interopCenter,
|
|
2611
2823
|
data,
|
|
2612
|
-
value: bundle.quoteExtras.totalActionValue,
|
|
2824
|
+
value: bundle.quoteExtras.totalActionValue + feeInfo.fee.amount,
|
|
2613
2825
|
...ctx.gasOverrides
|
|
2614
2826
|
}
|
|
2615
2827
|
});
|
|
2616
2828
|
return {
|
|
2617
2829
|
steps,
|
|
2618
2830
|
approvals: bundle.approvals,
|
|
2619
|
-
quoteExtras: bundle.quoteExtras
|
|
2831
|
+
quoteExtras: bundle.quoteExtras,
|
|
2832
|
+
interopFee: feeInfo.fee
|
|
2620
2833
|
};
|
|
2621
2834
|
}
|
|
2622
2835
|
};
|
|
@@ -2633,10 +2846,10 @@ function routeDirect() {
|
|
|
2633
2846
|
l2AssetRouter: ctx.l2AssetRouter,
|
|
2634
2847
|
l2NativeTokenVault: ctx.l2NativeTokenVault});
|
|
2635
2848
|
},
|
|
2636
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
2637
2849
|
async build(params, ctx) {
|
|
2638
2850
|
const steps = [];
|
|
2639
2851
|
const attrs = getInteropAttributes(params, ctx);
|
|
2852
|
+
const feeInfo = await buildFeeInfo(params, ctx, params.actions.length);
|
|
2640
2853
|
const built = buildDirectBundle(
|
|
2641
2854
|
params,
|
|
2642
2855
|
{
|
|
@@ -2646,8 +2859,10 @@ function routeDirect() {
|
|
|
2646
2859
|
l2NativeTokenVault: ctx.l2NativeTokenVault,
|
|
2647
2860
|
codec: interopCodec
|
|
2648
2861
|
},
|
|
2649
|
-
attrs
|
|
2862
|
+
attrs,
|
|
2863
|
+
feeInfo
|
|
2650
2864
|
);
|
|
2865
|
+
steps.push(...await buildApproveSteps(built.approvals, ctx));
|
|
2651
2866
|
const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
|
|
2652
2867
|
built.dstChain,
|
|
2653
2868
|
built.starters,
|
|
@@ -2657,19 +2872,19 @@ function routeDirect() {
|
|
|
2657
2872
|
key: "sendBundle",
|
|
2658
2873
|
kind: "interop.center",
|
|
2659
2874
|
description: `Send interop bundle (direct route; ${params.actions.length} actions)`,
|
|
2660
|
-
//
|
|
2661
|
-
// all calls (sendNative.amount + call.value).
|
|
2875
|
+
// msg.value = forwarded action value + protocol fee.
|
|
2662
2876
|
tx: {
|
|
2663
2877
|
to: ctx.interopCenter,
|
|
2664
2878
|
data,
|
|
2665
|
-
value: built.quoteExtras.totalActionValue,
|
|
2879
|
+
value: built.quoteExtras.totalActionValue + feeInfo.fee.amount,
|
|
2666
2880
|
...ctx.gasOverrides
|
|
2667
2881
|
}
|
|
2668
2882
|
});
|
|
2669
2883
|
return {
|
|
2670
2884
|
steps,
|
|
2671
2885
|
approvals: built.approvals,
|
|
2672
|
-
quoteExtras: built.quoteExtras
|
|
2886
|
+
quoteExtras: built.quoteExtras,
|
|
2887
|
+
interopFee: feeInfo.fee
|
|
2673
2888
|
};
|
|
2674
2889
|
}
|
|
2675
2890
|
};
|
|
@@ -2749,7 +2964,7 @@ function getTopics() {
|
|
|
2749
2964
|
};
|
|
2750
2965
|
return { topics, centerIface };
|
|
2751
2966
|
}
|
|
2752
|
-
var { wrap:
|
|
2967
|
+
var { wrap: wrap3 } = createErrorHandlers("interop");
|
|
2753
2968
|
var DEFAULT_BLOCKS_RANGE_SIZE = 1e4;
|
|
2754
2969
|
var DEFAULT_MAX_BLOCKS_BACK = 2e4;
|
|
2755
2970
|
var SAFE_BLOCKS_RANGE_SIZE = 1e3;
|
|
@@ -2762,7 +2977,7 @@ function parseMaxBlockRangeLimit(error) {
|
|
|
2762
2977
|
return Number.isInteger(limit) && limit > 0 ? limit : null;
|
|
2763
2978
|
}
|
|
2764
2979
|
async function getTxReceipt(provider, txHash) {
|
|
2765
|
-
const receipt = await
|
|
2980
|
+
const receipt = await wrap3(
|
|
2766
2981
|
OP_INTEROP.svc.status.sourceReceipt,
|
|
2767
2982
|
() => provider.getTransactionReceipt(txHash),
|
|
2768
2983
|
{
|
|
@@ -2783,7 +2998,7 @@ async function getTxReceipt(provider, txHash) {
|
|
|
2783
2998
|
async function getLogs(provider, address, topics, opts) {
|
|
2784
2999
|
const maxBlocksBack = opts?.maxBlocksBack ?? DEFAULT_MAX_BLOCKS_BACK;
|
|
2785
3000
|
const initialChunkSize = opts?.logChunkSize ?? DEFAULT_BLOCKS_RANGE_SIZE;
|
|
2786
|
-
return await
|
|
3001
|
+
return await wrap3(
|
|
2787
3002
|
OP_INTEROP.svc.status.dstLogs,
|
|
2788
3003
|
async () => {
|
|
2789
3004
|
const currentBlock = await provider.getBlockNumber();
|
|
@@ -2830,7 +3045,7 @@ async function getLogs(provider, address, topics, opts) {
|
|
|
2830
3045
|
);
|
|
2831
3046
|
}
|
|
2832
3047
|
async function getInteropRoot(provider, rootChainId, batchNumber) {
|
|
2833
|
-
return await
|
|
3048
|
+
return await wrap3(
|
|
2834
3049
|
OP_INTEROP.svc.status.getRoot,
|
|
2835
3050
|
async () => {
|
|
2836
3051
|
const rootStorage = new Contract(
|
|
@@ -2848,7 +3063,7 @@ async function getInteropRoot(provider, rootChainId, batchNumber) {
|
|
|
2848
3063
|
}
|
|
2849
3064
|
|
|
2850
3065
|
// src/adapters/ethers/resources/interop/services/finalization/bundle.ts
|
|
2851
|
-
var { wrap:
|
|
3066
|
+
var { wrap: wrap4 } = createErrorHandlers("interop");
|
|
2852
3067
|
async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
|
|
2853
3068
|
const { interopHandler } = await client.ensureAddresses();
|
|
2854
3069
|
const bundleLogs = await getLogs(dstProvider, interopHandler, [null, bundleHash], opts);
|
|
@@ -2880,7 +3095,7 @@ async function executeBundle(client, dstProvider, info, opts) {
|
|
|
2880
3095
|
context: { bundleHash }
|
|
2881
3096
|
});
|
|
2882
3097
|
}
|
|
2883
|
-
const signer = await
|
|
3098
|
+
const signer = await wrap4(OP_INTEROP.exec.sendStep, () => client.signerFor(dstProvider), {
|
|
2884
3099
|
message: "Failed to resolve destination signer."
|
|
2885
3100
|
});
|
|
2886
3101
|
const { interopHandler } = await client.ensureAddresses();
|
|
@@ -3042,11 +3257,6 @@ function getBundleEncodedData(messageData) {
|
|
|
3042
3257
|
return `0x${messageData.slice(4)}`;
|
|
3043
3258
|
}
|
|
3044
3259
|
function buildFinalizationInfo(ids, bundleInfo, proof, messageData) {
|
|
3045
|
-
const expectedRoot = {
|
|
3046
|
-
rootChainId: bundleInfo.sourceChainId,
|
|
3047
|
-
batchNumber: proof.batchNumber,
|
|
3048
|
-
expectedRoot: proof.root
|
|
3049
|
-
};
|
|
3050
3260
|
const messageProof = {
|
|
3051
3261
|
chainId: bundleInfo.sourceChainId,
|
|
3052
3262
|
l1BatchNumber: proof.batchNumber,
|
|
@@ -3062,7 +3272,6 @@ function buildFinalizationInfo(ids, bundleInfo, proof, messageData) {
|
|
|
3062
3272
|
l2SrcTxHash: ids.l2SrcTxHash,
|
|
3063
3273
|
bundleHash: bundleInfo.bundleHash,
|
|
3064
3274
|
dstChainId: bundleInfo.dstChainId,
|
|
3065
|
-
expectedRoot,
|
|
3066
3275
|
proof: messageProof,
|
|
3067
3276
|
encodedData: getBundleEncodedData(messageData)
|
|
3068
3277
|
};
|
|
@@ -3085,7 +3294,7 @@ function decodeL1MessageData(log) {
|
|
|
3085
3294
|
}
|
|
3086
3295
|
|
|
3087
3296
|
// src/adapters/ethers/resources/interop/services/finalization/polling.ts
|
|
3088
|
-
var { wrap:
|
|
3297
|
+
var { wrap: wrap5 } = createErrorHandlers("interop");
|
|
3089
3298
|
function isProofNotReadyError(error) {
|
|
3090
3299
|
return isZKsyncError(error, {
|
|
3091
3300
|
operation: "zksrpc.getL2ToL1LogProof",
|
|
@@ -3122,30 +3331,26 @@ async function waitForProof(client, l2SrcTxHash, logIndex, blockNumber, pollMs,
|
|
|
3122
3331
|
});
|
|
3123
3332
|
}
|
|
3124
3333
|
try {
|
|
3125
|
-
return await client.zks.getL2ToL1LogProof(l2SrcTxHash, logIndex);
|
|
3334
|
+
return await client.zks.getL2ToL1LogProof(l2SrcTxHash, logIndex, "messageRoot" /* MessageRoot */);
|
|
3126
3335
|
} catch (error) {
|
|
3127
3336
|
if (!isProofNotReadyError(error)) throw error;
|
|
3128
3337
|
}
|
|
3129
3338
|
await sleep(pollMs);
|
|
3130
3339
|
}
|
|
3131
3340
|
}
|
|
3132
|
-
async function waitForRoot(provider,
|
|
3341
|
+
async function waitForRoot(provider, chainId, batchNumber, pollMs, deadline) {
|
|
3133
3342
|
while (true) {
|
|
3134
3343
|
if (Date.now() > deadline) {
|
|
3135
3344
|
throw createError("TIMEOUT", {
|
|
3136
3345
|
resource: "interop",
|
|
3137
3346
|
operation: OP_INTEROP.svc.wait.timeout,
|
|
3138
3347
|
message: "Timed out waiting for interop root to become available.",
|
|
3139
|
-
context: {
|
|
3348
|
+
context: { chainId, batchNumber }
|
|
3140
3349
|
});
|
|
3141
3350
|
}
|
|
3142
3351
|
let interopRoot = null;
|
|
3143
3352
|
try {
|
|
3144
|
-
const root = await getInteropRoot(
|
|
3145
|
-
provider,
|
|
3146
|
-
expectedRoot.rootChainId,
|
|
3147
|
-
expectedRoot.batchNumber
|
|
3148
|
-
);
|
|
3353
|
+
const root = await getInteropRoot(provider, chainId, batchNumber);
|
|
3149
3354
|
if (root !== ZERO_HASH) {
|
|
3150
3355
|
interopRoot = root;
|
|
3151
3356
|
}
|
|
@@ -3154,18 +3359,7 @@ async function waitForRoot(provider, expectedRoot, pollMs, deadline) {
|
|
|
3154
3359
|
interopRoot = null;
|
|
3155
3360
|
}
|
|
3156
3361
|
if (interopRoot) {
|
|
3157
|
-
|
|
3158
|
-
return;
|
|
3159
|
-
}
|
|
3160
|
-
throw createError("STATE", {
|
|
3161
|
-
resource: "interop",
|
|
3162
|
-
operation: OP_INTEROP.wait,
|
|
3163
|
-
message: "Interop root mismatch.",
|
|
3164
|
-
context: {
|
|
3165
|
-
expected: expectedRoot.expectedRoot,
|
|
3166
|
-
got: interopRoot
|
|
3167
|
-
}
|
|
3168
|
-
});
|
|
3362
|
+
return interopRoot;
|
|
3169
3363
|
}
|
|
3170
3364
|
await sleep(pollMs);
|
|
3171
3365
|
}
|
|
@@ -3180,7 +3374,7 @@ async function waitForTxReceipt(client, txHash, pollMs, deadline) {
|
|
|
3180
3374
|
context: { txHash }
|
|
3181
3375
|
});
|
|
3182
3376
|
}
|
|
3183
|
-
const receipt = await
|
|
3377
|
+
const receipt = await wrap5(
|
|
3184
3378
|
OP_INTEROP.svc.status.sourceReceipt,
|
|
3185
3379
|
() => client.zks.getReceiptWithL2ToL1(txHash),
|
|
3186
3380
|
{
|
|
@@ -3194,7 +3388,7 @@ async function waitForTxReceipt(client, txHash, pollMs, deadline) {
|
|
|
3194
3388
|
await sleep(pollMs);
|
|
3195
3389
|
}
|
|
3196
3390
|
}
|
|
3197
|
-
async function waitForFinalization(client, dstProvider, input, opts) {
|
|
3391
|
+
async function waitForFinalization(client, dstProvider, gwProvider, input, opts) {
|
|
3198
3392
|
const { topics, centerIface } = getTopics();
|
|
3199
3393
|
const pollMs = opts?.pollMs ?? DEFAULT_POLL_MS;
|
|
3200
3394
|
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -3243,7 +3437,16 @@ async function waitForFinalization(client, dstProvider, input, opts) {
|
|
|
3243
3437
|
proof,
|
|
3244
3438
|
bundleInfo.l1MessageData
|
|
3245
3439
|
);
|
|
3246
|
-
|
|
3440
|
+
if (proof.gatewayBlockNumber == null) {
|
|
3441
|
+
throw createError("STATE", {
|
|
3442
|
+
resource: "interop",
|
|
3443
|
+
operation: OP_INTEROP.svc.wait.timeout,
|
|
3444
|
+
message: "Proof missing gatewayBlockNumber required for interop finalization.",
|
|
3445
|
+
context: { l2SrcTxHash: ids.l2SrcTxHash }
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
const { chainId: gwChainId } = await gwProvider.getNetwork();
|
|
3449
|
+
await waitForRoot(dstProvider, gwChainId, proof.gatewayBlockNumber, pollMs, deadline);
|
|
3247
3450
|
return finalizationInfo;
|
|
3248
3451
|
}
|
|
3249
3452
|
|
|
@@ -3289,8 +3492,8 @@ function createInteropFinalizationServices(client) {
|
|
|
3289
3492
|
status(dstProvider, input, opts) {
|
|
3290
3493
|
return getStatus(client, dstProvider, input, opts);
|
|
3291
3494
|
},
|
|
3292
|
-
wait(dstProvider, input, opts) {
|
|
3293
|
-
return waitForFinalization(client, dstProvider, input, opts);
|
|
3495
|
+
wait(dstProvider, gwProvider, input, opts) {
|
|
3496
|
+
return waitForFinalization(client, dstProvider, gwProvider, input, opts);
|
|
3294
3497
|
},
|
|
3295
3498
|
async finalize(dstProvider, info, opts) {
|
|
3296
3499
|
const execResult = await executeBundle(client, dstProvider, info, opts);
|
|
@@ -3302,24 +3505,31 @@ function createInteropFinalizationServices(client) {
|
|
|
3302
3505
|
}
|
|
3303
3506
|
};
|
|
3304
3507
|
}
|
|
3305
|
-
function
|
|
3306
|
-
return typeof
|
|
3307
|
-
}
|
|
3308
|
-
function resolveWaitableInput(waitableInput) {
|
|
3309
|
-
const input = waitableInput;
|
|
3310
|
-
return {
|
|
3311
|
-
dstProvider: resolveDstProvider(waitableInput.dstChain),
|
|
3312
|
-
waitable: input.waitable ? input.waitable : waitableInput
|
|
3313
|
-
};
|
|
3508
|
+
function resolveChainRef(ref) {
|
|
3509
|
+
return typeof ref === "string" ? new JsonRpcProvider(ref) : ref;
|
|
3314
3510
|
}
|
|
3315
3511
|
|
|
3316
3512
|
// src/adapters/ethers/resources/interop/index.ts
|
|
3317
|
-
var { wrap:
|
|
3513
|
+
var { wrap: wrap6, toResult: toResult2 } = createErrorHandlers("interop");
|
|
3318
3514
|
var ROUTES3 = {
|
|
3319
3515
|
direct: routeDirect(),
|
|
3320
3516
|
indirect: routeIndirect()
|
|
3321
3517
|
};
|
|
3322
|
-
function createInteropResource(client, tokens, contracts, attributes) {
|
|
3518
|
+
function createInteropResource(client, config, tokens, contracts, attributes) {
|
|
3519
|
+
let gwProviderCache;
|
|
3520
|
+
function requireConfig() {
|
|
3521
|
+
if (!config)
|
|
3522
|
+
throw createError("STATE", {
|
|
3523
|
+
resource: "interop",
|
|
3524
|
+
operation: "interop.init",
|
|
3525
|
+
message: "Interop is not configured. Pass gwChain in createEthersSdk options."
|
|
3526
|
+
});
|
|
3527
|
+
return config;
|
|
3528
|
+
}
|
|
3529
|
+
function getGwProvider() {
|
|
3530
|
+
if (!gwProviderCache) gwProviderCache = resolveChainRef(requireConfig().gwChain);
|
|
3531
|
+
return gwProviderCache;
|
|
3532
|
+
}
|
|
3323
3533
|
const svc = createInteropFinalizationServices(client);
|
|
3324
3534
|
const tokensResource = tokens ?? createTokensResource(client);
|
|
3325
3535
|
const contractsResource = contracts ?? createContractsResource(client);
|
|
@@ -3343,11 +3553,11 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3343
3553
|
baseTokenDst: ctx.baseTokens.dst
|
|
3344
3554
|
}
|
|
3345
3555
|
});
|
|
3346
|
-
await
|
|
3556
|
+
await wrap6(OP_INTEROP.routes[route].preflight, () => ROUTES3[route].preflight?.(params, ctx), {
|
|
3347
3557
|
message: "Interop preflight failed.",
|
|
3348
3558
|
ctx: { where: `routes.${route}.preflight` }
|
|
3349
3559
|
});
|
|
3350
|
-
const { steps, approvals, quoteExtras } = await
|
|
3560
|
+
const { steps, approvals, quoteExtras, interopFee } = await wrap6(
|
|
3351
3561
|
OP_INTEROP.routes[route].build,
|
|
3352
3562
|
() => ROUTES3[route].build(params, ctx),
|
|
3353
3563
|
{
|
|
@@ -3359,7 +3569,8 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3359
3569
|
route,
|
|
3360
3570
|
approvalsNeeded: approvals,
|
|
3361
3571
|
totalActionValue: quoteExtras.totalActionValue,
|
|
3362
|
-
bridgedTokenTotal: quoteExtras.bridgedTokenTotal
|
|
3572
|
+
bridgedTokenTotal: quoteExtras.bridgedTokenTotal,
|
|
3573
|
+
interopFee
|
|
3363
3574
|
};
|
|
3364
3575
|
return { plan: { route, summary, steps }, ctx };
|
|
3365
3576
|
}
|
|
@@ -3367,20 +3578,23 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3367
3578
|
const { plan } = await buildPlanWithCtx(dstProvider, params);
|
|
3368
3579
|
return plan;
|
|
3369
3580
|
}
|
|
3370
|
-
const quote = (params) =>
|
|
3371
|
-
const plan = await buildPlan(
|
|
3581
|
+
const quote = (dstChain, params) => wrap6(OP_INTEROP.quote, async () => {
|
|
3582
|
+
const plan = await buildPlan(resolveChainRef(dstChain), params);
|
|
3372
3583
|
return plan.summary;
|
|
3373
3584
|
});
|
|
3374
|
-
const tryQuote = (params) => toResult2(OP_INTEROP.tryQuote, () => quote(params));
|
|
3375
|
-
const prepare = (params) =>
|
|
3585
|
+
const tryQuote = (dstChain, params) => toResult2(OP_INTEROP.tryQuote, () => quote(dstChain, params));
|
|
3586
|
+
const prepare = (dstChain, params) => wrap6(OP_INTEROP.prepare, () => buildPlan(resolveChainRef(dstChain), params), {
|
|
3376
3587
|
message: "Internal error while preparing an interop plan.",
|
|
3377
3588
|
ctx: { where: "interop.prepare" }
|
|
3378
3589
|
});
|
|
3379
|
-
const tryPrepare = (params) => toResult2(
|
|
3380
|
-
|
|
3590
|
+
const tryPrepare = (dstChain, params) => toResult2(
|
|
3591
|
+
OP_INTEROP.tryPrepare,
|
|
3592
|
+
() => prepare(dstChain, params)
|
|
3593
|
+
);
|
|
3594
|
+
const create = (dstChain, params) => wrap6(
|
|
3381
3595
|
OP_INTEROP.create,
|
|
3382
3596
|
async () => {
|
|
3383
|
-
const { plan, ctx } = await buildPlanWithCtx(
|
|
3597
|
+
const { plan, ctx } = await buildPlanWithCtx(resolveChainRef(dstChain), params);
|
|
3384
3598
|
const signer = ctx.client.signerFor(ctx.client.l2);
|
|
3385
3599
|
const srcProvider = ctx.client.l2;
|
|
3386
3600
|
const from = await signer.getAddress();
|
|
@@ -3442,7 +3656,6 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3442
3656
|
const last = Object.values(stepHashes).pop();
|
|
3443
3657
|
return {
|
|
3444
3658
|
kind: "interop",
|
|
3445
|
-
dstChain: params.dstChain,
|
|
3446
3659
|
stepHashes,
|
|
3447
3660
|
plan,
|
|
3448
3661
|
l2SrcTxHash: last ?? "0x"
|
|
@@ -3453,46 +3666,27 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3453
3666
|
ctx: { where: "interop.create" }
|
|
3454
3667
|
}
|
|
3455
3668
|
);
|
|
3456
|
-
const tryCreate = (params) => toResult2(
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
}
|
|
3463
|
-
};
|
|
3464
|
-
const wait = (h, opts) => {
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
return { ...info, dstChain: h.dstChain };
|
|
3471
|
-
},
|
|
3472
|
-
{
|
|
3473
|
-
message: "Internal error while waiting for interop finalization.",
|
|
3474
|
-
ctx: { where: "interop.wait" }
|
|
3475
|
-
}
|
|
3476
|
-
);
|
|
3477
|
-
};
|
|
3478
|
-
const tryWait = (h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(h, opts));
|
|
3479
|
-
const finalize = (h, opts) => wrap5(
|
|
3669
|
+
const tryCreate = (dstChain, params) => toResult2(
|
|
3670
|
+
OP_INTEROP.tryCreate,
|
|
3671
|
+
() => create(dstChain, params)
|
|
3672
|
+
);
|
|
3673
|
+
const status = (dstChain, h, opts) => wrap6(OP_INTEROP.status, () => svc.status(resolveChainRef(dstChain), h, opts), {
|
|
3674
|
+
message: "Internal error while checking interop status.",
|
|
3675
|
+
ctx: { where: "interop.status" }
|
|
3676
|
+
});
|
|
3677
|
+
const wait = (dstChain, h, opts) => wrap6(OP_INTEROP.wait, () => svc.wait(resolveChainRef(dstChain), getGwProvider(), h, opts), {
|
|
3678
|
+
message: "Internal error while waiting for interop finalization.",
|
|
3679
|
+
ctx: { where: "interop.wait" }
|
|
3680
|
+
});
|
|
3681
|
+
const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
|
|
3682
|
+
const finalize = (dstChain, h, opts) => wrap6(
|
|
3480
3683
|
OP_INTEROP.finalize,
|
|
3481
3684
|
async () => {
|
|
3685
|
+
const dstProvider = resolveChainRef(dstChain);
|
|
3482
3686
|
if (isInteropFinalizationInfo(h)) {
|
|
3483
|
-
|
|
3484
|
-
throw createError("STATE", {
|
|
3485
|
-
resource: "interop",
|
|
3486
|
-
operation: OP_INTEROP.finalize,
|
|
3487
|
-
message: "Missing dstChain in interop finalization info.",
|
|
3488
|
-
context: { input: h }
|
|
3489
|
-
});
|
|
3490
|
-
}
|
|
3491
|
-
const dstProvider2 = resolveDstProvider(h.dstChain);
|
|
3492
|
-
return svc.finalize(dstProvider2, h, opts);
|
|
3687
|
+
return svc.finalize(dstProvider, h, opts);
|
|
3493
3688
|
}
|
|
3494
|
-
const
|
|
3495
|
-
const info = await svc.wait(dstProvider, waitable);
|
|
3689
|
+
const info = await svc.wait(dstProvider, getGwProvider(), h);
|
|
3496
3690
|
return svc.finalize(dstProvider, info, opts);
|
|
3497
3691
|
},
|
|
3498
3692
|
{
|
|
@@ -3500,7 +3694,7 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3500
3694
|
ctx: { where: "interop.finalize" }
|
|
3501
3695
|
}
|
|
3502
3696
|
);
|
|
3503
|
-
const tryFinalize = (h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(h, opts));
|
|
3697
|
+
const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
|
|
3504
3698
|
return {
|
|
3505
3699
|
quote,
|
|
3506
3700
|
tryQuote,
|
|
@@ -3517,10 +3711,10 @@ function createInteropResource(client, tokens, contracts, attributes) {
|
|
|
3517
3711
|
}
|
|
3518
3712
|
|
|
3519
3713
|
// src/adapters/ethers/sdk.ts
|
|
3520
|
-
function createEthersSdk(client) {
|
|
3714
|
+
function createEthersSdk(client, options) {
|
|
3521
3715
|
const tokens = createTokensResource(client);
|
|
3522
3716
|
const contracts = createContractsResource(client);
|
|
3523
|
-
const interop = createInteropResource(client);
|
|
3717
|
+
const interop = createInteropResource(client, options?.interop, tokens, contracts);
|
|
3524
3718
|
return {
|
|
3525
3719
|
deposits: createDepositsResource(client, tokens, contracts),
|
|
3526
3720
|
withdrawals: createWithdrawalsResource(client, tokens, contracts),
|