@matterlabs/zksync-js 0.0.1 → 0.0.3

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 (103) hide show
  1. package/README.md +12 -12
  2. package/dist/adapters/ethers/client.cjs +642 -1
  3. package/dist/adapters/ethers/client.cjs.map +1 -1
  4. package/dist/adapters/ethers/client.js +6 -5
  5. package/dist/adapters/ethers/estimator.d.ts +4 -0
  6. package/dist/adapters/ethers/index.cjs +1279 -925
  7. package/dist/adapters/ethers/index.cjs.map +1 -1
  8. package/dist/adapters/ethers/index.d.ts +1 -0
  9. package/dist/adapters/ethers/index.js +9 -8
  10. package/dist/adapters/ethers/resources/contracts/contracts.d.ts +9 -0
  11. package/dist/adapters/ethers/resources/contracts/index.d.ts +2 -0
  12. package/dist/adapters/ethers/resources/contracts/types.d.ts +60 -0
  13. package/dist/adapters/ethers/resources/deposits/context.d.ts +21 -7
  14. package/dist/adapters/ethers/resources/deposits/index.d.ts +3 -1
  15. package/dist/adapters/ethers/resources/deposits/routes/types.d.ts +2 -6
  16. package/dist/adapters/ethers/resources/deposits/services/fee.d.ts +6 -0
  17. package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +41 -0
  18. package/dist/adapters/ethers/resources/tokens/index.d.ts +1 -0
  19. package/dist/adapters/ethers/resources/tokens/tokens.d.ts +10 -0
  20. package/dist/adapters/ethers/resources/utils.d.ts +3 -17
  21. package/dist/adapters/ethers/resources/withdrawals/context.d.ts +15 -7
  22. package/dist/adapters/ethers/resources/withdrawals/index.d.ts +3 -1
  23. package/dist/adapters/ethers/resources/withdrawals/routes/types.d.ts +2 -2
  24. package/dist/adapters/ethers/resources/withdrawals/services/fees.d.ts +14 -0
  25. package/dist/adapters/ethers/resources/withdrawals/services/gas.d.ts +12 -0
  26. package/dist/adapters/ethers/sdk.cjs +1388 -1501
  27. package/dist/adapters/ethers/sdk.cjs.map +1 -1
  28. package/dist/adapters/ethers/sdk.d.ts +5 -22
  29. package/dist/adapters/ethers/sdk.js +7 -6
  30. package/dist/adapters/viem/client.cjs.map +1 -1
  31. package/dist/adapters/viem/client.d.ts +1 -1
  32. package/dist/adapters/viem/client.js +4 -5
  33. package/dist/adapters/viem/estimator.d.ts +4 -0
  34. package/dist/adapters/viem/index.cjs +1233 -744
  35. package/dist/adapters/viem/index.cjs.map +1 -1
  36. package/dist/adapters/viem/index.d.ts +3 -0
  37. package/dist/adapters/viem/index.js +8 -8
  38. package/dist/adapters/viem/resources/contracts/contracts.d.ts +9 -0
  39. package/dist/adapters/viem/resources/contracts/index.d.ts +2 -0
  40. package/dist/adapters/viem/resources/contracts/types.d.ts +61 -0
  41. package/dist/adapters/viem/resources/deposits/context.d.ts +21 -7
  42. package/dist/adapters/viem/resources/deposits/index.d.ts +3 -1
  43. package/dist/adapters/viem/resources/deposits/routes/types.d.ts +2 -6
  44. package/dist/adapters/viem/resources/deposits/services/fee.d.ts +6 -0
  45. package/dist/adapters/viem/resources/deposits/services/gas.d.ts +37 -0
  46. package/dist/adapters/viem/resources/tokens/index.d.ts +1 -0
  47. package/dist/adapters/viem/resources/tokens/tokens.d.ts +3 -0
  48. package/dist/adapters/viem/resources/utils.d.ts +3 -19
  49. package/dist/adapters/viem/resources/withdrawals/context.d.ts +14 -9
  50. package/dist/adapters/viem/resources/withdrawals/index.d.ts +3 -1
  51. package/dist/adapters/viem/resources/withdrawals/routes/types.d.ts +12 -2
  52. package/dist/adapters/viem/resources/withdrawals/services/fee.d.ts +17 -0
  53. package/dist/adapters/viem/resources/withdrawals/services/gas.d.ts +12 -0
  54. package/dist/adapters/viem/sdk.cjs +1225 -699
  55. package/dist/adapters/viem/sdk.cjs.map +1 -1
  56. package/dist/adapters/viem/sdk.d.ts +5 -25
  57. package/dist/adapters/viem/sdk.js +6 -6
  58. package/dist/{chunk-3LALBFFE.js → chunk-3MRGU4HV.js} +9 -5
  59. package/dist/{chunk-CGO27P7F.js → chunk-5YWP4CZP.js} +849 -835
  60. package/dist/{chunk-4HLJJKIY.js → chunk-6K6VJQAL.js} +2 -2
  61. package/dist/{chunk-6GCT6TLS.js → chunk-F2ENUV3A.js} +13 -1
  62. package/dist/{chunk-7M4V3FMT.js → chunk-JXUFGIJG.js} +986 -678
  63. package/dist/chunk-LL3WKCFJ.js +231 -0
  64. package/dist/{chunk-Y75OMFK6.js → chunk-M5J2MM2U.js} +351 -1
  65. package/dist/{chunk-263G6636.js → chunk-NCAIVYBR.js} +1 -14
  66. package/dist/{chunk-DI2CJDPZ.js → chunk-NEC2ZKHI.js} +5 -13
  67. package/dist/chunk-NTEIA5KA.js +13 -0
  68. package/dist/chunk-XRE7H466.js +157 -0
  69. package/dist/{chunk-BD2LUO5T.js → chunk-YUK547UF.js} +3 -3
  70. package/dist/core/abi.d.ts +9 -0
  71. package/dist/core/adapters/interfaces.d.ts +25 -0
  72. package/dist/core/codec/ntv.d.ts +48 -0
  73. package/dist/core/constants.cjs +12 -0
  74. package/dist/core/constants.cjs.map +1 -1
  75. package/dist/core/constants.d.ts +6 -0
  76. package/dist/core/constants.js +1 -1
  77. package/dist/core/index.cjs +4508 -1
  78. package/dist/core/index.cjs.map +1 -1
  79. package/dist/core/index.d.ts +2 -0
  80. package/dist/core/index.js +5 -4
  81. package/dist/core/resources/deposits/fee.d.ts +15 -0
  82. package/dist/core/resources/deposits/gas.d.ts +38 -0
  83. package/dist/core/resources/withdrawals/gas.d.ts +14 -0
  84. package/dist/core/types/errors.d.ts +1 -1
  85. package/dist/core/types/fees.d.ts +40 -0
  86. package/dist/core/types/flows/base.d.ts +0 -10
  87. package/dist/core/types/flows/deposits.d.ts +20 -6
  88. package/dist/core/types/flows/route.d.ts +2 -3
  89. package/dist/core/types/flows/token.d.ts +192 -0
  90. package/dist/core/types/flows/withdrawals.d.ts +12 -6
  91. package/dist/core/utils/addr.d.ts +2 -0
  92. package/dist/index.cjs +4520 -1
  93. package/dist/index.cjs.map +1 -1
  94. package/dist/index.d.ts +2 -0
  95. package/dist/index.js +5 -4
  96. package/package.json +5 -1
  97. package/dist/adapters/ethers/resources/token-info.d.ts +0 -31
  98. package/dist/adapters/ethers/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
  99. package/dist/adapters/viem/resources/token-info.d.ts +0 -34
  100. package/dist/adapters/viem/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
  101. package/dist/chunk-B77GWPO5.js +0 -339
  102. package/dist/core/internal/abi-registry.d.ts +0 -9
  103. package/dist/core/utils/gas.d.ts +0 -13
@@ -223,35 +223,17 @@ var OP_DEPOSITS = {
223
223
  assertErc20Asset: "deposits.erc20-base:assertErc20Asset",
224
224
  assertMatchesBase: "deposits.erc20-base:assertMatchesBase",
225
225
  baseToken: "deposits.erc20-base:baseToken",
226
- allowance: "deposits.erc20-base:allowance",
227
- baseCost: "deposits.erc20-base:l2TransactionBaseCost",
228
- estGas: "deposits.erc20-base:estimateGas"
229
- },
226
+ allowance: "deposits.erc20-base:allowance"},
230
227
  nonbase: {
231
- baseToken: "deposits.erc20-nonbase:baseToken",
232
- assertNotEthAsset: "deposits.erc20-nonbase:assertNotEthAsset",
233
- allowance: "deposits.erc20-nonbase:allowance",
234
- allowanceFees: "deposits.erc20-nonbase:allowanceFeesBaseToken",
235
- baseCost: "deposits.erc20-nonbase:l2TransactionBaseCost",
236
228
  encodeCalldata: "deposits.erc20-nonbase:encodeSecondBridgeErc20Args",
237
- estGas: "deposits.erc20-nonbase:estimateGas",
238
- assertBaseIsEth: "deposits.erc20-nonbase:assertBaseIsEth",
239
- assertBaseIsErc20: "deposits.erc20-nonbase:assertBaseIsErc20",
240
229
  assertNonBaseToken: "deposits.erc20-nonbase:assertNonBaseToken",
241
230
  allowanceToken: "deposits.erc20-nonbase:allowanceToken",
242
231
  allowanceBase: "deposits.erc20-nonbase:allowanceBase"
243
232
  },
244
- eth: {
245
- baseCost: "deposits.eth:l2TransactionBaseCost",
246
- estGas: "deposits.eth:estimateGas"
247
- },
248
233
  ethNonBase: {
249
- baseToken: "deposits.eth-nonbase:baseToken",
250
- baseCost: "deposits.eth-nonbase:l2TransactionBaseCost",
251
234
  allowanceBase: "deposits.eth-nonbase:allowanceBaseToken",
252
235
  ethBalance: "deposits.eth-nonbase:getEthBalance",
253
236
  encodeCalldata: "deposits.eth-nonbase:encodeSecondBridgeEthArgs",
254
- estGas: "deposits.eth-nonbase:estimateGas",
255
237
  assertEthAsset: "deposits.eth-nonbase:assertEthAsset",
256
238
  assertNonEthBase: "deposits.eth-nonbase:assertNonEthBase",
257
239
  assertEthBalance: "deposits.eth-nonbase:assertEthBalance"
@@ -603,8 +585,12 @@ var TOPIC_L1_MESSAGE_SENT_NEW = k256hex("L1MessageSent(uint256,bytes32,bytes)");
603
585
  var TOPIC_L1_MESSAGE_SENT_LEG = k256hex("L1MessageSent(address,bytes32,bytes)");
604
586
  var TOPIC_CANONICAL_ASSIGNED = "0x779f441679936c5441b671969f37400b8c3ed0071cb47444431bf985754560df";
605
587
  var TOPIC_CANONICAL_SUCCESS = "0xe4def01b981193a97a9e81230d7b9f31812ceaf23f864a828a82c687911cb2df";
606
- var L1_FEE_ESTIMATION_COEF_NUMERATOR = 12;
607
- var L1_FEE_ESTIMATION_COEF_DENOMINATOR = 10;
588
+ var BUFFER = 20n;
589
+ var TX_OVERHEAD_GAS = 10000n;
590
+ var TX_MEMORY_OVERHEAD_GAS = 10n;
591
+ var DEFAULT_PUBDATA_BYTES = 155n;
592
+ var DEFAULT_ABI_BYTES = 400n;
593
+ var SAFE_L1_BRIDGE_GAS = 600000n;
608
594
 
609
595
  // src/core/internal/abis/IBridgehub.ts
610
596
  var IBridgehubABI = [
@@ -5094,7 +5080,183 @@ var MailboxABI = [
5094
5080
  ];
5095
5081
  var Mailbox_default = MailboxABI;
5096
5082
 
5083
+ // src/core/errors/withdrawal-revert-map.ts
5084
+ var REVERT_TO_READINESS = {
5085
+ // Already done
5086
+ WithdrawalAlreadyFinalized: { kind: "FINALIZED" },
5087
+ // Temporary — try later
5088
+ BatchNotExecuted: { kind: "NOT_READY", reason: "batch-not-executed" },
5089
+ LocalRootIsZero: { kind: "NOT_READY", reason: "root-missing" },
5090
+ // Permanent — won’t become ready for this tx
5091
+ WrongL2Sender: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5092
+ InvalidSelector: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5093
+ L2WithdrawalMessageWrongLength: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5094
+ WrongMsgLength: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5095
+ TokenNotLegacy: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5096
+ TokenIsLegacy: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5097
+ InvalidProof: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5098
+ InvalidChainId: { kind: "UNFINALIZABLE", reason: "invalid-chain" },
5099
+ NotSettlementLayer: { kind: "UNFINALIZABLE", reason: "settlement-layer" },
5100
+ // Likely environment mismatch — treat as permanent for this tx
5101
+ OnlyEraSupported: { kind: "UNFINALIZABLE", reason: "unsupported" },
5102
+ LocalRootMustBeZero: { kind: "UNFINALIZABLE", reason: "unsupported" }
5103
+ };
5104
+
5105
+ // src/adapters/ethers/errors/revert.ts
5106
+ var ERROR_IFACES = [];
5107
+ var IFACE_ERROR_STRING = new ethers.Interface(["error Error(string)"]);
5108
+ var IFACE_PANIC = new ethers.Interface(["error Panic(uint256)"]);
5109
+ (function bootstrapDefaultIfaces() {
5110
+ try {
5111
+ ERROR_IFACES.push({
5112
+ name: "IL1Nullifier",
5113
+ iface: new ethers.Interface(IL1Nullifier_default)
5114
+ });
5115
+ } catch {
5116
+ }
5117
+ try {
5118
+ ERROR_IFACES.push({ name: "IERC20", iface: new ethers.Interface(IERC20_default) });
5119
+ } catch {
5120
+ }
5121
+ try {
5122
+ ERROR_IFACES.push({
5123
+ name: "IL1NativeTokenVault",
5124
+ iface: new ethers.Interface(L1NativeTokenVault_default)
5125
+ });
5126
+ } catch {
5127
+ }
5128
+ try {
5129
+ ERROR_IFACES.push({
5130
+ name: "IL2NativeTokenVault",
5131
+ iface: new ethers.Interface(L2NativeTokenVault_default)
5132
+ });
5133
+ } catch {
5134
+ }
5135
+ try {
5136
+ ERROR_IFACES.push({ name: "Mailbox", iface: new ethers.Interface(Mailbox_default) });
5137
+ } catch {
5138
+ }
5139
+ })();
5140
+ function registerErrorAbi(name, abi2) {
5141
+ const existing = ERROR_IFACES.findIndex((x) => x.name === name);
5142
+ const entry = { name, iface: new ethers.Interface(abi2) };
5143
+ if (existing >= 0) ERROR_IFACES[existing] = entry;
5144
+ else ERROR_IFACES.push(entry);
5145
+ }
5146
+ function extractRevertData(e) {
5147
+ const maybe = (
5148
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5149
+ e?.data?.data ?? e?.error?.data ?? e?.data ?? e?.error?.error?.data ?? e?.info?.error?.data
5150
+ );
5151
+ if (typeof maybe === "string" && maybe.startsWith("0x") && maybe.length >= 10) {
5152
+ return maybe;
5153
+ }
5154
+ return void 0;
5155
+ }
5156
+ function decodeRevert(e) {
5157
+ const data = extractRevertData(e);
5158
+ if (!data) return;
5159
+ const selector = `0x${data.slice(2, 10)}`;
5160
+ try {
5161
+ const parsed = IFACE_ERROR_STRING.parseError(data);
5162
+ if (parsed?.name === "Error") {
5163
+ const args = parsed.args ? Array.from(parsed.args) : void 0;
5164
+ return { selector, name: "Error", args };
5165
+ }
5166
+ } catch {
5167
+ }
5168
+ try {
5169
+ const parsed = IFACE_PANIC.parseError(data);
5170
+ if (parsed?.name === "Panic") {
5171
+ const args = parsed.args ? Array.from(parsed.args) : void 0;
5172
+ return { selector, name: "Panic", args };
5173
+ }
5174
+ } catch {
5175
+ }
5176
+ for (const { name, iface } of ERROR_IFACES) {
5177
+ try {
5178
+ const parsed = iface.parseError(data);
5179
+ if (parsed) {
5180
+ const args = parsed.args ? Array.from(parsed.args) : void 0;
5181
+ return {
5182
+ selector,
5183
+ name: parsed.name,
5184
+ args,
5185
+ contract: name
5186
+ };
5187
+ }
5188
+ } catch {
5189
+ }
5190
+ }
5191
+ return { selector };
5192
+ }
5193
+ function classifyReadinessFromRevert(e) {
5194
+ const r = decodeRevert(e);
5195
+ const name = r?.name;
5196
+ if (name && REVERT_TO_READINESS[name]) return REVERT_TO_READINESS[name];
5197
+ const msg = (() => {
5198
+ if (typeof e !== "object" || e === null) return "";
5199
+ const obj = e;
5200
+ const maybeMsg = obj["shortMessage"] ?? obj["message"];
5201
+ return typeof maybeMsg === "string" ? maybeMsg : "";
5202
+ })();
5203
+ const lower = String(msg).toLowerCase();
5204
+ if (lower.includes("paused")) return { kind: "NOT_READY", reason: "paused" };
5205
+ if (name || r?.selector) {
5206
+ return { kind: "UNFINALIZABLE", reason: "unsupported", detail: name ?? r?.selector };
5207
+ }
5208
+ return { kind: "NOT_READY", reason: "unknown", detail: lower || void 0 };
5209
+ }
5210
+
5211
+ // src/adapters/ethers/errors/error-ops.ts
5212
+ function toZKsyncError(type, base, err) {
5213
+ if (isZKsyncError(err)) return err;
5214
+ const revert = decodeRevert(err);
5215
+ return createError(type, { ...base, ...revert ? { revert } : {}, cause: shapeCause(err) });
5216
+ }
5217
+ function resolveMessage(op, msg) {
5218
+ if (!msg) return `Error during ${op}.`;
5219
+ return typeof msg === "function" ? msg() : msg;
5220
+ }
5221
+ function createErrorHandlers(resource) {
5222
+ async function run(kind, operation, fn, opts) {
5223
+ try {
5224
+ return await fn();
5225
+ } catch (e) {
5226
+ if (isZKsyncError(e)) throw e;
5227
+ const message = resolveMessage(operation, opts?.message);
5228
+ throw toZKsyncError(kind, { resource, operation, context: opts?.ctx ?? {}, message }, e);
5229
+ }
5230
+ }
5231
+ function wrap2(operation, fn, opts) {
5232
+ return run("INTERNAL", operation, fn, opts);
5233
+ }
5234
+ function wrapAs10(kind, operation, fn, opts) {
5235
+ return run(kind, operation, fn, opts);
5236
+ }
5237
+ async function toResult2(operation, fn, opts) {
5238
+ try {
5239
+ const value = await wrap2(operation, fn, opts);
5240
+ return { ok: true, value };
5241
+ } catch (e) {
5242
+ const shaped = isZKsyncError(e) ? e : toZKsyncError(
5243
+ "INTERNAL",
5244
+ {
5245
+ resource,
5246
+ operation,
5247
+ context: opts?.ctx ?? {},
5248
+ message: resolveMessage(operation, opts?.message)
5249
+ },
5250
+ e
5251
+ );
5252
+ return { ok: false, error: shaped };
5253
+ }
5254
+ }
5255
+ return { wrap: wrap2, wrapAs: wrapAs10, toResult: toResult2 };
5256
+ }
5257
+
5097
5258
  // src/adapters/ethers/client.ts
5259
+ var { wrapAs } = createErrorHandlers("client");
5098
5260
  function createEthersClient(args) {
5099
5261
  const { l1, l2, signer } = args;
5100
5262
  let boundSigner = signer;
@@ -5192,7 +5354,10 @@ function createEthersClient(args) {
5192
5354
  async function baseToken(chainId) {
5193
5355
  const { bridgehub } = await ensureAddresses();
5194
5356
  const bh = new ethers.Contract(bridgehub, IBridgehub_default, l1);
5195
- return await bh.baseToken(chainId);
5357
+ return await wrapAs("CONTRACT", OP_DEPOSITS.base.baseToken, () => bh.baseToken(chainId), {
5358
+ ctx: { where: "bridgehub.baseToken", chainIdL2: chainId },
5359
+ message: "Failed to read base token."
5360
+ });
5196
5361
  }
5197
5362
  const client = {
5198
5363
  kind: "ethers",
@@ -5231,6 +5396,8 @@ function normalizeAddrEq(a, b) {
5231
5396
  };
5232
5397
  return normalize(a) === normalize(b);
5233
5398
  }
5399
+ var hexEq = (a, b) => a.toLowerCase() === b.toLowerCase();
5400
+ var normalizeL1Token = (token) => isAddressEq(token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : token;
5234
5401
 
5235
5402
  // src/adapters/ethers/resources/deposits/services/verification.ts
5236
5403
  var I_BRIDGEHUB = new ethers.Interface([
@@ -5297,119 +5464,66 @@ async function waitForL2ExecutionFromL1Tx(l1, l2, l1TxHash) {
5297
5464
  return { l2Receipt, l2TxHash };
5298
5465
  }
5299
5466
 
5300
- // src/core/utils/gas.ts
5301
- function assertNoLegacyGas(overrides) {
5302
- if (!overrides) return;
5303
- if ("gasPrice" in overrides && overrides.gasPrice !== void 0) {
5304
- throw new Error("Legacy gasPrice is not supported; use EIP-1559 fields instead.");
5305
- }
5306
- }
5307
- function assertPriorityFeeBounds(fees) {
5308
- if (fees.maxPriorityFeePerGas > fees.maxFeePerGas) {
5309
- throw new Error("maxPriorityFeePerGas cannot exceed maxFeePerGas.");
5310
- }
5311
- }
5312
-
5313
- // src/adapters/ethers/resources/utils.ts
5314
- function supportsGetGasPrice(provider) {
5315
- return typeof provider === "object" && provider !== null && typeof provider.getGasPrice === "function";
5316
- }
5317
- function encodeNativeTokenVaultAssetId(chainId, address) {
5318
- const abi = new ethers.AbiCoder();
5319
- const hex = abi.encode(
5320
- ["uint256", "address", "address"],
5321
- [chainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, address]
5322
- );
5323
- return ethers.ethers.keccak256(hex);
5467
+ // src/adapters/ethers/resources/deposits/context.ts
5468
+ async function commonCtx(p, client, tokens, contracts) {
5469
+ const { bridgehub, l1AssetRouter } = await contracts.addresses();
5470
+ const { chainId } = await client.l2.getNetwork();
5471
+ const sender = await client.signer.getAddress();
5472
+ const gasPerPubdata = p.gasPerPubdata ?? 800n;
5473
+ const operatorTip = p.operatorTip ?? 0n;
5474
+ const refundRecipient = p.refundRecipient ?? sender;
5475
+ const resolvedToken = await tokens.resolve(p.token, { chain: "l1" });
5476
+ const baseTokenAssetId = resolvedToken.baseTokenAssetId;
5477
+ const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
5478
+ const baseIsEth = resolvedToken.isChainEthBased;
5479
+ const route = (() => {
5480
+ if (resolvedToken.kind === "eth") {
5481
+ return baseIsEth ? "eth-base" : "eth-nonbase";
5482
+ }
5483
+ if (resolvedToken.kind === "base") {
5484
+ return baseIsEth ? "eth-base" : "erc20-base";
5485
+ }
5486
+ return "erc20-nonbase";
5487
+ })();
5488
+ return {
5489
+ client,
5490
+ tokens,
5491
+ contracts,
5492
+ resolvedToken,
5493
+ baseTokenAssetId,
5494
+ baseTokenL1,
5495
+ baseIsEth,
5496
+ l1AssetRouter,
5497
+ route,
5498
+ bridgehub,
5499
+ chainIdL2: BigInt(chainId),
5500
+ sender,
5501
+ gasOverrides: p.l1TxOverrides,
5502
+ l2GasLimit: p.l2GasLimit,
5503
+ gasPerPubdata,
5504
+ operatorTip,
5505
+ refundRecipient
5506
+ };
5324
5507
  }
5325
5508
  function encodeNativeTokenVaultTransferData(amount, receiver, token) {
5326
5509
  return new ethers.AbiCoder().encode(["uint256", "address", "address"], [amount, receiver, token]);
5327
5510
  }
5328
5511
  function encodeSecondBridgeDataV1(assetId, transferData) {
5329
- const abi = new ethers.AbiCoder();
5330
- const data = abi.encode(["bytes32", "bytes"], [assetId, transferData]);
5512
+ const abi2 = new ethers.AbiCoder();
5513
+ const data = abi2.encode(["bytes32", "bytes"], [assetId, transferData]);
5331
5514
  return ethers.ethers.concat(["0x01", data]);
5332
5515
  }
5333
- function encodeNTVAssetId(chainId, address) {
5334
- const abi = new ethers.AbiCoder();
5335
- const hex = abi.encode(
5336
- ["uint256", "address", "address"],
5337
- [chainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, address]
5516
+ function encodeSecondBridgeArgs(token, amount, l2Receiver) {
5517
+ return ethers.AbiCoder.defaultAbiCoder().encode(
5518
+ ["address", "uint256", "address"],
5519
+ [token, amount, l2Receiver]
5338
5520
  );
5339
- return ethers.ethers.keccak256(hex);
5340
5521
  }
5341
- function encodeNTVTransferData(amount, receiver, token) {
5342
- return new ethers.AbiCoder().encode(["uint256", "address", "address"], [amount, receiver, token]);
5343
- }
5344
- function scaleGasLimit(gasLimit) {
5345
- return gasLimit * BigInt(L1_FEE_ESTIMATION_COEF_NUMERATOR) / BigInt(L1_FEE_ESTIMATION_COEF_DENOMINATOR);
5346
- }
5347
- async function checkBaseCost(baseCost, value) {
5348
- const resolvedValue = await value;
5349
- if (baseCost > resolvedValue) {
5350
- throw new Error(
5351
- `The base cost of performing the priority operation is higher than the provided value parameter for the transaction: baseCost: ${String(baseCost)}, provided value: ${String(resolvedValue)}!`
5352
- );
5353
- }
5354
- }
5355
- async function getFeeOverrides(client, overrides) {
5356
- assertNoLegacyGas(overrides);
5357
- const fd = await client.l1.getFeeData();
5358
- const maxFeeFromProvider = fd.maxFeePerGas ?? void 0;
5359
- const maxPriorityFromProvider = fd.maxPriorityFeePerGas ?? void 0;
5360
- const gasPriceFallback = fd.gasPrice ?? void 0;
5361
- const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback;
5362
- if (maxFeePerGas == null) throw new Error("provider returned no gas price data");
5363
- const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
5364
- assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
5365
- const gasPriceForBaseCost = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback ?? maxFeePerGas;
5366
- return {
5367
- gasLimit: overrides?.gasLimit,
5368
- maxFeePerGas,
5369
- maxPriorityFeePerGas,
5370
- gasPriceForBaseCost
5371
- };
5372
- }
5373
- async function getL2FeeOverrides(client, overrides) {
5374
- assertNoLegacyGas(overrides);
5375
- let maxFeeFromProvider;
5376
- let maxPriorityFromProvider;
5377
- let gasPriceFallback;
5378
- try {
5379
- const fd = await client.l2.getFeeData();
5380
- if (fd?.maxFeePerGas != null) maxFeeFromProvider = fd.maxFeePerGas;
5381
- if (fd?.maxPriorityFeePerGas != null) {
5382
- maxPriorityFromProvider = fd.maxPriorityFeePerGas;
5383
- }
5384
- if (fd?.gasPrice != null) gasPriceFallback = fd.gasPrice;
5385
- } catch {
5386
- }
5387
- if (gasPriceFallback == null) {
5388
- try {
5389
- if (supportsGetGasPrice(client.l2)) {
5390
- const gp = await client.l2.getGasPrice();
5391
- gasPriceFallback = typeof gp === "bigint" ? gp : BigInt(gp.toString());
5392
- }
5393
- } catch {
5394
- }
5395
- }
5396
- const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback;
5397
- if (maxFeePerGas == null) {
5398
- throw new Error("L2 provider returned no gas price data");
5399
- }
5400
- const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
5401
- assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
5402
- return {
5403
- gasLimit: overrides?.gasLimit,
5404
- maxFeePerGas,
5405
- maxPriorityFeePerGas
5406
- };
5522
+ function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
5523
+ return encodeSecondBridgeArgs(token, amount, l2Receiver);
5407
5524
  }
5408
- async function getGasPriceWei(client) {
5409
- const fd = await client.l1.getFeeData();
5410
- if (fd.gasPrice != null) return fd.gasPrice;
5411
- if (fd.maxFeePerGas != null) return fd.maxFeePerGas;
5412
- throw new Error("provider returned no gas price data");
5525
+ function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
5526
+ return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
5413
5527
  }
5414
5528
  function buildDirectRequestStruct(args) {
5415
5529
  return {
@@ -5424,389 +5538,465 @@ function buildDirectRequestStruct(args) {
5424
5538
  refundRecipient: args.refundRecipient
5425
5539
  };
5426
5540
  }
5427
- function encodeSecondBridgeArgs(token, amount, l2Receiver) {
5428
- return ethers.AbiCoder.defaultAbiCoder().encode(
5429
- ["address", "uint256", "address"],
5430
- [token, amount, l2Receiver]
5431
- );
5432
- }
5433
- function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
5434
- return encodeSecondBridgeArgs(token, amount, l2Receiver);
5435
- }
5436
- function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
5437
- return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
5438
- }
5439
-
5440
- // src/core/resources/deposits/route.ts
5441
- async function pickDepositRoute(client, chainIdL2, token) {
5442
- if (isETH(token)) {
5443
- const base2 = await client.baseToken(chainIdL2);
5444
- return isETH(base2) ? "eth-base" : "eth-nonbase";
5445
- }
5446
- const base = await client.baseToken(chainIdL2);
5447
- return normalizeAddrEq(token, base) ? "erc20-base" : "erc20-nonbase";
5448
- }
5449
5541
 
5450
- // src/adapters/ethers/resources/deposits/context.ts
5451
- async function commonCtx(p, client) {
5452
- const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
5453
- const { chainId } = await client.l2.getNetwork();
5454
- const sender = await client.signer.getAddress();
5455
- const fee = await getFeeOverrides(client, p.l1TxOverrides);
5456
- const l2GasLimit = p.l2GasLimit ?? 300000n;
5457
- const gasPerPubdata = p.gasPerPubdata ?? 800n;
5458
- const operatorTip = p.operatorTip ?? 0n;
5459
- const refundRecipient = p.refundRecipient ?? sender;
5460
- const route = await pickDepositRoute(client, BigInt(chainId), p.token);
5542
+ // src/core/resources/deposits/gas.ts
5543
+ function makeGasQuote(p) {
5544
+ const maxPriorityFeePerGas = p.maxPriorityFeePerGas ?? 0n;
5461
5545
  return {
5462
- client,
5463
- l1AssetRouter,
5464
- route,
5465
- bridgehub,
5466
- chainIdL2: BigInt(chainId),
5467
- sender,
5468
- fee,
5469
- l2GasLimit,
5470
- gasPerPubdata,
5471
- operatorTip,
5472
- refundRecipient
5546
+ gasLimit: p.gasLimit,
5547
+ maxFeePerGas: p.maxFeePerGas,
5548
+ maxPriorityFeePerGas,
5549
+ gasPerPubdata: p.gasPerPubdata,
5550
+ maxCost: p.gasLimit * p.maxFeePerGas
5473
5551
  };
5474
5552
  }
5475
-
5476
- // src/core/errors/withdrawal-revert-map.ts
5477
- var REVERT_TO_READINESS = {
5478
- // Already done
5479
- WithdrawalAlreadyFinalized: { kind: "FINALIZED" },
5480
- // Temporary — try later
5481
- BatchNotExecuted: { kind: "NOT_READY", reason: "batch-not-executed" },
5482
- LocalRootIsZero: { kind: "NOT_READY", reason: "root-missing" },
5483
- // Permanent — won’t become ready for this tx
5484
- WrongL2Sender: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5485
- InvalidSelector: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5486
- L2WithdrawalMessageWrongLength: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5487
- WrongMsgLength: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5488
- TokenNotLegacy: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5489
- TokenIsLegacy: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5490
- InvalidProof: { kind: "UNFINALIZABLE", reason: "message-invalid" },
5491
- InvalidChainId: { kind: "UNFINALIZABLE", reason: "invalid-chain" },
5492
- NotSettlementLayer: { kind: "UNFINALIZABLE", reason: "settlement-layer" },
5493
- // Likely environment mismatch — treat as permanent for this tx
5494
- OnlyEraSupported: { kind: "UNFINALIZABLE", reason: "unsupported" },
5495
- LocalRootMustBeZero: { kind: "UNFINALIZABLE", reason: "unsupported" }
5496
- };
5497
-
5498
- // src/adapters/ethers/errors/revert.ts
5499
- var ERROR_IFACES = [];
5500
- var IFACE_ERROR_STRING = new ethers.Interface(["error Error(string)"]);
5501
- var IFACE_PANIC = new ethers.Interface(["error Panic(uint256)"]);
5502
- (function bootstrapDefaultIfaces() {
5553
+ async function fetchFees(estimator) {
5503
5554
  try {
5504
- ERROR_IFACES.push({
5505
- name: "IL1Nullifier",
5506
- iface: new ethers.Interface(IL1Nullifier_default)
5507
- });
5555
+ const fees = await estimator.estimateFeesPerGas();
5556
+ if (fees.maxFeePerGas != null) {
5557
+ return {
5558
+ maxFeePerGas: fees.maxFeePerGas,
5559
+ maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
5560
+ };
5561
+ }
5562
+ if (fees.gasPrice != null) {
5563
+ return {
5564
+ maxFeePerGas: fees.gasPrice,
5565
+ maxPriorityFeePerGas: 0n
5566
+ };
5567
+ }
5508
5568
  } catch {
5509
5569
  }
5510
5570
  try {
5511
- ERROR_IFACES.push({ name: "IERC20", iface: new ethers.Interface(IERC20_default) });
5571
+ const gp = await estimator.getGasPrice();
5572
+ return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
5512
5573
  } catch {
5574
+ return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
5575
+ }
5576
+ }
5577
+ async function quoteL1Gas(input) {
5578
+ const { estimator, tx, overrides, fallbackGasLimit } = input;
5579
+ let market;
5580
+ const getMarket = async () => {
5581
+ if (market) return market;
5582
+ market = await fetchFees(estimator);
5583
+ return market;
5584
+ };
5585
+ const maxFeePerGas = overrides?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : (await getMarket()).maxFeePerGas);
5586
+ const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : (await getMarket()).maxPriorityFeePerGas);
5587
+ const explicitGasLimit = overrides?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
5588
+ if (explicitGasLimit != null) {
5589
+ return makeGasQuote({ gasLimit: explicitGasLimit, maxFeePerGas, maxPriorityFeePerGas });
5513
5590
  }
5514
5591
  try {
5515
- ERROR_IFACES.push({
5516
- name: "IL1NativeTokenVault",
5517
- iface: new ethers.Interface(L1NativeTokenVault_default)
5592
+ const est = await estimator.estimateGas(tx);
5593
+ const buffered = BigInt(est) * (100n + BUFFER) / 100n;
5594
+ return makeGasQuote({ gasLimit: buffered, maxFeePerGas, maxPriorityFeePerGas });
5595
+ } catch (err) {
5596
+ if (fallbackGasLimit != null) {
5597
+ return makeGasQuote({ gasLimit: fallbackGasLimit, maxFeePerGas, maxPriorityFeePerGas });
5598
+ }
5599
+ console.warn("L1 gas estimation failed", err);
5600
+ return void 0;
5601
+ }
5602
+ }
5603
+ async function quoteL2Gas(input) {
5604
+ const { estimator, route, tx, gasPerPubdata, l2GasLimit, overrideGasLimit, stateOverrides } = input;
5605
+ const market = await fetchFees(estimator);
5606
+ const maxFeePerGas = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
5607
+ const txGasLimit = tx?.gasLimit != null ? BigInt(tx.gasLimit) : void 0;
5608
+ const explicit = overrideGasLimit ?? txGasLimit;
5609
+ if (explicit != null) {
5610
+ return makeGasQuote({
5611
+ gasLimit: explicit,
5612
+ maxFeePerGas,
5613
+ gasPerPubdata
5518
5614
  });
5519
- } catch {
5520
5615
  }
5521
- try {
5522
- ERROR_IFACES.push({
5523
- name: "IL2NativeTokenVault",
5524
- iface: new ethers.Interface(L2NativeTokenVault_default)
5616
+ if (!tx) {
5617
+ return makeGasQuote({
5618
+ gasLimit: l2GasLimit ?? 0n,
5619
+ maxFeePerGas,
5620
+ gasPerPubdata
5525
5621
  });
5526
- } catch {
5527
5622
  }
5528
5623
  try {
5529
- ERROR_IFACES.push({ name: "Mailbox", iface: new ethers.Interface(Mailbox_default) });
5530
- } catch {
5624
+ const execEstimate = await estimator.estimateGas(tx, stateOverrides);
5625
+ const memoryBytes = route === "erc20-nonbase" ? 500n : DEFAULT_ABI_BYTES;
5626
+ const pubdataBytes = route === "erc20-nonbase" ? 200n : DEFAULT_PUBDATA_BYTES;
5627
+ const pp = gasPerPubdata ?? 800n;
5628
+ const memoryOverhead = memoryBytes * TX_MEMORY_OVERHEAD_GAS;
5629
+ const pubdataOverhead = pubdataBytes * pp;
5630
+ let total = BigInt(execEstimate) + TX_OVERHEAD_GAS + memoryOverhead + pubdataOverhead;
5631
+ total = total * (100n + BUFFER) / 100n;
5632
+ return makeGasQuote({
5633
+ gasLimit: total,
5634
+ maxFeePerGas,
5635
+ gasPerPubdata: pp
5636
+ });
5637
+ } catch (err) {
5638
+ console.warn("L2 gas estimation failed", err);
5639
+ return makeGasQuote({
5640
+ gasLimit: l2GasLimit ?? 0n,
5641
+ maxFeePerGas,
5642
+ gasPerPubdata
5643
+ });
5531
5644
  }
5532
- })();
5533
- function registerErrorAbi(name, abi) {
5534
- const existing = ERROR_IFACES.findIndex((x) => x.name === name);
5535
- const entry = { name, iface: new ethers.Interface(abi) };
5536
- if (existing >= 0) ERROR_IFACES[existing] = entry;
5537
- else ERROR_IFACES.push(entry);
5538
5645
  }
5539
- function extractRevertData(e) {
5540
- const maybe = (
5541
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5542
- e?.data?.data ?? e?.error?.data ?? e?.data ?? e?.error?.error?.data ?? e?.info?.error?.data
5543
- );
5544
- if (typeof maybe === "string" && maybe.startsWith("0x") && maybe.length >= 10) {
5545
- return maybe;
5646
+ async function quoteL2BaseCost(input) {
5647
+ const { estimator, encode: encode2, bridgehub, chainIdL2, l2GasLimit, gasPerPubdata } = input;
5648
+ const market = await fetchFees(estimator);
5649
+ const l1GasPrice = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
5650
+ if (l1GasPrice === 0n) {
5651
+ throw new Error("Could not fetch L1 gas price for Bridgehub base cost calculation.");
5546
5652
  }
5547
- return void 0;
5653
+ const data = encode2(IBridgehub_default, "l2TransactionBaseCost", [
5654
+ chainIdL2,
5655
+ l1GasPrice,
5656
+ l2GasLimit,
5657
+ gasPerPubdata
5658
+ ]);
5659
+ const raw = await estimator.call({
5660
+ to: bridgehub,
5661
+ data
5662
+ });
5663
+ return BigInt(raw);
5548
5664
  }
5549
- function decodeRevert(e) {
5550
- const data = extractRevertData(e);
5551
- if (!data) return;
5552
- const selector = `0x${data.slice(2, 10)}`;
5553
- try {
5554
- const parsed = IFACE_ERROR_STRING.parseError(data);
5555
- if (parsed?.name === "Error") {
5556
- const args = parsed.args ? Array.from(parsed.args) : void 0;
5557
- return { selector, name: "Error", args };
5558
- }
5559
- } catch {
5560
- }
5561
- try {
5562
- const parsed = IFACE_PANIC.parseError(data);
5563
- if (parsed?.name === "Panic") {
5564
- const args = parsed.args ? Array.from(parsed.args) : void 0;
5565
- return { selector, name: "Panic", args };
5566
- }
5567
- } catch {
5568
- }
5569
- for (const { name, iface } of ERROR_IFACES) {
5570
- try {
5571
- const parsed = iface.parseError(data);
5572
- if (parsed) {
5573
- const args = parsed.args ? Array.from(parsed.args) : void 0;
5574
- return {
5575
- selector,
5576
- name: parsed.name,
5577
- args,
5578
- contract: name
5579
- };
5665
+
5666
+ // src/adapters/ethers/estimator.ts
5667
+ function toCoreTx(tx) {
5668
+ return {
5669
+ to: tx.to,
5670
+ from: tx.from,
5671
+ data: tx.data,
5672
+ value: tx.value ? BigInt(tx.value) : void 0,
5673
+ gasLimit: tx.gasLimit ? BigInt(tx.gasLimit) : void 0,
5674
+ maxFeePerGas: tx.maxFeePerGas ? BigInt(tx.maxFeePerGas) : void 0,
5675
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas ? BigInt(tx.maxPriorityFeePerGas) : void 0
5676
+ };
5677
+ }
5678
+ function ethersToGasEstimator(provider) {
5679
+ return {
5680
+ async estimateGas(tx, stateOverrides) {
5681
+ const ethTx = {
5682
+ to: tx.to,
5683
+ from: tx.from,
5684
+ data: tx.data,
5685
+ value: tx.value,
5686
+ gasLimit: tx.gasLimit,
5687
+ maxFeePerGas: tx.maxFeePerGas,
5688
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas
5689
+ };
5690
+ if (stateOverrides && "send" in provider) {
5691
+ try {
5692
+ const jsonRpcProvider = provider;
5693
+ const result = await jsonRpcProvider.send("eth_estimateGas", [
5694
+ ethTx,
5695
+ "latest",
5696
+ stateOverrides
5697
+ ]);
5698
+ return BigInt(result);
5699
+ } catch (error) {
5700
+ console.warn(
5701
+ "Failed to estimate gas with state overrides, falling back to standard estimation:",
5702
+ error
5703
+ );
5704
+ }
5705
+ } else if (stateOverrides) {
5706
+ console.warn('Provider does not support "send", skipping state overrides estimation.');
5580
5707
  }
5581
- } catch {
5708
+ return await provider.estimateGas(ethTx);
5709
+ },
5710
+ async estimateFeesPerGas() {
5711
+ const fd = await provider.getFeeData();
5712
+ return {
5713
+ maxFeePerGas: fd.maxFeePerGas != null ? BigInt(fd.maxFeePerGas) : void 0,
5714
+ maxPriorityFeePerGas: fd.maxPriorityFeePerGas != null ? BigInt(fd.maxPriorityFeePerGas) : void 0,
5715
+ gasPrice: fd.gasPrice != null ? BigInt(fd.gasPrice) : void 0
5716
+ };
5717
+ },
5718
+ async getGasPrice() {
5719
+ const fd = await provider.getFeeData();
5720
+ if (fd.gasPrice != null) return BigInt(fd.gasPrice);
5721
+ throw new Error("Could not fetch gas price");
5722
+ },
5723
+ async call(tx) {
5724
+ const ethTx = {
5725
+ to: tx.to,
5726
+ data: tx.data,
5727
+ value: tx.value,
5728
+ from: tx.from
5729
+ };
5730
+ return await provider.call(ethTx);
5582
5731
  }
5583
- }
5584
- return { selector };
5732
+ };
5585
5733
  }
5586
- function classifyReadinessFromRevert(e) {
5587
- const r = decodeRevert(e);
5588
- const name = r?.name;
5589
- if (name && REVERT_TO_READINESS[name]) return REVERT_TO_READINESS[name];
5590
- const msg = (() => {
5591
- if (typeof e !== "object" || e === null) return "";
5592
- const obj = e;
5593
- const maybeMsg = obj["shortMessage"] ?? obj["message"];
5594
- return typeof maybeMsg === "string" ? maybeMsg : "";
5595
- })();
5596
- const lower = String(msg).toLowerCase();
5597
- if (lower.includes("paused")) return { kind: "NOT_READY", reason: "paused" };
5598
- if (name || r?.selector) {
5599
- return { kind: "UNFINALIZABLE", reason: "unsupported", detail: name ?? r?.selector };
5600
- }
5601
- return { kind: "NOT_READY", reason: "unknown", detail: lower || void 0 };
5734
+
5735
+ // src/adapters/ethers/resources/deposits/services/fee.ts
5736
+ var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
5737
+ var encode = (abi2, fn, args) => {
5738
+ return new ethers.Interface(abi2).encodeFunctionData(fn, args);
5739
+ };
5740
+ async function quoteL2BaseCost2(input) {
5741
+ const { ctx, l2GasLimit } = input;
5742
+ const estimator = ethersToGasEstimator(ctx.client.l1);
5743
+ return wrapAs2(
5744
+ "RPC",
5745
+ "deposits.fees.l2BaseCost",
5746
+ () => quoteL2BaseCost({
5747
+ estimator,
5748
+ encode,
5749
+ bridgehub: ctx.bridgehub,
5750
+ chainIdL2: ctx.chainIdL2,
5751
+ l2GasLimit,
5752
+ gasPerPubdata: ctx.gasPerPubdata
5753
+ }),
5754
+ { ctx: { chainIdL2: ctx.chainIdL2 } }
5755
+ );
5602
5756
  }
5603
5757
 
5604
- // src/adapters/ethers/errors/error-ops.ts
5605
- function toZKsyncError(type, base, err) {
5606
- if (isZKsyncError(err)) return err;
5607
- const revert = decodeRevert(err);
5608
- return createError(type, { ...base, ...revert ? { revert } : {}, cause: shapeCause(err) });
5758
+ // src/adapters/ethers/resources/deposits/services/gas.ts
5759
+ async function quoteL1Gas2(input) {
5760
+ const { ctx, tx, overrides, fallbackGasLimit } = input;
5761
+ const estimator = ethersToGasEstimator(ctx.client.l1);
5762
+ return quoteL1Gas({
5763
+ estimator,
5764
+ tx: toCoreTx(tx),
5765
+ overrides,
5766
+ fallbackGasLimit
5767
+ });
5609
5768
  }
5610
- function resolveMessage(op, msg) {
5611
- if (!msg) return `Error during ${op}.`;
5612
- return typeof msg === "function" ? msg() : msg;
5769
+ async function quoteL2Gas2(input) {
5770
+ const { ctx, route, l2TxForModeling, overrideGasLimit } = input;
5771
+ const estimator = ethersToGasEstimator(ctx.client.l2);
5772
+ return quoteL2Gas({
5773
+ estimator,
5774
+ route,
5775
+ tx: l2TxForModeling ? toCoreTx(l2TxForModeling) : void 0,
5776
+ gasPerPubdata: ctx.gasPerPubdata,
5777
+ l2GasLimit: ctx.l2GasLimit,
5778
+ overrideGasLimit,
5779
+ stateOverrides: input.stateOverrides
5780
+ });
5613
5781
  }
5614
- function createErrorHandlers(resource) {
5615
- async function run(kind, operation, fn, opts) {
5616
- try {
5617
- return await fn();
5618
- } catch (e) {
5619
- if (isZKsyncError(e)) throw e;
5620
- const message = resolveMessage(operation, opts?.message);
5621
- throw toZKsyncError(kind, { resource, operation, context: opts?.ctx ?? {}, message }, e);
5622
- }
5623
- }
5624
- function wrap2(operation, fn, opts) {
5625
- return run("INTERNAL", operation, fn, opts);
5626
- }
5627
- function wrapAs9(kind, operation, fn, opts) {
5628
- return run(kind, operation, fn, opts);
5782
+ async function determineErc20L2Gas(input) {
5783
+ const { ctx, l1Token } = input;
5784
+ const DEFAULT_SAFE_L2_GAS_LIMIT = 3000000n;
5785
+ if (ctx.l2GasLimit != null) {
5786
+ return quoteL2Gas2({
5787
+ ctx,
5788
+ route: "erc20-nonbase",
5789
+ overrideGasLimit: ctx.l2GasLimit
5790
+ });
5629
5791
  }
5630
- async function toResult2(operation, fn, opts) {
5631
- try {
5632
- const value = await wrap2(operation, fn, opts);
5633
- return { ok: true, value };
5634
- } catch (e) {
5635
- const shaped = isZKsyncError(e) ? e : toZKsyncError(
5636
- "INTERNAL",
5637
- {
5638
- resource,
5639
- operation,
5640
- context: opts?.ctx ?? {},
5641
- message: resolveMessage(operation, opts?.message)
5642
- },
5643
- e
5644
- );
5645
- return { ok: false, error: shaped };
5792
+ try {
5793
+ const l2TokenAddress = ctx.tokens ? await ctx.tokens.toL2Address(l1Token) : await (await ctx.contracts.l2NativeTokenVault()).l2TokenAddress(l1Token);
5794
+ if (l2TokenAddress === "0x0000000000000000000000000000000000000000") {
5795
+ return quoteL2Gas2({
5796
+ ctx,
5797
+ route: "erc20-nonbase",
5798
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
5799
+ });
5646
5800
  }
5801
+ const modelTx = {
5802
+ to: input.modelTx?.to ?? ctx.sender,
5803
+ from: input.modelTx?.from ?? ctx.sender,
5804
+ data: input.modelTx?.data ?? "0x",
5805
+ value: input.modelTx?.value ?? 0n
5806
+ };
5807
+ const gas = await quoteL2Gas2({
5808
+ ctx,
5809
+ route: "erc20-nonbase",
5810
+ l2TxForModeling: modelTx
5811
+ });
5812
+ if (!gas) {
5813
+ return quoteL2Gas2({
5814
+ ctx,
5815
+ route: "erc20-nonbase",
5816
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
5817
+ });
5818
+ }
5819
+ return gas;
5820
+ } catch (err) {
5821
+ console.warn("Failed to determine ERC20 L2 gas; defaulting to safe gas limit.", err);
5822
+ return quoteL2Gas2({
5823
+ ctx,
5824
+ route: "erc20-nonbase",
5825
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
5826
+ });
5647
5827
  }
5648
- return { wrap: wrap2, wrapAs: wrapAs9, toResult: toResult2 };
5828
+ }
5829
+
5830
+ // src/core/resources/deposits/fee.ts
5831
+ function buildFeeBreakdown(p) {
5832
+ const l1MaxTotal = p.l1Gas?.maxCost ?? 0n;
5833
+ const l2Total = p.l2BaseCost + p.operatorTip;
5834
+ const l1 = {
5835
+ gasLimit: p.l1Gas?.gasLimit ?? 0n,
5836
+ maxFeePerGas: p.l1Gas?.maxFeePerGas ?? 0n,
5837
+ maxPriorityFeePerGas: p.l1Gas?.maxPriorityFeePerGas,
5838
+ maxTotal: l1MaxTotal
5839
+ };
5840
+ const l2 = {
5841
+ total: l2Total,
5842
+ baseCost: p.l2BaseCost,
5843
+ operatorTip: p.operatorTip,
5844
+ gasLimit: p.l2Gas?.gasLimit ?? 0n,
5845
+ maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
5846
+ maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas,
5847
+ gasPerPubdata: p.l2Gas?.gasPerPubdata ?? 0n
5848
+ };
5849
+ return {
5850
+ token: p.feeToken,
5851
+ maxTotal: l1MaxTotal + l2Total,
5852
+ mintValue: p.mintValue,
5853
+ l1,
5854
+ l2
5855
+ };
5649
5856
  }
5650
5857
 
5651
5858
  // src/adapters/ethers/resources/deposits/routes/eth.ts
5652
- var { wrapAs } = createErrorHandlers("deposits");
5653
5859
  function routeEthDirect() {
5654
5860
  return {
5655
5861
  async build(p, ctx) {
5656
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
5657
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
5658
- const rawBaseCost = await wrapAs(
5659
- "CONTRACT",
5660
- OP_DEPOSITS.eth.baseCost,
5661
- () => bh.l2TransactionBaseCost(
5662
- ctx.chainIdL2,
5663
- gasPriceForBaseCost,
5664
- ctx.l2GasLimit,
5665
- ctx.gasPerPubdata
5666
- ),
5667
- {
5668
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
5669
- message: "Could not fetch L2 base cost from Bridgehub."
5862
+ const bh = await ctx.contracts.bridgehub();
5863
+ const l2TxModel = {
5864
+ to: p.to ?? ctx.sender,
5865
+ from: ctx.sender,
5866
+ data: "0x",
5867
+ value: 0n
5868
+ };
5869
+ const l2GasParams = await quoteL2Gas2({
5870
+ ctx,
5871
+ route: "eth-base",
5872
+ l2TxForModeling: l2TxModel,
5873
+ overrideGasLimit: ctx.l2GasLimit,
5874
+ stateOverrides: {
5875
+ [ctx.sender]: {
5876
+ balance: "0xffffffffffffffffffff"
5877
+ }
5670
5878
  }
5671
- );
5672
- const baseCost = BigInt(rawBaseCost);
5673
- const l2Contract = p.to ?? ctx.sender;
5674
- const l2Value = p.amount;
5675
- const mintValue = baseCost + ctx.operatorTip + l2Value;
5879
+ });
5880
+ if (!l2GasParams) {
5881
+ throw new Error("Failed to estimate L2 gas for deposit.");
5882
+ }
5883
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
5884
+ const mintValue = baseCost + ctx.operatorTip + p.amount;
5676
5885
  const req = buildDirectRequestStruct({
5677
5886
  chainId: ctx.chainIdL2,
5678
5887
  mintValue,
5679
- l2GasLimit: ctx.l2GasLimit,
5888
+ l2GasLimit: l2GasParams.gasLimit,
5680
5889
  gasPerPubdata: ctx.gasPerPubdata,
5681
5890
  refundRecipient: ctx.refundRecipient,
5682
- l2Contract,
5683
- l2Value
5891
+ l2Contract: p.to ?? ctx.sender,
5892
+ l2Value: p.amount
5684
5893
  });
5685
5894
  const data = bh.interface.encodeFunctionData("requestL2TransactionDirect", [req]);
5686
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
5687
- const tx = {
5895
+ const l1TxCandidate = {
5688
5896
  to: ctx.bridgehub,
5689
5897
  data,
5690
5898
  value: mintValue,
5691
5899
  from: ctx.sender,
5692
- ...txFeeOverrides
5900
+ ...ctx.gasOverrides
5693
5901
  };
5694
- if (overrideGasLimit != null) {
5695
- tx.gasLimit = overrideGasLimit;
5696
- resolvedL1GasLimit = overrideGasLimit;
5697
- } else {
5698
- try {
5699
- const est = await wrapAs(
5700
- "RPC",
5701
- OP_DEPOSITS.eth.estGas,
5702
- () => ctx.client.l1.estimateGas(tx),
5703
- {
5704
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
5705
- message: "Failed to estimate gas for Bridgehub request."
5706
- }
5707
- );
5708
- const buffered = BigInt(est) * 115n / 100n;
5709
- tx.gasLimit = buffered;
5710
- resolvedL1GasLimit = buffered;
5711
- } catch {
5712
- }
5902
+ const l1GasParams = await quoteL1Gas2({
5903
+ ctx,
5904
+ tx: l1TxCandidate,
5905
+ overrides: ctx.gasOverrides
5906
+ });
5907
+ if (l1GasParams) {
5908
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
5909
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
5910
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
5713
5911
  }
5714
5912
  const steps = [
5715
5913
  {
5716
5914
  key: "bridgehub:direct",
5717
5915
  kind: "bridgehub:direct",
5718
5916
  description: "Bridge ETH via Bridgehub.requestL2TransactionDirect",
5719
- tx
5917
+ tx: l1TxCandidate
5720
5918
  }
5721
5919
  ];
5920
+ const fees = buildFeeBreakdown({
5921
+ feeToken: ETH_ADDRESS,
5922
+ l1Gas: l1GasParams,
5923
+ l2Gas: l2GasParams,
5924
+ l2BaseCost: baseCost,
5925
+ operatorTip: ctx.operatorTip,
5926
+ mintValue
5927
+ });
5722
5928
  return {
5723
5929
  steps,
5724
5930
  approvals: [],
5725
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
5931
+ fees
5726
5932
  };
5727
5933
  }
5728
5934
  };
5729
5935
  }
5730
- var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
5731
- var MIN_L2_GAS_FOR_ERC20 = 2500000n;
5936
+ var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
5732
5937
  function routeErc20NonBase() {
5733
5938
  return {
5734
- async preflight() {
5735
- },
5736
- async build(p, ctx) {
5737
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
5738
- const assetRouter = ctx.l1AssetRouter;
5739
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
5740
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
5741
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
5742
- const baseToken = await wrapAs2(
5743
- "CONTRACT",
5744
- OP_DEPOSITS.nonbase.baseToken,
5745
- () => bh.baseToken(ctx.chainIdL2),
5746
- {
5747
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
5748
- message: "Failed to read base token."
5749
- }
5750
- );
5751
- await wrapAs2(
5939
+ async preflight(p, ctx) {
5940
+ const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l1" }) : void 0);
5941
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
5942
+ await wrapAs3(
5752
5943
  "VALIDATION",
5753
5944
  OP_DEPOSITS.nonbase.assertNonBaseToken,
5754
5945
  () => {
5755
- if (normalizeAddrEq(baseToken, p.token)) {
5946
+ if (resolved?.kind === "base" || resolved?.kind === "eth") {
5756
5947
  throw new Error("erc20-nonbase route requires a non-base ERC-20 deposit token.");
5757
5948
  }
5758
5949
  },
5759
5950
  { ctx: { depositToken: p.token, baseToken } }
5760
5951
  );
5761
- const l2GasLimitUsed = ctx.l2GasLimit && ctx.l2GasLimit > 0n ? ctx.l2GasLimit < MIN_L2_GAS_FOR_ERC20 ? MIN_L2_GAS_FOR_ERC20 : ctx.l2GasLimit : MIN_L2_GAS_FOR_ERC20;
5762
- const rawBaseCost = await wrapAs2(
5763
- "RPC",
5764
- OP_DEPOSITS.nonbase.baseCost,
5765
- () => bh.l2TransactionBaseCost(
5766
- ctx.chainIdL2,
5767
- gasPriceForBaseCost,
5768
- l2GasLimitUsed,
5769
- ctx.gasPerPubdata
5770
- ),
5771
- {
5772
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
5773
- message: "Could not fetch L2 base cost from Bridgehub."
5952
+ },
5953
+ async build(p, ctx) {
5954
+ const l1Signer = ctx.client.getL1Signer();
5955
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
5956
+ const baseIsEth = ctx.baseIsEth ?? isETH(baseToken);
5957
+ const l2GasParams = await determineErc20L2Gas({
5958
+ ctx,
5959
+ l1Token: p.token,
5960
+ modelTx: {
5961
+ to: p.to ?? ctx.sender,
5962
+ from: ctx.sender,
5963
+ data: "0x",
5964
+ value: 0n
5774
5965
  }
5775
- );
5776
- const baseCost = BigInt(rawBaseCost);
5966
+ });
5967
+ if (!l2GasParams) throw new Error("Failed to establish L2 gas parameters.");
5968
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
5777
5969
  const mintValue = baseCost + ctx.operatorTip;
5778
5970
  const approvals = [];
5779
5971
  const steps = [];
5780
- const l1Signer = ctx.client.getL1Signer();
5781
- {
5782
- const erc20Deposit = new ethers.Contract(p.token, IERC20_default, l1Signer);
5783
- const allowanceToken = await wrapAs2(
5784
- "RPC",
5785
- OP_DEPOSITS.nonbase.allowanceToken,
5786
- () => erc20Deposit.allowance(ctx.sender, assetRouter),
5787
- {
5788
- ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
5789
- message: "Failed to read deposit-token allowance."
5790
- }
5791
- );
5792
- if (allowanceToken < p.amount) {
5793
- approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
5794
- const data = erc20Deposit.interface.encodeFunctionData("approve", [
5795
- assetRouter,
5796
- p.amount
5797
- ]);
5798
- steps.push({
5799
- key: `approve:${p.token}:${assetRouter}`,
5800
- kind: "approve",
5801
- description: `Approve ${p.amount} for router (deposit token)`,
5802
- tx: { to: p.token, data, from: ctx.sender, ...txOverrides }
5803
- });
5972
+ const assetRouter = ctx.l1AssetRouter;
5973
+ const erc20Deposit = new ethers.Contract(p.token, IERC20_default, l1Signer);
5974
+ const allowanceToken = await wrapAs3(
5975
+ "RPC",
5976
+ OP_DEPOSITS.nonbase.allowanceToken,
5977
+ () => erc20Deposit.allowance(ctx.sender, assetRouter),
5978
+ {
5979
+ ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
5980
+ message: "Failed to read deposit-token allowance."
5804
5981
  }
5982
+ );
5983
+ if (allowanceToken < p.amount) {
5984
+ approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
5985
+ steps.push({
5986
+ key: `approve:${p.token}:${assetRouter}`,
5987
+ kind: "approve",
5988
+ description: `Approve ${p.amount} for router (deposit token)`,
5989
+ tx: {
5990
+ to: p.token,
5991
+ data: erc20Deposit.interface.encodeFunctionData("approve", [assetRouter, p.amount]),
5992
+ from: ctx.sender,
5993
+ ...ctx.gasOverrides
5994
+ }
5995
+ });
5805
5996
  }
5806
- const baseIsEth = isETH(baseToken);
5807
5997
  if (!baseIsEth) {
5808
5998
  const erc20Base = new ethers.Contract(baseToken, IERC20_default, l1Signer);
5809
- const allowanceBase = await wrapAs2(
5999
+ const allowanceBase = await wrapAs3(
5810
6000
  "RPC",
5811
6001
  OP_DEPOSITS.nonbase.allowanceBase,
5812
6002
  () => erc20Base.allowance(ctx.sender, assetRouter),
@@ -5817,16 +6007,20 @@ function routeErc20NonBase() {
5817
6007
  );
5818
6008
  if (allowanceBase < mintValue) {
5819
6009
  approvals.push({ token: baseToken, spender: assetRouter, amount: mintValue });
5820
- const data = erc20Base.interface.encodeFunctionData("approve", [assetRouter, mintValue]);
5821
6010
  steps.push({
5822
6011
  key: `approve:${baseToken}:${assetRouter}`,
5823
6012
  kind: "approve",
5824
6013
  description: `Approve base token for mintValue`,
5825
- tx: { to: baseToken, data, from: ctx.sender, ...txOverrides }
6014
+ tx: {
6015
+ to: baseToken,
6016
+ data: erc20Base.interface.encodeFunctionData("approve", [assetRouter, mintValue]),
6017
+ from: ctx.sender,
6018
+ ...ctx.gasOverrides
6019
+ }
5826
6020
  });
5827
6021
  }
5828
6022
  }
5829
- const secondBridgeCalldata = await wrapAs2(
6023
+ const secondBridgeCalldata = await wrapAs3(
5830
6024
  "INTERNAL",
5831
6025
  OP_DEPOSITS.nonbase.encodeCalldata,
5832
6026
  () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, p.to ?? ctx.sender)),
@@ -5835,98 +6029,88 @@ function routeErc20NonBase() {
5835
6029
  message: "Failed to encode bridging calldata."
5836
6030
  }
5837
6031
  );
5838
- const outer = {
6032
+ const requestStruct = {
5839
6033
  chainId: ctx.chainIdL2,
5840
6034
  mintValue,
5841
- // fees (in ETH if base=ETH, else pulled as base ERC-20)
5842
6035
  l2Value: 0n,
5843
- l2GasLimit: l2GasLimitUsed,
6036
+ l2GasLimit: l2GasParams.gasLimit,
5844
6037
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
5845
6038
  refundRecipient: ctx.refundRecipient,
5846
6039
  secondBridgeAddress: assetRouter,
5847
6040
  secondBridgeValue: 0n,
5848
6041
  secondBridgeCalldata
5849
6042
  };
5850
- const dataTwo = bh.interface.encodeFunctionData("requestL2TransactionTwoBridges", [outer]);
5851
- const bridgeTx = {
6043
+ const bh = await ctx.contracts.bridgehub();
6044
+ const data = bh.interface.encodeFunctionData("requestL2TransactionTwoBridges", [
6045
+ requestStruct
6046
+ ]);
6047
+ const txValue = baseIsEth ? mintValue : 0n;
6048
+ const l1TxCandidate = {
5852
6049
  to: ctx.bridgehub,
5853
- data: dataTwo,
5854
- value: baseIsEth ? mintValue : 0n,
6050
+ data,
6051
+ value: txValue,
5855
6052
  from: ctx.sender,
5856
- ...txOverrides
6053
+ ...ctx.gasOverrides
5857
6054
  };
5858
- if (overrideGasLimit != null) {
5859
- bridgeTx.gasLimit = overrideGasLimit;
5860
- resolvedL1GasLimit = overrideGasLimit;
5861
- } else {
5862
- try {
5863
- const est = await wrapAs2(
5864
- "RPC",
5865
- OP_DEPOSITS.nonbase.estGas,
5866
- () => ctx.client.l1.estimateGas(bridgeTx),
5867
- {
5868
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub, baseIsEth },
5869
- message: "Failed to estimate gas for Bridgehub request."
5870
- }
5871
- );
5872
- const buffered = BigInt(est) * 125n / 100n;
5873
- bridgeTx.gasLimit = buffered;
5874
- resolvedL1GasLimit = buffered;
5875
- } catch {
5876
- }
6055
+ const l1GasParams = await quoteL1Gas2({
6056
+ ctx,
6057
+ tx: l1TxCandidate,
6058
+ overrides: ctx.gasOverrides,
6059
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
6060
+ });
6061
+ if (l1GasParams) {
6062
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
6063
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
6064
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
5877
6065
  }
5878
6066
  steps.push({
5879
- key: "bridgehub:two-bridges:nonbase",
6067
+ key: "bridgehub:two-bridges",
5880
6068
  kind: "bridgehub:two-bridges",
5881
- description: baseIsEth ? "Bridge ERC-20 (fees in ETH) via Bridgehub.requestL2TransactionTwoBridges" : "Bridge ERC-20 (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
5882
- tx: bridgeTx
6069
+ description: baseIsEth ? "Bridge ERC-20 (Fees paid in ETH)" : "Bridge ERC-20 (Fees paid in Base Token)",
6070
+ tx: l1TxCandidate
6071
+ });
6072
+ const fees = buildFeeBreakdown({
6073
+ feeToken: baseToken,
6074
+ l1Gas: l1GasParams,
6075
+ l2Gas: l2GasParams,
6076
+ l2BaseCost: baseCost,
6077
+ operatorTip: ctx.operatorTip,
6078
+ mintValue
5883
6079
  });
5884
6080
  return {
5885
6081
  steps,
5886
6082
  approvals,
5887
- quoteExtras: { baseCost, mintValue, baseToken, baseIsEth, l1GasLimit: resolvedL1GasLimit }
6083
+ fees
5888
6084
  };
5889
6085
  }
5890
6086
  };
5891
6087
  }
5892
- var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
5893
- var BASE_COST_BUFFER_BPS = 100n;
5894
- var BPS = 10000n;
5895
- var withBuffer = (x) => x * (BPS + BASE_COST_BUFFER_BPS) / BPS;
6088
+ var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
5896
6089
  function routeEthNonBase() {
5897
6090
  return {
5898
6091
  async preflight(p, ctx) {
5899
- await wrapAs3(
6092
+ const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l1" }) : void 0);
6093
+ await wrapAs4(
5900
6094
  "VALIDATION",
5901
6095
  OP_DEPOSITS.ethNonBase.assertEthAsset,
5902
6096
  () => {
5903
- if (!isETH(p.token)) {
6097
+ if (resolved?.kind !== "eth" && !isETH(p.token)) {
5904
6098
  throw new Error("eth-nonbase route requires ETH as the deposit asset.");
5905
6099
  }
5906
6100
  },
5907
6101
  { ctx: { token: p.token } }
5908
6102
  );
5909
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
5910
- const baseToken = await wrapAs3(
5911
- "CONTRACT",
5912
- OP_DEPOSITS.ethNonBase.baseToken,
5913
- () => bh.baseToken(ctx.chainIdL2),
5914
- {
5915
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
5916
- message: "Failed to read base token."
5917
- }
5918
- );
5919
- await wrapAs3(
6103
+ await wrapAs4(
5920
6104
  "VALIDATION",
5921
6105
  OP_DEPOSITS.ethNonBase.assertNonEthBase,
5922
6106
  () => {
5923
- if (isETH(baseToken)) {
6107
+ if (ctx.baseIsEth) {
5924
6108
  throw new Error("eth-nonbase route requires target chain base token \u2260 ETH.");
5925
6109
  }
5926
6110
  },
5927
- { ctx: { baseToken, chainIdL2: ctx.chainIdL2 } }
6111
+ { ctx: { baseIsEth: ctx.baseIsEth, chainIdL2: ctx.chainIdL2 } }
5928
6112
  );
5929
- const ethBal = await wrapAs3(
6113
+ const ethBal = await wrapAs4(
5930
6114
  "RPC",
5931
6115
  OP_DEPOSITS.ethNonBase.ethBalance,
5932
6116
  () => ctx.client.l1.getBalance(ctx.sender),
@@ -5935,7 +6119,7 @@ function routeEthNonBase() {
5935
6119
  message: "Failed to read L1 ETH balance."
5936
6120
  }
5937
6121
  );
5938
- await wrapAs3(
6122
+ await wrapAs4(
5939
6123
  "VALIDATION",
5940
6124
  OP_DEPOSITS.ethNonBase.assertEthBalance,
5941
6125
  () => {
@@ -5948,63 +6132,50 @@ function routeEthNonBase() {
5948
6132
  return;
5949
6133
  },
5950
6134
  async build(p, ctx) {
5951
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
5952
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
5953
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
5954
- const baseToken = await wrapAs3(
5955
- "CONTRACT",
5956
- OP_DEPOSITS.ethNonBase.baseToken,
5957
- () => bh.baseToken(ctx.chainIdL2),
5958
- {
5959
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
5960
- message: "Failed to read base token."
5961
- }
5962
- );
5963
- const rawBaseCost = await wrapAs3(
6135
+ const l1Signer = ctx.client.getL1Signer();
6136
+ const baseToken = ctx.baseTokenL1;
6137
+ const l2TxModel = {
6138
+ to: p.to ?? ctx.sender,
6139
+ from: ctx.sender,
6140
+ data: "0x",
6141
+ value: 0n
6142
+ };
6143
+ const l2GasParams = await quoteL2Gas2({
6144
+ ctx,
6145
+ route: "eth-nonbase",
6146
+ l2TxForModeling: l2TxModel,
6147
+ overrideGasLimit: ctx.l2GasLimit
6148
+ });
6149
+ if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
6150
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
6151
+ const mintValue = baseCost + ctx.operatorTip;
6152
+ const approvals = [];
6153
+ const steps = [];
6154
+ const erc20Base = new ethers.Contract(baseToken, IERC20_default, l1Signer);
6155
+ const allowance = await wrapAs4(
5964
6156
  "RPC",
5965
- OP_DEPOSITS.ethNonBase.baseCost,
5966
- () => bh.l2TransactionBaseCost(
5967
- ctx.chainIdL2,
5968
- gasPriceForBaseCost,
5969
- ctx.l2GasLimit,
5970
- ctx.gasPerPubdata
5971
- ),
6157
+ OP_DEPOSITS.ethNonBase.allowanceBase,
6158
+ () => erc20Base.allowance(ctx.sender, ctx.l1AssetRouter),
5972
6159
  {
5973
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
5974
- message: "Could not fetch L2 base cost."
6160
+ ctx: { where: "erc20.allowance", token: baseToken, spender: ctx.l1AssetRouter },
6161
+ message: "Failed to read base-token allowance."
5975
6162
  }
5976
6163
  );
5977
- const baseCost = BigInt(rawBaseCost);
5978
- const mintValueRaw = baseCost + ctx.operatorTip;
5979
- const mintValue = withBuffer(mintValueRaw);
5980
- const approvals = [];
5981
- const steps = [];
5982
- {
5983
- const erc20 = new ethers.Contract(baseToken, IERC20_default, ctx.client.getL1Signer());
5984
- const allowance = await wrapAs3(
5985
- "RPC",
5986
- OP_DEPOSITS.ethNonBase.allowanceBase,
5987
- () => erc20.allowance(ctx.sender, ctx.l1AssetRouter),
5988
- {
5989
- ctx: { where: "erc20.allowance", token: baseToken, spender: ctx.l1AssetRouter },
5990
- message: "Failed to read base-token allowance."
6164
+ if (allowance < mintValue) {
6165
+ approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
6166
+ steps.push({
6167
+ key: `approve:${baseToken}`,
6168
+ kind: "approve",
6169
+ description: `Approve base token for fees (mintValue)`,
6170
+ tx: {
6171
+ to: baseToken,
6172
+ data: erc20Base.interface.encodeFunctionData("approve", [ctx.l1AssetRouter, mintValue]),
6173
+ from: ctx.sender,
6174
+ ...ctx.gasOverrides
5991
6175
  }
5992
- );
5993
- if (allowance < mintValue) {
5994
- approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
5995
- const data = erc20.interface.encodeFunctionData("approve", [
5996
- ctx.l1AssetRouter,
5997
- mintValue
5998
- ]);
5999
- steps.push({
6000
- key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
6001
- kind: "approve",
6002
- description: `Approve base token for mintValue`,
6003
- tx: { to: baseToken, data, from: ctx.sender, ...txOverrides }
6004
- });
6005
- }
6176
+ });
6006
6177
  }
6007
- const secondBridgeCalldata = await wrapAs3(
6178
+ const secondBridgeCalldata = await wrapAs4(
6008
6179
  "INTERNAL",
6009
6180
  OP_DEPOSITS.ethNonBase.encodeCalldata,
6010
6181
  () => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, p.to ?? ctx.sender)),
@@ -6016,93 +6187,79 @@ function routeEthNonBase() {
6016
6187
  }
6017
6188
  }
6018
6189
  );
6019
- const outer = {
6190
+ const requestStruct = {
6020
6191
  chainId: ctx.chainIdL2,
6021
6192
  mintValue,
6022
- l2Value: 0n,
6023
- l2GasLimit: ctx.l2GasLimit,
6193
+ l2Value: p.amount,
6194
+ l2GasLimit: l2GasParams.gasLimit,
6024
6195
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
6025
6196
  refundRecipient: ctx.refundRecipient,
6026
6197
  secondBridgeAddress: ctx.l1AssetRouter,
6027
6198
  secondBridgeValue: p.amount,
6028
6199
  secondBridgeCalldata
6029
6200
  };
6030
- const dataTwo = new ethers.Contract(
6031
- ctx.bridgehub,
6032
- IBridgehub_default,
6033
- ctx.client.l1
6034
- ).interface.encodeFunctionData("requestL2TransactionTwoBridges", [outer]);
6035
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
6036
- const bridgeTx = {
6201
+ const bridgehub = await ctx.contracts.bridgehub();
6202
+ const data = bridgehub.interface.encodeFunctionData("requestL2TransactionTwoBridges", [
6203
+ requestStruct
6204
+ ]);
6205
+ const l1TxCandidate = {
6037
6206
  to: ctx.bridgehub,
6038
- data: dataTwo,
6207
+ data,
6039
6208
  value: p.amount,
6040
6209
  // base ≠ ETH ⇒ msg.value == secondBridgeValue
6041
6210
  from: ctx.sender,
6042
- ...txOverrides
6211
+ ...ctx.gasOverrides
6043
6212
  };
6044
- if (overrideGasLimit != null) {
6045
- bridgeTx.gasLimit = overrideGasLimit;
6046
- resolvedL1GasLimit = overrideGasLimit;
6047
- } else {
6048
- try {
6049
- const est = await wrapAs3(
6050
- "RPC",
6051
- OP_DEPOSITS.ethNonBase.estGas,
6052
- () => ctx.client.l1.estimateGas(bridgeTx),
6053
- {
6054
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
6055
- message: "Failed to estimate gas for Bridgehub request."
6056
- }
6057
- );
6058
- const buffered = BigInt(est) * 115n / 100n;
6059
- bridgeTx.gasLimit = buffered;
6060
- resolvedL1GasLimit = buffered;
6061
- } catch {
6062
- }
6213
+ const l1GasParams = await quoteL1Gas2({
6214
+ ctx,
6215
+ tx: l1TxCandidate,
6216
+ overrides: ctx.gasOverrides,
6217
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
6218
+ });
6219
+ if (l1GasParams) {
6220
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
6221
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
6222
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
6063
6223
  }
6064
6224
  steps.push({
6065
6225
  key: "bridgehub:two-bridges:eth-nonbase",
6066
6226
  kind: "bridgehub:two-bridges",
6067
6227
  description: "Bridge ETH (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
6068
- tx: bridgeTx
6228
+ tx: l1TxCandidate
6229
+ });
6230
+ const fees = buildFeeBreakdown({
6231
+ feeToken: baseToken,
6232
+ l1Gas: l1GasParams,
6233
+ l2Gas: l2GasParams,
6234
+ l2BaseCost: baseCost,
6235
+ operatorTip: ctx.operatorTip,
6236
+ mintValue
6069
6237
  });
6070
6238
  return {
6071
6239
  steps,
6072
6240
  approvals,
6073
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
6241
+ fees
6074
6242
  };
6075
6243
  }
6076
6244
  };
6077
6245
  }
6078
- var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
6079
- var BASE_COST_BUFFER_BPS2 = 100n;
6080
- var BPS2 = 10000n;
6081
- var withBuffer2 = (x) => x * (BPS2 + BASE_COST_BUFFER_BPS2) / BPS2;
6246
+ var { wrapAs: wrapAs5 } = createErrorHandlers("deposits");
6082
6247
  function routeErc20Base() {
6083
6248
  return {
6084
6249
  async preflight(p, ctx) {
6085
- await wrapAs4(
6250
+ const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l1" }) : void 0);
6251
+ await wrapAs5(
6086
6252
  "VALIDATION",
6087
6253
  OP_DEPOSITS.base.assertErc20Asset,
6088
6254
  () => {
6089
- if (isETH(p.token)) {
6255
+ if (resolved?.kind === "eth" || isETH(p.token)) {
6090
6256
  throw new Error("erc20-base route requires an ERC-20 token (not ETH).");
6091
6257
  }
6092
6258
  },
6093
6259
  { ctx: { token: p.token } }
6094
6260
  );
6095
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
6096
- const baseToken = await wrapAs4(
6097
- "CONTRACT",
6098
- OP_DEPOSITS.base.baseToken,
6099
- () => bh.baseToken(ctx.chainIdL2),
6100
- {
6101
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
6102
- message: "Failed to read base token."
6103
- }
6104
- );
6105
- await wrapAs4(
6261
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
6262
+ await wrapAs5(
6106
6263
  "VALIDATION",
6107
6264
  OP_DEPOSITS.base.assertMatchesBase,
6108
6265
  () => {
@@ -6115,42 +6272,28 @@ function routeErc20Base() {
6115
6272
  return;
6116
6273
  },
6117
6274
  async build(p, ctx) {
6118
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
6119
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
6120
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
6121
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
6122
- const baseToken = await wrapAs4(
6123
- "CONTRACT",
6124
- OP_DEPOSITS.base.baseToken,
6125
- () => bh.baseToken(ctx.chainIdL2),
6126
- {
6127
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
6128
- message: "Failed to read base token."
6129
- }
6130
- );
6131
- const rawBaseCost = await wrapAs4(
6132
- "RPC",
6133
- OP_DEPOSITS.base.baseCost,
6134
- () => bh.l2TransactionBaseCost(
6135
- ctx.chainIdL2,
6136
- gasPriceForBaseCost,
6137
- ctx.l2GasLimit,
6138
- ctx.gasPerPubdata
6139
- ),
6140
- {
6141
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
6142
- message: "Could not fetch L2 base cost from Bridgehub."
6143
- }
6144
- );
6145
- const baseCost = BigInt(rawBaseCost);
6146
- const l2Value = p.amount;
6147
- const rawMintValue = baseCost + ctx.operatorTip + l2Value;
6148
- const mintValue = withBuffer2(rawMintValue);
6275
+ const l1Signer = ctx.client.getL1Signer();
6276
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
6277
+ const l2TxModel = {
6278
+ to: p.to ?? ctx.sender,
6279
+ from: ctx.sender,
6280
+ data: "0x",
6281
+ value: 0n
6282
+ };
6283
+ const l2GasParams = await quoteL2Gas2({
6284
+ ctx,
6285
+ route: "erc20-base",
6286
+ l2TxForModeling: l2TxModel,
6287
+ overrideGasLimit: ctx.l2GasLimit
6288
+ });
6289
+ if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
6290
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
6291
+ const mintValue = baseCost + ctx.operatorTip + p.amount;
6149
6292
  const approvals = [];
6150
6293
  const steps = [];
6151
6294
  {
6152
- const erc20 = new ethers.Contract(baseToken, IERC20_default, ctx.client.getL1Signer());
6153
- const allowance = await wrapAs4(
6295
+ const erc20 = new ethers.Contract(baseToken, IERC20_default, l1Signer);
6296
+ const allowance = await wrapAs5(
6154
6297
  "RPC",
6155
6298
  OP_DEPOSITS.base.allowance,
6156
6299
  () => erc20.allowance(ctx.sender, ctx.l1AssetRouter),
@@ -6161,75 +6304,350 @@ function routeErc20Base() {
6161
6304
  );
6162
6305
  if (allowance < mintValue) {
6163
6306
  approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
6164
- const data2 = erc20.interface.encodeFunctionData("approve", [
6165
- ctx.l1AssetRouter,
6166
- mintValue
6167
- ]);
6168
6307
  steps.push({
6169
6308
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
6170
6309
  kind: "approve",
6171
6310
  description: "Approve base token for mintValue",
6172
- tx: { to: baseToken, data: data2, from: ctx.sender, ...txOverrides }
6311
+ tx: {
6312
+ to: baseToken,
6313
+ data: erc20.interface.encodeFunctionData("approve", [ctx.l1AssetRouter, mintValue]),
6314
+ from: ctx.sender,
6315
+ ...ctx.gasOverrides
6316
+ }
6173
6317
  });
6174
6318
  }
6175
6319
  }
6176
- const req = buildDirectRequestStruct({
6320
+ const requestStruct = buildDirectRequestStruct({
6177
6321
  chainId: ctx.chainIdL2,
6178
6322
  mintValue,
6179
- l2GasLimit: ctx.l2GasLimit,
6323
+ l2GasLimit: l2GasParams.gasLimit,
6180
6324
  gasPerPubdata: ctx.gasPerPubdata,
6181
6325
  refundRecipient: ctx.refundRecipient,
6182
6326
  l2Contract: p.to ?? ctx.sender,
6183
- l2Value
6327
+ l2Value: p.amount
6184
6328
  });
6185
- const data = new ethers.Contract(
6186
- ctx.bridgehub,
6187
- IBridgehub_default,
6188
- ctx.client.l1
6189
- ).interface.encodeFunctionData("requestL2TransactionDirect", [req]);
6190
- const tx = {
6329
+ const bridgehub = await ctx.contracts.bridgehub();
6330
+ const data = bridgehub.interface.encodeFunctionData("requestL2TransactionDirect", [
6331
+ requestStruct
6332
+ ]);
6333
+ const l1TxCandidate = {
6191
6334
  to: ctx.bridgehub,
6192
6335
  data,
6193
6336
  value: 0n,
6194
6337
  // base token is ERC-20 ⇒ msg.value MUST be 0
6195
6338
  from: ctx.sender,
6196
- ...txOverrides
6339
+ ...ctx.gasOverrides
6197
6340
  };
6198
- if (overrideGasLimit != null) {
6199
- tx.gasLimit = overrideGasLimit;
6200
- resolvedL1GasLimit = overrideGasLimit;
6201
- } else {
6202
- try {
6203
- const est = await wrapAs4(
6204
- "RPC",
6205
- OP_DEPOSITS.base.estGas,
6206
- () => ctx.client.l1.estimateGas(tx),
6207
- {
6208
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
6209
- message: "Failed to estimate gas for Bridgehub request."
6210
- }
6211
- );
6212
- const buffered = BigInt(est) * 115n / 100n;
6213
- tx.gasLimit = buffered;
6214
- resolvedL1GasLimit = buffered;
6215
- } catch {
6216
- }
6341
+ const l1GasParams = await quoteL1Gas2({
6342
+ ctx,
6343
+ tx: l1TxCandidate,
6344
+ overrides: ctx.gasOverrides,
6345
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
6346
+ });
6347
+ if (l1GasParams) {
6348
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
6349
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
6350
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
6217
6351
  }
6218
6352
  steps.push({
6219
6353
  key: "bridgehub:direct:erc20-base",
6220
6354
  kind: "bridgehub:direct",
6221
6355
  description: "Bridge base ERC-20 via Bridgehub.requestL2TransactionDirect",
6222
- tx
6356
+ tx: l1TxCandidate
6357
+ });
6358
+ const fees = buildFeeBreakdown({
6359
+ feeToken: baseToken,
6360
+ l1Gas: l1GasParams,
6361
+ l2Gas: l2GasParams,
6362
+ l2BaseCost: baseCost,
6363
+ operatorTip: ctx.operatorTip,
6364
+ mintValue
6223
6365
  });
6224
6366
  return {
6225
6367
  steps,
6226
6368
  approvals,
6227
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
6369
+ fees
6228
6370
  };
6229
6371
  }
6230
6372
  };
6231
6373
  }
6232
6374
 
6375
+ // src/core/codec/ntv.ts
6376
+ function createNTVCodec(deps) {
6377
+ function encodeAssetId(originChainId, ntvAddress, tokenAddress) {
6378
+ const encoded = deps.encode(
6379
+ ["uint256", "address", "address"],
6380
+ [originChainId, ntvAddress, tokenAddress]
6381
+ );
6382
+ return deps.keccak256(encoded);
6383
+ }
6384
+ return {
6385
+ encodeAssetId
6386
+ };
6387
+ }
6388
+
6389
+ // src/adapters/ethers/resources/tokens/tokens.ts
6390
+ var { wrapAs: wrapAs6 } = createErrorHandlers("tokens");
6391
+ var abi = ethers.AbiCoder.defaultAbiCoder();
6392
+ var ntvCodec = createNTVCodec({
6393
+ encode: (types, values) => abi.encode(types, values),
6394
+ keccak256: (data) => ethers.ethers.keccak256(data)
6395
+ });
6396
+ function createTokensResource(client) {
6397
+ let l2NtvL1ChainIdPromise = null;
6398
+ let baseTokenAssetIdPromise = null;
6399
+ let wethL1Promise = null;
6400
+ let wethL2Promise = null;
6401
+ async function getL1ChainId() {
6402
+ if (!l2NtvL1ChainIdPromise) {
6403
+ l2NtvL1ChainIdPromise = wrapAs6("INTERNAL", "getL1ChainId", async () => {
6404
+ const { l2NativeTokenVault } = await client.contracts();
6405
+ const chainId = await l2NativeTokenVault.L1_CHAIN_ID();
6406
+ return chainId;
6407
+ });
6408
+ }
6409
+ return l2NtvL1ChainIdPromise;
6410
+ }
6411
+ async function getBaseTokenAssetId() {
6412
+ if (!baseTokenAssetIdPromise) {
6413
+ baseTokenAssetIdPromise = wrapAs6("INTERNAL", "baseTokenAssetId", async () => {
6414
+ const { l2NativeTokenVault } = await client.contracts();
6415
+ const assetId = await l2NativeTokenVault.BASE_TOKEN_ASSET_ID();
6416
+ return assetId;
6417
+ });
6418
+ }
6419
+ return baseTokenAssetIdPromise;
6420
+ }
6421
+ async function getWethL1() {
6422
+ if (!wethL1Promise) {
6423
+ wethL1Promise = wrapAs6("INTERNAL", "wethL1", async () => {
6424
+ const { l1NativeTokenVault } = await client.contracts();
6425
+ const weth = await l1NativeTokenVault.WETH_TOKEN();
6426
+ return weth;
6427
+ });
6428
+ }
6429
+ return wethL1Promise;
6430
+ }
6431
+ async function getWethL2() {
6432
+ if (!wethL2Promise) {
6433
+ wethL2Promise = wrapAs6("INTERNAL", "wethL2", async () => {
6434
+ const { l2NativeTokenVault } = await client.contracts();
6435
+ const weth = await l2NativeTokenVault.WETH_TOKEN();
6436
+ return weth;
6437
+ });
6438
+ }
6439
+ return wethL2Promise;
6440
+ }
6441
+ async function toL2Address(l1Token) {
6442
+ return wrapAs6("CONTRACT", "tokens.toL2Address", async () => {
6443
+ const normalized = normalizeL1Token(l1Token);
6444
+ const { chainId } = await client.l2.getNetwork();
6445
+ const baseToken = await client.baseToken(BigInt(chainId));
6446
+ if (isAddressEq(normalized, baseToken)) {
6447
+ return L2_BASE_TOKEN_ADDRESS;
6448
+ }
6449
+ const { l2NativeTokenVault } = await client.contracts();
6450
+ const l2Token = await l2NativeTokenVault.l2TokenAddress(normalized);
6451
+ return l2Token;
6452
+ });
6453
+ }
6454
+ async function toL1Address(l2Token) {
6455
+ return wrapAs6("CONTRACT", "tokens.toL1Address", async () => {
6456
+ if (isAddressEq(l2Token, ETH_ADDRESS)) {
6457
+ return ETH_ADDRESS;
6458
+ }
6459
+ if (isAddressEq(l2Token, L2_BASE_TOKEN_ADDRESS)) {
6460
+ const { chainId } = await client.l2.getNetwork();
6461
+ return await client.baseToken(BigInt(chainId));
6462
+ }
6463
+ const { l2AssetRouter } = await client.contracts();
6464
+ const l1Token = await l2AssetRouter.l1TokenAddress(l2Token);
6465
+ return l1Token;
6466
+ });
6467
+ }
6468
+ async function assetIdOfL1(l1Token) {
6469
+ return wrapAs6("CONTRACT", "tokens.assetIdOfL1", async () => {
6470
+ const normalized = normalizeL1Token(l1Token);
6471
+ const { l1NativeTokenVault } = await client.contracts();
6472
+ const assetId = await l1NativeTokenVault.assetId(normalized);
6473
+ return assetId;
6474
+ });
6475
+ }
6476
+ async function assetIdOfL2(l2Token) {
6477
+ return wrapAs6("CONTRACT", "tokens.assetIdOfL2", async () => {
6478
+ const { l2NativeTokenVault } = await client.contracts();
6479
+ const assetId = await l2NativeTokenVault.assetId(l2Token);
6480
+ return assetId;
6481
+ });
6482
+ }
6483
+ async function l2TokenFromAssetId(assetId) {
6484
+ return wrapAs6("CONTRACT", "tokens.l2TokenFromAssetId", async () => {
6485
+ const { l2NativeTokenVault } = await client.contracts();
6486
+ const tokenAddr = await l2NativeTokenVault.tokenAddress(assetId);
6487
+ return tokenAddr;
6488
+ });
6489
+ }
6490
+ async function l1TokenFromAssetId(assetId) {
6491
+ return wrapAs6("CONTRACT", "tokens.l1TokenFromAssetId", async () => {
6492
+ const { l1NativeTokenVault } = await client.contracts();
6493
+ const tokenAddr = await l1NativeTokenVault.tokenAddress(assetId);
6494
+ return tokenAddr;
6495
+ });
6496
+ }
6497
+ async function originChainId(assetId) {
6498
+ return wrapAs6("CONTRACT", "tokens.originChainId", async () => {
6499
+ const { l2NativeTokenVault } = await client.contracts();
6500
+ const chainId = await l2NativeTokenVault.originChainId(assetId);
6501
+ return chainId;
6502
+ });
6503
+ }
6504
+ async function baseTokenAssetId() {
6505
+ return getBaseTokenAssetId();
6506
+ }
6507
+ async function isChainEthBased() {
6508
+ return wrapAs6("CONTRACT", "tokens.isChainEthBased", async () => {
6509
+ const baseAssetId = await getBaseTokenAssetId();
6510
+ const l1ChainId = await getL1ChainId();
6511
+ const ethAssetId = ntvCodec.encodeAssetId(
6512
+ l1ChainId,
6513
+ L2_NATIVE_TOKEN_VAULT_ADDRESS,
6514
+ ETH_ADDRESS
6515
+ );
6516
+ return hexEq(baseAssetId, ethAssetId);
6517
+ });
6518
+ }
6519
+ async function wethL1() {
6520
+ return getWethL1();
6521
+ }
6522
+ async function wethL2() {
6523
+ return getWethL2();
6524
+ }
6525
+ async function computeL2BridgedAddress(args) {
6526
+ return wrapAs6("CONTRACT", "tokens.computeL2BridgedAddress", async () => {
6527
+ const normalized = normalizeL1Token(args.l1Token);
6528
+ const { l2NativeTokenVault } = await client.contracts();
6529
+ const predicted = await l2NativeTokenVault.calculateCreate2TokenAddress(
6530
+ args.originChainId,
6531
+ normalized
6532
+ );
6533
+ return predicted;
6534
+ });
6535
+ }
6536
+ async function resolve(ref, opts) {
6537
+ return wrapAs6("CONTRACT", "tokens.resolve", async () => {
6538
+ let chain;
6539
+ let address;
6540
+ if (typeof ref === "string") {
6541
+ chain = opts?.chain ?? "l1";
6542
+ address = ref;
6543
+ } else {
6544
+ chain = ref.chain;
6545
+ address = ref.address;
6546
+ }
6547
+ let l1;
6548
+ let l2;
6549
+ if (chain === "l1") {
6550
+ l1 = normalizeL1Token(address);
6551
+ l2 = await toL2Address(address);
6552
+ } else {
6553
+ l2 = address;
6554
+ l1 = await toL1Address(address);
6555
+ }
6556
+ const assetId = await assetIdOfL1(l1);
6557
+ const originChainIdVal = await originChainId(assetId);
6558
+ const [baseAssetId, wethL1Addr, wethL2Addr, ethBased] = await Promise.all([
6559
+ baseTokenAssetId(),
6560
+ wethL1(),
6561
+ wethL2(),
6562
+ isChainEthBased()
6563
+ ]);
6564
+ let kind;
6565
+ if (isAddressEq(l1, ETH_ADDRESS)) {
6566
+ kind = "eth";
6567
+ } else if (hexEq(assetId, baseAssetId)) {
6568
+ kind = "base";
6569
+ } else {
6570
+ kind = "erc20";
6571
+ }
6572
+ return {
6573
+ kind,
6574
+ l1,
6575
+ l2,
6576
+ assetId,
6577
+ originChainId: originChainIdVal,
6578
+ isChainEthBased: ethBased,
6579
+ baseTokenAssetId: baseAssetId,
6580
+ wethL1: wethL1Addr,
6581
+ wethL2: wethL2Addr
6582
+ };
6583
+ });
6584
+ }
6585
+ return {
6586
+ resolve,
6587
+ toL2Address,
6588
+ toL1Address,
6589
+ assetIdOfL1,
6590
+ assetIdOfL2,
6591
+ l2TokenFromAssetId,
6592
+ l1TokenFromAssetId,
6593
+ originChainId,
6594
+ baseTokenAssetId,
6595
+ isChainEthBased,
6596
+ wethL1,
6597
+ wethL2,
6598
+ computeL2BridgedAddress
6599
+ };
6600
+ }
6601
+
6602
+ // src/adapters/ethers/resources/contracts/contracts.ts
6603
+ function createContractsResource(client) {
6604
+ async function addresses() {
6605
+ return client.ensureAddresses();
6606
+ }
6607
+ async function instances() {
6608
+ return client.contracts();
6609
+ }
6610
+ async function bridgehub() {
6611
+ const { bridgehub: bridgehub2 } = await instances();
6612
+ return bridgehub2;
6613
+ }
6614
+ async function l1AssetRouter() {
6615
+ const { l1AssetRouter: l1AssetRouter2 } = await instances();
6616
+ return l1AssetRouter2;
6617
+ }
6618
+ async function l1NativeTokenVault() {
6619
+ const { l1NativeTokenVault: l1NativeTokenVault2 } = await instances();
6620
+ return l1NativeTokenVault2;
6621
+ }
6622
+ async function l1Nullifier() {
6623
+ const { l1Nullifier: l1Nullifier2 } = await instances();
6624
+ return l1Nullifier2;
6625
+ }
6626
+ async function l2AssetRouter() {
6627
+ const { l2AssetRouter: l2AssetRouter2 } = await instances();
6628
+ return l2AssetRouter2;
6629
+ }
6630
+ async function l2NativeTokenVault() {
6631
+ const { l2NativeTokenVault: l2NativeTokenVault2 } = await instances();
6632
+ return l2NativeTokenVault2;
6633
+ }
6634
+ async function l2BaseTokenSystem() {
6635
+ const { l2BaseTokenSystem: l2BaseTokenSystem2 } = await instances();
6636
+ return l2BaseTokenSystem2;
6637
+ }
6638
+ return {
6639
+ addresses,
6640
+ instances,
6641
+ bridgehub,
6642
+ l1AssetRouter,
6643
+ l1NativeTokenVault,
6644
+ l1Nullifier,
6645
+ l2AssetRouter,
6646
+ l2NativeTokenVault,
6647
+ l2BaseTokenSystem
6648
+ };
6649
+ }
6650
+
6233
6651
  // src/adapters/ethers/resources/deposits/index.ts
6234
6652
  var { wrap, toResult } = createErrorHandlers("deposits");
6235
6653
  var ROUTES = {
@@ -6238,42 +6656,26 @@ var ROUTES = {
6238
6656
  "erc20-nonbase": routeErc20NonBase(),
6239
6657
  "erc20-base": routeErc20Base()
6240
6658
  };
6241
- function createDepositsResource(client) {
6659
+ function createDepositsResource(client, tokens, contracts) {
6660
+ const tokensResource = tokens ?? createTokensResource(client);
6661
+ const contractsResource = contracts ?? createContractsResource(client);
6242
6662
  async function buildPlan(p) {
6243
- const ctx = await commonCtx(p, client);
6663
+ const ctx = await commonCtx(p, client, tokensResource, contractsResource);
6244
6664
  const route = ctx.route;
6245
6665
  await ROUTES[route].preflight?.(p, ctx);
6246
- const { steps, approvals, quoteExtras } = await ROUTES[route].build(p, ctx);
6247
- const { baseCost, mintValue } = quoteExtras;
6248
- const fallbackGasLimit = quoteExtras.l1GasLimit;
6249
- const resolveGasLimit = () => {
6250
- if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
6251
- for (let i = steps.length - 1; i >= 0; i--) {
6252
- const candidate = steps[i].tx.gasLimit;
6253
- if (candidate == null) continue;
6254
- if (typeof candidate === "bigint") return candidate;
6255
- try {
6256
- return BigInt(candidate.toString());
6257
- } catch {
6258
- }
6259
- }
6260
- if (fallbackGasLimit != null) return fallbackGasLimit;
6261
- return ctx.l2GasLimit;
6262
- };
6263
- const gasLimit = resolveGasLimit();
6666
+ const { steps, approvals, fees } = await ROUTES[route].build(p, ctx);
6264
6667
  return {
6265
6668
  route: ctx.route,
6266
6669
  summary: {
6267
6670
  route: ctx.route,
6268
6671
  approvalsNeeded: approvals,
6269
- baseCost,
6270
- mintValue,
6271
- gasPerPubdata: ctx.gasPerPubdata,
6272
- fees: {
6273
- gasLimit,
6274
- maxFeePerGas: ctx.fee.maxFeePerGas,
6275
- maxPriorityFeePerGas: ctx.fee.maxPriorityFeePerGas
6276
- }
6672
+ amounts: {
6673
+ transfer: { token: p.token, amount: p.amount }
6674
+ },
6675
+ fees,
6676
+ // Legacy fields (maintained for backward compatibility)
6677
+ baseCost: fees.l2?.baseCost,
6678
+ mintValue: fees.mintValue
6277
6679
  },
6278
6680
  steps
6279
6681
  };
@@ -6342,7 +6744,7 @@ function createDepositsResource(client) {
6342
6744
  step.tx.maxPriorityFeePerGas = overrides.maxPriorityFeePerGas;
6343
6745
  }
6344
6746
  }
6345
- if (!step.tx.gasLimit) {
6747
+ if (!p.l1TxOverrides?.gasLimit) {
6346
6748
  try {
6347
6749
  const est = await client.l1.estimateGas(step.tx);
6348
6750
  step.tx.gasLimit = BigInt(est) * 115n / 100n;
@@ -6533,28 +6935,12 @@ function normalizeTokenForRouting(token) {
6533
6935
  function pickWithdrawRoute(args) {
6534
6936
  const tokenNorm = normalizeTokenForRouting(args.token);
6535
6937
  const isL2BaseAlias = tokenNorm.toLowerCase() === L2_BASE_TOKEN_ADDRESS.toLowerCase();
6536
- if (isL2BaseAlias) return args.baseIsEth ? "eth-base" : "eth-nonbase";
6938
+ if (isL2BaseAlias) return "base";
6537
6939
  return "erc20-nonbase";
6538
6940
  }
6539
- async function ntvBaseAssetId(l2, ntv) {
6540
- const c = new ethers.Contract(ntv, L2NativeTokenVault_default, l2);
6541
- return await c.BASE_TOKEN_ASSET_ID();
6542
- }
6543
- async function ntvL1ChainId(l2, ntv) {
6544
- const c = new ethers.Contract(ntv, L2NativeTokenVault_default, l2);
6545
- return await c.L1_CHAIN_ID();
6546
- }
6547
- async function isEthBasedChain(l2, ntv) {
6548
- const [baseAssetId, l1ChainId] = await Promise.all([
6549
- ntvBaseAssetId(l2, ntv),
6550
- ntvL1ChainId(l2, ntv)
6551
- ]);
6552
- const ethAssetId = encodeNativeTokenVaultAssetId(l1ChainId, ETH_ADDRESS);
6553
- return baseAssetId.toLowerCase() === ethAssetId.toLowerCase();
6554
- }
6555
6941
 
6556
6942
  // src/adapters/ethers/resources/withdrawals/context.ts
6557
- async function commonCtx2(p, client) {
6943
+ async function commonCtx2(p, client, tokens, contracts) {
6558
6944
  const sender = await client.signer.getAddress();
6559
6945
  const {
6560
6946
  bridgehub,
@@ -6563,16 +6949,21 @@ async function commonCtx2(p, client) {
6563
6949
  l2AssetRouter,
6564
6950
  l2NativeTokenVault,
6565
6951
  l2BaseTokenSystem
6566
- } = await client.ensureAddresses();
6952
+ } = await contracts.addresses();
6567
6953
  const { chainId } = await client.l2.getNetwork();
6568
6954
  const chainIdL2 = BigInt(chainId);
6569
- const baseIsEth = await isEthBasedChain(client.l2, l2NativeTokenVault);
6570
- const fee = await getL2FeeOverrides(client, p.l2TxOverrides);
6571
- const route = pickWithdrawRoute({ token: p.token, baseIsEth });
6572
- const l2GasLimit = p.l2GasLimit ?? 300000n;
6573
- const gasBufferPct = 15;
6955
+ const resolvedToken = await tokens.resolve(p.token, { chain: "l2" });
6956
+ const baseTokenAssetId = resolvedToken.baseTokenAssetId;
6957
+ const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
6958
+ const baseIsEth = resolvedToken.isChainEthBased;
6959
+ const route = pickWithdrawRoute({ token: p.token});
6574
6960
  return {
6575
6961
  client,
6962
+ tokens,
6963
+ contracts,
6964
+ resolvedToken,
6965
+ baseTokenAssetId,
6966
+ baseTokenL1,
6576
6967
  bridgehub,
6577
6968
  chainIdL2,
6578
6969
  sender,
@@ -6583,29 +6974,111 @@ async function commonCtx2(p, client) {
6583
6974
  l2NativeTokenVault,
6584
6975
  l2BaseTokenSystem,
6585
6976
  baseIsEth,
6586
- l2GasLimit,
6587
- gasBufferPct,
6588
- fee
6977
+ gasOverrides: p.l2TxOverrides
6978
+ };
6979
+ }
6980
+
6981
+ // src/core/resources/withdrawals/gas.ts
6982
+ function makeGasQuote2(p) {
6983
+ return {
6984
+ gasLimit: p.gasLimit,
6985
+ maxFeePerGas: p.maxFeePerGas,
6986
+ maxPriorityFeePerGas: p.maxPriorityFeePerGas,
6987
+ maxCost: p.gasLimit * p.maxFeePerGas
6988
+ };
6989
+ }
6990
+ async function fetchFees2(estimator) {
6991
+ try {
6992
+ const fees = await estimator.estimateFeesPerGas();
6993
+ if (fees.maxFeePerGas != null) {
6994
+ return {
6995
+ maxFeePerGas: fees.maxFeePerGas,
6996
+ maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
6997
+ };
6998
+ }
6999
+ if (fees.gasPrice != null) {
7000
+ return {
7001
+ maxFeePerGas: fees.gasPrice,
7002
+ maxPriorityFeePerGas: 0n
7003
+ };
7004
+ }
7005
+ } catch {
7006
+ }
7007
+ try {
7008
+ const gp = await estimator.getGasPrice();
7009
+ return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
7010
+ } catch {
7011
+ return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
7012
+ }
7013
+ }
7014
+ async function quoteL2Gas3(input) {
7015
+ const { estimator, tx, overrides } = input;
7016
+ const market = await fetchFees2(estimator);
7017
+ const o = overrides;
7018
+ const maxFeePerGas = o?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : market.maxFeePerGas);
7019
+ const maxPriorityFeePerGas = o?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : market.maxPriorityFeePerGas);
7020
+ const explicitGasLimit = o?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
7021
+ if (explicitGasLimit != null) {
7022
+ return makeGasQuote2({
7023
+ gasLimit: explicitGasLimit,
7024
+ maxFeePerGas,
7025
+ maxPriorityFeePerGas
7026
+ });
7027
+ }
7028
+ try {
7029
+ const est = await estimator.estimateGas(tx);
7030
+ const buffered = BigInt(est) * (100n + BUFFER) / 100n;
7031
+ return makeGasQuote2({
7032
+ gasLimit: buffered,
7033
+ maxFeePerGas,
7034
+ maxPriorityFeePerGas
7035
+ });
7036
+ } catch (err) {
7037
+ console.warn("Failed to estimate L2 gas for withdrawal.", err);
7038
+ return void 0;
7039
+ }
7040
+ }
7041
+
7042
+ // src/adapters/ethers/resources/withdrawals/services/gas.ts
7043
+ async function quoteL2Gas4(input) {
7044
+ const { ctx, tx } = input;
7045
+ const estimator = ethersToGasEstimator(ctx.client.l2);
7046
+ return quoteL2Gas3({
7047
+ estimator,
7048
+ tx: toCoreTx(tx),
7049
+ overrides: ctx.gasOverrides
7050
+ });
7051
+ }
7052
+
7053
+ // src/adapters/ethers/resources/withdrawals/services/fees.ts
7054
+ function buildFeeBreakdown2(p) {
7055
+ const l2Total = p.l2Gas?.maxCost ?? 0n;
7056
+ const l2 = {
7057
+ total: l2Total,
7058
+ gasLimit: p.l2Gas?.gasLimit ?? 0n,
7059
+ maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
7060
+ maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
7061
+ };
7062
+ return {
7063
+ token: p.feeToken,
7064
+ maxTotal: l2Total,
7065
+ l2
6589
7066
  };
6590
7067
  }
6591
- var { wrapAs: wrapAs5 } = createErrorHandlers("withdrawals");
7068
+
7069
+ // src/adapters/ethers/resources/withdrawals/routes/eth.ts
7070
+ var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
6592
7071
  function routeEthBase() {
6593
7072
  return {
6594
7073
  async build(p, ctx) {
6595
7074
  const steps = [];
6596
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
6597
- const base = new ethers.Contract(
6598
- L2_BASE_TOKEN_ADDRESS,
6599
- new ethers.Interface(IBaseToken_default),
6600
- ctx.client.l2
6601
- );
6602
- const toL1 = p.to ?? ctx.sender;
6603
- const data = await wrapAs5(
7075
+ const base = await ctx.contracts.l2BaseTokenSystem();
7076
+ const data = await wrapAs7(
6604
7077
  "INTERNAL",
6605
7078
  OP_WITHDRAWALS.eth.encodeWithdraw,
6606
- () => Promise.resolve(base.interface.encodeFunctionData("withdraw", [toL1])),
7079
+ () => Promise.resolve(base.interface.encodeFunctionData("withdraw", [p.to ?? ctx.sender])),
6607
7080
  {
6608
- ctx: { where: "L2BaseToken.withdraw", to: toL1 },
7081
+ ctx: { where: "L2BaseToken.withdraw", to: p.to ?? ctx.sender },
6609
7082
  message: "Failed to encode ETH withdraw calldata."
6610
7083
  }
6611
7084
  );
@@ -6613,38 +7086,29 @@ function routeEthBase() {
6613
7086
  to: L2_BASE_TOKEN_ADDRESS,
6614
7087
  data,
6615
7088
  from: ctx.sender,
6616
- value: p.amount,
6617
- maxFeePerGas,
6618
- maxPriorityFeePerGas
7089
+ value: p.amount
6619
7090
  };
6620
- if (overrideGasLimit != null) {
6621
- tx.gasLimit = overrideGasLimit;
6622
- } else {
6623
- try {
6624
- const est = await wrapAs5(
6625
- "RPC",
6626
- OP_WITHDRAWALS.eth.estGas,
6627
- () => ctx.client.l2.estimateGas(tx),
6628
- {
6629
- ctx: { where: "l2.estimateGas", to: L2_BASE_TOKEN_ADDRESS },
6630
- message: "Failed to estimate gas for L2 ETH withdraw."
6631
- }
6632
- );
6633
- tx.gasLimit = BigInt(est) * 115n / 100n;
6634
- } catch {
6635
- }
6636
- }
7091
+ const gas = await quoteL2Gas4({ ctx, tx });
7092
+ if (gas) {
7093
+ tx.gasLimit = gas.gasLimit;
7094
+ tx.maxFeePerGas = gas.maxFeePerGas;
7095
+ tx.maxPriorityFeePerGas = gas.maxPriorityFeePerGas;
7096
+ }
7097
+ const fees = buildFeeBreakdown2({
7098
+ feeToken: L2_BASE_TOKEN_ADDRESS,
7099
+ l2Gas: gas
7100
+ });
6637
7101
  steps.push({
6638
7102
  key: "l2-base-token:withdraw",
6639
7103
  kind: "l2-base-token:withdraw",
6640
7104
  description: "Withdraw ETH via L2 Base Token System",
6641
7105
  tx
6642
7106
  });
6643
- return { steps, approvals: [], quoteExtras: {} };
7107
+ return { steps, approvals: [], fees };
6644
7108
  }
6645
7109
  };
6646
7110
  }
6647
- var { wrapAs: wrapAs6 } = createErrorHandlers("withdrawals");
7111
+ var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
6648
7112
  var SIG = {
6649
7113
  withdraw: "withdraw(bytes32,bytes)"
6650
7114
  };
@@ -6653,10 +7117,8 @@ function routeErc20NonBase2() {
6653
7117
  async build(p, ctx) {
6654
7118
  const steps = [];
6655
7119
  const approvals = [];
6656
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
6657
- const txOverrides = overrideGasLimit != null ? { maxFeePerGas, maxPriorityFeePerGas, gasLimit: overrideGasLimit } : { maxFeePerGas, maxPriorityFeePerGas };
6658
7120
  const erc20 = new ethers.Contract(p.token, IERC20_default, ctx.client.getL2Signer());
6659
- const current = await wrapAs6(
7121
+ const current = await wrapAs8(
6660
7122
  "CONTRACT",
6661
7123
  OP_WITHDRAWALS.erc20.allowance,
6662
7124
  () => erc20.allowance(ctx.sender, ctx.l2NativeTokenVault),
@@ -6676,39 +7138,51 @@ function routeErc20NonBase2() {
6676
7138
  ctx.l2NativeTokenVault,
6677
7139
  p.amount
6678
7140
  ]);
7141
+ const approveTx = {
7142
+ to: p.token,
7143
+ data,
7144
+ from: ctx.sender
7145
+ };
7146
+ const approveGas = await quoteL2Gas4({ ctx, tx: approveTx });
7147
+ if (approveGas) {
7148
+ approveTx.gasLimit = approveGas.gasLimit;
7149
+ approveTx.maxFeePerGas = approveGas.maxFeePerGas;
7150
+ approveTx.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
7151
+ }
6679
7152
  steps.push({
6680
7153
  key: `approve:l2:${p.token}:${ctx.l2NativeTokenVault}`,
6681
7154
  kind: "approve:l2",
6682
7155
  description: `Approve ${p.amount} to NativeTokenVault`,
6683
- tx: { to: p.token, data, from: ctx.sender, ...txOverrides }
7156
+ tx: approveTx
6684
7157
  });
6685
7158
  }
6686
- const ntv = new ethers.Contract(ctx.l2NativeTokenVault, L2NativeTokenVault_default, ctx.client.l2);
6687
- const assetId = await wrapAs6(
7159
+ const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l2" }) : void 0);
7160
+ const assetId = resolved?.assetId ?? await wrapAs8(
6688
7161
  "CONTRACT",
6689
7162
  OP_WITHDRAWALS.erc20.ensureRegistered,
6690
- () => ntv.getFunction("ensureTokenIsRegistered").staticCall(p.token),
7163
+ async () => {
7164
+ const ntv = await ctx.contracts.l2NativeTokenVault();
7165
+ const ensured = await ntv.getFunction("ensureTokenIsRegistered").staticCall(p.token);
7166
+ return ensured;
7167
+ },
6691
7168
  {
6692
7169
  ctx: { where: "L2NativeTokenVault.ensureTokenIsRegistered", token: p.token },
6693
7170
  message: "Failed to ensure token is registered in L2NativeTokenVault."
6694
7171
  }
6695
7172
  );
6696
- const assetData = await wrapAs6(
7173
+ const assetData = await wrapAs8(
6697
7174
  "INTERNAL",
6698
7175
  OP_WITHDRAWALS.erc20.encodeAssetData,
6699
7176
  () => Promise.resolve(
6700
- ethers.AbiCoder.defaultAbiCoder().encode(
6701
- ["uint256", "address", "address"],
6702
- [p.amount, p.to ?? ctx.sender, p.token]
6703
- )
7177
+ encodeNativeTokenVaultTransferData(p.amount, p.to ?? ctx.sender, p.token)
6704
7178
  ),
6705
7179
  {
6706
7180
  ctx: { where: "AbiCoder.encode", token: p.token, to: p.to ?? ctx.sender },
6707
7181
  message: "Failed to encode burn/withdraw asset data."
6708
7182
  }
6709
7183
  );
6710
- const l2ar = new ethers.Contract(ctx.l2AssetRouter, IL2AssetRouter_default, ctx.client.l2);
6711
- const dataWithdraw = await wrapAs6(
7184
+ const l2ar = await ctx.contracts.l2AssetRouter();
7185
+ const dataWithdraw = await wrapAs8(
6712
7186
  "INTERNAL",
6713
7187
  OP_WITHDRAWALS.erc20.encodeWithdraw,
6714
7188
  () => Promise.resolve(l2ar.interface.encodeFunctionData(SIG.withdraw, [assetId, assetData])),
@@ -6720,81 +7194,25 @@ function routeErc20NonBase2() {
6720
7194
  const withdrawTx = {
6721
7195
  to: ctx.l2AssetRouter,
6722
7196
  data: dataWithdraw,
6723
- from: ctx.sender,
6724
- ...txOverrides
7197
+ from: ctx.sender
6725
7198
  };
7199
+ const withdrawGas = await quoteL2Gas4({ ctx, tx: withdrawTx });
7200
+ if (withdrawGas) {
7201
+ withdrawTx.gasLimit = withdrawGas.gasLimit;
7202
+ withdrawTx.maxFeePerGas = withdrawGas.maxFeePerGas;
7203
+ withdrawTx.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
7204
+ }
6726
7205
  steps.push({
6727
7206
  key: "l2-asset-router:withdraw",
6728
7207
  kind: "l2-asset-router:withdraw",
6729
7208
  description: "Burn on L2 & send L2\u2192L1 message",
6730
7209
  tx: withdrawTx
6731
7210
  });
6732
- return { steps, approvals, quoteExtras: {} };
6733
- }
6734
- };
6735
- }
6736
- var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
6737
- function routeEthNonBase2() {
6738
- return {
6739
- async preflight(p, ctx) {
6740
- await wrapAs7(
6741
- "VALIDATION",
6742
- OP_WITHDRAWALS.ethNonBase.assertNonEthBase,
6743
- () => {
6744
- if (p.token.toLowerCase() !== L2_BASE_TOKEN_ADDRESS.toLowerCase()) {
6745
- throw new Error("eth-nonbase route requires the L2 base-token alias (0x\u2026800A).");
6746
- }
6747
- if (ctx.baseIsEth) {
6748
- throw new Error("eth-nonbase route requires chain base \u2260 ETH.");
6749
- }
6750
- },
6751
- { ctx: { token: p.token, baseIsEth: ctx.baseIsEth } }
6752
- );
6753
- },
6754
- async build(p, ctx) {
6755
- const steps = [];
6756
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
6757
- const toL1 = p.to ?? ctx.sender;
6758
- const iface = new ethers.Interface(IBaseToken_default);
6759
- const data = await wrapAs7(
6760
- "INTERNAL",
6761
- OP_WITHDRAWALS.eth.encodeWithdraw,
6762
- // reuse label for base-token system call
6763
- () => Promise.resolve(iface.encodeFunctionData("withdraw", [toL1])),
6764
- { ctx: { where: "L2BaseToken.withdraw", to: toL1 } }
6765
- );
6766
- const tx = {
6767
- to: L2_BASE_TOKEN_ADDRESS,
6768
- data,
6769
- from: ctx.sender,
6770
- value: p.amount,
6771
- maxFeePerGas,
6772
- maxPriorityFeePerGas
6773
- };
6774
- if (overrideGasLimit != null) {
6775
- tx.gasLimit = overrideGasLimit;
6776
- } else {
6777
- try {
6778
- const est = await wrapAs7(
6779
- "RPC",
6780
- OP_WITHDRAWALS.eth.estGas,
6781
- () => ctx.client.l2.estimateGas(tx),
6782
- {
6783
- ctx: { where: "l2.estimateGas", to: L2_BASE_TOKEN_ADDRESS },
6784
- message: "Failed to estimate gas for L2 base-token withdraw."
6785
- }
6786
- );
6787
- tx.gasLimit = BigInt(est) * 115n / 100n;
6788
- } catch {
6789
- }
6790
- }
6791
- steps.push({
6792
- key: "l2-base-token:withdraw",
6793
- kind: "l2-base-token:withdraw",
6794
- description: "Withdraw base token via L2 Base Token System (base \u2260 ETH)",
6795
- tx
7211
+ const fees = buildFeeBreakdown2({
7212
+ feeToken: ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2),
7213
+ l2Gas: withdrawGas
6796
7214
  });
6797
- return { steps, approvals: [], quoteExtras: {} };
7215
+ return { steps, approvals, fees };
6798
7216
  }
6799
7217
  };
6800
7218
  }
@@ -6832,7 +7250,7 @@ function messengerLogIndex(raw, opts) {
6832
7250
  }
6833
7251
 
6834
7252
  // src/adapters/ethers/resources/withdrawals/services/finalization.ts
6835
- var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
7253
+ var { wrapAs: wrapAs9 } = createErrorHandlers("withdrawals");
6836
7254
  var IL1NullifierMini = [
6837
7255
  "function isWithdrawalFinalized(uint256,uint256,uint256) view returns (bool)"
6838
7256
  ];
@@ -6840,7 +7258,7 @@ function createFinalizationServices(client) {
6840
7258
  const { l1, l2, signer } = client;
6841
7259
  return {
6842
7260
  async fetchFinalizeDepositParams(l2TxHash) {
6843
- const parsed = await wrapAs8(
7261
+ const parsed = await wrapAs9(
6844
7262
  "RPC",
6845
7263
  OP_WITHDRAWALS.finalize.fetchParams.receipt,
6846
7264
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -6857,7 +7275,7 @@ function createFinalizationServices(client) {
6857
7275
  context: { l2TxHash }
6858
7276
  });
6859
7277
  }
6860
- const ev = await wrapAs8(
7278
+ const ev = await wrapAs9(
6861
7279
  "INTERNAL",
6862
7280
  OP_WITHDRAWALS.finalize.fetchParams.findMessage,
6863
7281
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
@@ -6867,7 +7285,7 @@ function createFinalizationServices(client) {
6867
7285
  message: "Failed to locate L1MessageSent event in L2 receipt."
6868
7286
  }
6869
7287
  );
6870
- const message = await wrapAs8(
7288
+ const message = await wrapAs9(
6871
7289
  "INTERNAL",
6872
7290
  OP_WITHDRAWALS.finalize.fetchParams.decodeMessage,
6873
7291
  () => Promise.resolve(ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], ev.data)[0]),
@@ -6876,7 +7294,7 @@ function createFinalizationServices(client) {
6876
7294
  message: "Failed to decode withdrawal message."
6877
7295
  }
6878
7296
  );
6879
- const raw = await wrapAs8(
7297
+ const raw = await wrapAs9(
6880
7298
  "RPC",
6881
7299
  OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
6882
7300
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -6893,7 +7311,7 @@ function createFinalizationServices(client) {
6893
7311
  context: { l2TxHash }
6894
7312
  });
6895
7313
  }
6896
- const idx = await wrapAs8(
7314
+ const idx = await wrapAs9(
6897
7315
  "INTERNAL",
6898
7316
  OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
6899
7317
  () => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
@@ -6902,7 +7320,7 @@ function createFinalizationServices(client) {
6902
7320
  message: "Failed to derive messenger log index."
6903
7321
  }
6904
7322
  );
6905
- const proof = await wrapAs8(
7323
+ const proof = await wrapAs9(
6906
7324
  "RPC",
6907
7325
  OP_WITHDRAWALS.finalize.fetchParams.proof,
6908
7326
  () => client.zks.getL2ToL1LogProof(l2TxHash, idx),
@@ -6911,7 +7329,7 @@ function createFinalizationServices(client) {
6911
7329
  message: "Failed to fetch L2\u2192L1 log proof."
6912
7330
  }
6913
7331
  );
6914
- const { chainId } = await wrapAs8(
7332
+ const { chainId } = await wrapAs9(
6915
7333
  "RPC",
6916
7334
  OP_WITHDRAWALS.finalize.fetchParams.network,
6917
7335
  () => l2.getNetwork(),
@@ -6930,7 +7348,7 @@ function createFinalizationServices(client) {
6930
7348
  message,
6931
7349
  merkleProof: proof.proof
6932
7350
  };
6933
- const { l1Nullifier } = await wrapAs8(
7351
+ const { l1Nullifier } = await wrapAs9(
6934
7352
  "INTERNAL",
6935
7353
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
6936
7354
  () => client.ensureAddresses(),
@@ -6942,7 +7360,7 @@ function createFinalizationServices(client) {
6942
7360
  return { params, nullifier: l1Nullifier };
6943
7361
  },
6944
7362
  async simulateFinalizeReadiness(params) {
6945
- const { l1Nullifier } = await wrapAs8(
7363
+ const { l1Nullifier } = await wrapAs9(
6946
7364
  "INTERNAL",
6947
7365
  OP_WITHDRAWALS.finalize.readiness.ensureAddresses,
6948
7366
  () => client.ensureAddresses(),
@@ -6954,7 +7372,7 @@ function createFinalizationServices(client) {
6954
7372
  const done = await (async () => {
6955
7373
  try {
6956
7374
  const cMini = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
6957
- const isFinalized = await wrapAs8(
7375
+ const isFinalized = await wrapAs9(
6958
7376
  "RPC",
6959
7377
  OP_WITHDRAWALS.finalize.readiness.isFinalized,
6960
7378
  () => cMini.isWithdrawalFinalized(
@@ -6982,7 +7400,7 @@ function createFinalizationServices(client) {
6982
7400
  }
6983
7401
  },
6984
7402
  async isWithdrawalFinalized(key) {
6985
- const { l1Nullifier } = await wrapAs8(
7403
+ const { l1Nullifier } = await wrapAs9(
6986
7404
  "INTERNAL",
6987
7405
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
6988
7406
  () => client.ensureAddresses(),
@@ -6992,7 +7410,7 @@ function createFinalizationServices(client) {
6992
7410
  }
6993
7411
  );
6994
7412
  const c = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
6995
- return await wrapAs8(
7413
+ return await wrapAs9(
6996
7414
  "RPC",
6997
7415
  OP_WITHDRAWALS.finalize.isFinalized,
6998
7416
  () => c.isWithdrawalFinalized(key.chainIdL2, key.l2BatchNumber, key.l2MessageIndex),
@@ -7003,7 +7421,7 @@ function createFinalizationServices(client) {
7003
7421
  );
7004
7422
  },
7005
7423
  async estimateFinalization(params) {
7006
- const { l1Nullifier } = await wrapAs8(
7424
+ const { l1Nullifier } = await wrapAs9(
7007
7425
  "INTERNAL",
7008
7426
  OP_WITHDRAWALS.finalize.estimate,
7009
7427
  () => client.ensureAddresses(),
@@ -7014,7 +7432,7 @@ function createFinalizationServices(client) {
7014
7432
  );
7015
7433
  const signer2 = client.getL1Signer();
7016
7434
  const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, signer2);
7017
- const gasLimit = await wrapAs8(
7435
+ const gasLimit = await wrapAs9(
7018
7436
  "RPC",
7019
7437
  OP_WITHDRAWALS.finalize.estimate,
7020
7438
  () => c.finalizeDeposit.estimateGas(params),
@@ -7029,7 +7447,7 @@ function createFinalizationServices(client) {
7029
7447
  message: "Failed to estimate gas for finalizeDeposit."
7030
7448
  }
7031
7449
  );
7032
- const feeData = await wrapAs8("RPC", OP_WITHDRAWALS.finalize.estimate, () => l1.getFeeData(), {
7450
+ const feeData = await wrapAs9("RPC", OP_WITHDRAWALS.finalize.estimate, () => l1.getFeeData(), {
7033
7451
  ctx: { where: "l1.getFeeData" },
7034
7452
  message: "Failed to estimate fee data for finalizeDeposit."
7035
7453
  });
@@ -7050,7 +7468,7 @@ function createFinalizationServices(client) {
7050
7468
  };
7051
7469
  },
7052
7470
  async finalizeDeposit(params) {
7053
- const { l1Nullifier } = await wrapAs8(
7471
+ const { l1Nullifier } = await wrapAs9(
7054
7472
  "INTERNAL",
7055
7473
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
7056
7474
  () => client.ensureAddresses(),
@@ -7106,45 +7524,32 @@ function createFinalizationServices(client) {
7106
7524
 
7107
7525
  // src/adapters/ethers/resources/withdrawals/index.ts
7108
7526
  var ROUTES2 = {
7109
- "eth-base": routeEthBase(),
7527
+ base: routeEthBase(),
7110
7528
  // BaseTokenSystem.withdraw, chain base = ETH
7111
- "eth-nonbase": routeEthNonBase2(),
7112
- // BaseTokenSystem.withdraw, chain base ≠ ETH
7113
7529
  "erc20-nonbase": routeErc20NonBase2()
7114
7530
  // AssetRouter.withdraw for non-base ERC-20s
7115
7531
  };
7116
- function createWithdrawalsResource(client) {
7532
+ function createWithdrawalsResource(client, tokens, contracts) {
7117
7533
  const svc = createFinalizationServices(client);
7118
7534
  const { wrap: wrap2, toResult: toResult2 } = createErrorHandlers("withdrawals");
7535
+ const tokensResource = tokens ?? createTokensResource(client);
7536
+ const contractsResource = contracts ?? createContractsResource(client);
7119
7537
  async function buildPlan(p) {
7120
- const ctx = await commonCtx2(p, client);
7538
+ const ctx = await commonCtx2(p, client, tokensResource, contractsResource);
7121
7539
  await ROUTES2[ctx.route].preflight?.(p, ctx);
7122
- const { steps, approvals } = await ROUTES2[ctx.route].build(p, ctx);
7123
- const resolveGasLimit = () => {
7124
- if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
7125
- for (let i = steps.length - 1; i >= 0; i--) {
7126
- const candidate = steps[i].tx.gasLimit;
7127
- if (candidate == null) continue;
7128
- if (typeof candidate === "bigint") return candidate;
7129
- try {
7130
- return BigInt(candidate.toString());
7131
- } catch {
7132
- }
7133
- }
7134
- return void 0;
7135
- };
7136
- const gasLimit = resolveGasLimit();
7137
- const summary = {
7540
+ const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
7541
+ return {
7138
7542
  route: ctx.route,
7139
- approvalsNeeded: approvals,
7140
- suggestedL2GasLimit: ctx.l2GasLimit,
7141
- fees: {
7142
- gasLimit,
7143
- maxFeePerGas: ctx.fee.maxFeePerGas,
7144
- maxPriorityFeePerGas: ctx.fee.maxPriorityFeePerGas
7145
- }
7543
+ summary: {
7544
+ route: ctx.route,
7545
+ approvalsNeeded: approvals,
7546
+ amounts: {
7547
+ transfer: { token: p.token, amount: p.amount }
7548
+ },
7549
+ fees
7550
+ },
7551
+ steps
7146
7552
  };
7147
- return { route: ctx.route, summary, steps };
7148
7553
  }
7149
7554
  const finalizeCache = /* @__PURE__ */ new Map();
7150
7555
  const quote = (p) => wrap2(
@@ -7454,62 +7859,17 @@ function createWithdrawalsResource(client) {
7454
7859
 
7455
7860
  // src/adapters/ethers/sdk.ts
7456
7861
  function createEthersSdk(client) {
7862
+ const tokens = createTokensResource(client);
7863
+ const contracts = createContractsResource(client);
7457
7864
  return {
7458
- deposits: createDepositsResource(client),
7459
- withdrawals: createWithdrawalsResource(client),
7460
- // TODO: might update to create dedicated resources for these
7461
- helpers: {
7462
- addresses: () => client.ensureAddresses(),
7463
- contracts: () => client.contracts(),
7464
- async l1AssetRouter() {
7465
- const { l1AssetRouter } = await client.contracts();
7466
- return l1AssetRouter;
7467
- },
7468
- async l1NativeTokenVault() {
7469
- const { l1NativeTokenVault } = await client.contracts();
7470
- return l1NativeTokenVault;
7471
- },
7472
- async l1Nullifier() {
7473
- const { l1Nullifier } = await client.contracts();
7474
- return l1Nullifier;
7475
- },
7476
- async baseToken(chainId) {
7477
- const id = chainId ?? BigInt((await client.l2.getNetwork()).chainId);
7478
- return client.baseToken(id);
7479
- },
7480
- async l2TokenAddress(l1Token) {
7481
- if (isAddressEq(l1Token, FORMAL_ETH_ADDRESS)) {
7482
- return ETH_ADDRESS;
7483
- }
7484
- const { chainId } = await client.l2.getNetwork();
7485
- const base = await client.baseToken(BigInt(chainId));
7486
- if (isAddressEq(l1Token, base)) {
7487
- return L2_BASE_TOKEN_ADDRESS;
7488
- }
7489
- const { l2NativeTokenVault } = await client.contracts();
7490
- const addr = await l2NativeTokenVault.l2TokenAddress(l1Token);
7491
- return addr;
7492
- },
7493
- async l1TokenAddress(l2Token) {
7494
- if (isAddressEq(l2Token, ETH_ADDRESS)) {
7495
- return ETH_ADDRESS;
7496
- }
7497
- const { l2AssetRouter } = await client.contracts();
7498
- const addr = await l2AssetRouter.l1TokenAddress(l2Token);
7499
- return addr;
7500
- },
7501
- async assetId(l1Token) {
7502
- const norm = isAddressEq(l1Token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : l1Token;
7503
- const { l1NativeTokenVault } = await client.contracts();
7504
- const id = await l1NativeTokenVault.assetId(norm);
7505
- return id;
7506
- }
7507
- }
7865
+ deposits: createDepositsResource(client, tokens, contracts),
7866
+ withdrawals: createWithdrawalsResource(client, tokens, contracts),
7867
+ tokens,
7868
+ contracts
7508
7869
  };
7509
7870
  }
7510
7871
 
7511
7872
  exports.buildDirectRequestStruct = buildDirectRequestStruct;
7512
- exports.checkBaseCost = checkBaseCost;
7513
7873
  exports.classifyReadinessFromRevert = classifyReadinessFromRevert;
7514
7874
  exports.createClient = createEthersClient;
7515
7875
  exports.createDepositsResource = createDepositsResource;
@@ -7517,21 +7877,15 @@ exports.createErrorHandlers = createErrorHandlers;
7517
7877
  exports.createEthersClient = createEthersClient;
7518
7878
  exports.createEthersSdk = createEthersSdk;
7519
7879
  exports.createFinalizationServices = createFinalizationServices;
7880
+ exports.createTokensResource = createTokensResource;
7520
7881
  exports.createWithdrawalsResource = createWithdrawalsResource;
7521
7882
  exports.decodeRevert = decodeRevert;
7522
- exports.encodeNTVAssetId = encodeNTVAssetId;
7523
- exports.encodeNTVTransferData = encodeNTVTransferData;
7524
- exports.encodeNativeTokenVaultAssetId = encodeNativeTokenVaultAssetId;
7525
7883
  exports.encodeNativeTokenVaultTransferData = encodeNativeTokenVaultTransferData;
7526
7884
  exports.encodeSecondBridgeArgs = encodeSecondBridgeArgs;
7527
7885
  exports.encodeSecondBridgeDataV1 = encodeSecondBridgeDataV1;
7528
7886
  exports.encodeSecondBridgeErc20Args = encodeSecondBridgeErc20Args;
7529
7887
  exports.encodeSecondBridgeEthArgs = encodeSecondBridgeEthArgs;
7530
- exports.getFeeOverrides = getFeeOverrides;
7531
- exports.getGasPriceWei = getGasPriceWei;
7532
- exports.getL2FeeOverrides = getL2FeeOverrides;
7533
7888
  exports.registerErrorAbi = registerErrorAbi;
7534
- exports.scaleGasLimit = scaleGasLimit;
7535
7889
  exports.toZKsyncError = toZKsyncError;
7536
7890
  //# sourceMappingURL=index.cjs.map
7537
7891
  //# sourceMappingURL=index.cjs.map