@matterlabs/zksync-js 0.0.16 → 0.0.18

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.
@@ -1,5 +1,5 @@
1
- export { createViemSdk } from '../../chunk-3KH5PCD6.js';
2
- import '../../chunk-NLUCYVMX.js';
1
+ export { createViemSdk } from '../../chunk-GBS7KQFU.js';
2
+ import '../../chunk-6LYAENO6.js';
3
3
  import '../../chunk-3HHUZXSV.js';
4
4
  import '../../chunk-SBGBYZJM.js';
5
5
  import '../../chunk-JSBMIT4S.js';
@@ -237,8 +237,8 @@ function buildFeeBreakdown(p) {
237
237
 
238
238
  // src/core/resources/deposits/priority.ts
239
239
  var PRIORITY_TX_ENCODING_STEP_BYTES = 544n;
240
- var DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER = 6n;
241
- var ERAVM_PRIORITY_L2_GAS_BUFFER = 30n;
240
+ var DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER = 7n;
241
+ var PRIORITY_L2_GAS_BUFFER = 40n;
242
242
  var maxBigInt2 = (a, b) => a > b ? a : b;
243
243
  var ceilDiv = (a, b) => (a + b - 1n) / b;
244
244
  function derivePriorityTxGasBreakdown(input) {
@@ -266,10 +266,7 @@ function derivePriorityBodyGasEstimateCap(input) {
266
266
  return input.minBodyGas * (input.multiplier ?? DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER);
267
267
  }
268
268
  function applyPriorityL2GasLimitBuffer(input) {
269
- if (!isEraVmChain(input.chainIdL2)) {
270
- return input.gasLimit;
271
- }
272
- return input.gasLimit * (100n + ERAVM_PRIORITY_L2_GAS_BUFFER) / 100n;
269
+ return input.gasLimit * (100n + PRIORITY_L2_GAS_BUFFER) / 100n;
273
270
  }
274
271
 
275
272
  // src/core/resources/interop/attributes/call.ts
@@ -1,4 +1,4 @@
1
- import { createNTVCodec, resolveCreateDepositL1GasLimit, isInteropFinalizationInfo, DEFAULT_POLL_MS, DEFAULT_TIMEOUT_MS, resolveIdsFromWaitable, parseBundleReceiptInfo, buildFinalizationInfo, parseBundleSentFromReceipt, createAttributesResource, pickInteropRoute, ZERO_HASH, toGasOverrides, applyPriorityL2GasLimitBuffer, buildFeeBreakdown, buildIndirectBundle, preflightIndirect, buildDirectBundle, preflightDirect, derivePriorityTxGasBreakdown, quoteL2Gas, quoteL1Gas, derivePriorityBodyGasEstimateCap, quoteL2Gas2, assertProtocolVersion } from './chunk-NLUCYVMX.js';
1
+ import { createNTVCodec, resolveCreateDepositL1GasLimit, isInteropFinalizationInfo, DEFAULT_POLL_MS, DEFAULT_TIMEOUT_MS, resolveIdsFromWaitable, parseBundleReceiptInfo, buildFinalizationInfo, parseBundleSentFromReceipt, createAttributesResource, pickInteropRoute, ZERO_HASH, toGasOverrides, applyPriorityL2GasLimitBuffer, buildFeeBreakdown, buildIndirectBundle, preflightIndirect, buildDirectBundle, preflightDirect, derivePriorityTxGasBreakdown, quoteL2Gas, quoteL1Gas, derivePriorityBodyGasEstimateCap, quoteL2Gas2, assertProtocolVersion } from './chunk-6LYAENO6.js';
2
2
  import { findL1MessageSentLog, messengerLogIndex, pickWithdrawRoute } from './chunk-3HHUZXSV.js';
3
3
  import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-SBGBYZJM.js';
4
4
  import { isHash66, IL1Nullifier_default, OP_WITHDRAWALS, createError, normalizeL1Token, isAddressEq, hexEq, OP_DEPOSITS, IERC20_default, isZKsyncError, isReceiptNotFound, OP_INTEROP, IInteropHandler_default, IInteropRootStorage_default, IInteropCenter_default, sleep, IERC7786Attributes_default, IBridgehub_default, isETH, normalizeAddrEq, L2NativeTokenVault_default, IL2AssetRouter_default, IBaseToken_default, assertNever } from './chunk-UEKFQAOS.js';
@@ -461,8 +461,73 @@ function routeEthDirect() {
461
461
  }
462
462
  };
463
463
  }
464
+
465
+ // src/adapters/viem/resources/deposits/routes/approval.ts
466
+ function errorText(error) {
467
+ const parts = [];
468
+ let current = error;
469
+ for (let depth = 0; current && depth < 8; depth++) {
470
+ const record = current;
471
+ for (const key of ["name", "shortMessage", "message", "details"]) {
472
+ const value = record[key];
473
+ if (typeof value === "string") parts.push(value);
474
+ }
475
+ current = record.cause;
476
+ }
477
+ return parts.join("\n");
478
+ }
479
+ function isNoReturnApproveSimulationError(error) {
480
+ const text = errorText(error);
481
+ return /approve/i.test(text) && (/returned no data/i.test(text) || /return(?:ed)? data[^\n]*0x/i.test(text) || /0x[^\n]*no data/i.test(text));
482
+ }
483
+ async function buildApprovalRequest({
484
+ ctx,
485
+ token,
486
+ spender,
487
+ amount
488
+ }) {
489
+ try {
490
+ const sim = await ctx.client.l1.simulateContract({
491
+ address: token,
492
+ abi: IERC20_default,
493
+ functionName: "approve",
494
+ args: [spender, amount],
495
+ account: ctx.client.account
496
+ });
497
+ return { ...sim.request };
498
+ } catch (error) {
499
+ if (!isNoReturnApproveSimulationError(error)) {
500
+ throw error;
501
+ }
502
+ return {
503
+ address: token,
504
+ abi: IERC20_default,
505
+ functionName: "approve",
506
+ args: [spender, amount],
507
+ account: ctx.client.account
508
+ };
509
+ }
510
+ }
511
+
512
+ // src/adapters/viem/resources/deposits/routes/erc20-nonbase.ts
464
513
  var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
465
514
  var ZERO_ASSET_ID = "0x0000000000000000000000000000000000000000000000000000000000000000";
515
+ async function encodeSecondBridgeErc20DepositCalldata(input) {
516
+ if (!input.ctx.resolvedToken) {
517
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
518
+ }
519
+ const l1ChainId = BigInt(await input.ctx.client.l1.getChainId());
520
+ const isL1Origin = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n || input.ctx.resolvedToken.originChainId === l1ChainId;
521
+ if (isL1Origin) {
522
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
523
+ }
524
+ const transferData = encodeNativeTokenVaultTransferData(
525
+ input.amount,
526
+ input.receiver,
527
+ input.token
528
+ );
529
+ return encodeSecondBridgeDataV1(input.ctx.resolvedToken.assetId, transferData);
530
+ }
466
531
  async function getPriorityGasModel(input) {
467
532
  try {
468
533
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
@@ -552,10 +617,15 @@ function routeErc20NonBase() {
552
617
  const secondBridgeCalldata = await wrapAs3(
553
618
  "INTERNAL",
554
619
  OP_DEPOSITS.nonbase.encodeCalldata,
555
- () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
620
+ () => encodeSecondBridgeErc20DepositCalldata({
621
+ ctx,
622
+ token: p.token,
623
+ amount: p.amount,
624
+ receiver
625
+ }),
556
626
  {
557
627
  ctx: {
558
- where: "encodeSecondBridgeErc20Args",
628
+ where: "encodeSecondBridgeErc20DepositCalldata",
559
629
  token: p.token,
560
630
  amount: p.amount.toString()
561
631
  },
@@ -600,15 +670,14 @@ function routeErc20NonBase() {
600
670
  }
601
671
  );
602
672
  if (depositAllowance < p.amount) {
603
- const approveSim = await wrapAs3(
673
+ const approveTx = await wrapAs3(
604
674
  "CONTRACT",
605
675
  OP_DEPOSITS.nonbase.estGas,
606
- () => ctx.client.l1.simulateContract({
607
- address: p.token,
608
- abi: IERC20_default,
609
- functionName: "approve",
610
- args: [assetRouter, p.amount],
611
- account: ctx.client.account
676
+ () => buildApprovalRequest({
677
+ ctx,
678
+ token: p.token,
679
+ spender: assetRouter,
680
+ amount: p.amount
612
681
  }),
613
682
  {
614
683
  ctx: { where: "l1.simulateContract", to: p.token },
@@ -620,7 +689,7 @@ function routeErc20NonBase() {
620
689
  key: `approve:${p.token}:${assetRouter}`,
621
690
  kind: "approve",
622
691
  description: `Approve deposit token for amount`,
623
- tx: { ...approveSim.request }
692
+ tx: approveTx
624
693
  });
625
694
  }
626
695
  if (!baseIsEth) {
@@ -639,15 +708,14 @@ function routeErc20NonBase() {
639
708
  }
640
709
  );
641
710
  if (baseAllowance < mintValue) {
642
- const approveBaseSim = await wrapAs3(
711
+ const approveBaseTx = await wrapAs3(
643
712
  "CONTRACT",
644
713
  OP_DEPOSITS.nonbase.estGas,
645
- () => ctx.client.l1.simulateContract({
646
- address: baseToken,
647
- abi: IERC20_default,
648
- functionName: "approve",
649
- args: [assetRouter, mintValue],
650
- account: ctx.client.account
714
+ () => buildApprovalRequest({
715
+ ctx,
716
+ token: baseToken,
717
+ spender: assetRouter,
718
+ amount: mintValue
651
719
  }),
652
720
  {
653
721
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -659,7 +727,7 @@ function routeErc20NonBase() {
659
727
  key: `approve:${baseToken}:${assetRouter}`,
660
728
  kind: "approve",
661
729
  description: `Approve base token for mintValue`,
662
- tx: { ...approveBaseSim.request }
730
+ tx: approveBaseTx
663
731
  });
664
732
  }
665
733
  }
@@ -895,15 +963,14 @@ function routeEthNonBase() {
895
963
  );
896
964
  const needsApprove = allowance < mintValue;
897
965
  if (needsApprove) {
898
- const approveSim = await wrapAs4(
966
+ const approveTx = await wrapAs4(
899
967
  "CONTRACT",
900
968
  OP_DEPOSITS.ethNonBase.estGas,
901
- () => ctx.client.l1.simulateContract({
902
- address: baseToken,
903
- abi: IERC20_default,
904
- functionName: "approve",
905
- args: [ctx.l1AssetRouter, mintValue],
906
- account: ctx.client.account
969
+ () => buildApprovalRequest({
970
+ ctx,
971
+ token: baseToken,
972
+ spender: ctx.l1AssetRouter,
973
+ amount: mintValue
907
974
  }),
908
975
  {
909
976
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -915,7 +982,7 @@ function routeEthNonBase() {
915
982
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
916
983
  kind: "approve",
917
984
  description: `Approve base token for fees (mintValue)`,
918
- tx: { ...approveSim.request }
985
+ tx: approveTx
919
986
  });
920
987
  }
921
988
  const secondBridgeCalldata = await wrapAs4(
@@ -1095,15 +1162,14 @@ function routeErc20Base() {
1095
1162
  );
1096
1163
  const needsApprove = allowance < mintValue;
1097
1164
  if (needsApprove) {
1098
- const approveSim = await wrapAs5(
1165
+ const approveTx = await wrapAs5(
1099
1166
  "CONTRACT",
1100
1167
  OP_DEPOSITS.base.estGas,
1101
- () => ctx.client.l1.simulateContract({
1102
- address: baseToken,
1103
- abi: IERC20_default,
1104
- functionName: "approve",
1105
- args: [ctx.l1AssetRouter, mintValue],
1106
- account: ctx.client.account
1168
+ () => buildApprovalRequest({
1169
+ ctx,
1170
+ token: baseToken,
1171
+ spender: ctx.l1AssetRouter,
1172
+ amount: mintValue
1107
1173
  }),
1108
1174
  {
1109
1175
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -1115,7 +1181,7 @@ function routeErc20Base() {
1115
1181
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
1116
1182
  kind: "approve",
1117
1183
  description: "Approve base token for mintValue",
1118
- tx: { ...approveSim.request }
1184
+ tx: approveTx
1119
1185
  });
1120
1186
  }
1121
1187
  const req = buildDirectRequestStruct({
@@ -3101,7 +3167,6 @@ function routeIndirect() {
3101
3167
  }
3102
3168
  function routeDirect() {
3103
3169
  return {
3104
- // eslint-disable-next-line @typescript-eslint/require-await
3105
3170
  async preflight(params, ctx) {
3106
3171
  preflightDirect(params, {
3107
3172
  dstChainId: ctx.dstChainId,
@@ -3110,6 +3175,17 @@ function routeDirect() {
3110
3175
  l2NativeTokenVault: ctx.l2NativeTokenVault,
3111
3176
  codec: interopCodec
3112
3177
  });
3178
+ for (const action of params.actions) {
3179
+ const bytecode = await ctx.dstPublicClient.getCode({ address: action.to });
3180
+ if (!bytecode || bytecode === "0x") {
3181
+ throw createError("VALIDATION", {
3182
+ resource: "interop",
3183
+ operation: OP_INTEROP.routes.direct.preflight,
3184
+ message: `Destination address ${action.to} is not a contract on the destination chain. The receiver must be a contract that implements the IERC7786Recipient interface (receiveMessage).`,
3185
+ context: { to: action.to, action: action.type }
3186
+ });
3187
+ }
3188
+ }
3113
3189
  },
3114
3190
  async build(params, ctx) {
3115
3191
  const steps = [];
@@ -3352,7 +3428,7 @@ async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
3352
3428
  }
3353
3429
  return { phase: "SENT" };
3354
3430
  }
3355
- async function executeBundle(client, dstProvider, info, opts) {
3431
+ async function executeBundle(client, dstProvider, info, opts, txOverrides) {
3356
3432
  const { topics } = getTopics();
3357
3433
  const { bundleHash, encodedData, proof } = info;
3358
3434
  const dstStatus = await getBundleStatus(client, dstProvider, topics, bundleHash, opts);
@@ -3381,7 +3457,10 @@ async function executeBundle(client, dstProvider, info, opts) {
3381
3457
  functionName: "executeBundle",
3382
3458
  args: [encodedData, proof],
3383
3459
  account: client.account,
3384
- chain: dstProvider.chain ?? null
3460
+ chain: dstProvider.chain ?? null,
3461
+ gas: txOverrides?.gasLimit,
3462
+ maxFeePerGas: txOverrides?.maxFeePerGas,
3463
+ maxPriorityFeePerGas: txOverrides?.maxPriorityFeePerGas
3385
3464
  });
3386
3465
  return {
3387
3466
  hash,
@@ -3706,8 +3785,8 @@ function createInteropFinalizationServices(client) {
3706
3785
  wait(dstProvider, gwProvider, input, opts) {
3707
3786
  return waitForFinalization(client, dstProvider, gwProvider, input, opts);
3708
3787
  },
3709
- async finalize(dstProvider, info, opts) {
3710
- const execResult = await executeBundle(client, dstProvider, info, opts);
3788
+ async finalize(dstProvider, info, opts, txOverrides) {
3789
+ const execResult = await executeBundle(client, dstProvider, info, opts, txOverrides);
3711
3790
  await execResult.wait();
3712
3791
  return {
3713
3792
  bundleHash: info.bundleHash,
@@ -3935,22 +4014,25 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3935
4014
  ctx: { where: "interop.wait" }
3936
4015
  });
3937
4016
  const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
3938
- const finalize = (dstChain, h, opts) => wrap6(
4017
+ const finalize = (dstChain, h, opts, txOverrides) => wrap6(
3939
4018
  OP_INTEROP.finalize,
3940
4019
  async () => {
3941
4020
  const dstProvider = resolveChainRef(dstChain);
3942
4021
  if (isInteropFinalizationInfo(h)) {
3943
- return svc.finalize(dstProvider, h, opts);
4022
+ return svc.finalize(dstProvider, h, opts, txOverrides);
3944
4023
  }
3945
4024
  const info = await svc.wait(dstProvider, getGwProvider(), h);
3946
- return svc.finalize(dstProvider, info, opts);
4025
+ return svc.finalize(dstProvider, info, opts, txOverrides);
3947
4026
  },
3948
4027
  {
3949
4028
  message: "Failed to finalize/execute interop bundle on destination.",
3950
4029
  ctx: { where: "interop.finalize" }
3951
4030
  }
3952
4031
  );
3953
- const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
4032
+ const tryFinalize = (dstChain, h, opts, txOverrides) => toResult2(
4033
+ OP_INTEROP.tryFinalize,
4034
+ () => finalize(dstChain, h, opts, txOverrides)
4035
+ );
3954
4036
  const interopGetRoot = (dstChain, rootChainId, batchNumber) => wrap6(
3955
4037
  OP_INTEROP.svc.status.getRoot,
3956
4038
  () => getInteropRoot(resolveChainRef(dstChain), rootChainId, batchNumber),
@@ -1,5 +1,5 @@
1
1
  import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-NJK325XV.js';
2
- import { createNTVCodec, resolveCreateDepositL1GasLimit, isInteropFinalizationInfo, DEFAULT_POLL_MS, DEFAULT_TIMEOUT_MS, resolveIdsFromWaitable, parseBundleReceiptInfo, buildFinalizationInfo, parseBundleSentFromReceipt, createAttributesResource, pickInteropRoute, ZERO_HASH, toGasOverrides, applyPriorityL2GasLimitBuffer, buildFeeBreakdown, buildIndirectBundle, preflightIndirect, buildDirectBundle, preflightDirect, derivePriorityTxGasBreakdown, quoteL2Gas, quoteL2BaseCost, quoteL1Gas, derivePriorityBodyGasEstimateCap, quoteL2Gas2, assertProtocolVersion } from './chunk-NLUCYVMX.js';
2
+ import { createNTVCodec, resolveCreateDepositL1GasLimit, isInteropFinalizationInfo, DEFAULT_POLL_MS, DEFAULT_TIMEOUT_MS, resolveIdsFromWaitable, parseBundleReceiptInfo, buildFinalizationInfo, parseBundleSentFromReceipt, createAttributesResource, pickInteropRoute, ZERO_HASH, toGasOverrides, applyPriorityL2GasLimitBuffer, buildFeeBreakdown, buildIndirectBundle, preflightIndirect, buildDirectBundle, preflightDirect, derivePriorityTxGasBreakdown, quoteL2Gas, quoteL2BaseCost, quoteL1Gas, derivePriorityBodyGasEstimateCap, quoteL2Gas2, assertProtocolVersion } from './chunk-6LYAENO6.js';
3
3
  import { findL1MessageSentLog, messengerLogIndex, pickWithdrawRoute } from './chunk-3HHUZXSV.js';
4
4
  import { isHash66, IL1Nullifier_default, OP_WITHDRAWALS, createError, normalizeL1Token, isAddressEq, hexEq, OP_DEPOSITS, IERC20_default, isZKsyncError, isReceiptNotFound, OP_INTEROP, IInteropHandler_default, IERC7786Attributes_default, IInteropRootStorage_default, IInteropCenter_default, sleep, isETH, normalizeAddrEq, IL2AssetRouter_default, L2NativeTokenVault_default, assertNever } from './chunk-UEKFQAOS.js';
5
5
  import { ETH_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_INTEROP_ROOT_STORAGE_ADDRESS, BUFFER, SAFE_L1_BRIDGE_GAS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
@@ -456,6 +456,22 @@ function routeEthDirect() {
456
456
  var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
457
457
  var ZERO_L2_TOKEN_ADDRESS2 = "0x0000000000000000000000000000000000000000";
458
458
  var ZERO_ASSET_ID = "0x0000000000000000000000000000000000000000000000000000000000000000";
459
+ async function encodeSecondBridgeErc20DepositCalldata(input) {
460
+ if (!input.ctx.resolvedToken) {
461
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
462
+ }
463
+ const { chainId: l1ChainId } = await input.ctx.client.l1.getNetwork();
464
+ const isL1Origin = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n || input.ctx.resolvedToken.originChainId === BigInt(l1ChainId);
465
+ if (isL1Origin) {
466
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
467
+ }
468
+ const transferData = encodeNativeTokenVaultTransferData(
469
+ input.amount,
470
+ input.receiver,
471
+ input.token
472
+ );
473
+ return encodeSecondBridgeDataV1(input.ctx.resolvedToken.assetId, transferData);
474
+ }
459
475
  async function getPriorityGasModel(input) {
460
476
  try {
461
477
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
@@ -528,9 +544,14 @@ function routeErc20NonBase() {
528
544
  const secondBridgeCalldata = await wrapAs2(
529
545
  "INTERNAL",
530
546
  OP_DEPOSITS.nonbase.encodeCalldata,
531
- () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
547
+ () => encodeSecondBridgeErc20DepositCalldata({
548
+ ctx,
549
+ token: p.token,
550
+ amount: p.amount,
551
+ receiver
552
+ }),
532
553
  {
533
- ctx: { where: "encodeSecondBridgeErc20Args" },
554
+ ctx: { where: "encodeSecondBridgeErc20DepositCalldata" },
534
555
  message: "Failed to encode bridging calldata."
535
556
  }
536
557
  );
@@ -2646,7 +2667,6 @@ function routeIndirect() {
2646
2667
  // src/adapters/ethers/resources/interop/routes/direct.ts
2647
2668
  function routeDirect() {
2648
2669
  return {
2649
- // eslint-disable-next-line @typescript-eslint/require-await
2650
2670
  async preflight(params, ctx) {
2651
2671
  preflightDirect(params, {
2652
2672
  dstChainId: ctx.dstChainId,
@@ -2655,6 +2675,17 @@ function routeDirect() {
2655
2675
  l2NativeTokenVault: ctx.l2NativeTokenVault,
2656
2676
  codec: interopCodec
2657
2677
  });
2678
+ for (const action of params.actions) {
2679
+ const code = await ctx.dstProvider.getCode(action.to);
2680
+ if (!code || code === "0x") {
2681
+ throw createError("VALIDATION", {
2682
+ resource: "interop",
2683
+ operation: OP_INTEROP.routes.direct.preflight,
2684
+ message: `Destination address ${action.to} is not a contract on the destination chain. The receiver must be a contract that implements the IERC7786Recipient interface (receiveMessage).`,
2685
+ context: { to: action.to, action: action.type }
2686
+ });
2687
+ }
2688
+ }
2658
2689
  },
2659
2690
  async build(params, ctx) {
2660
2691
  const steps = [];
@@ -2885,7 +2916,7 @@ async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
2885
2916
  }
2886
2917
  return { phase: "SENT" };
2887
2918
  }
2888
- async function executeBundle(client, dstProvider, info, opts) {
2919
+ async function executeBundle(client, dstProvider, info, opts, txOverrides) {
2889
2920
  const { topics } = getTopics();
2890
2921
  const { bundleHash, encodedData, proof } = info;
2891
2922
  const dstStatus = await getBundleStatus(client, dstProvider, topics, bundleHash, opts);
@@ -2903,7 +2934,11 @@ async function executeBundle(client, dstProvider, info, opts) {
2903
2934
  const { interopHandler } = await client.ensureAddresses();
2904
2935
  const handler = new Contract(interopHandler, IInteropHandler_default, signer);
2905
2936
  try {
2906
- const txResponse = await handler.executeBundle(encodedData, proof);
2937
+ const txResponse = await handler.executeBundle(
2938
+ encodedData,
2939
+ proof,
2940
+ txOverrides ?? {}
2941
+ );
2907
2942
  const hash = txResponse.hash;
2908
2943
  return {
2909
2944
  hash,
@@ -3219,8 +3254,8 @@ function createInteropFinalizationServices(client) {
3219
3254
  wait(dstProvider, gwProvider, input, opts) {
3220
3255
  return waitForFinalization(client, dstProvider, gwProvider, input, opts);
3221
3256
  },
3222
- async finalize(dstProvider, info, opts) {
3223
- const execResult = await executeBundle(client, dstProvider, info, opts);
3257
+ async finalize(dstProvider, info, opts, txOverrides) {
3258
+ const execResult = await executeBundle(client, dstProvider, info, opts, txOverrides);
3224
3259
  await execResult.wait();
3225
3260
  return {
3226
3261
  bundleHash: info.bundleHash,
@@ -3430,22 +3465,25 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3430
3465
  ctx: { where: "interop.wait" }
3431
3466
  });
3432
3467
  const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
3433
- const finalize = (dstChain, h, opts) => wrap6(
3468
+ const finalize = (dstChain, h, opts, txOverrides) => wrap6(
3434
3469
  OP_INTEROP.finalize,
3435
3470
  async () => {
3436
3471
  const dstProvider = resolveChainRef(dstChain);
3437
3472
  if (isInteropFinalizationInfo(h)) {
3438
- return svc.finalize(dstProvider, h, opts);
3473
+ return svc.finalize(dstProvider, h, opts, txOverrides);
3439
3474
  }
3440
3475
  const info = await svc.wait(dstProvider, getGwProvider(), h);
3441
- return svc.finalize(dstProvider, info, opts);
3476
+ return svc.finalize(dstProvider, info, opts, txOverrides);
3442
3477
  },
3443
3478
  {
3444
3479
  message: "Failed to finalize/execute interop bundle on destination.",
3445
3480
  ctx: { where: "interop.finalize" }
3446
3481
  }
3447
3482
  );
3448
- const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
3483
+ const tryFinalize = (dstChain, h, opts, txOverrides) => toResult2(
3484
+ OP_INTEROP.tryFinalize,
3485
+ () => finalize(dstChain, h, opts, txOverrides)
3486
+ );
3449
3487
  const interopGetRoot = (dstChain, rootChainId, batchNumber) => wrap6(
3450
3488
  OP_INTEROP.svc.status.getRoot,
3451
3489
  () => getInteropRoot(resolveChainRef(dstChain), rootChainId, batchNumber),
@@ -8,7 +8,7 @@ export type PriorityTxGasBreakdown = {
8
8
  priorityTxMaxGasLimit: bigint;
9
9
  priorityTxMaxGasLimitExceeded: boolean;
10
10
  };
11
- export declare const DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER = 6n;
11
+ export declare const DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER = 7n;
12
12
  export declare function applyL1ToL2Alias(address: Address): Address;
13
13
  /**
14
14
  * Mirrors the priority-tx floor math used by ZKsync's TransactionValidator.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterlabs/zksync-js",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {
@@ -141,8 +141,10 @@
141
141
  "docs:serve": "mdbook serve docs -p 3000",
142
142
  "docs:build": "mdbook build docs",
143
143
  "test": "bun test",
144
- "test:e2e:ethers": "bun test ./src/adapters/ethers/e2e/*.e2e.ts",
145
- "test:e2e:viem": "bun test ./src/adapters/viem/e2e/*.e2e.ts",
144
+ "test:e2e:ethers": "bun test ./src/adapters/ethers/e2e/*.e2e.ts --path-ignore-patterns='**/interop*'",
145
+ "test:e2e:viem": "bun test ./src/adapters/viem/e2e/*.e2e.ts --path-ignore-patterns='**/interop*'",
146
+ "test:e2e:interop:ethers": "bun test ./src/adapters/ethers/e2e/interop.e2e.ts",
147
+ "test:e2e:interop:viem": "bun test ./src/adapters/viem/e2e/interop.e2e.ts",
146
148
  "test:watch": "bun test --watch",
147
149
  "test:cov": "bun test --coverage",
148
150
  "test:core": "bun test src/core",