@matterlabs/zksync-js 0.0.15 → 0.0.17

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.
Files changed (35) hide show
  1. package/dist/adapters/ethers/client.js +4 -4
  2. package/dist/adapters/ethers/index.cjs +112 -19
  3. package/dist/adapters/ethers/index.cjs.map +1 -1
  4. package/dist/adapters/ethers/index.js +6 -6
  5. package/dist/adapters/ethers/resources/interop/index.d.ts +7 -3
  6. package/dist/adapters/ethers/resources/interop/services/finalization/bundle.d.ts +6 -1
  7. package/dist/adapters/ethers/resources/interop/services/finalization/index.d.ts +2 -1
  8. package/dist/adapters/ethers/sdk.cjs +112 -19
  9. package/dist/adapters/ethers/sdk.cjs.map +1 -1
  10. package/dist/adapters/ethers/sdk.js +5 -5
  11. package/dist/adapters/viem/client.js +4 -4
  12. package/dist/adapters/viem/index.cjs +121 -21
  13. package/dist/adapters/viem/index.cjs.map +1 -1
  14. package/dist/adapters/viem/index.js +6 -6
  15. package/dist/adapters/viem/resources/interop/index.d.ts +7 -3
  16. package/dist/adapters/viem/resources/interop/services/finalization/bundle.d.ts +6 -1
  17. package/dist/adapters/viem/resources/interop/services/finalization/index.d.ts +2 -1
  18. package/dist/adapters/viem/sdk.cjs +121 -21
  19. package/dist/adapters/viem/sdk.cjs.map +1 -1
  20. package/dist/adapters/viem/sdk.js +5 -5
  21. package/dist/{chunk-MZBKM3GH.js → chunk-24TE2NNJ.js} +2 -2
  22. package/dist/{chunk-K2UVKMLN.js → chunk-6LYAENO6.js} +4 -7
  23. package/dist/{chunk-JHRYNLZG.js → chunk-CK5UFAZK.js} +2 -2
  24. package/dist/{chunk-HGB3DOV2.js → chunk-J2RPWU2R.js} +112 -17
  25. package/dist/{chunk-MDPX5LNW.js → chunk-JSBMIT4S.js} +1 -1
  26. package/dist/{chunk-65HAYKVL.js → chunk-NJK325XV.js} +2 -2
  27. package/dist/{chunk-4PZCNTQ3.js → chunk-ONCNOWNC.js} +121 -19
  28. package/dist/{chunk-YIWXIP2M.js → chunk-SBGBYZJM.js} +2 -2
  29. package/dist/{chunk-HVHMLAYH.js → chunk-TYYUG5GA.js} +1 -1
  30. package/dist/{chunk-JXR5V5YK.js → chunk-UEKFQAOS.js} +1 -0
  31. package/dist/core/index.js +2 -2
  32. package/dist/core/resources/deposits/priority.d.ts +1 -1
  33. package/dist/core/types/errors.d.ts +1 -0
  34. package/dist/index.js +2 -2
  35. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
- export { createViemSdk } from '../../chunk-4PZCNTQ3.js';
2
- import '../../chunk-K2UVKMLN.js';
1
+ export { createViemSdk } from '../../chunk-ONCNOWNC.js';
2
+ import '../../chunk-6LYAENO6.js';
3
3
  import '../../chunk-3HHUZXSV.js';
4
- import '../../chunk-YIWXIP2M.js';
5
- import '../../chunk-MDPX5LNW.js';
6
- import '../../chunk-JXR5V5YK.js';
4
+ import '../../chunk-SBGBYZJM.js';
5
+ import '../../chunk-JSBMIT4S.js';
6
+ import '../../chunk-UEKFQAOS.js';
7
7
  import '../../chunk-MT4X5FEO.js';
@@ -1,6 +1,6 @@
1
- import { createErrorHandlers } from './chunk-65HAYKVL.js';
1
+ import { createErrorHandlers } from './chunk-NJK325XV.js';
2
2
  import { makeTransportFromEthers } from './chunk-BWKWWLY4.js';
3
- import { createError, OP_CLIENT, IBridgehub_default, IL1AssetRouter_default, IL1Nullifier_default, L2MessageVerification_default, IInteropHandler_default, IInteropCenter_default, IBaseToken_default, L2NativeTokenVault_default, IL2AssetRouter_default, L1NativeTokenVault_default, OP_DEPOSITS, createZksRpc } from './chunk-JXR5V5YK.js';
3
+ import { createError, OP_CLIENT, IBridgehub_default, IL1AssetRouter_default, IL1Nullifier_default, L2MessageVerification_default, IInteropHandler_default, IInteropCenter_default, IBaseToken_default, L2NativeTokenVault_default, IL2AssetRouter_default, L1NativeTokenVault_default, OP_DEPOSITS, createZksRpc } from './chunk-UEKFQAOS.js';
4
4
  import { L2_ASSET_ROUTER_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_INTEROP_CENTER_ADDRESS, L2_INTEROP_HANDLER_ADDRESS, L2_MESSAGE_VERIFICATION_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
5
5
  import { BrowserProvider, Interface, Contract } from 'ethers';
6
6
 
@@ -1,5 +1,5 @@
1
1
  import { isL1MessageSentLog } from './chunk-3HHUZXSV.js';
2
- import { IBridgehub_default, isHash66, isBigint, isHash, assertNever, createError, OP_INTEROP, isNumber, isAddress, isHash66Array } from './chunk-JXR5V5YK.js';
2
+ import { IBridgehub_default, isHash66, isBigint, isHash, assertNever, createError, OP_INTEROP, isNumber, isAddress, isHash66Array } from './chunk-UEKFQAOS.js';
3
3
  import { BUFFER, DEFAULT_ABI_BYTES, DEFAULT_PUBDATA_BYTES, TX_MEMORY_OVERHEAD_GAS, TX_OVERHEAD_GAS, L1_TX_MIN_L2_GAS_BASE, L1_TX_INTRINSIC_L2_GAS, L1_TX_DELTA_544_ENCODING_BYTES, L1_TX_DELTA_FACTORY_DEPS_L2_GAS, L1_TX_INTRINSIC_PUBDATA, L1_TX_DELTA_FACTORY_DEPS_PUBDATA, TX_SLOT_OVERHEAD_L2_GAS, PRIORITY_TX_MAX_GAS_LIMIT, L2_INTEROP_CENTER_ADDRESS, BUNDLE_IDENTIFIER } from './chunk-MT4X5FEO.js';
4
4
 
5
5
  // src/core/resources/deposits/chains.ts
@@ -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,6 +1,6 @@
1
- import { createErrorHandlers } from './chunk-YIWXIP2M.js';
1
+ import { createErrorHandlers } from './chunk-SBGBYZJM.js';
2
2
  import { makeTransportFromViem } from './chunk-BWKWWLY4.js';
3
- import { OP_CLIENT, IBridgehub_default, IL1AssetRouter_default, IL1Nullifier_default, IBaseToken_default, L2NativeTokenVault_default, IL2AssetRouter_default, L1NativeTokenVault_default, createError, createZksRpc } from './chunk-JXR5V5YK.js';
3
+ import { OP_CLIENT, IBridgehub_default, IL1AssetRouter_default, IL1Nullifier_default, IBaseToken_default, L2NativeTokenVault_default, IL2AssetRouter_default, L1NativeTokenVault_default, createError, createZksRpc } from './chunk-UEKFQAOS.js';
4
4
  import { L2_ASSET_ROUTER_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_INTEROP_CENTER_ADDRESS, L2_INTEROP_HANDLER_ADDRESS, L2_MESSAGE_VERIFICATION_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
5
5
  import { getContract, createWalletClient, custom } from 'viem';
6
6
 
@@ -1,8 +1,8 @@
1
- import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-65HAYKVL.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-K2UVKMLN.js';
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-6LYAENO6.js';
3
3
  import { findL1MessageSentLog, messengerLogIndex, 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, IInteropCenter_default, sleep, isETH, normalizeAddrEq, IInteropRootStorage_default, IL2AssetRouter_default, L2NativeTokenVault_default, assertNever } from './chunk-JXR5V5YK.js';
5
- import { ETH_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, BUFFER, L2_INTEROP_ROOT_STORAGE_ADDRESS, SAFE_L1_BRIDGE_GAS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
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
+ 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';
6
6
  import { Interface, keccak256, AbiCoder, ethers, getBytes, Contract, NonceManager, JsonRpcProvider, getAddress, concat, hexlify, toBeArray, toBeHex, isError } from 'ethers';
7
7
 
8
8
  var I_BRIDGEHUB = new Interface([
@@ -823,7 +823,7 @@ function routeEthNonBase() {
823
823
  const requestStruct = {
824
824
  chainId: ctx.chainIdL2,
825
825
  mintValue,
826
- l2Value: p.amount,
826
+ l2Value: 0n,
827
827
  l2GasLimit: l2GasParams.gasLimit,
828
828
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
829
829
  refundRecipient: ctx.refundRecipient,
@@ -831,6 +831,7 @@ function routeEthNonBase() {
831
831
  secondBridgeValue: p.amount,
832
832
  secondBridgeCalldata
833
833
  };
834
+ const bridgehubValue = p.amount;
834
835
  const bridgehub = await ctx.contracts.bridgehub();
835
836
  const data = bridgehub.interface.encodeFunctionData("requestL2TransactionTwoBridges", [
836
837
  requestStruct
@@ -838,8 +839,7 @@ function routeEthNonBase() {
838
839
  const l1TxCandidate = {
839
840
  to: ctx.bridgehub,
840
841
  data,
841
- value: p.amount,
842
- // base ≠ ETH ⇒ msg.value == secondBridgeValue
842
+ value: bridgehubValue,
843
843
  from: ctx.sender,
844
844
  ...ctx.gasOverrides
845
845
  };
@@ -2646,7 +2646,6 @@ function routeIndirect() {
2646
2646
  // src/adapters/ethers/resources/interop/routes/direct.ts
2647
2647
  function routeDirect() {
2648
2648
  return {
2649
- // eslint-disable-next-line @typescript-eslint/require-await
2650
2649
  async preflight(params, ctx) {
2651
2650
  preflightDirect(params, {
2652
2651
  dstChainId: ctx.dstChainId,
@@ -2655,6 +2654,17 @@ function routeDirect() {
2655
2654
  l2NativeTokenVault: ctx.l2NativeTokenVault,
2656
2655
  codec: interopCodec
2657
2656
  });
2657
+ for (const action of params.actions) {
2658
+ const code = await ctx.dstProvider.getCode(action.to);
2659
+ if (!code || code === "0x") {
2660
+ throw createError("VALIDATION", {
2661
+ resource: "interop",
2662
+ operation: OP_INTEROP.routes.direct.preflight,
2663
+ 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).`,
2664
+ context: { to: action.to, action: action.type }
2665
+ });
2666
+ }
2667
+ }
2658
2668
  },
2659
2669
  async build(params, ctx) {
2660
2670
  const steps = [];
@@ -2885,7 +2895,7 @@ async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
2885
2895
  }
2886
2896
  return { phase: "SENT" };
2887
2897
  }
2888
- async function executeBundle(client, dstProvider, info, opts) {
2898
+ async function executeBundle(client, dstProvider, info, opts, txOverrides) {
2889
2899
  const { topics } = getTopics();
2890
2900
  const { bundleHash, encodedData, proof } = info;
2891
2901
  const dstStatus = await getBundleStatus(client, dstProvider, topics, bundleHash, opts);
@@ -2903,7 +2913,11 @@ async function executeBundle(client, dstProvider, info, opts) {
2903
2913
  const { interopHandler } = await client.ensureAddresses();
2904
2914
  const handler = new Contract(interopHandler, IInteropHandler_default, signer);
2905
2915
  try {
2906
- const txResponse = await handler.executeBundle(encodedData, proof);
2916
+ const txResponse = await handler.executeBundle(
2917
+ encodedData,
2918
+ proof,
2919
+ txOverrides ?? {}
2920
+ );
2907
2921
  const hash = txResponse.hash;
2908
2922
  return {
2909
2923
  hash,
@@ -2946,6 +2960,60 @@ async function executeBundle(client, dstProvider, info, opts) {
2946
2960
  );
2947
2961
  }
2948
2962
  }
2963
+ async function verifyBundle(client, dstProvider, info) {
2964
+ const signer = await wrap4(OP_INTEROP.verify, () => client.signerFor(dstProvider), {
2965
+ message: "Failed to resolve destination signer for verifyBundle."
2966
+ });
2967
+ const { interopHandler } = await client.ensureAddresses();
2968
+ const handler = new Contract(interopHandler, IInteropHandler_default, signer);
2969
+ try {
2970
+ const txResponse = await handler.verifyBundle(
2971
+ info.encodedData,
2972
+ info.proof
2973
+ );
2974
+ const hash = txResponse.hash;
2975
+ return {
2976
+ hash,
2977
+ wait: async () => {
2978
+ try {
2979
+ const receipt = await txResponse.wait();
2980
+ if (!receipt || receipt.status !== 1) {
2981
+ throw createError("EXECUTION", {
2982
+ resource: "interop",
2983
+ operation: OP_INTEROP.verify,
2984
+ message: "Interop bundle verification reverted on destination.",
2985
+ context: { txHash: hash }
2986
+ });
2987
+ }
2988
+ return receipt;
2989
+ } catch (e) {
2990
+ if (isZKsyncError(e)) throw e;
2991
+ throw toZKsyncError(
2992
+ "EXECUTION",
2993
+ {
2994
+ resource: "interop",
2995
+ operation: OP_INTEROP.verify,
2996
+ message: "Failed while waiting for verifyBundle transaction on destination.",
2997
+ context: { txHash: hash }
2998
+ },
2999
+ e
3000
+ );
3001
+ }
3002
+ }
3003
+ };
3004
+ } catch (e) {
3005
+ if (isZKsyncError(e)) throw e;
3006
+ throw toZKsyncError(
3007
+ "EXECUTION",
3008
+ {
3009
+ resource: "interop",
3010
+ operation: OP_INTEROP.verify,
3011
+ message: "Failed to send verifyBundle transaction on destination chain."
3012
+ },
3013
+ e
3014
+ );
3015
+ }
3016
+ }
2949
3017
  function decodeInteropBundleSent(centerIface, log) {
2950
3018
  const decoded = centerIface.decodeEventLog(
2951
3019
  "InteropBundleSent",
@@ -3165,8 +3233,8 @@ function createInteropFinalizationServices(client) {
3165
3233
  wait(dstProvider, gwProvider, input, opts) {
3166
3234
  return waitForFinalization(client, dstProvider, gwProvider, input, opts);
3167
3235
  },
3168
- async finalize(dstProvider, info, opts) {
3169
- const execResult = await executeBundle(client, dstProvider, info, opts);
3236
+ async finalize(dstProvider, info, opts, txOverrides) {
3237
+ const execResult = await executeBundle(client, dstProvider, info, opts, txOverrides);
3170
3238
  await execResult.wait();
3171
3239
  return {
3172
3240
  bundleHash: info.bundleHash,
@@ -3376,22 +3444,47 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3376
3444
  ctx: { where: "interop.wait" }
3377
3445
  });
3378
3446
  const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
3379
- const finalize = (dstChain, h, opts) => wrap6(
3447
+ const finalize = (dstChain, h, opts, txOverrides) => wrap6(
3380
3448
  OP_INTEROP.finalize,
3381
3449
  async () => {
3382
3450
  const dstProvider = resolveChainRef(dstChain);
3383
3451
  if (isInteropFinalizationInfo(h)) {
3384
- return svc.finalize(dstProvider, h, opts);
3452
+ return svc.finalize(dstProvider, h, opts, txOverrides);
3385
3453
  }
3386
3454
  const info = await svc.wait(dstProvider, getGwProvider(), h);
3387
- return svc.finalize(dstProvider, info, opts);
3455
+ return svc.finalize(dstProvider, info, opts, txOverrides);
3388
3456
  },
3389
3457
  {
3390
3458
  message: "Failed to finalize/execute interop bundle on destination.",
3391
3459
  ctx: { where: "interop.finalize" }
3392
3460
  }
3393
3461
  );
3394
- const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
3462
+ const tryFinalize = (dstChain, h, opts, txOverrides) => toResult2(
3463
+ OP_INTEROP.tryFinalize,
3464
+ () => finalize(dstChain, h, opts, txOverrides)
3465
+ );
3466
+ const interopGetRoot = (dstChain, rootChainId, batchNumber) => wrap6(
3467
+ OP_INTEROP.svc.status.getRoot,
3468
+ () => getInteropRoot(resolveChainRef(dstChain), rootChainId, batchNumber),
3469
+ {
3470
+ message: "Failed to get interop root from the destination chain.",
3471
+ ctx: { where: "interop.getInteropRoot" }
3472
+ }
3473
+ );
3474
+ const verifyBundle2 = (dstChain, h) => wrap6(
3475
+ OP_INTEROP.verify,
3476
+ async () => {
3477
+ const dstProvider = resolveChainRef(dstChain);
3478
+ const info = isInteropFinalizationInfo(h) ? h : await svc.wait(dstProvider, getGwProvider(), h);
3479
+ const result = await verifyBundle(client, dstProvider, info);
3480
+ await result.wait();
3481
+ return { bundleHash: info.bundleHash, dstExecTxHash: result.hash };
3482
+ },
3483
+ {
3484
+ message: "Failed to verify interop bundle on destination.",
3485
+ ctx: { where: "interop.verifyBundle" }
3486
+ }
3487
+ );
3395
3488
  return {
3396
3489
  quote,
3397
3490
  tryQuote,
@@ -3403,7 +3496,9 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3403
3496
  wait,
3404
3497
  tryWait,
3405
3498
  finalize,
3406
- tryFinalize
3499
+ tryFinalize,
3500
+ getInteropRoot: interopGetRoot,
3501
+ verifyBundle: verifyBundle2
3407
3502
  };
3408
3503
  }
3409
3504
 
@@ -1,4 +1,4 @@
1
- import { isZKsyncError, createError, shapeCause } from './chunk-JXR5V5YK.js';
1
+ import { isZKsyncError, createError, shapeCause } from './chunk-UEKFQAOS.js';
2
2
 
3
3
  // src/core/errors/error-ops.ts
4
4
  function resolveMessage(op, msg) {
@@ -1,5 +1,5 @@
1
- import { createErrorOps, REVERT_TO_READINESS } from './chunk-MDPX5LNW.js';
2
- import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, IL1ContractErrors_default, IInteropErrors_default } from './chunk-JXR5V5YK.js';
1
+ import { createErrorOps, REVERT_TO_READINESS } from './chunk-JSBMIT4S.js';
2
+ import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, IL1ContractErrors_default, IInteropErrors_default } from './chunk-UEKFQAOS.js';
3
3
  import { Interface } from 'ethers';
4
4
 
5
5
  var ERROR_IFACES = [];
@@ -1,8 +1,8 @@
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-K2UVKMLN.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
- import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-YIWXIP2M.js';
4
- import { isHash66, IL1Nullifier_default, OP_WITHDRAWALS, createError, normalizeL1Token, isAddressEq, hexEq, OP_DEPOSITS, IERC20_default, isZKsyncError, isReceiptNotFound, OP_INTEROP, IInteropHandler_default, IInteropCenter_default, sleep, IERC7786Attributes_default, IBridgehub_default, isETH, normalizeAddrEq, L2NativeTokenVault_default, IL2AssetRouter_default, IBaseToken_default, IInteropRootStorage_default, assertNever } from './chunk-JXR5V5YK.js';
5
- import { ETH_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, L1_MESSENGER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, BUFFER, L2_INTEROP_ROOT_STORAGE_ADDRESS, SAFE_L1_BRIDGE_GAS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS } from './chunk-MT4X5FEO.js';
3
+ import { createErrorHandlers, toZKsyncError, classifyReadinessFromRevert } from './chunk-SBGBYZJM.js';
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';
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';
6
6
  import { keccak256, encodeAbiParameters, toBytes, concat, decodeEventLog, decodeAbiParameters, createWalletClient, custom, encodeFunctionData, createPublicClient, http, encodeEventTopics, numberToHex, zeroAddress, getAddress, toHex } from 'viem';
7
7
 
8
8
  // src/adapters/viem/resources/deposits/context.ts
@@ -934,7 +934,7 @@ function routeEthNonBase() {
934
934
  const requestStruct = {
935
935
  chainId: ctx.chainIdL2,
936
936
  mintValue,
937
- l2Value: p.amount,
937
+ l2Value: 0n,
938
938
  l2GasLimit: l2Gas.gasLimit,
939
939
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
940
940
  refundRecipient: ctx.refundRecipient,
@@ -942,6 +942,7 @@ function routeEthNonBase() {
942
942
  secondBridgeValue: p.amount,
943
943
  secondBridgeCalldata
944
944
  };
945
+ const bridgehubValue = p.amount;
945
946
  let bridgeTx;
946
947
  let calldata;
947
948
  if (needsApprove) {
@@ -950,8 +951,7 @@ function routeEthNonBase() {
950
951
  abi: IBridgehub_default,
951
952
  functionName: "requestL2TransactionTwoBridges",
952
953
  args: [requestStruct],
953
- value: p.amount,
954
- // base ≠ ETH ⇒ msg.value == secondBridgeValue
954
+ value: bridgehubValue,
955
955
  account: ctx.client.account
956
956
  };
957
957
  calldata = encodeFunctionData({
@@ -968,7 +968,7 @@ function routeEthNonBase() {
968
968
  abi: IBridgehub_default,
969
969
  functionName: "requestL2TransactionTwoBridges",
970
970
  args: [requestStruct],
971
- value: p.amount,
971
+ value: bridgehubValue,
972
972
  account: ctx.client.account
973
973
  }),
974
974
  {
@@ -986,7 +986,7 @@ function routeEthNonBase() {
986
986
  const l1TxCandidate = {
987
987
  to: ctx.bridgehub,
988
988
  data: calldata,
989
- value: p.amount,
989
+ value: bridgehubValue,
990
990
  from: ctx.sender,
991
991
  ...ctx.gasOverrides
992
992
  };
@@ -3101,7 +3101,6 @@ function routeIndirect() {
3101
3101
  }
3102
3102
  function routeDirect() {
3103
3103
  return {
3104
- // eslint-disable-next-line @typescript-eslint/require-await
3105
3104
  async preflight(params, ctx) {
3106
3105
  preflightDirect(params, {
3107
3106
  dstChainId: ctx.dstChainId,
@@ -3110,6 +3109,17 @@ function routeDirect() {
3110
3109
  l2NativeTokenVault: ctx.l2NativeTokenVault,
3111
3110
  codec: interopCodec
3112
3111
  });
3112
+ for (const action of params.actions) {
3113
+ const bytecode = await ctx.dstPublicClient.getCode({ address: action.to });
3114
+ if (!bytecode || bytecode === "0x") {
3115
+ throw createError("VALIDATION", {
3116
+ resource: "interop",
3117
+ operation: OP_INTEROP.routes.direct.preflight,
3118
+ 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).`,
3119
+ context: { to: action.to, action: action.type }
3120
+ });
3121
+ }
3122
+ }
3113
3123
  },
3114
3124
  async build(params, ctx) {
3115
3125
  const steps = [];
@@ -3352,7 +3362,7 @@ async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
3352
3362
  }
3353
3363
  return { phase: "SENT" };
3354
3364
  }
3355
- async function executeBundle(client, dstProvider, info, opts) {
3365
+ async function executeBundle(client, dstProvider, info, opts, txOverrides) {
3356
3366
  const { topics } = getTopics();
3357
3367
  const { bundleHash, encodedData, proof } = info;
3358
3368
  const dstStatus = await getBundleStatus(client, dstProvider, topics, bundleHash, opts);
@@ -3381,7 +3391,10 @@ async function executeBundle(client, dstProvider, info, opts) {
3381
3391
  functionName: "executeBundle",
3382
3392
  args: [encodedData, proof],
3383
3393
  account: client.account,
3384
- chain: dstProvider.chain ?? null
3394
+ chain: dstProvider.chain ?? null,
3395
+ gas: txOverrides?.gasLimit,
3396
+ maxFeePerGas: txOverrides?.maxFeePerGas,
3397
+ maxPriorityFeePerGas: txOverrides?.maxPriorityFeePerGas
3385
3398
  });
3386
3399
  return {
3387
3400
  hash,
@@ -3424,6 +3437,68 @@ async function executeBundle(client, dstProvider, info, opts) {
3424
3437
  );
3425
3438
  }
3426
3439
  }
3440
+ async function verifyBundle(client, dstProvider, info) {
3441
+ const { interopHandler } = await client.ensureAddresses();
3442
+ const dstWallet = await wrap4(
3443
+ OP_INTEROP.verify,
3444
+ () => createWalletClient({
3445
+ account: client.account,
3446
+ transport: custom(dstProvider.transport),
3447
+ chain: dstProvider.chain
3448
+ }),
3449
+ { message: "Failed to create destination wallet client for verifyBundle." }
3450
+ );
3451
+ try {
3452
+ const hash = await dstWallet.writeContract({
3453
+ address: interopHandler,
3454
+ abi: IInteropHandler_default,
3455
+ functionName: "verifyBundle",
3456
+ args: [info.encodedData, info.proof],
3457
+ account: client.account,
3458
+ chain: dstProvider.chain ?? null
3459
+ });
3460
+ return {
3461
+ hash,
3462
+ wait: async () => {
3463
+ try {
3464
+ const receipt = await dstProvider.waitForTransactionReceipt({ hash });
3465
+ if (receipt.status === "reverted") {
3466
+ throw createError("EXECUTION", {
3467
+ resource: "interop",
3468
+ operation: OP_INTEROP.verify,
3469
+ message: "Interop bundle verification reverted on destination.",
3470
+ context: { txHash: hash }
3471
+ });
3472
+ }
3473
+ return receipt;
3474
+ } catch (e) {
3475
+ if (isZKsyncError(e)) throw e;
3476
+ throw toZKsyncError(
3477
+ "EXECUTION",
3478
+ {
3479
+ resource: "interop",
3480
+ operation: OP_INTEROP.verify,
3481
+ message: "Failed while waiting for verifyBundle transaction on destination.",
3482
+ context: { txHash: hash }
3483
+ },
3484
+ e
3485
+ );
3486
+ }
3487
+ }
3488
+ };
3489
+ } catch (e) {
3490
+ if (isZKsyncError(e)) throw e;
3491
+ throw toZKsyncError(
3492
+ "EXECUTION",
3493
+ {
3494
+ resource: "interop",
3495
+ operation: OP_INTEROP.verify,
3496
+ message: "Failed to send verifyBundle transaction on destination chain."
3497
+ },
3498
+ e
3499
+ );
3500
+ }
3501
+ }
3427
3502
  function decodeInteropBundleSent(log) {
3428
3503
  const { args } = decodeEventLog({
3429
3504
  abi: IInteropCenter_default,
@@ -3644,8 +3719,8 @@ function createInteropFinalizationServices(client) {
3644
3719
  wait(dstProvider, gwProvider, input, opts) {
3645
3720
  return waitForFinalization(client, dstProvider, gwProvider, input, opts);
3646
3721
  },
3647
- async finalize(dstProvider, info, opts) {
3648
- const execResult = await executeBundle(client, dstProvider, info, opts);
3722
+ async finalize(dstProvider, info, opts, txOverrides) {
3723
+ const execResult = await executeBundle(client, dstProvider, info, opts, txOverrides);
3649
3724
  await execResult.wait();
3650
3725
  return {
3651
3726
  bundleHash: info.bundleHash,
@@ -3873,22 +3948,47 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3873
3948
  ctx: { where: "interop.wait" }
3874
3949
  });
3875
3950
  const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
3876
- const finalize = (dstChain, h, opts) => wrap6(
3951
+ const finalize = (dstChain, h, opts, txOverrides) => wrap6(
3877
3952
  OP_INTEROP.finalize,
3878
3953
  async () => {
3879
3954
  const dstProvider = resolveChainRef(dstChain);
3880
3955
  if (isInteropFinalizationInfo(h)) {
3881
- return svc.finalize(dstProvider, h, opts);
3956
+ return svc.finalize(dstProvider, h, opts, txOverrides);
3882
3957
  }
3883
3958
  const info = await svc.wait(dstProvider, getGwProvider(), h);
3884
- return svc.finalize(dstProvider, info, opts);
3959
+ return svc.finalize(dstProvider, info, opts, txOverrides);
3885
3960
  },
3886
3961
  {
3887
3962
  message: "Failed to finalize/execute interop bundle on destination.",
3888
3963
  ctx: { where: "interop.finalize" }
3889
3964
  }
3890
3965
  );
3891
- const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
3966
+ const tryFinalize = (dstChain, h, opts, txOverrides) => toResult2(
3967
+ OP_INTEROP.tryFinalize,
3968
+ () => finalize(dstChain, h, opts, txOverrides)
3969
+ );
3970
+ const interopGetRoot = (dstChain, rootChainId, batchNumber) => wrap6(
3971
+ OP_INTEROP.svc.status.getRoot,
3972
+ () => getInteropRoot(resolveChainRef(dstChain), rootChainId, batchNumber),
3973
+ {
3974
+ message: "Failed to get interop root from the destination chain.",
3975
+ ctx: { where: "interop.getInteropRoot" }
3976
+ }
3977
+ );
3978
+ const verifyBundle2 = (dstChain, h) => wrap6(
3979
+ OP_INTEROP.verify,
3980
+ async () => {
3981
+ const dstProvider = resolveChainRef(dstChain);
3982
+ const info = isInteropFinalizationInfo(h) ? h : await svc.wait(dstProvider, getGwProvider(), h);
3983
+ const result = await verifyBundle(client, dstProvider, info);
3984
+ await result.wait();
3985
+ return { bundleHash: info.bundleHash, dstExecTxHash: result.hash };
3986
+ },
3987
+ {
3988
+ message: "Failed to verify interop bundle on destination.",
3989
+ ctx: { where: "interop.verifyBundle" }
3990
+ }
3991
+ );
3892
3992
  return {
3893
3993
  quote,
3894
3994
  tryQuote,
@@ -3900,7 +4000,9 @@ function createInteropResource(client, config, tokens, contracts, attributes) {
3900
4000
  wait,
3901
4001
  tryWait,
3902
4002
  finalize,
3903
- tryFinalize
4003
+ tryFinalize,
4004
+ getInteropRoot: interopGetRoot,
4005
+ verifyBundle: verifyBundle2
3904
4006
  };
3905
4007
  }
3906
4008
 
@@ -1,5 +1,5 @@
1
- import { createErrorOps, REVERT_TO_READINESS } from './chunk-MDPX5LNW.js';
2
- import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, IL1ContractErrors_default, IInteropErrors_default } from './chunk-JXR5V5YK.js';
1
+ import { createErrorOps, REVERT_TO_READINESS } from './chunk-JSBMIT4S.js';
2
+ import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, IL1ContractErrors_default, IInteropErrors_default } from './chunk-UEKFQAOS.js';
3
3
  import { decodeErrorResult } from 'viem';
4
4
 
5
5
  var ERROR_ABIS = [];
@@ -1,4 +1,4 @@
1
- import { isETH, normalizeAddrEq } from './chunk-JXR5V5YK.js';
1
+ import { isETH, normalizeAddrEq } from './chunk-UEKFQAOS.js';
2
2
 
3
3
  // src/core/resources/deposits/route.ts
4
4
  async function pickDepositRoute(client, chainIdL2, token) {
@@ -7027,6 +7027,7 @@ var OP_INTEROP = {
7027
7027
  tryWait: "interop.tryWait",
7028
7028
  finalize: "interop.finalize",
7029
7029
  tryFinalize: "interop.tryFinalize",
7030
+ verify: "interop.verify",
7030
7031
  context: {
7031
7032
  chainTypeManager: "interop.chainTypeManager",
7032
7033
  protocolVersion: "interop.protocolVersion"
@@ -1,5 +1,5 @@
1
- export { pickDepositRoute } from '../chunk-HVHMLAYH.js';
1
+ export { pickDepositRoute } from '../chunk-TYYUG5GA.js';
2
2
  export { findL1MessageSentLog, isL1MessageSentLog, messengerLogIndex, pickWithdrawRoute } from '../chunk-3HHUZXSV.js';
3
3
  export { makeTransportFromEthers, makeTransportFromViem } from '../chunk-BWKWWLY4.js';
4
- export { abi_exports as abi, factory_exports as errors, formatEnvelopePretty, hexEq, isAddress, isAddressEq, isETH, isHash, isHash66, isHash66Array, isHashArray, normalizeAddrEq, normalizeL1Token, zks_exports as zksRpc } from '../chunk-JXR5V5YK.js';
4
+ export { abi_exports as abi, factory_exports as errors, formatEnvelopePretty, hexEq, isAddress, isAddressEq, isETH, isHash, isHash66, isHash66Array, isHashArray, normalizeAddrEq, normalizeL1Token, zks_exports as zksRpc } from '../chunk-UEKFQAOS.js';
5
5
  export { ETH_ADDRESS, FORMAL_ETH_ADDRESS, L1_MESSENGER_ADDRESS, L1_SOPH_TOKEN_ADDRESS, L2_ASSET_ROUTER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS } from '../chunk-MT4X5FEO.js';
@@ -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.
@@ -194,6 +194,7 @@ export declare const OP_INTEROP: {
194
194
  readonly tryWait: "interop.tryWait";
195
195
  readonly finalize: "interop.finalize";
196
196
  readonly tryFinalize: "interop.tryFinalize";
197
+ readonly verify: "interop.verify";
197
198
  readonly context: {
198
199
  readonly chainTypeManager: "interop.chainTypeManager";
199
200
  readonly protocolVersion: "interop.protocolVersion";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { pickDepositRoute } from './chunk-HVHMLAYH.js';
1
+ export { pickDepositRoute } from './chunk-TYYUG5GA.js';
2
2
  export { findL1MessageSentLog, isL1MessageSentLog, messengerLogIndex, pickWithdrawRoute } from './chunk-3HHUZXSV.js';
3
3
  export { makeTransportFromEthers, makeTransportFromViem } from './chunk-BWKWWLY4.js';
4
- export { abi_exports as abi, factory_exports as errors, formatEnvelopePretty, hexEq, isAddress, isAddressEq, isETH, isHash, isHash66, isHash66Array, isHashArray, normalizeAddrEq, normalizeL1Token, zks_exports as zksRpc } from './chunk-JXR5V5YK.js';
4
+ export { abi_exports as abi, factory_exports as errors, formatEnvelopePretty, hexEq, isAddress, isAddressEq, isETH, isHash, isHash66, isHash66Array, isHashArray, normalizeAddrEq, normalizeL1Token, zks_exports as zksRpc } from './chunk-UEKFQAOS.js';
5
5
  export { constants_exports as constants } from './chunk-MT4X5FEO.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterlabs/zksync-js",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {