@matterlabs/zksync-js 0.0.17 → 0.0.19

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,4 +1,4 @@
1
- export { createViemSdk } from '../../chunk-ONCNOWNC.js';
1
+ export { createViemSdk } from '../../chunk-3T5V4HKS.js';
2
2
  import '../../chunk-6LYAENO6.js';
3
3
  import '../../chunk-3HHUZXSV.js';
4
4
  import '../../chunk-SBGBYZJM.js';
@@ -461,15 +461,93 @@ 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
+ var ntvCodec = createNTVCodec({
516
+ encode: (types, values) => encodeAbiParameters(
517
+ types.map((t, i) => ({ type: t, name: `arg${i}` })),
518
+ values
519
+ ),
520
+ keccak256
521
+ });
522
+ async function encodeSecondBridgeErc20DepositCalldata(input) {
523
+ if (!input.ctx.resolvedToken) {
524
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
525
+ }
526
+ const l1ChainId = BigInt(await input.ctx.client.l1.getChainId());
527
+ const expectedL1AssetId = ntvCodec.encodeAssetId(
528
+ l1ChainId,
529
+ L2_NATIVE_TOKEN_VAULT_ADDRESS,
530
+ input.token
531
+ );
532
+ const assetId = input.ctx.resolvedToken.assetId.toLowerCase();
533
+ const isL1Origin = assetId === ZERO_ASSET_ID || assetId === expectedL1AssetId.toLowerCase();
534
+ if (isL1Origin) {
535
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
536
+ }
537
+ const transferData = encodeNativeTokenVaultTransferData(
538
+ input.amount,
539
+ input.receiver,
540
+ input.token
541
+ );
542
+ return encodeSecondBridgeDataV1(input.ctx.resolvedToken.assetId, transferData);
543
+ }
466
544
  async function getPriorityGasModel(input) {
467
545
  try {
468
546
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
469
547
  const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
470
548
  const l1ChainId = BigInt(await input.ctx.client.l1.getChainId());
471
- const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n;
472
- const erc20MetadataOriginChainId = isFirstBridge ? l1ChainId : input.ctx.resolvedToken.originChainId;
549
+ const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID;
550
+ const erc20MetadataOriginChainId = isFirstBridge ? l1ChainId : input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : await l1NativeTokenVault.read.originChainId([input.ctx.resolvedToken.assetId]);
473
551
  const erc20Metadata = await l1NativeTokenVault.read.getERC20Getters([
474
552
  input.token,
475
553
  erc20MetadataOriginChainId
@@ -552,10 +630,15 @@ function routeErc20NonBase() {
552
630
  const secondBridgeCalldata = await wrapAs3(
553
631
  "INTERNAL",
554
632
  OP_DEPOSITS.nonbase.encodeCalldata,
555
- () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
633
+ () => encodeSecondBridgeErc20DepositCalldata({
634
+ ctx,
635
+ token: p.token,
636
+ amount: p.amount,
637
+ receiver
638
+ }),
556
639
  {
557
640
  ctx: {
558
- where: "encodeSecondBridgeErc20Args",
641
+ where: "encodeSecondBridgeErc20DepositCalldata",
559
642
  token: p.token,
560
643
  amount: p.amount.toString()
561
644
  },
@@ -600,15 +683,14 @@ function routeErc20NonBase() {
600
683
  }
601
684
  );
602
685
  if (depositAllowance < p.amount) {
603
- const approveSim = await wrapAs3(
686
+ const approveTx = await wrapAs3(
604
687
  "CONTRACT",
605
688
  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
689
+ () => buildApprovalRequest({
690
+ ctx,
691
+ token: p.token,
692
+ spender: assetRouter,
693
+ amount: p.amount
612
694
  }),
613
695
  {
614
696
  ctx: { where: "l1.simulateContract", to: p.token },
@@ -620,7 +702,7 @@ function routeErc20NonBase() {
620
702
  key: `approve:${p.token}:${assetRouter}`,
621
703
  kind: "approve",
622
704
  description: `Approve deposit token for amount`,
623
- tx: { ...approveSim.request }
705
+ tx: approveTx
624
706
  });
625
707
  }
626
708
  if (!baseIsEth) {
@@ -639,15 +721,14 @@ function routeErc20NonBase() {
639
721
  }
640
722
  );
641
723
  if (baseAllowance < mintValue) {
642
- const approveBaseSim = await wrapAs3(
724
+ const approveBaseTx = await wrapAs3(
643
725
  "CONTRACT",
644
726
  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
727
+ () => buildApprovalRequest({
728
+ ctx,
729
+ token: baseToken,
730
+ spender: assetRouter,
731
+ amount: mintValue
651
732
  }),
652
733
  {
653
734
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -659,7 +740,7 @@ function routeErc20NonBase() {
659
740
  key: `approve:${baseToken}:${assetRouter}`,
660
741
  kind: "approve",
661
742
  description: `Approve base token for mintValue`,
662
- tx: { ...approveBaseSim.request }
743
+ tx: approveBaseTx
663
744
  });
664
745
  }
665
746
  }
@@ -755,19 +836,19 @@ function routeErc20NonBase() {
755
836
  }
756
837
  var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
757
838
  var ZERO_ASSET_ID2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
758
- var ntvCodec = createNTVCodec({
839
+ var ntvCodec2 = createNTVCodec({
759
840
  encode: (types, values) => encodeAbiParameters(
760
841
  types.map((type, index) => ({ type, name: `arg${index}` })),
761
842
  values
762
843
  ),
763
- keccak256
844
+ keccak256: keccak256
764
845
  });
765
846
  async function getPriorityGasModel2(input) {
766
847
  try {
767
848
  const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
768
849
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
769
850
  const originChainId = input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : BigInt(await input.ctx.client.l1.getChainId());
770
- const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
851
+ const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec2.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
771
852
  const erc20Metadata = await l1NativeTokenVault.read.getERC20Getters([
772
853
  ETH_ADDRESS,
773
854
  originChainId
@@ -895,15 +976,14 @@ function routeEthNonBase() {
895
976
  );
896
977
  const needsApprove = allowance < mintValue;
897
978
  if (needsApprove) {
898
- const approveSim = await wrapAs4(
979
+ const approveTx = await wrapAs4(
899
980
  "CONTRACT",
900
981
  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
982
+ () => buildApprovalRequest({
983
+ ctx,
984
+ token: baseToken,
985
+ spender: ctx.l1AssetRouter,
986
+ amount: mintValue
907
987
  }),
908
988
  {
909
989
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -915,7 +995,7 @@ function routeEthNonBase() {
915
995
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
916
996
  kind: "approve",
917
997
  description: `Approve base token for fees (mintValue)`,
918
- tx: { ...approveSim.request }
998
+ tx: approveTx
919
999
  });
920
1000
  }
921
1001
  const secondBridgeCalldata = await wrapAs4(
@@ -1095,15 +1175,14 @@ function routeErc20Base() {
1095
1175
  );
1096
1176
  const needsApprove = allowance < mintValue;
1097
1177
  if (needsApprove) {
1098
- const approveSim = await wrapAs5(
1178
+ const approveTx = await wrapAs5(
1099
1179
  "CONTRACT",
1100
1180
  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
1181
+ () => buildApprovalRequest({
1182
+ ctx,
1183
+ token: baseToken,
1184
+ spender: ctx.l1AssetRouter,
1185
+ amount: mintValue
1107
1186
  }),
1108
1187
  {
1109
1188
  ctx: { where: "l1.simulateContract", to: baseToken },
@@ -1115,7 +1194,7 @@ function routeErc20Base() {
1115
1194
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
1116
1195
  kind: "approve",
1117
1196
  description: "Approve base token for mintValue",
1118
- tx: { ...approveSim.request }
1197
+ tx: approveTx
1119
1198
  });
1120
1199
  }
1121
1200
  const req = buildDirectRequestStruct({
@@ -1287,7 +1366,7 @@ async function waitForL2ExecutionFromL1Tx(l1, l2, l1TxHash) {
1287
1366
  return { l2Receipt, l2TxHash };
1288
1367
  }
1289
1368
  var { wrapAs: wrapAs6 } = createErrorHandlers("tokens");
1290
- var ntvCodec2 = createNTVCodec({
1369
+ var ntvCodec3 = createNTVCodec({
1291
1370
  encode: (types, values) => encodeAbiParameters(
1292
1371
  types.map((t, i) => ({ type: t, name: `arg${i}` })),
1293
1372
  values
@@ -1401,7 +1480,7 @@ function createTokensResource(client) {
1401
1480
  return wrapAs6("CONTRACT", "tokens.isChainEthBased", async () => {
1402
1481
  const baseAssetId = await getBaseTokenAssetId();
1403
1482
  const l1ChainId = await getL1ChainId();
1404
- const ethAssetId = ntvCodec2.encodeAssetId(
1483
+ const ethAssetId = ntvCodec3.encodeAssetId(
1405
1484
  l1ChainId,
1406
1485
  L2_NATIVE_TOKEN_VAULT_ADDRESS,
1407
1486
  ETH_ADDRESS
@@ -456,13 +456,39 @@ 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
+ var ntvCodec = createNTVCodec({
460
+ encode: (types, values) => AbiCoder.defaultAbiCoder().encode(types, values),
461
+ keccak256: (data) => keccak256(data)
462
+ });
463
+ async function encodeSecondBridgeErc20DepositCalldata(input) {
464
+ if (!input.ctx.resolvedToken) {
465
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
466
+ }
467
+ const { chainId } = await input.ctx.client.l1.getNetwork();
468
+ const expectedL1AssetId = ntvCodec.encodeAssetId(
469
+ BigInt(chainId),
470
+ L2_NATIVE_TOKEN_VAULT_ADDRESS,
471
+ input.token
472
+ );
473
+ const assetId = input.ctx.resolvedToken.assetId.toLowerCase();
474
+ const isL1Origin = assetId === ZERO_ASSET_ID || assetId === expectedL1AssetId.toLowerCase();
475
+ if (isL1Origin) {
476
+ return encodeSecondBridgeErc20Args(input.token, input.amount, input.receiver);
477
+ }
478
+ const transferData = encodeNativeTokenVaultTransferData(
479
+ input.amount,
480
+ input.receiver,
481
+ input.token
482
+ );
483
+ return encodeSecondBridgeDataV1(input.ctx.resolvedToken.assetId, transferData);
484
+ }
459
485
  async function getPriorityGasModel(input) {
460
486
  try {
461
487
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
462
488
  const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
463
489
  const { chainId: l1ChainId } = await input.ctx.client.l1.getNetwork();
464
- const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n;
465
- const erc20MetadataOriginChainId = isFirstBridge ? BigInt(l1ChainId) : input.ctx.resolvedToken.originChainId;
490
+ const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID;
491
+ const erc20MetadataOriginChainId = isFirstBridge ? BigInt(l1ChainId) : input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : await l1NativeTokenVault.originChainId(input.ctx.resolvedToken.assetId);
466
492
  const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
467
493
  input.token,
468
494
  erc20MetadataOriginChainId
@@ -528,9 +554,14 @@ function routeErc20NonBase() {
528
554
  const secondBridgeCalldata = await wrapAs2(
529
555
  "INTERNAL",
530
556
  OP_DEPOSITS.nonbase.encodeCalldata,
531
- () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
557
+ () => encodeSecondBridgeErc20DepositCalldata({
558
+ ctx,
559
+ token: p.token,
560
+ amount: p.amount,
561
+ receiver
562
+ }),
532
563
  {
533
- ctx: { where: "encodeSecondBridgeErc20Args" },
564
+ ctx: { where: "encodeSecondBridgeErc20DepositCalldata" },
534
565
  message: "Failed to encode bridging calldata."
535
566
  }
536
567
  );
@@ -667,7 +698,7 @@ function routeErc20NonBase() {
667
698
  var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
668
699
  var ZERO_L2_TOKEN_ADDRESS3 = "0x0000000000000000000000000000000000000000";
669
700
  var ZERO_ASSET_ID2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
670
- var ntvCodec = createNTVCodec({
701
+ var ntvCodec2 = createNTVCodec({
671
702
  encode: (types, values) => AbiCoder.defaultAbiCoder().encode(types, values),
672
703
  keccak256: (data) => keccak256(data)
673
704
  });
@@ -676,7 +707,7 @@ async function getPriorityGasModel2(input) {
676
707
  const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
677
708
  const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
678
709
  const originChainId = input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : BigInt((await input.ctx.client.l1.getNetwork()).chainId);
679
- const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
710
+ const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec2.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
680
711
  const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
681
712
  ETH_ADDRESS,
682
713
  originChainId
@@ -1014,7 +1045,7 @@ function routeErc20Base() {
1014
1045
  }
1015
1046
  var { wrapAs: wrapAs5 } = createErrorHandlers("tokens");
1016
1047
  var abi = AbiCoder.defaultAbiCoder();
1017
- var ntvCodec2 = createNTVCodec({
1048
+ var ntvCodec3 = createNTVCodec({
1018
1049
  encode: (types, values) => abi.encode(types, values),
1019
1050
  keccak256: (data) => ethers.keccak256(data)
1020
1051
  });
@@ -1133,7 +1164,7 @@ function createTokensResource(client) {
1133
1164
  return wrapAs5("CONTRACT", "tokens.isChainEthBased", async () => {
1134
1165
  const baseAssetId = await getBaseTokenAssetId();
1135
1166
  const l1ChainId = await getL1ChainId();
1136
- const ethAssetId = ntvCodec2.encodeAssetId(
1167
+ const ethAssetId = ntvCodec3.encodeAssetId(
1137
1168
  l1ChainId,
1138
1169
  L2_NATIVE_TOKEN_VAULT_ADDRESS,
1139
1170
  ETH_ADDRESS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterlabs/zksync-js",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {
@@ -141,12 +141,14 @@
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",
149
- "test:docs": "bun test docs/snippets --timeout 100000"
151
+ "test:docs": "bun test docs/snippets --timeout 200000"
150
152
  },
151
153
  "sideEffects": false,
152
154
  "type": "module",