@matterlabs/zksync-js 0.0.1 → 0.0.2

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 (80) 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 +934 -801
  7. package/dist/adapters/ethers/index.cjs.map +1 -1
  8. package/dist/adapters/ethers/index.js +9 -8
  9. package/dist/adapters/ethers/resources/deposits/context.d.ts +5 -5
  10. package/dist/adapters/ethers/resources/deposits/routes/types.d.ts +2 -6
  11. package/dist/adapters/ethers/resources/deposits/services/fee.d.ts +6 -0
  12. package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +40 -0
  13. package/dist/adapters/ethers/resources/utils.d.ts +4 -15
  14. package/dist/adapters/ethers/resources/withdrawals/context.d.ts +4 -4
  15. package/dist/adapters/ethers/resources/withdrawals/routes/types.d.ts +2 -2
  16. package/dist/adapters/ethers/resources/withdrawals/services/fees.d.ts +14 -0
  17. package/dist/adapters/ethers/resources/withdrawals/services/gas.d.ts +12 -0
  18. package/dist/adapters/ethers/sdk.cjs +947 -1292
  19. package/dist/adapters/ethers/sdk.cjs.map +1 -1
  20. package/dist/adapters/ethers/sdk.js +7 -6
  21. package/dist/adapters/viem/client.cjs.map +1 -1
  22. package/dist/adapters/viem/client.d.ts +1 -1
  23. package/dist/adapters/viem/client.js +4 -5
  24. package/dist/adapters/viem/estimator.d.ts +4 -0
  25. package/dist/adapters/viem/index.cjs +944 -662
  26. package/dist/adapters/viem/index.cjs.map +1 -1
  27. package/dist/adapters/viem/index.js +8 -8
  28. package/dist/adapters/viem/resources/deposits/context.d.ts +5 -5
  29. package/dist/adapters/viem/resources/deposits/routes/types.d.ts +2 -6
  30. package/dist/adapters/viem/resources/deposits/services/fee.d.ts +6 -0
  31. package/dist/adapters/viem/resources/deposits/services/gas.d.ts +36 -0
  32. package/dist/adapters/viem/resources/utils.d.ts +3 -16
  33. package/dist/adapters/viem/resources/withdrawals/context.d.ts +3 -6
  34. package/dist/adapters/viem/resources/withdrawals/routes/types.d.ts +12 -2
  35. package/dist/adapters/viem/resources/withdrawals/services/fee.d.ts +17 -0
  36. package/dist/adapters/viem/resources/withdrawals/services/gas.d.ts +12 -0
  37. package/dist/adapters/viem/sdk.cjs +877 -563
  38. package/dist/adapters/viem/sdk.cjs.map +1 -1
  39. package/dist/adapters/viem/sdk.d.ts +1 -1
  40. package/dist/adapters/viem/sdk.js +6 -6
  41. package/dist/{chunk-3LALBFFE.js → chunk-3MRGU4HV.js} +9 -5
  42. package/dist/{chunk-4HLJJKIY.js → chunk-6K6VJQAL.js} +2 -2
  43. package/dist/{chunk-CGO27P7F.js → chunk-BCCKWWOX.js} +540 -741
  44. package/dist/{chunk-6GCT6TLS.js → chunk-F2ENUV3A.js} +13 -1
  45. package/dist/{chunk-DI2CJDPZ.js → chunk-HLUANWGN.js} +2 -2
  46. package/dist/{chunk-Y75OMFK6.js → chunk-M5J2MM2U.js} +351 -1
  47. package/dist/{chunk-263G6636.js → chunk-NCAIVYBR.js} +1 -14
  48. package/dist/{chunk-7M4V3FMT.js → chunk-OC6ZVLSP.js} +669 -559
  49. package/dist/chunk-QJS6ETEE.js +217 -0
  50. package/dist/chunk-XRE7H466.js +157 -0
  51. package/dist/{chunk-BD2LUO5T.js → chunk-YUK547UF.js} +3 -3
  52. package/dist/core/abi.d.ts +9 -0
  53. package/dist/core/adapters/interfaces.d.ts +25 -0
  54. package/dist/core/constants.cjs +12 -0
  55. package/dist/core/constants.cjs.map +1 -1
  56. package/dist/core/constants.d.ts +6 -0
  57. package/dist/core/constants.js +1 -1
  58. package/dist/core/index.cjs +4504 -1
  59. package/dist/core/index.cjs.map +1 -1
  60. package/dist/core/index.d.ts +1 -0
  61. package/dist/core/index.js +4 -4
  62. package/dist/core/resources/deposits/fee.d.ts +15 -0
  63. package/dist/core/resources/deposits/gas.d.ts +38 -0
  64. package/dist/core/resources/withdrawals/gas.d.ts +14 -0
  65. package/dist/core/types/errors.d.ts +1 -1
  66. package/dist/core/types/fees.d.ts +40 -0
  67. package/dist/core/types/flows/base.d.ts +0 -10
  68. package/dist/core/types/flows/deposits.d.ts +20 -6
  69. package/dist/core/types/flows/route.d.ts +2 -3
  70. package/dist/core/types/flows/withdrawals.d.ts +12 -6
  71. package/dist/index.cjs +4516 -1
  72. package/dist/index.cjs.map +1 -1
  73. package/dist/index.d.ts +1 -0
  74. package/dist/index.js +4 -4
  75. package/package.json +5 -1
  76. package/dist/adapters/ethers/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
  77. package/dist/adapters/viem/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
  78. package/dist/chunk-B77GWPO5.js +0 -339
  79. package/dist/core/internal/abi-registry.d.ts +0 -9
  80. package/dist/core/utils/gas.d.ts +0 -13
@@ -16,6 +16,12 @@ var TOPIC_L1_MESSAGE_SENT_NEW = k256hex("L1MessageSent(uint256,bytes32,bytes)");
16
16
  var TOPIC_L1_MESSAGE_SENT_LEG = k256hex("L1MessageSent(address,bytes32,bytes)");
17
17
  var TOPIC_CANONICAL_ASSIGNED = "0x779f441679936c5441b671969f37400b8c3ed0071cb47444431bf985754560df";
18
18
  var TOPIC_CANONICAL_SUCCESS = "0xe4def01b981193a97a9e81230d7b9f31812ceaf23f864a828a82c687911cb2df";
19
+ var BUFFER = 20n;
20
+ var TX_OVERHEAD_GAS = 10000n;
21
+ var TX_MEMORY_OVERHEAD_GAS = 10n;
22
+ var DEFAULT_PUBDATA_BYTES = 155n;
23
+ var DEFAULT_ABI_BYTES = 400n;
24
+ var SAFE_L1_BRIDGE_GAS = 600000n;
19
25
 
20
26
  // src/core/utils/addr.ts
21
27
  var isHash66 = (x) => !!x && x.startsWith("0x") && x.length === 66;
@@ -246,36 +252,17 @@ var OP_DEPOSITS = {
246
252
  base: {
247
253
  assertErc20Asset: "deposits.erc20-base:assertErc20Asset",
248
254
  assertMatchesBase: "deposits.erc20-base:assertMatchesBase",
249
- baseToken: "deposits.erc20-base:baseToken",
250
- allowance: "deposits.erc20-base:allowance",
251
- baseCost: "deposits.erc20-base:l2TransactionBaseCost",
252
- estGas: "deposits.erc20-base:estimateGas"
253
- },
255
+ allowance: "deposits.erc20-base:allowance"},
254
256
  nonbase: {
255
- baseToken: "deposits.erc20-nonbase:baseToken",
256
- assertNotEthAsset: "deposits.erc20-nonbase:assertNotEthAsset",
257
- allowance: "deposits.erc20-nonbase:allowance",
258
- allowanceFees: "deposits.erc20-nonbase:allowanceFeesBaseToken",
259
- baseCost: "deposits.erc20-nonbase:l2TransactionBaseCost",
260
257
  encodeCalldata: "deposits.erc20-nonbase:encodeSecondBridgeErc20Args",
261
- estGas: "deposits.erc20-nonbase:estimateGas",
262
- assertBaseIsEth: "deposits.erc20-nonbase:assertBaseIsEth",
263
- assertBaseIsErc20: "deposits.erc20-nonbase:assertBaseIsErc20",
264
258
  assertNonBaseToken: "deposits.erc20-nonbase:assertNonBaseToken",
265
259
  allowanceToken: "deposits.erc20-nonbase:allowanceToken",
266
260
  allowanceBase: "deposits.erc20-nonbase:allowanceBase"
267
261
  },
268
- eth: {
269
- baseCost: "deposits.eth:l2TransactionBaseCost",
270
- estGas: "deposits.eth:estimateGas"
271
- },
272
262
  ethNonBase: {
273
- baseToken: "deposits.eth-nonbase:baseToken",
274
- baseCost: "deposits.eth-nonbase:l2TransactionBaseCost",
275
263
  allowanceBase: "deposits.eth-nonbase:allowanceBaseToken",
276
264
  ethBalance: "deposits.eth-nonbase:getEthBalance",
277
265
  encodeCalldata: "deposits.eth-nonbase:encodeSecondBridgeEthArgs",
278
- estGas: "deposits.eth-nonbase:estimateGas",
279
266
  assertEthAsset: "deposits.eth-nonbase:assertEthAsset",
280
267
  assertNonEthBase: "deposits.eth-nonbase:assertNonEthBase",
281
268
  assertEthBalance: "deposits.eth-nonbase:assertEthBalance"
@@ -2203,39 +2190,49 @@ var IL1NullifierABI = [
2203
2190
  ];
2204
2191
  var IL1Nullifier_default = IL1NullifierABI;
2205
2192
 
2206
- // src/core/internal/abis/IL2AssetRouter.ts
2207
- var IL2AssetRouterABI = [
2193
+ // src/core/internal/abis/L1NativeTokenVault.ts
2194
+ var L1NativeTokenVaultABI = [
2195
+ {
2196
+ type: "constructor",
2197
+ inputs: [
2198
+ { name: "_l1WethAddress", type: "address", internalType: "address" },
2199
+ { name: "_l1AssetRouter", type: "address", internalType: "address" },
2200
+ { name: "_l1Nullifier", type: "address", internalType: "contract IL1Nullifier" }
2201
+ ],
2202
+ stateMutability: "nonpayable"
2203
+ },
2204
+ { type: "receive", stateMutability: "payable" },
2208
2205
  {
2209
2206
  type: "function",
2210
- name: "BASE_TOKEN_ASSET_ID",
2207
+ name: "ASSET_ROUTER",
2211
2208
  inputs: [],
2212
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
2209
+ outputs: [{ name: "", type: "address", internalType: "contract IAssetRouterBase" }],
2213
2210
  stateMutability: "view"
2214
2211
  },
2215
2212
  {
2216
2213
  type: "function",
2217
- name: "BRIDGE_HUB",
2214
+ name: "BASE_TOKEN_ASSET_ID",
2218
2215
  inputs: [],
2219
- outputs: [{ name: "", type: "address", internalType: "contract IBridgehub" }],
2216
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
2220
2217
  stateMutability: "view"
2221
2218
  },
2222
2219
  {
2223
2220
  type: "function",
2224
- name: "L1_ASSET_ROUTER",
2221
+ name: "L1_CHAIN_ID",
2225
2222
  inputs: [],
2226
- outputs: [{ name: "", type: "address", internalType: "address" }],
2223
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2227
2224
  stateMutability: "view"
2228
2225
  },
2229
2226
  {
2230
2227
  type: "function",
2231
- name: "L1_CHAIN_ID",
2228
+ name: "L1_NULLIFIER",
2232
2229
  inputs: [],
2233
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2230
+ outputs: [{ name: "", type: "address", internalType: "contract IL1Nullifier" }],
2234
2231
  stateMutability: "view"
2235
2232
  },
2236
2233
  {
2237
2234
  type: "function",
2238
- name: "L2_LEGACY_SHARED_BRIDGE",
2235
+ name: "WETH_TOKEN",
2239
2236
  inputs: [],
2240
2237
  outputs: [{ name: "", type: "address", internalType: "address" }],
2241
2238
  stateMutability: "view"
@@ -2249,44 +2246,53 @@ var IL2AssetRouterABI = [
2249
2246
  },
2250
2247
  {
2251
2248
  type: "function",
2252
- name: "assetDeploymentTracker",
2253
- inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2254
- outputs: [{ name: "assetDeploymentTracker", type: "address", internalType: "address" }],
2255
- stateMutability: "view"
2249
+ name: "addLegacyTokenToBridgedTokensList",
2250
+ inputs: [{ name: "_token", type: "address", internalType: "address" }],
2251
+ outputs: [],
2252
+ stateMutability: "nonpayable"
2256
2253
  },
2257
2254
  {
2258
2255
  type: "function",
2259
- name: "assetHandlerAddress",
2260
- inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2261
- outputs: [{ name: "assetHandlerAddress", type: "address", internalType: "address" }],
2256
+ name: "assetId",
2257
+ inputs: [{ name: "tokenAddress", type: "address", internalType: "address" }],
2258
+ outputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2262
2259
  stateMutability: "view"
2263
2260
  },
2264
2261
  {
2265
2262
  type: "function",
2266
- name: "eraChainId",
2267
- inputs: [],
2268
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2269
- stateMutability: "view"
2263
+ name: "bridgeBurn",
2264
+ inputs: [
2265
+ { name: "_chainId", type: "uint256", internalType: "uint256" },
2266
+ { name: "_l2MsgValue", type: "uint256", internalType: "uint256" },
2267
+ { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2268
+ { name: "_originalCaller", type: "address", internalType: "address" },
2269
+ { name: "_data", type: "bytes", internalType: "bytes" }
2270
+ ],
2271
+ outputs: [{ name: "_bridgeMintData", type: "bytes", internalType: "bytes" }],
2272
+ stateMutability: "payable"
2270
2273
  },
2271
2274
  {
2272
2275
  type: "function",
2273
- name: "finalizeDeposit",
2276
+ name: "bridgeCheckCounterpartAddress",
2274
2277
  inputs: [
2275
2278
  { name: "", type: "uint256", internalType: "uint256" },
2276
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2277
- { name: "_transferData", type: "bytes", internalType: "bytes" }
2279
+ { name: "", type: "bytes32", internalType: "bytes32" },
2280
+ { name: "", type: "address", internalType: "address" },
2281
+ {
2282
+ name: "_assetHandlerAddressOnCounterpart",
2283
+ type: "address",
2284
+ internalType: "address"
2285
+ }
2278
2286
  ],
2279
2287
  outputs: [],
2280
- stateMutability: "payable"
2288
+ stateMutability: "view"
2281
2289
  },
2282
2290
  {
2283
2291
  type: "function",
2284
- name: "finalizeDeposit",
2292
+ name: "bridgeMint",
2285
2293
  inputs: [
2286
- { name: "_l1Sender", type: "address", internalType: "address" },
2287
- { name: "_l2Receiver", type: "address", internalType: "address" },
2288
- { name: "_l1Token", type: "address", internalType: "address" },
2289
- { name: "_amount", type: "uint256", internalType: "uint256" },
2294
+ { name: "_chainId", type: "uint256", internalType: "uint256" },
2295
+ { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2290
2296
  { name: "_data", type: "bytes", internalType: "bytes" }
2291
2297
  ],
2292
2298
  outputs: [],
@@ -2294,50 +2300,96 @@ var IL2AssetRouterABI = [
2294
2300
  },
2295
2301
  {
2296
2302
  type: "function",
2297
- name: "finalizeDepositLegacyBridge",
2303
+ name: "bridgeRecoverFailedTransfer",
2298
2304
  inputs: [
2299
- { name: "_l1Sender", type: "address", internalType: "address" },
2300
- { name: "_l2Receiver", type: "address", internalType: "address" },
2301
- { name: "_l1Token", type: "address", internalType: "address" },
2302
- { name: "_amount", type: "uint256", internalType: "uint256" },
2305
+ { name: "_chainId", type: "uint256", internalType: "uint256" },
2306
+ { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2307
+ { name: "_depositSender", type: "address", internalType: "address" },
2303
2308
  { name: "_data", type: "bytes", internalType: "bytes" }
2304
2309
  ],
2305
2310
  outputs: [],
2306
- stateMutability: "nonpayable"
2311
+ stateMutability: "payable"
2312
+ },
2313
+ {
2314
+ type: "function",
2315
+ name: "bridgedTokenBeacon",
2316
+ inputs: [],
2317
+ outputs: [{ name: "", type: "address", internalType: "contract IBeacon" }],
2318
+ stateMutability: "view"
2319
+ },
2320
+ {
2321
+ type: "function",
2322
+ name: "bridgedTokens",
2323
+ inputs: [{ name: "count", type: "uint256", internalType: "uint256" }],
2324
+ outputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2325
+ stateMutability: "view"
2326
+ },
2327
+ {
2328
+ type: "function",
2329
+ name: "bridgedTokensCount",
2330
+ inputs: [],
2331
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2332
+ stateMutability: "view"
2307
2333
  },
2308
2334
  {
2309
2335
  type: "function",
2310
- name: "initL2",
2336
+ name: "calculateCreate2TokenAddress",
2311
2337
  inputs: [
2312
- { name: "_l1ChainId", type: "uint256", internalType: "uint256" },
2313
- { name: "_eraChainId", type: "uint256", internalType: "uint256" },
2314
- { name: "_l1AssetRouter", type: "address", internalType: "address" },
2315
- { name: "_legacySharedBridge", type: "address", internalType: "address" },
2316
- { name: "_baseTokenAssetId", type: "bytes32", internalType: "bytes32" },
2317
- { name: "_aliasedOwner", type: "address", internalType: "address" }
2338
+ { name: "_originChainId", type: "uint256", internalType: "uint256" },
2339
+ { name: "_nonNativeToken", type: "address", internalType: "address" }
2318
2340
  ],
2319
- outputs: [],
2341
+ outputs: [{ name: "", type: "address", internalType: "address" }],
2342
+ stateMutability: "view"
2343
+ },
2344
+ {
2345
+ type: "function",
2346
+ name: "chainBalance",
2347
+ inputs: [
2348
+ { name: "_chainId", type: "uint256", internalType: "uint256" },
2349
+ { name: "_assetId", type: "bytes32", internalType: "bytes32" }
2350
+ ],
2351
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2352
+ stateMutability: "view"
2353
+ },
2354
+ {
2355
+ type: "function",
2356
+ name: "ensureTokenIsRegistered",
2357
+ inputs: [{ name: "_nativeToken", type: "address", internalType: "address" }],
2358
+ outputs: [{ name: "tokenAssetId", type: "bytes32", internalType: "bytes32" }],
2320
2359
  stateMutability: "nonpayable"
2321
2360
  },
2322
2361
  {
2323
2362
  type: "function",
2324
- name: "l1Bridge",
2325
- inputs: [],
2326
- outputs: [{ name: "", type: "address", internalType: "address" }],
2363
+ name: "getERC20Getters",
2364
+ inputs: [
2365
+ { name: "_token", type: "address", internalType: "address" },
2366
+ { name: "_originChainId", type: "uint256", internalType: "uint256" }
2367
+ ],
2368
+ outputs: [{ name: "", type: "bytes", internalType: "bytes" }],
2327
2369
  stateMutability: "view"
2328
2370
  },
2329
2371
  {
2330
2372
  type: "function",
2331
- name: "l1TokenAddress",
2332
- inputs: [{ name: "_l2Token", type: "address", internalType: "address" }],
2333
- outputs: [{ name: "", type: "address", internalType: "address" }],
2373
+ name: "initialize",
2374
+ inputs: [
2375
+ { name: "_owner", type: "address", internalType: "address" },
2376
+ { name: "_bridgedTokenBeacon", type: "address", internalType: "address" }
2377
+ ],
2378
+ outputs: [],
2379
+ stateMutability: "nonpayable"
2380
+ },
2381
+ {
2382
+ type: "function",
2383
+ name: "l1AssetTracker",
2384
+ inputs: [],
2385
+ outputs: [{ name: "", type: "address", internalType: "contract IL1AssetTracker" }],
2334
2386
  stateMutability: "view"
2335
2387
  },
2336
2388
  {
2337
2389
  type: "function",
2338
- name: "l2TokenAddress",
2339
- inputs: [{ name: "_l1Token", type: "address", internalType: "address" }],
2340
- outputs: [{ name: "", type: "address", internalType: "address" }],
2390
+ name: "originChainId",
2391
+ inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2392
+ outputs: [{ name: "originChainId", type: "uint256", internalType: "uint256" }],
2341
2393
  stateMutability: "view"
2342
2394
  },
2343
2395
  {
@@ -2370,610 +2422,140 @@ var IL2AssetRouterABI = [
2370
2422
  },
2371
2423
  {
2372
2424
  type: "function",
2373
- name: "renounceOwnership",
2425
+ name: "registerEthToken",
2374
2426
  inputs: [],
2375
2427
  outputs: [],
2376
2428
  stateMutability: "nonpayable"
2377
2429
  },
2378
2430
  {
2379
2431
  type: "function",
2380
- name: "setAssetHandlerAddress",
2381
- inputs: [
2382
- { name: "_originChainId", type: "uint256", internalType: "uint256" },
2383
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2384
- { name: "_assetHandlerAddress", type: "address", internalType: "address" }
2385
- ],
2432
+ name: "registerToken",
2433
+ inputs: [{ name: "_nativeToken", type: "address", internalType: "address" }],
2386
2434
  outputs: [],
2387
2435
  stateMutability: "nonpayable"
2388
2436
  },
2389
2437
  {
2390
2438
  type: "function",
2391
- name: "setAssetHandlerAddressThisChain",
2392
- inputs: [
2393
- { name: "_assetRegistrationData", type: "bytes32", internalType: "bytes32" },
2394
- { name: "_assetHandlerAddress", type: "address", internalType: "address" }
2395
- ],
2439
+ name: "renounceOwnership",
2440
+ inputs: [],
2396
2441
  outputs: [],
2397
2442
  stateMutability: "nonpayable"
2398
2443
  },
2399
2444
  {
2400
2445
  type: "function",
2401
- name: "setLegacyTokenAssetHandler",
2402
- inputs: [{ name: "_assetId", type: "bytes32", internalType: "bytes32" }],
2446
+ name: "setAssetTracker",
2447
+ inputs: [{ name: "_l1AssetTracker", type: "address", internalType: "address" }],
2403
2448
  outputs: [],
2404
2449
  stateMutability: "nonpayable"
2405
2450
  },
2406
2451
  {
2407
2452
  type: "function",
2408
- name: "transferOwnership",
2409
- inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
2410
- outputs: [],
2411
- stateMutability: "nonpayable"
2453
+ name: "tokenAddress",
2454
+ inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2455
+ outputs: [{ name: "tokenAddress", type: "address", internalType: "address" }],
2456
+ stateMutability: "view"
2412
2457
  },
2413
2458
  {
2414
2459
  type: "function",
2415
- name: "unpause",
2416
- inputs: [],
2417
- outputs: [],
2418
- stateMutability: "nonpayable"
2460
+ name: "tokenDataOriginChainId",
2461
+ inputs: [{ name: "_erc20Data", type: "bytes", internalType: "bytes" }],
2462
+ outputs: [{ name: "tokenOriginChainId", type: "uint256", internalType: "uint256" }],
2463
+ stateMutability: "view"
2419
2464
  },
2420
2465
  {
2421
2466
  type: "function",
2422
- name: "updateL2",
2423
- inputs: [
2424
- { name: "_l1ChainId", type: "uint256", internalType: "uint256" },
2425
- { name: "_eraChainId", type: "uint256", internalType: "uint256" },
2426
- { name: "_l1AssetRouter", type: "address", internalType: "address" },
2427
- { name: "_legacySharedBridge", type: "address", internalType: "address" },
2428
- { name: "_baseTokenAssetId", type: "bytes32", internalType: "bytes32" }
2429
- ],
2467
+ name: "transferOwnership",
2468
+ inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
2430
2469
  outputs: [],
2431
2470
  stateMutability: "nonpayable"
2432
2471
  },
2433
2472
  {
2434
2473
  type: "function",
2435
- name: "withdraw",
2474
+ name: "tryRegisterTokenFromBurnData",
2436
2475
  inputs: [
2437
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2438
- { name: "_assetData", type: "bytes", internalType: "bytes" }
2476
+ { name: "_burnData", type: "bytes", internalType: "bytes" },
2477
+ { name: "_expectedAssetId", type: "bytes32", internalType: "bytes32" }
2439
2478
  ],
2440
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
2479
+ outputs: [],
2441
2480
  stateMutability: "nonpayable"
2442
2481
  },
2443
2482
  {
2444
2483
  type: "function",
2445
- name: "withdraw",
2446
- inputs: [
2447
- { name: "_l1Receiver", type: "address", internalType: "address" },
2448
- { name: "_l2Token", type: "address", internalType: "address" },
2449
- { name: "_amount", type: "uint256", internalType: "uint256" }
2450
- ],
2484
+ name: "unpause",
2485
+ inputs: [],
2451
2486
  outputs: [],
2452
2487
  stateMutability: "nonpayable"
2453
2488
  },
2454
2489
  {
2455
- type: "function",
2456
- name: "withdrawLegacyBridge",
2490
+ type: "event",
2491
+ name: "BridgeBurn",
2457
2492
  inputs: [
2458
- { name: "_l1Receiver", type: "address", internalType: "address" },
2459
- { name: "_l2Token", type: "address", internalType: "address" },
2460
- { name: "_amount", type: "uint256", internalType: "uint256" },
2461
- { name: "_sender", type: "address", internalType: "address" }
2493
+ { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2494
+ { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2495
+ { name: "sender", type: "address", indexed: true, internalType: "address" },
2496
+ { name: "receiver", type: "address", indexed: false, internalType: "address" },
2497
+ { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
2462
2498
  ],
2463
- outputs: [],
2464
- stateMutability: "nonpayable"
2499
+ anonymous: false
2465
2500
  },
2466
2501
  {
2467
2502
  type: "event",
2468
- name: "AssetDeploymentTrackerRegistered",
2503
+ name: "BridgeMint",
2469
2504
  inputs: [
2505
+ { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2470
2506
  { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2471
- { name: "additionalData", type: "bytes32", indexed: true, internalType: "bytes32" },
2472
- {
2473
- name: "assetDeploymentTracker",
2474
- type: "address",
2475
- indexed: false,
2476
- internalType: "address"
2477
- }
2507
+ { name: "receiver", type: "address", indexed: false, internalType: "address" },
2508
+ { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
2478
2509
  ],
2479
2510
  anonymous: false
2480
2511
  },
2481
2512
  {
2482
2513
  type: "event",
2483
- name: "AssetHandlerRegistered",
2514
+ name: "BridgedTokenBeaconUpdated",
2484
2515
  inputs: [
2485
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2486
2516
  {
2487
- name: "_assetHandlerAddress",
2517
+ name: "bridgedTokenBeacon",
2488
2518
  type: "address",
2489
- indexed: true,
2519
+ indexed: false,
2490
2520
  internalType: "address"
2521
+ },
2522
+ {
2523
+ name: "bridgedTokenProxyBytecodeHash",
2524
+ type: "bytes32",
2525
+ indexed: false,
2526
+ internalType: "bytes32"
2491
2527
  }
2492
2528
  ],
2493
2529
  anonymous: false
2494
2530
  },
2495
2531
  {
2496
2532
  type: "event",
2497
- name: "BridgehubDepositBaseTokenInitiated",
2498
- inputs: [
2499
- { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2500
- { name: "from", type: "address", indexed: true, internalType: "address" },
2501
- { name: "assetId", type: "bytes32", indexed: false, internalType: "bytes32" },
2502
- { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
2503
- ],
2533
+ name: "Initialized",
2534
+ inputs: [{ name: "version", type: "uint8", indexed: false, internalType: "uint8" }],
2504
2535
  anonymous: false
2505
2536
  },
2506
2537
  {
2507
2538
  type: "event",
2508
- name: "BridgehubDepositInitiated",
2539
+ name: "OwnershipTransferStarted",
2509
2540
  inputs: [
2510
- { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2511
- { name: "txDataHash", type: "bytes32", indexed: true, internalType: "bytes32" },
2512
- { name: "from", type: "address", indexed: true, internalType: "address" },
2513
- { name: "assetId", type: "bytes32", indexed: false, internalType: "bytes32" },
2514
- { name: "bridgeMintCalldata", type: "bytes", indexed: false, internalType: "bytes" }
2541
+ { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2542
+ { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2515
2543
  ],
2516
2544
  anonymous: false
2517
2545
  },
2518
2546
  {
2519
2547
  type: "event",
2520
- name: "BridgehubWithdrawalInitiated",
2548
+ name: "OwnershipTransferred",
2521
2549
  inputs: [
2522
- { name: "chainId", type: "uint256", indexed: false, internalType: "uint256" },
2523
- { name: "sender", type: "address", indexed: true, internalType: "address" },
2524
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2525
- { name: "assetDataHash", type: "bytes32", indexed: false, internalType: "bytes32" }
2550
+ { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2551
+ { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2526
2552
  ],
2527
2553
  anonymous: false
2528
2554
  },
2529
2555
  {
2530
2556
  type: "event",
2531
- name: "DepositFinalizedAssetRouter",
2532
- inputs: [
2533
- { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2534
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2535
- { name: "assetData", type: "bytes", indexed: false, internalType: "bytes" }
2536
- ],
2537
- anonymous: false
2538
- },
2539
- {
2540
- type: "event",
2541
- name: "Initialized",
2542
- inputs: [{ name: "version", type: "uint8", indexed: false, internalType: "uint8" }],
2543
- anonymous: false
2544
- },
2545
- {
2546
- type: "event",
2547
- name: "OwnershipTransferStarted",
2548
- inputs: [
2549
- { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2550
- { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2551
- ],
2552
- anonymous: false
2553
- },
2554
- {
2555
- type: "event",
2556
- name: "OwnershipTransferred",
2557
- inputs: [
2558
- { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2559
- { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2560
- ],
2561
- anonymous: false
2562
- },
2563
- {
2564
- type: "event",
2565
- name: "Paused",
2566
- inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
2567
- anonymous: false
2568
- },
2569
- {
2570
- type: "event",
2571
- name: "Unpaused",
2572
- inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
2573
- anonymous: false
2574
- },
2575
- {
2576
- type: "event",
2577
- name: "WithdrawalInitiatedAssetRouter",
2578
- inputs: [
2579
- { name: "chainId", type: "uint256", indexed: false, internalType: "uint256" },
2580
- { name: "l2Sender", type: "address", indexed: true, internalType: "address" },
2581
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2582
- { name: "assetData", type: "bytes", indexed: false, internalType: "bytes" }
2583
- ],
2584
- anonymous: false
2585
- },
2586
- { type: "error", name: "AmountMustBeGreaterThanZero", inputs: [] },
2587
- {
2588
- type: "error",
2589
- name: "AssetIdNotSupported",
2590
- inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }]
2591
- },
2592
- { type: "error", name: "EmptyAddress", inputs: [] },
2593
- {
2594
- type: "error",
2595
- name: "InvalidCaller",
2596
- inputs: [{ name: "", type: "address", internalType: "address" }]
2597
- },
2598
- { type: "error", name: "InvalidNTVBurnData", inputs: [] },
2599
- { type: "error", name: "NotInitializedReentrancyGuard", inputs: [] },
2600
- { type: "error", name: "Reentrancy", inputs: [] },
2601
- { type: "error", name: "SlotOccupied", inputs: [] },
2602
- { type: "error", name: "TokenNotLegacy", inputs: [] },
2603
- {
2604
- type: "error",
2605
- name: "Unauthorized",
2606
- inputs: [{ name: "caller", type: "address", internalType: "address" }]
2607
- }
2608
- ];
2609
- var IL2AssetRouter_default = IL2AssetRouterABI;
2610
-
2611
- // src/core/internal/abis/L1NativeTokenVault.ts
2612
- var L1NativeTokenVaultABI = [
2613
- {
2614
- type: "constructor",
2615
- inputs: [
2616
- { name: "_l1WethAddress", type: "address", internalType: "address" },
2617
- { name: "_l1AssetRouter", type: "address", internalType: "address" },
2618
- { name: "_l1Nullifier", type: "address", internalType: "contract IL1Nullifier" }
2619
- ],
2620
- stateMutability: "nonpayable"
2621
- },
2622
- { type: "receive", stateMutability: "payable" },
2623
- {
2624
- type: "function",
2625
- name: "ASSET_ROUTER",
2626
- inputs: [],
2627
- outputs: [{ name: "", type: "address", internalType: "contract IAssetRouterBase" }],
2628
- stateMutability: "view"
2629
- },
2630
- {
2631
- type: "function",
2632
- name: "BASE_TOKEN_ASSET_ID",
2633
- inputs: [],
2634
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
2635
- stateMutability: "view"
2636
- },
2637
- {
2638
- type: "function",
2639
- name: "L1_CHAIN_ID",
2640
- inputs: [],
2641
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2642
- stateMutability: "view"
2643
- },
2644
- {
2645
- type: "function",
2646
- name: "L1_NULLIFIER",
2647
- inputs: [],
2648
- outputs: [{ name: "", type: "address", internalType: "contract IL1Nullifier" }],
2649
- stateMutability: "view"
2650
- },
2651
- {
2652
- type: "function",
2653
- name: "WETH_TOKEN",
2654
- inputs: [],
2655
- outputs: [{ name: "", type: "address", internalType: "address" }],
2656
- stateMutability: "view"
2657
- },
2658
- {
2659
- type: "function",
2660
- name: "acceptOwnership",
2661
- inputs: [],
2662
- outputs: [],
2663
- stateMutability: "nonpayable"
2664
- },
2665
- {
2666
- type: "function",
2667
- name: "addLegacyTokenToBridgedTokensList",
2668
- inputs: [{ name: "_token", type: "address", internalType: "address" }],
2669
- outputs: [],
2670
- stateMutability: "nonpayable"
2671
- },
2672
- {
2673
- type: "function",
2674
- name: "assetId",
2675
- inputs: [{ name: "tokenAddress", type: "address", internalType: "address" }],
2676
- outputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2677
- stateMutability: "view"
2678
- },
2679
- {
2680
- type: "function",
2681
- name: "bridgeBurn",
2682
- inputs: [
2683
- { name: "_chainId", type: "uint256", internalType: "uint256" },
2684
- { name: "_l2MsgValue", type: "uint256", internalType: "uint256" },
2685
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2686
- { name: "_originalCaller", type: "address", internalType: "address" },
2687
- { name: "_data", type: "bytes", internalType: "bytes" }
2688
- ],
2689
- outputs: [{ name: "_bridgeMintData", type: "bytes", internalType: "bytes" }],
2690
- stateMutability: "payable"
2691
- },
2692
- {
2693
- type: "function",
2694
- name: "bridgeCheckCounterpartAddress",
2695
- inputs: [
2696
- { name: "", type: "uint256", internalType: "uint256" },
2697
- { name: "", type: "bytes32", internalType: "bytes32" },
2698
- { name: "", type: "address", internalType: "address" },
2699
- {
2700
- name: "_assetHandlerAddressOnCounterpart",
2701
- type: "address",
2702
- internalType: "address"
2703
- }
2704
- ],
2705
- outputs: [],
2706
- stateMutability: "view"
2707
- },
2708
- {
2709
- type: "function",
2710
- name: "bridgeMint",
2711
- inputs: [
2712
- { name: "_chainId", type: "uint256", internalType: "uint256" },
2713
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2714
- { name: "_data", type: "bytes", internalType: "bytes" }
2715
- ],
2716
- outputs: [],
2717
- stateMutability: "payable"
2718
- },
2719
- {
2720
- type: "function",
2721
- name: "bridgeRecoverFailedTransfer",
2722
- inputs: [
2723
- { name: "_chainId", type: "uint256", internalType: "uint256" },
2724
- { name: "_assetId", type: "bytes32", internalType: "bytes32" },
2725
- { name: "_depositSender", type: "address", internalType: "address" },
2726
- { name: "_data", type: "bytes", internalType: "bytes" }
2727
- ],
2728
- outputs: [],
2729
- stateMutability: "payable"
2730
- },
2731
- {
2732
- type: "function",
2733
- name: "bridgedTokenBeacon",
2734
- inputs: [],
2735
- outputs: [{ name: "", type: "address", internalType: "contract IBeacon" }],
2736
- stateMutability: "view"
2737
- },
2738
- {
2739
- type: "function",
2740
- name: "bridgedTokens",
2741
- inputs: [{ name: "count", type: "uint256", internalType: "uint256" }],
2742
- outputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2743
- stateMutability: "view"
2744
- },
2745
- {
2746
- type: "function",
2747
- name: "bridgedTokensCount",
2748
- inputs: [],
2749
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2750
- stateMutability: "view"
2751
- },
2752
- {
2753
- type: "function",
2754
- name: "calculateCreate2TokenAddress",
2755
- inputs: [
2756
- { name: "_originChainId", type: "uint256", internalType: "uint256" },
2757
- { name: "_nonNativeToken", type: "address", internalType: "address" }
2758
- ],
2759
- outputs: [{ name: "", type: "address", internalType: "address" }],
2760
- stateMutability: "view"
2761
- },
2762
- {
2763
- type: "function",
2764
- name: "chainBalance",
2765
- inputs: [
2766
- { name: "_chainId", type: "uint256", internalType: "uint256" },
2767
- { name: "_assetId", type: "bytes32", internalType: "bytes32" }
2768
- ],
2769
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
2770
- stateMutability: "view"
2771
- },
2772
- {
2773
- type: "function",
2774
- name: "ensureTokenIsRegistered",
2775
- inputs: [{ name: "_nativeToken", type: "address", internalType: "address" }],
2776
- outputs: [{ name: "tokenAssetId", type: "bytes32", internalType: "bytes32" }],
2777
- stateMutability: "nonpayable"
2778
- },
2779
- {
2780
- type: "function",
2781
- name: "getERC20Getters",
2782
- inputs: [
2783
- { name: "_token", type: "address", internalType: "address" },
2784
- { name: "_originChainId", type: "uint256", internalType: "uint256" }
2785
- ],
2786
- outputs: [{ name: "", type: "bytes", internalType: "bytes" }],
2787
- stateMutability: "view"
2788
- },
2789
- {
2790
- type: "function",
2791
- name: "initialize",
2792
- inputs: [
2793
- { name: "_owner", type: "address", internalType: "address" },
2794
- { name: "_bridgedTokenBeacon", type: "address", internalType: "address" }
2795
- ],
2796
- outputs: [],
2797
- stateMutability: "nonpayable"
2798
- },
2799
- {
2800
- type: "function",
2801
- name: "l1AssetTracker",
2802
- inputs: [],
2803
- outputs: [{ name: "", type: "address", internalType: "contract IL1AssetTracker" }],
2804
- stateMutability: "view"
2805
- },
2806
- {
2807
- type: "function",
2808
- name: "originChainId",
2809
- inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2810
- outputs: [{ name: "originChainId", type: "uint256", internalType: "uint256" }],
2811
- stateMutability: "view"
2812
- },
2813
- {
2814
- type: "function",
2815
- name: "owner",
2816
- inputs: [],
2817
- outputs: [{ name: "", type: "address", internalType: "address" }],
2818
- stateMutability: "view"
2819
- },
2820
- {
2821
- type: "function",
2822
- name: "pause",
2823
- inputs: [],
2824
- outputs: [],
2825
- stateMutability: "nonpayable"
2826
- },
2827
- {
2828
- type: "function",
2829
- name: "paused",
2830
- inputs: [],
2831
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
2832
- stateMutability: "view"
2833
- },
2834
- {
2835
- type: "function",
2836
- name: "pendingOwner",
2837
- inputs: [],
2838
- outputs: [{ name: "", type: "address", internalType: "address" }],
2839
- stateMutability: "view"
2840
- },
2841
- {
2842
- type: "function",
2843
- name: "registerEthToken",
2844
- inputs: [],
2845
- outputs: [],
2846
- stateMutability: "nonpayable"
2847
- },
2848
- {
2849
- type: "function",
2850
- name: "registerToken",
2851
- inputs: [{ name: "_nativeToken", type: "address", internalType: "address" }],
2852
- outputs: [],
2853
- stateMutability: "nonpayable"
2854
- },
2855
- {
2856
- type: "function",
2857
- name: "renounceOwnership",
2858
- inputs: [],
2859
- outputs: [],
2860
- stateMutability: "nonpayable"
2861
- },
2862
- {
2863
- type: "function",
2864
- name: "setAssetTracker",
2865
- inputs: [{ name: "_l1AssetTracker", type: "address", internalType: "address" }],
2866
- outputs: [],
2867
- stateMutability: "nonpayable"
2868
- },
2869
- {
2870
- type: "function",
2871
- name: "tokenAddress",
2872
- inputs: [{ name: "assetId", type: "bytes32", internalType: "bytes32" }],
2873
- outputs: [{ name: "tokenAddress", type: "address", internalType: "address" }],
2874
- stateMutability: "view"
2875
- },
2876
- {
2877
- type: "function",
2878
- name: "tokenDataOriginChainId",
2879
- inputs: [{ name: "_erc20Data", type: "bytes", internalType: "bytes" }],
2880
- outputs: [{ name: "tokenOriginChainId", type: "uint256", internalType: "uint256" }],
2881
- stateMutability: "view"
2882
- },
2883
- {
2884
- type: "function",
2885
- name: "transferOwnership",
2886
- inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
2887
- outputs: [],
2888
- stateMutability: "nonpayable"
2889
- },
2890
- {
2891
- type: "function",
2892
- name: "tryRegisterTokenFromBurnData",
2893
- inputs: [
2894
- { name: "_burnData", type: "bytes", internalType: "bytes" },
2895
- { name: "_expectedAssetId", type: "bytes32", internalType: "bytes32" }
2896
- ],
2897
- outputs: [],
2898
- stateMutability: "nonpayable"
2899
- },
2900
- {
2901
- type: "function",
2902
- name: "unpause",
2903
- inputs: [],
2904
- outputs: [],
2905
- stateMutability: "nonpayable"
2906
- },
2907
- {
2908
- type: "event",
2909
- name: "BridgeBurn",
2910
- inputs: [
2911
- { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2912
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2913
- { name: "sender", type: "address", indexed: true, internalType: "address" },
2914
- { name: "receiver", type: "address", indexed: false, internalType: "address" },
2915
- { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
2916
- ],
2917
- anonymous: false
2918
- },
2919
- {
2920
- type: "event",
2921
- name: "BridgeMint",
2922
- inputs: [
2923
- { name: "chainId", type: "uint256", indexed: true, internalType: "uint256" },
2924
- { name: "assetId", type: "bytes32", indexed: true, internalType: "bytes32" },
2925
- { name: "receiver", type: "address", indexed: false, internalType: "address" },
2926
- { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
2927
- ],
2928
- anonymous: false
2929
- },
2930
- {
2931
- type: "event",
2932
- name: "BridgedTokenBeaconUpdated",
2933
- inputs: [
2934
- {
2935
- name: "bridgedTokenBeacon",
2936
- type: "address",
2937
- indexed: false,
2938
- internalType: "address"
2939
- },
2940
- {
2941
- name: "bridgedTokenProxyBytecodeHash",
2942
- type: "bytes32",
2943
- indexed: false,
2944
- internalType: "bytes32"
2945
- }
2946
- ],
2947
- anonymous: false
2948
- },
2949
- {
2950
- type: "event",
2951
- name: "Initialized",
2952
- inputs: [{ name: "version", type: "uint8", indexed: false, internalType: "uint8" }],
2953
- anonymous: false
2954
- },
2955
- {
2956
- type: "event",
2957
- name: "OwnershipTransferStarted",
2958
- inputs: [
2959
- { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2960
- { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2961
- ],
2962
- anonymous: false
2963
- },
2964
- {
2965
- type: "event",
2966
- name: "OwnershipTransferred",
2967
- inputs: [
2968
- { name: "previousOwner", type: "address", indexed: true, internalType: "address" },
2969
- { name: "newOwner", type: "address", indexed: true, internalType: "address" }
2970
- ],
2971
- anonymous: false
2972
- },
2973
- {
2974
- type: "event",
2975
- name: "Paused",
2976
- inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
2557
+ name: "Paused",
2558
+ inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
2977
2559
  anonymous: false
2978
2560
  },
2979
2561
  {
@@ -3468,103 +3050,6 @@ var L2NativeTokenVaultABI = [
3468
3050
  ];
3469
3051
  var L2NativeTokenVault_default = L2NativeTokenVaultABI;
3470
3052
 
3471
- // src/core/internal/abis/IBaseToken.ts
3472
- var IBaseTokenABI = [
3473
- {
3474
- type: "function",
3475
- name: "balanceOf",
3476
- inputs: [{ name: "", type: "uint256", internalType: "uint256" }],
3477
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
3478
- stateMutability: "view"
3479
- },
3480
- {
3481
- type: "function",
3482
- name: "mint",
3483
- inputs: [
3484
- { name: "_account", type: "address", internalType: "address" },
3485
- { name: "_amount", type: "uint256", internalType: "uint256" }
3486
- ],
3487
- outputs: [],
3488
- stateMutability: "nonpayable"
3489
- },
3490
- {
3491
- type: "function",
3492
- name: "totalSupply",
3493
- inputs: [],
3494
- outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
3495
- stateMutability: "view"
3496
- },
3497
- {
3498
- type: "function",
3499
- name: "transferFromTo",
3500
- inputs: [
3501
- { name: "_from", type: "address", internalType: "address" },
3502
- { name: "_to", type: "address", internalType: "address" },
3503
- { name: "_amount", type: "uint256", internalType: "uint256" }
3504
- ],
3505
- outputs: [],
3506
- stateMutability: "nonpayable"
3507
- },
3508
- {
3509
- type: "function",
3510
- name: "withdraw",
3511
- inputs: [{ name: "_l1Receiver", type: "address", internalType: "address" }],
3512
- outputs: [],
3513
- stateMutability: "payable"
3514
- },
3515
- {
3516
- type: "function",
3517
- name: "withdrawWithMessage",
3518
- inputs: [
3519
- { name: "_l1Receiver", type: "address", internalType: "address" },
3520
- { name: "_additionalData", type: "bytes", internalType: "bytes" }
3521
- ],
3522
- outputs: [],
3523
- stateMutability: "payable"
3524
- },
3525
- {
3526
- type: "event",
3527
- name: "Mint",
3528
- inputs: [
3529
- { name: "account", type: "address", indexed: true, internalType: "address" },
3530
- { name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
3531
- ],
3532
- anonymous: false
3533
- },
3534
- {
3535
- type: "event",
3536
- name: "Transfer",
3537
- inputs: [
3538
- { name: "from", type: "address", indexed: true, internalType: "address" },
3539
- { name: "to", type: "address", indexed: true, internalType: "address" },
3540
- { name: "value", type: "uint256", indexed: false, internalType: "uint256" }
3541
- ],
3542
- anonymous: false
3543
- },
3544
- {
3545
- type: "event",
3546
- name: "Withdrawal",
3547
- inputs: [
3548
- { name: "_l2Sender", type: "address", indexed: true, internalType: "address" },
3549
- { name: "_l1Receiver", type: "address", indexed: true, internalType: "address" },
3550
- { name: "_amount", type: "uint256", indexed: false, internalType: "uint256" }
3551
- ],
3552
- anonymous: false
3553
- },
3554
- {
3555
- type: "event",
3556
- name: "WithdrawalWithMessage",
3557
- inputs: [
3558
- { name: "_l2Sender", type: "address", indexed: true, internalType: "address" },
3559
- { name: "_l1Receiver", type: "address", indexed: true, internalType: "address" },
3560
- { name: "_amount", type: "uint256", indexed: false, internalType: "uint256" },
3561
- { name: "_additionalData", type: "bytes", indexed: false, internalType: "bytes" }
3562
- ],
3563
- anonymous: false
3564
- }
3565
- ];
3566
- var IBaseToken_default = IBaseTokenABI;
3567
-
3568
3053
  // src/core/internal/abis/IERC20.ts
3569
3054
  var IERC20ABI = [
3570
3055
  {
@@ -4071,22 +3556,38 @@ var MailboxABI = [
4071
3556
  ];
4072
3557
  var Mailbox_default = MailboxABI;
4073
3558
 
4074
- // src/core/utils/gas.ts
4075
- function assertNoLegacyGas(overrides) {
4076
- if (!overrides) return;
4077
- if ("gasPrice" in overrides && overrides.gasPrice !== void 0) {
4078
- throw new Error("Legacy gasPrice is not supported; use EIP-1559 fields instead.");
4079
- }
4080
- }
4081
- function assertPriorityFeeBounds(fees) {
4082
- if (fees.maxPriorityFeePerGas > fees.maxFeePerGas) {
4083
- throw new Error("maxPriorityFeePerGas cannot exceed maxFeePerGas.");
3559
+ // src/core/resources/deposits/route.ts
3560
+ async function pickDepositRoute(client, chainIdL2, token) {
3561
+ if (isETH(token)) {
3562
+ const base2 = await client.baseToken(chainIdL2);
3563
+ return isETH(base2) ? "eth-base" : "eth-nonbase";
4084
3564
  }
3565
+ const base = await client.baseToken(chainIdL2);
3566
+ return normalizeAddrEq(token, base) ? "erc20-base" : "erc20-nonbase";
4085
3567
  }
4086
3568
 
4087
- // src/adapters/ethers/resources/utils.ts
4088
- function supportsGetGasPrice(provider) {
4089
- return typeof provider === "object" && provider !== null && typeof provider.getGasPrice === "function";
3569
+ // src/adapters/ethers/resources/deposits/context.ts
3570
+ async function commonCtx(p, client) {
3571
+ const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
3572
+ const { chainId } = await client.l2.getNetwork();
3573
+ const sender = await client.signer.getAddress();
3574
+ const gasPerPubdata = p.gasPerPubdata ?? 800n;
3575
+ const operatorTip = p.operatorTip ?? 0n;
3576
+ const refundRecipient = p.refundRecipient ?? sender;
3577
+ const route = await pickDepositRoute(client, BigInt(chainId), p.token);
3578
+ return {
3579
+ client,
3580
+ l1AssetRouter,
3581
+ route,
3582
+ bridgehub,
3583
+ chainIdL2: BigInt(chainId),
3584
+ sender,
3585
+ gasOverrides: p.l1TxOverrides,
3586
+ l2GasLimit: p.l2GasLimit,
3587
+ gasPerPubdata,
3588
+ operatorTip,
3589
+ refundRecipient
3590
+ };
4090
3591
  }
4091
3592
  function encodeNativeTokenVaultAssetId(chainId, address) {
4092
3593
  const abi = new ethers.AbiCoder();
@@ -4096,58 +3597,20 @@ function encodeNativeTokenVaultAssetId(chainId, address) {
4096
3597
  );
4097
3598
  return ethers.ethers.keccak256(hex);
4098
3599
  }
4099
- async function getFeeOverrides(client, overrides) {
4100
- assertNoLegacyGas(overrides);
4101
- const fd = await client.l1.getFeeData();
4102
- const maxFeeFromProvider = fd.maxFeePerGas ?? void 0;
4103
- const maxPriorityFromProvider = fd.maxPriorityFeePerGas ?? void 0;
4104
- const gasPriceFallback = fd.gasPrice ?? void 0;
4105
- const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback;
4106
- if (maxFeePerGas == null) throw new Error("provider returned no gas price data");
4107
- const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
4108
- assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
4109
- const gasPriceForBaseCost = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback ?? maxFeePerGas;
4110
- return {
4111
- gasLimit: overrides?.gasLimit,
4112
- maxFeePerGas,
4113
- maxPriorityFeePerGas,
4114
- gasPriceForBaseCost
4115
- };
3600
+ function encodeNativeTokenVaultTransferData(amount, receiver, token) {
3601
+ return new ethers.AbiCoder().encode(["uint256", "address", "address"], [amount, receiver, token]);
4116
3602
  }
4117
- async function getL2FeeOverrides(client, overrides) {
4118
- assertNoLegacyGas(overrides);
4119
- let maxFeeFromProvider;
4120
- let maxPriorityFromProvider;
4121
- let gasPriceFallback;
4122
- try {
4123
- const fd = await client.l2.getFeeData();
4124
- if (fd?.maxFeePerGas != null) maxFeeFromProvider = fd.maxFeePerGas;
4125
- if (fd?.maxPriorityFeePerGas != null) {
4126
- maxPriorityFromProvider = fd.maxPriorityFeePerGas;
4127
- }
4128
- if (fd?.gasPrice != null) gasPriceFallback = fd.gasPrice;
4129
- } catch {
4130
- }
4131
- if (gasPriceFallback == null) {
4132
- try {
4133
- if (supportsGetGasPrice(client.l2)) {
4134
- const gp = await client.l2.getGasPrice();
4135
- gasPriceFallback = typeof gp === "bigint" ? gp : BigInt(gp.toString());
4136
- }
4137
- } catch {
4138
- }
4139
- }
4140
- const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeeFromProvider ?? gasPriceFallback;
4141
- if (maxFeePerGas == null) {
4142
- throw new Error("L2 provider returned no gas price data");
4143
- }
4144
- const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
4145
- assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
4146
- return {
4147
- gasLimit: overrides?.gasLimit,
4148
- maxFeePerGas,
4149
- maxPriorityFeePerGas
4150
- };
3603
+ function encodeSecondBridgeArgs(token, amount, l2Receiver) {
3604
+ return ethers.AbiCoder.defaultAbiCoder().encode(
3605
+ ["address", "uint256", "address"],
3606
+ [token, amount, l2Receiver]
3607
+ );
3608
+ }
3609
+ function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
3610
+ return encodeSecondBridgeArgs(token, amount, l2Receiver);
3611
+ }
3612
+ function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
3613
+ return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
4151
3614
  }
4152
3615
  function buildDirectRequestStruct(args) {
4153
3616
  return {
@@ -4162,52 +3625,197 @@ function buildDirectRequestStruct(args) {
4162
3625
  refundRecipient: args.refundRecipient
4163
3626
  };
4164
3627
  }
4165
- function encodeSecondBridgeArgs(token, amount, l2Receiver) {
4166
- return ethers.AbiCoder.defaultAbiCoder().encode(
4167
- ["address", "uint256", "address"],
4168
- [token, amount, l2Receiver]
4169
- );
3628
+
3629
+ // src/core/resources/deposits/gas.ts
3630
+ function makeGasQuote(p) {
3631
+ const maxPriorityFeePerGas = p.maxPriorityFeePerGas ?? 0n;
3632
+ return {
3633
+ gasLimit: p.gasLimit,
3634
+ maxFeePerGas: p.maxFeePerGas,
3635
+ maxPriorityFeePerGas,
3636
+ gasPerPubdata: p.gasPerPubdata,
3637
+ maxCost: p.gasLimit * p.maxFeePerGas
3638
+ };
4170
3639
  }
4171
- function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
4172
- return encodeSecondBridgeArgs(token, amount, l2Receiver);
3640
+ async function fetchFees(estimator) {
3641
+ try {
3642
+ const fees = await estimator.estimateFeesPerGas();
3643
+ if (fees.maxFeePerGas != null) {
3644
+ return {
3645
+ maxFeePerGas: fees.maxFeePerGas,
3646
+ maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
3647
+ };
3648
+ }
3649
+ if (fees.gasPrice != null) {
3650
+ return {
3651
+ maxFeePerGas: fees.gasPrice,
3652
+ maxPriorityFeePerGas: 0n
3653
+ };
3654
+ }
3655
+ } catch {
3656
+ }
3657
+ try {
3658
+ const gp = await estimator.getGasPrice();
3659
+ return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
3660
+ } catch {
3661
+ return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
3662
+ }
4173
3663
  }
4174
- function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
4175
- return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
3664
+ async function quoteL1Gas(input) {
3665
+ const { estimator, tx, overrides, fallbackGasLimit } = input;
3666
+ let market;
3667
+ const getMarket = async () => {
3668
+ if (market) return market;
3669
+ market = await fetchFees(estimator);
3670
+ return market;
3671
+ };
3672
+ const maxFeePerGas = overrides?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : (await getMarket()).maxFeePerGas);
3673
+ const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : (await getMarket()).maxPriorityFeePerGas);
3674
+ const explicitGasLimit = overrides?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
3675
+ if (explicitGasLimit != null) {
3676
+ return makeGasQuote({ gasLimit: explicitGasLimit, maxFeePerGas, maxPriorityFeePerGas });
3677
+ }
3678
+ try {
3679
+ const est = await estimator.estimateGas(tx);
3680
+ const buffered = BigInt(est) * (100n + BUFFER) / 100n;
3681
+ return makeGasQuote({ gasLimit: buffered, maxFeePerGas, maxPriorityFeePerGas });
3682
+ } catch (err) {
3683
+ if (fallbackGasLimit != null) {
3684
+ return makeGasQuote({ gasLimit: fallbackGasLimit, maxFeePerGas, maxPriorityFeePerGas });
3685
+ }
3686
+ console.warn("L1 gas estimation failed", err);
3687
+ return void 0;
3688
+ }
4176
3689
  }
4177
-
4178
- // src/core/resources/deposits/route.ts
4179
- async function pickDepositRoute(client, chainIdL2, token) {
4180
- if (isETH(token)) {
4181
- const base2 = await client.baseToken(chainIdL2);
4182
- return isETH(base2) ? "eth-base" : "eth-nonbase";
3690
+ async function quoteL2Gas(input) {
3691
+ const { estimator, route, tx, gasPerPubdata, l2GasLimit, overrideGasLimit, stateOverrides } = input;
3692
+ const market = await fetchFees(estimator);
3693
+ const maxFeePerGas = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
3694
+ const txGasLimit = tx?.gasLimit != null ? BigInt(tx.gasLimit) : void 0;
3695
+ const explicit = overrideGasLimit ?? txGasLimit;
3696
+ if (explicit != null) {
3697
+ return makeGasQuote({
3698
+ gasLimit: explicit,
3699
+ maxFeePerGas,
3700
+ gasPerPubdata
3701
+ });
4183
3702
  }
4184
- const base = await client.baseToken(chainIdL2);
4185
- return normalizeAddrEq(token, base) ? "erc20-base" : "erc20-nonbase";
3703
+ if (!tx) {
3704
+ return makeGasQuote({
3705
+ gasLimit: l2GasLimit ?? 0n,
3706
+ maxFeePerGas,
3707
+ gasPerPubdata
3708
+ });
3709
+ }
3710
+ try {
3711
+ const execEstimate = await estimator.estimateGas(tx, stateOverrides);
3712
+ const memoryBytes = route === "erc20-nonbase" ? 500n : DEFAULT_ABI_BYTES;
3713
+ const pubdataBytes = route === "erc20-nonbase" ? 200n : DEFAULT_PUBDATA_BYTES;
3714
+ const pp = gasPerPubdata ?? 800n;
3715
+ const memoryOverhead = memoryBytes * TX_MEMORY_OVERHEAD_GAS;
3716
+ const pubdataOverhead = pubdataBytes * pp;
3717
+ let total = BigInt(execEstimate) + TX_OVERHEAD_GAS + memoryOverhead + pubdataOverhead;
3718
+ total = total * (100n + BUFFER) / 100n;
3719
+ return makeGasQuote({
3720
+ gasLimit: total,
3721
+ maxFeePerGas,
3722
+ gasPerPubdata: pp
3723
+ });
3724
+ } catch (err) {
3725
+ console.warn("L2 gas estimation failed", err);
3726
+ return makeGasQuote({
3727
+ gasLimit: l2GasLimit ?? 0n,
3728
+ maxFeePerGas,
3729
+ gasPerPubdata
3730
+ });
3731
+ }
3732
+ }
3733
+ async function quoteL2BaseCost(input) {
3734
+ const { estimator, encode: encode2, bridgehub, chainIdL2, l2GasLimit, gasPerPubdata } = input;
3735
+ const market = await fetchFees(estimator);
3736
+ const l1GasPrice = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
3737
+ if (l1GasPrice === 0n) {
3738
+ throw new Error("Could not fetch L1 gas price for Bridgehub base cost calculation.");
3739
+ }
3740
+ const data = encode2(IBridgehub_default, "l2TransactionBaseCost", [
3741
+ chainIdL2,
3742
+ l1GasPrice,
3743
+ l2GasLimit,
3744
+ gasPerPubdata
3745
+ ]);
3746
+ const raw = await estimator.call({
3747
+ to: bridgehub,
3748
+ data
3749
+ });
3750
+ return BigInt(raw);
4186
3751
  }
4187
3752
 
4188
- // src/adapters/ethers/resources/deposits/context.ts
4189
- async function commonCtx(p, client) {
4190
- const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
4191
- const { chainId } = await client.l2.getNetwork();
4192
- const sender = await client.signer.getAddress();
4193
- const fee = await getFeeOverrides(client, p.l1TxOverrides);
4194
- const l2GasLimit = p.l2GasLimit ?? 300000n;
4195
- const gasPerPubdata = p.gasPerPubdata ?? 800n;
4196
- const operatorTip = p.operatorTip ?? 0n;
4197
- const refundRecipient = p.refundRecipient ?? sender;
4198
- const route = await pickDepositRoute(client, BigInt(chainId), p.token);
3753
+ // src/adapters/ethers/estimator.ts
3754
+ function toCoreTx(tx) {
4199
3755
  return {
4200
- client,
4201
- l1AssetRouter,
4202
- route,
4203
- bridgehub,
4204
- chainIdL2: BigInt(chainId),
4205
- sender,
4206
- fee,
4207
- l2GasLimit,
4208
- gasPerPubdata,
4209
- operatorTip,
4210
- refundRecipient
3756
+ to: tx.to,
3757
+ from: tx.from,
3758
+ data: tx.data,
3759
+ value: tx.value ? BigInt(tx.value) : void 0,
3760
+ gasLimit: tx.gasLimit ? BigInt(tx.gasLimit) : void 0,
3761
+ maxFeePerGas: tx.maxFeePerGas ? BigInt(tx.maxFeePerGas) : void 0,
3762
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas ? BigInt(tx.maxPriorityFeePerGas) : void 0
3763
+ };
3764
+ }
3765
+ function ethersToGasEstimator(provider) {
3766
+ return {
3767
+ async estimateGas(tx, stateOverrides) {
3768
+ const ethTx = {
3769
+ to: tx.to,
3770
+ from: tx.from,
3771
+ data: tx.data,
3772
+ value: tx.value,
3773
+ gasLimit: tx.gasLimit,
3774
+ maxFeePerGas: tx.maxFeePerGas,
3775
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas
3776
+ };
3777
+ if (stateOverrides && "send" in provider) {
3778
+ try {
3779
+ const jsonRpcProvider = provider;
3780
+ const result = await jsonRpcProvider.send("eth_estimateGas", [
3781
+ ethTx,
3782
+ "latest",
3783
+ stateOverrides
3784
+ ]);
3785
+ return BigInt(result);
3786
+ } catch (error) {
3787
+ console.warn(
3788
+ "Failed to estimate gas with state overrides, falling back to standard estimation:",
3789
+ error
3790
+ );
3791
+ }
3792
+ } else if (stateOverrides) {
3793
+ console.warn('Provider does not support "send", skipping state overrides estimation.');
3794
+ }
3795
+ return await provider.estimateGas(ethTx);
3796
+ },
3797
+ async estimateFeesPerGas() {
3798
+ const fd = await provider.getFeeData();
3799
+ return {
3800
+ maxFeePerGas: fd.maxFeePerGas != null ? BigInt(fd.maxFeePerGas) : void 0,
3801
+ maxPriorityFeePerGas: fd.maxPriorityFeePerGas != null ? BigInt(fd.maxPriorityFeePerGas) : void 0,
3802
+ gasPrice: fd.gasPrice != null ? BigInt(fd.gasPrice) : void 0
3803
+ };
3804
+ },
3805
+ async getGasPrice() {
3806
+ const fd = await provider.getFeeData();
3807
+ if (fd.gasPrice != null) return BigInt(fd.gasPrice);
3808
+ throw new Error("Could not fetch gas price");
3809
+ },
3810
+ async call(tx) {
3811
+ const ethTx = {
3812
+ to: tx.to,
3813
+ data: tx.data,
3814
+ value: tx.value,
3815
+ from: tx.from
3816
+ };
3817
+ return await provider.call(ethTx);
3818
+ }
4211
3819
  };
4212
3820
  }
4213
3821
 
@@ -4356,7 +3964,7 @@ function createErrorHandlers(resource) {
4356
3964
  function wrap2(operation, fn, opts) {
4357
3965
  return run("INTERNAL", operation, fn, opts);
4358
3966
  }
4359
- function wrapAs9(kind, operation, fn, opts) {
3967
+ function wrapAs8(kind, operation, fn, opts) {
4360
3968
  return run(kind, operation, fn, opts);
4361
3969
  }
4362
3970
  async function toResult2(operation, fn, opts) {
@@ -4377,109 +3985,217 @@ function createErrorHandlers(resource) {
4377
3985
  return { ok: false, error: shaped };
4378
3986
  }
4379
3987
  }
4380
- return { wrap: wrap2, wrapAs: wrapAs9, toResult: toResult2 };
3988
+ return { wrap: wrap2, wrapAs: wrapAs8, toResult: toResult2 };
4381
3989
  }
4382
3990
 
4383
- // src/adapters/ethers/resources/deposits/routes/eth.ts
3991
+ // src/adapters/ethers/resources/deposits/services/fee.ts
4384
3992
  var { wrapAs } = createErrorHandlers("deposits");
3993
+ var encode = (abi, fn, args) => {
3994
+ return new ethers.Interface(abi).encodeFunctionData(fn, args);
3995
+ };
3996
+ async function quoteL2BaseCost2(input) {
3997
+ const { ctx, l2GasLimit } = input;
3998
+ const estimator = ethersToGasEstimator(ctx.client.l1);
3999
+ return wrapAs(
4000
+ "RPC",
4001
+ "deposits.fees.l2BaseCost",
4002
+ () => quoteL2BaseCost({
4003
+ estimator,
4004
+ encode,
4005
+ bridgehub: ctx.bridgehub,
4006
+ chainIdL2: ctx.chainIdL2,
4007
+ l2GasLimit,
4008
+ gasPerPubdata: ctx.gasPerPubdata
4009
+ }),
4010
+ { ctx: { chainIdL2: ctx.chainIdL2 } }
4011
+ );
4012
+ }
4013
+
4014
+ // src/adapters/ethers/resources/deposits/services/gas.ts
4015
+ async function quoteL1Gas2(input) {
4016
+ const { ctx, tx, overrides, fallbackGasLimit } = input;
4017
+ const estimator = ethersToGasEstimator(ctx.client.l1);
4018
+ return quoteL1Gas({
4019
+ estimator,
4020
+ tx: toCoreTx(tx),
4021
+ overrides,
4022
+ fallbackGasLimit
4023
+ });
4024
+ }
4025
+ async function quoteL2Gas2(input) {
4026
+ const { ctx, route, l2TxForModeling, overrideGasLimit } = input;
4027
+ const estimator = ethersToGasEstimator(ctx.client.l2);
4028
+ return quoteL2Gas({
4029
+ estimator,
4030
+ route,
4031
+ tx: l2TxForModeling ? toCoreTx(l2TxForModeling) : void 0,
4032
+ gasPerPubdata: ctx.gasPerPubdata,
4033
+ l2GasLimit: ctx.l2GasLimit,
4034
+ overrideGasLimit,
4035
+ stateOverrides: input.stateOverrides
4036
+ });
4037
+ }
4038
+ async function determineErc20L2Gas(input) {
4039
+ const { ctx, l1Token } = input;
4040
+ const DEFAULT_SAFE_L2_GAS_LIMIT = 3000000n;
4041
+ if (ctx.l2GasLimit != null) {
4042
+ return quoteL2Gas2({
4043
+ ctx,
4044
+ route: "erc20-nonbase",
4045
+ overrideGasLimit: ctx.l2GasLimit
4046
+ });
4047
+ }
4048
+ try {
4049
+ const { l2NativeTokenVault } = await ctx.client.contracts();
4050
+ const l2TokenAddress = await l2NativeTokenVault.l2TokenAddress(l1Token);
4051
+ if (l2TokenAddress === "0x0000000000000000000000000000000000000000") {
4052
+ return quoteL2Gas2({
4053
+ ctx,
4054
+ route: "erc20-nonbase",
4055
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
4056
+ });
4057
+ }
4058
+ const modelTx = {
4059
+ to: input.modelTx?.to ?? ctx.sender,
4060
+ from: input.modelTx?.from ?? ctx.sender,
4061
+ data: input.modelTx?.data ?? "0x",
4062
+ value: input.modelTx?.value ?? 0n
4063
+ };
4064
+ const gas = await quoteL2Gas2({
4065
+ ctx,
4066
+ route: "erc20-nonbase",
4067
+ l2TxForModeling: modelTx
4068
+ });
4069
+ if (!gas) {
4070
+ return quoteL2Gas2({
4071
+ ctx,
4072
+ route: "erc20-nonbase",
4073
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
4074
+ });
4075
+ }
4076
+ return gas;
4077
+ } catch (err) {
4078
+ console.warn("Failed to determine ERC20 L2 gas; defaulting to safe gas limit.", err);
4079
+ return quoteL2Gas2({
4080
+ ctx,
4081
+ route: "erc20-nonbase",
4082
+ overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
4083
+ });
4084
+ }
4085
+ }
4086
+
4087
+ // src/core/resources/deposits/fee.ts
4088
+ function buildFeeBreakdown(p) {
4089
+ const l1MaxTotal = p.l1Gas?.maxCost ?? 0n;
4090
+ const l2Total = p.l2BaseCost + p.operatorTip;
4091
+ const l1 = {
4092
+ gasLimit: p.l1Gas?.gasLimit ?? 0n,
4093
+ maxFeePerGas: p.l1Gas?.maxFeePerGas ?? 0n,
4094
+ maxPriorityFeePerGas: p.l1Gas?.maxPriorityFeePerGas,
4095
+ maxTotal: l1MaxTotal
4096
+ };
4097
+ const l2 = {
4098
+ total: l2Total,
4099
+ baseCost: p.l2BaseCost,
4100
+ operatorTip: p.operatorTip,
4101
+ gasLimit: p.l2Gas?.gasLimit ?? 0n,
4102
+ maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
4103
+ maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas,
4104
+ gasPerPubdata: p.l2Gas?.gasPerPubdata ?? 0n
4105
+ };
4106
+ return {
4107
+ token: p.feeToken,
4108
+ maxTotal: l1MaxTotal + l2Total,
4109
+ mintValue: p.mintValue,
4110
+ l1,
4111
+ l2
4112
+ };
4113
+ }
4114
+
4115
+ // src/adapters/ethers/resources/deposits/routes/eth.ts
4385
4116
  function routeEthDirect() {
4386
4117
  return {
4387
4118
  async build(p, ctx) {
4388
4119
  const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4389
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
4390
- const rawBaseCost = await wrapAs(
4391
- "CONTRACT",
4392
- OP_DEPOSITS.eth.baseCost,
4393
- () => bh.l2TransactionBaseCost(
4394
- ctx.chainIdL2,
4395
- gasPriceForBaseCost,
4396
- ctx.l2GasLimit,
4397
- ctx.gasPerPubdata
4398
- ),
4399
- {
4400
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
4401
- message: "Could not fetch L2 base cost from Bridgehub."
4120
+ const l2TxModel = {
4121
+ to: p.to ?? ctx.sender,
4122
+ from: ctx.sender,
4123
+ data: "0x",
4124
+ value: 0n
4125
+ };
4126
+ const l2GasParams = await quoteL2Gas2({
4127
+ ctx,
4128
+ route: "eth-base",
4129
+ l2TxForModeling: l2TxModel,
4130
+ overrideGasLimit: ctx.l2GasLimit,
4131
+ stateOverrides: {
4132
+ [ctx.sender]: {
4133
+ balance: "0xffffffffffffffffffff"
4134
+ }
4402
4135
  }
4403
- );
4404
- const baseCost = BigInt(rawBaseCost);
4405
- const l2Contract = p.to ?? ctx.sender;
4406
- const l2Value = p.amount;
4407
- const mintValue = baseCost + ctx.operatorTip + l2Value;
4136
+ });
4137
+ if (!l2GasParams) {
4138
+ throw new Error("Failed to estimate L2 gas for deposit.");
4139
+ }
4140
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
4141
+ const mintValue = baseCost + ctx.operatorTip + p.amount;
4408
4142
  const req = buildDirectRequestStruct({
4409
4143
  chainId: ctx.chainIdL2,
4410
4144
  mintValue,
4411
- l2GasLimit: ctx.l2GasLimit,
4145
+ l2GasLimit: l2GasParams.gasLimit,
4412
4146
  gasPerPubdata: ctx.gasPerPubdata,
4413
4147
  refundRecipient: ctx.refundRecipient,
4414
- l2Contract,
4415
- l2Value
4148
+ l2Contract: p.to ?? ctx.sender,
4149
+ l2Value: p.amount
4416
4150
  });
4417
4151
  const data = bh.interface.encodeFunctionData("requestL2TransactionDirect", [req]);
4418
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
4419
- const tx = {
4152
+ const l1TxCandidate = {
4420
4153
  to: ctx.bridgehub,
4421
4154
  data,
4422
4155
  value: mintValue,
4423
4156
  from: ctx.sender,
4424
- ...txFeeOverrides
4157
+ ...ctx.gasOverrides
4425
4158
  };
4426
- if (overrideGasLimit != null) {
4427
- tx.gasLimit = overrideGasLimit;
4428
- resolvedL1GasLimit = overrideGasLimit;
4429
- } else {
4430
- try {
4431
- const est = await wrapAs(
4432
- "RPC",
4433
- OP_DEPOSITS.eth.estGas,
4434
- () => ctx.client.l1.estimateGas(tx),
4435
- {
4436
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
4437
- message: "Failed to estimate gas for Bridgehub request."
4438
- }
4439
- );
4440
- const buffered = BigInt(est) * 115n / 100n;
4441
- tx.gasLimit = buffered;
4442
- resolvedL1GasLimit = buffered;
4443
- } catch {
4444
- }
4159
+ const l1GasParams = await quoteL1Gas2({
4160
+ ctx,
4161
+ tx: l1TxCandidate,
4162
+ overrides: ctx.gasOverrides
4163
+ });
4164
+ if (l1GasParams) {
4165
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
4166
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
4167
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
4445
4168
  }
4446
4169
  const steps = [
4447
4170
  {
4448
4171
  key: "bridgehub:direct",
4449
4172
  kind: "bridgehub:direct",
4450
4173
  description: "Bridge ETH via Bridgehub.requestL2TransactionDirect",
4451
- tx
4174
+ tx: l1TxCandidate
4452
4175
  }
4453
4176
  ];
4177
+ const fees = buildFeeBreakdown({
4178
+ feeToken: ETH_ADDRESS,
4179
+ l1Gas: l1GasParams,
4180
+ l2Gas: l2GasParams,
4181
+ l2BaseCost: baseCost,
4182
+ operatorTip: ctx.operatorTip,
4183
+ mintValue
4184
+ });
4454
4185
  return {
4455
4186
  steps,
4456
4187
  approvals: [],
4457
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
4188
+ fees
4458
4189
  };
4459
4190
  }
4460
4191
  };
4461
4192
  }
4462
4193
  var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
4463
- var MIN_L2_GAS_FOR_ERC20 = 2500000n;
4464
4194
  function routeErc20NonBase() {
4465
4195
  return {
4466
- async preflight() {
4467
- },
4468
- async build(p, ctx) {
4469
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4470
- const assetRouter = ctx.l1AssetRouter;
4471
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
4472
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
4473
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
4474
- const baseToken = await wrapAs2(
4475
- "CONTRACT",
4476
- OP_DEPOSITS.nonbase.baseToken,
4477
- () => bh.baseToken(ctx.chainIdL2),
4478
- {
4479
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
4480
- message: "Failed to read base token."
4481
- }
4482
- );
4196
+ // TODO: do we even need these validations?
4197
+ async preflight(p, ctx) {
4198
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4483
4199
  await wrapAs2(
4484
4200
  "VALIDATION",
4485
4201
  OP_DEPOSITS.nonbase.assertNonBaseToken,
@@ -4490,52 +4206,51 @@ function routeErc20NonBase() {
4490
4206
  },
4491
4207
  { ctx: { depositToken: p.token, baseToken } }
4492
4208
  );
4493
- 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;
4494
- const rawBaseCost = await wrapAs2(
4495
- "RPC",
4496
- OP_DEPOSITS.nonbase.baseCost,
4497
- () => bh.l2TransactionBaseCost(
4498
- ctx.chainIdL2,
4499
- gasPriceForBaseCost,
4500
- l2GasLimitUsed,
4501
- ctx.gasPerPubdata
4502
- ),
4503
- {
4504
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
4505
- message: "Could not fetch L2 base cost from Bridgehub."
4209
+ },
4210
+ async build(p, ctx) {
4211
+ const l1Signer = ctx.client.getL1Signer();
4212
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4213
+ const baseIsEth = isETH(baseToken);
4214
+ const l2GasParams = await determineErc20L2Gas({
4215
+ ctx,
4216
+ l1Token: p.token,
4217
+ modelTx: {
4218
+ to: p.to ?? ctx.sender,
4219
+ from: ctx.sender,
4220
+ data: "0x",
4221
+ value: 0n
4506
4222
  }
4507
- );
4508
- const baseCost = BigInt(rawBaseCost);
4223
+ });
4224
+ if (!l2GasParams) throw new Error("Failed to establish L2 gas parameters.");
4225
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
4509
4226
  const mintValue = baseCost + ctx.operatorTip;
4510
4227
  const approvals = [];
4511
4228
  const steps = [];
4512
- const l1Signer = ctx.client.getL1Signer();
4513
- {
4514
- const erc20Deposit = new ethers.Contract(p.token, IERC20_default, l1Signer);
4515
- const allowanceToken = await wrapAs2(
4516
- "RPC",
4517
- OP_DEPOSITS.nonbase.allowanceToken,
4518
- () => erc20Deposit.allowance(ctx.sender, assetRouter),
4519
- {
4520
- ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
4521
- message: "Failed to read deposit-token allowance."
4522
- }
4523
- );
4524
- if (allowanceToken < p.amount) {
4525
- approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
4526
- const data = erc20Deposit.interface.encodeFunctionData("approve", [
4527
- assetRouter,
4528
- p.amount
4529
- ]);
4530
- steps.push({
4531
- key: `approve:${p.token}:${assetRouter}`,
4532
- kind: "approve",
4533
- description: `Approve ${p.amount} for router (deposit token)`,
4534
- tx: { to: p.token, data, from: ctx.sender, ...txOverrides }
4535
- });
4229
+ const assetRouter = ctx.l1AssetRouter;
4230
+ const erc20Deposit = new ethers.Contract(p.token, IERC20_default, l1Signer);
4231
+ const allowanceToken = await wrapAs2(
4232
+ "RPC",
4233
+ OP_DEPOSITS.nonbase.allowanceToken,
4234
+ () => erc20Deposit.allowance(ctx.sender, assetRouter),
4235
+ {
4236
+ ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
4237
+ message: "Failed to read deposit-token allowance."
4536
4238
  }
4239
+ );
4240
+ if (allowanceToken < p.amount) {
4241
+ approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
4242
+ steps.push({
4243
+ key: `approve:${p.token}:${assetRouter}`,
4244
+ kind: "approve",
4245
+ description: `Approve ${p.amount} for router (deposit token)`,
4246
+ tx: {
4247
+ to: p.token,
4248
+ data: erc20Deposit.interface.encodeFunctionData("approve", [assetRouter, p.amount]),
4249
+ from: ctx.sender,
4250
+ ...ctx.gasOverrides
4251
+ }
4252
+ });
4537
4253
  }
4538
- const baseIsEth = isETH(baseToken);
4539
4254
  if (!baseIsEth) {
4540
4255
  const erc20Base = new ethers.Contract(baseToken, IERC20_default, l1Signer);
4541
4256
  const allowanceBase = await wrapAs2(
@@ -4549,12 +4264,16 @@ function routeErc20NonBase() {
4549
4264
  );
4550
4265
  if (allowanceBase < mintValue) {
4551
4266
  approvals.push({ token: baseToken, spender: assetRouter, amount: mintValue });
4552
- const data = erc20Base.interface.encodeFunctionData("approve", [assetRouter, mintValue]);
4553
4267
  steps.push({
4554
4268
  key: `approve:${baseToken}:${assetRouter}`,
4555
4269
  kind: "approve",
4556
4270
  description: `Approve base token for mintValue`,
4557
- tx: { to: baseToken, data, from: ctx.sender, ...txOverrides }
4271
+ tx: {
4272
+ to: baseToken,
4273
+ data: erc20Base.interface.encodeFunctionData("approve", [assetRouter, mintValue]),
4274
+ from: ctx.sender,
4275
+ ...ctx.gasOverrides
4276
+ }
4558
4277
  });
4559
4278
  }
4560
4279
  }
@@ -4567,64 +4286,63 @@ function routeErc20NonBase() {
4567
4286
  message: "Failed to encode bridging calldata."
4568
4287
  }
4569
4288
  );
4570
- const outer = {
4289
+ const requestStruct = {
4571
4290
  chainId: ctx.chainIdL2,
4572
4291
  mintValue,
4573
- // fees (in ETH if base=ETH, else pulled as base ERC-20)
4574
4292
  l2Value: 0n,
4575
- l2GasLimit: l2GasLimitUsed,
4293
+ l2GasLimit: l2GasParams.gasLimit,
4576
4294
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
4577
4295
  refundRecipient: ctx.refundRecipient,
4578
4296
  secondBridgeAddress: assetRouter,
4579
4297
  secondBridgeValue: 0n,
4580
4298
  secondBridgeCalldata
4581
4299
  };
4582
- const dataTwo = bh.interface.encodeFunctionData("requestL2TransactionTwoBridges", [outer]);
4583
- const bridgeTx = {
4300
+ const bh = (await ctx.client.contracts()).bridgehub;
4301
+ const data = bh.interface.encodeFunctionData("requestL2TransactionTwoBridges", [
4302
+ requestStruct
4303
+ ]);
4304
+ const txValue = baseIsEth ? mintValue : 0n;
4305
+ const l1TxCandidate = {
4584
4306
  to: ctx.bridgehub,
4585
- data: dataTwo,
4586
- value: baseIsEth ? mintValue : 0n,
4307
+ data,
4308
+ value: txValue,
4587
4309
  from: ctx.sender,
4588
- ...txOverrides
4310
+ ...ctx.gasOverrides
4589
4311
  };
4590
- if (overrideGasLimit != null) {
4591
- bridgeTx.gasLimit = overrideGasLimit;
4592
- resolvedL1GasLimit = overrideGasLimit;
4593
- } else {
4594
- try {
4595
- const est = await wrapAs2(
4596
- "RPC",
4597
- OP_DEPOSITS.nonbase.estGas,
4598
- () => ctx.client.l1.estimateGas(bridgeTx),
4599
- {
4600
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub, baseIsEth },
4601
- message: "Failed to estimate gas for Bridgehub request."
4602
- }
4603
- );
4604
- const buffered = BigInt(est) * 125n / 100n;
4605
- bridgeTx.gasLimit = buffered;
4606
- resolvedL1GasLimit = buffered;
4607
- } catch {
4608
- }
4312
+ const l1GasParams = await quoteL1Gas2({
4313
+ ctx,
4314
+ tx: l1TxCandidate,
4315
+ overrides: ctx.gasOverrides,
4316
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
4317
+ });
4318
+ if (l1GasParams) {
4319
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
4320
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
4321
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
4609
4322
  }
4610
4323
  steps.push({
4611
- key: "bridgehub:two-bridges:nonbase",
4324
+ key: "bridgehub:two-bridges",
4612
4325
  kind: "bridgehub:two-bridges",
4613
- description: baseIsEth ? "Bridge ERC-20 (fees in ETH) via Bridgehub.requestL2TransactionTwoBridges" : "Bridge ERC-20 (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
4614
- tx: bridgeTx
4326
+ description: baseIsEth ? "Bridge ERC-20 (Fees paid in ETH)" : "Bridge ERC-20 (Fees paid in Base Token)",
4327
+ tx: l1TxCandidate
4328
+ });
4329
+ const fees = buildFeeBreakdown({
4330
+ feeToken: baseToken,
4331
+ l1Gas: l1GasParams,
4332
+ l2Gas: l2GasParams,
4333
+ l2BaseCost: baseCost,
4334
+ operatorTip: ctx.operatorTip,
4335
+ mintValue
4615
4336
  });
4616
4337
  return {
4617
4338
  steps,
4618
4339
  approvals,
4619
- quoteExtras: { baseCost, mintValue, baseToken, baseIsEth, l1GasLimit: resolvedL1GasLimit }
4340
+ fees
4620
4341
  };
4621
4342
  }
4622
4343
  };
4623
4344
  }
4624
4345
  var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
4625
- var BASE_COST_BUFFER_BPS = 100n;
4626
- var BPS = 10000n;
4627
- var withBuffer = (x) => x * (BPS + BASE_COST_BUFFER_BPS) / BPS;
4628
4346
  function routeEthNonBase() {
4629
4347
  return {
4630
4348
  async preflight(p, ctx) {
@@ -4638,16 +4356,7 @@ function routeEthNonBase() {
4638
4356
  },
4639
4357
  { ctx: { token: p.token } }
4640
4358
  );
4641
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4642
- const baseToken = await wrapAs3(
4643
- "CONTRACT",
4644
- OP_DEPOSITS.ethNonBase.baseToken,
4645
- () => bh.baseToken(ctx.chainIdL2),
4646
- {
4647
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
4648
- message: "Failed to read base token."
4649
- }
4650
- );
4359
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4651
4360
  await wrapAs3(
4652
4361
  "VALIDATION",
4653
4362
  OP_DEPOSITS.ethNonBase.assertNonEthBase,
@@ -4680,61 +4389,48 @@ function routeEthNonBase() {
4680
4389
  return;
4681
4390
  },
4682
4391
  async build(p, ctx) {
4683
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4684
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
4685
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
4686
- const baseToken = await wrapAs3(
4687
- "CONTRACT",
4688
- OP_DEPOSITS.ethNonBase.baseToken,
4689
- () => bh.baseToken(ctx.chainIdL2),
4690
- {
4691
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
4692
- message: "Failed to read base token."
4693
- }
4694
- );
4695
- const rawBaseCost = await wrapAs3(
4392
+ const l1Signer = ctx.client.getL1Signer();
4393
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4394
+ const l2TxModel = {
4395
+ to: p.to ?? ctx.sender,
4396
+ from: ctx.sender,
4397
+ data: "0x",
4398
+ value: 0n
4399
+ };
4400
+ const l2GasParams = await quoteL2Gas2({
4401
+ ctx,
4402
+ route: "eth-nonbase",
4403
+ l2TxForModeling: l2TxModel,
4404
+ overrideGasLimit: ctx.l2GasLimit
4405
+ });
4406
+ if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
4407
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
4408
+ const mintValue = baseCost + ctx.operatorTip;
4409
+ const approvals = [];
4410
+ const steps = [];
4411
+ const erc20Base = new ethers.Contract(baseToken, IERC20_default, l1Signer);
4412
+ const allowance = await wrapAs3(
4696
4413
  "RPC",
4697
- OP_DEPOSITS.ethNonBase.baseCost,
4698
- () => bh.l2TransactionBaseCost(
4699
- ctx.chainIdL2,
4700
- gasPriceForBaseCost,
4701
- ctx.l2GasLimit,
4702
- ctx.gasPerPubdata
4703
- ),
4414
+ OP_DEPOSITS.ethNonBase.allowanceBase,
4415
+ () => erc20Base.allowance(ctx.sender, ctx.l1AssetRouter),
4704
4416
  {
4705
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
4706
- message: "Could not fetch L2 base cost."
4417
+ ctx: { where: "erc20.allowance", token: baseToken, spender: ctx.l1AssetRouter },
4418
+ message: "Failed to read base-token allowance."
4707
4419
  }
4708
4420
  );
4709
- const baseCost = BigInt(rawBaseCost);
4710
- const mintValueRaw = baseCost + ctx.operatorTip;
4711
- const mintValue = withBuffer(mintValueRaw);
4712
- const approvals = [];
4713
- const steps = [];
4714
- {
4715
- const erc20 = new ethers.Contract(baseToken, IERC20_default, ctx.client.getL1Signer());
4716
- const allowance = await wrapAs3(
4717
- "RPC",
4718
- OP_DEPOSITS.ethNonBase.allowanceBase,
4719
- () => erc20.allowance(ctx.sender, ctx.l1AssetRouter),
4720
- {
4721
- ctx: { where: "erc20.allowance", token: baseToken, spender: ctx.l1AssetRouter },
4722
- message: "Failed to read base-token allowance."
4421
+ if (allowance < mintValue) {
4422
+ approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
4423
+ steps.push({
4424
+ key: `approve:${baseToken}`,
4425
+ kind: "approve",
4426
+ description: `Approve base token for fees (mintValue)`,
4427
+ tx: {
4428
+ to: baseToken,
4429
+ data: erc20Base.interface.encodeFunctionData("approve", [ctx.l1AssetRouter, mintValue]),
4430
+ from: ctx.sender,
4431
+ ...ctx.gasOverrides
4723
4432
  }
4724
- );
4725
- if (allowance < mintValue) {
4726
- approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
4727
- const data = erc20.interface.encodeFunctionData("approve", [
4728
- ctx.l1AssetRouter,
4729
- mintValue
4730
- ]);
4731
- steps.push({
4732
- key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
4733
- kind: "approve",
4734
- description: `Approve base token for mintValue`,
4735
- tx: { to: baseToken, data, from: ctx.sender, ...txOverrides }
4736
- });
4737
- }
4433
+ });
4738
4434
  }
4739
4435
  const secondBridgeCalldata = await wrapAs3(
4740
4436
  "INTERNAL",
@@ -4748,69 +4444,64 @@ function routeEthNonBase() {
4748
4444
  }
4749
4445
  }
4750
4446
  );
4751
- const outer = {
4447
+ const requestStruct = {
4752
4448
  chainId: ctx.chainIdL2,
4753
4449
  mintValue,
4754
- l2Value: 0n,
4755
- l2GasLimit: ctx.l2GasLimit,
4450
+ l2Value: p.amount,
4451
+ l2GasLimit: l2GasParams.gasLimit,
4756
4452
  l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
4757
4453
  refundRecipient: ctx.refundRecipient,
4758
4454
  secondBridgeAddress: ctx.l1AssetRouter,
4759
4455
  secondBridgeValue: p.amount,
4760
4456
  secondBridgeCalldata
4761
4457
  };
4762
- const dataTwo = new ethers.Contract(
4458
+ const data = new ethers.Contract(
4763
4459
  ctx.bridgehub,
4764
4460
  IBridgehub_default,
4765
4461
  ctx.client.l1
4766
- ).interface.encodeFunctionData("requestL2TransactionTwoBridges", [outer]);
4767
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
4768
- const bridgeTx = {
4462
+ ).interface.encodeFunctionData("requestL2TransactionTwoBridges", [requestStruct]);
4463
+ const l1TxCandidate = {
4769
4464
  to: ctx.bridgehub,
4770
- data: dataTwo,
4465
+ data,
4771
4466
  value: p.amount,
4772
4467
  // base ≠ ETH ⇒ msg.value == secondBridgeValue
4773
4468
  from: ctx.sender,
4774
- ...txOverrides
4469
+ ...ctx.gasOverrides
4775
4470
  };
4776
- if (overrideGasLimit != null) {
4777
- bridgeTx.gasLimit = overrideGasLimit;
4778
- resolvedL1GasLimit = overrideGasLimit;
4779
- } else {
4780
- try {
4781
- const est = await wrapAs3(
4782
- "RPC",
4783
- OP_DEPOSITS.ethNonBase.estGas,
4784
- () => ctx.client.l1.estimateGas(bridgeTx),
4785
- {
4786
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
4787
- message: "Failed to estimate gas for Bridgehub request."
4788
- }
4789
- );
4790
- const buffered = BigInt(est) * 115n / 100n;
4791
- bridgeTx.gasLimit = buffered;
4792
- resolvedL1GasLimit = buffered;
4793
- } catch {
4794
- }
4471
+ const l1GasParams = await quoteL1Gas2({
4472
+ ctx,
4473
+ tx: l1TxCandidate,
4474
+ overrides: ctx.gasOverrides,
4475
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
4476
+ });
4477
+ if (l1GasParams) {
4478
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
4479
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
4480
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
4795
4481
  }
4796
4482
  steps.push({
4797
4483
  key: "bridgehub:two-bridges:eth-nonbase",
4798
4484
  kind: "bridgehub:two-bridges",
4799
4485
  description: "Bridge ETH (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
4800
- tx: bridgeTx
4486
+ tx: l1TxCandidate
4487
+ });
4488
+ const fees = buildFeeBreakdown({
4489
+ feeToken: baseToken,
4490
+ l1Gas: l1GasParams,
4491
+ l2Gas: l2GasParams,
4492
+ l2BaseCost: baseCost,
4493
+ operatorTip: ctx.operatorTip,
4494
+ mintValue
4801
4495
  });
4802
4496
  return {
4803
4497
  steps,
4804
4498
  approvals,
4805
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
4499
+ fees
4806
4500
  };
4807
4501
  }
4808
4502
  };
4809
4503
  }
4810
4504
  var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
4811
- var BASE_COST_BUFFER_BPS2 = 100n;
4812
- var BPS2 = 10000n;
4813
- var withBuffer2 = (x) => x * (BPS2 + BASE_COST_BUFFER_BPS2) / BPS2;
4814
4505
  function routeErc20Base() {
4815
4506
  return {
4816
4507
  async preflight(p, ctx) {
@@ -4824,16 +4515,7 @@ function routeErc20Base() {
4824
4515
  },
4825
4516
  { ctx: { token: p.token } }
4826
4517
  );
4827
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4828
- const baseToken = await wrapAs4(
4829
- "CONTRACT",
4830
- OP_DEPOSITS.base.baseToken,
4831
- () => bh.baseToken(ctx.chainIdL2),
4832
- {
4833
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
4834
- message: "Failed to read base token."
4835
- }
4836
- );
4518
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4837
4519
  await wrapAs4(
4838
4520
  "VALIDATION",
4839
4521
  OP_DEPOSITS.base.assertMatchesBase,
@@ -4847,41 +4529,27 @@ function routeErc20Base() {
4847
4529
  return;
4848
4530
  },
4849
4531
  async build(p, ctx) {
4850
- const bh = new ethers.Contract(ctx.bridgehub, IBridgehub_default, ctx.client.l1);
4851
- const { gasPriceForBaseCost, gasLimit: overrideGasLimit, ...txFeeOverrides } = ctx.fee;
4852
- const txOverrides = overrideGasLimit != null ? { ...txFeeOverrides, gasLimit: overrideGasLimit } : txFeeOverrides;
4853
- let resolvedL1GasLimit = overrideGasLimit ?? ctx.l2GasLimit;
4854
- const baseToken = await wrapAs4(
4855
- "CONTRACT",
4856
- OP_DEPOSITS.base.baseToken,
4857
- () => bh.baseToken(ctx.chainIdL2),
4858
- {
4859
- ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
4860
- message: "Failed to read base token."
4861
- }
4862
- );
4863
- const rawBaseCost = await wrapAs4(
4864
- "RPC",
4865
- OP_DEPOSITS.base.baseCost,
4866
- () => bh.l2TransactionBaseCost(
4867
- ctx.chainIdL2,
4868
- gasPriceForBaseCost,
4869
- ctx.l2GasLimit,
4870
- ctx.gasPerPubdata
4871
- ),
4872
- {
4873
- ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
4874
- message: "Could not fetch L2 base cost from Bridgehub."
4875
- }
4876
- );
4877
- const baseCost = BigInt(rawBaseCost);
4878
- const l2Value = p.amount;
4879
- const rawMintValue = baseCost + ctx.operatorTip + l2Value;
4880
- const mintValue = withBuffer2(rawMintValue);
4532
+ const l1Signer = ctx.client.getL1Signer();
4533
+ const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
4534
+ const l2TxModel = {
4535
+ to: p.to ?? ctx.sender,
4536
+ from: ctx.sender,
4537
+ data: "0x",
4538
+ value: 0n
4539
+ };
4540
+ const l2GasParams = await quoteL2Gas2({
4541
+ ctx,
4542
+ route: "erc20-base",
4543
+ l2TxForModeling: l2TxModel,
4544
+ overrideGasLimit: ctx.l2GasLimit
4545
+ });
4546
+ if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
4547
+ const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
4548
+ const mintValue = baseCost + ctx.operatorTip + p.amount;
4881
4549
  const approvals = [];
4882
4550
  const steps = [];
4883
4551
  {
4884
- const erc20 = new ethers.Contract(baseToken, IERC20_default, ctx.client.getL1Signer());
4552
+ const erc20 = new ethers.Contract(baseToken, IERC20_default, l1Signer);
4885
4553
  const allowance = await wrapAs4(
4886
4554
  "RPC",
4887
4555
  OP_DEPOSITS.base.allowance,
@@ -4893,70 +4561,70 @@ function routeErc20Base() {
4893
4561
  );
4894
4562
  if (allowance < mintValue) {
4895
4563
  approvals.push({ token: baseToken, spender: ctx.l1AssetRouter, amount: mintValue });
4896
- const data2 = erc20.interface.encodeFunctionData("approve", [
4897
- ctx.l1AssetRouter,
4898
- mintValue
4899
- ]);
4900
4564
  steps.push({
4901
4565
  key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
4902
4566
  kind: "approve",
4903
4567
  description: "Approve base token for mintValue",
4904
- tx: { to: baseToken, data: data2, from: ctx.sender, ...txOverrides }
4568
+ tx: {
4569
+ to: baseToken,
4570
+ data: erc20.interface.encodeFunctionData("approve", [ctx.l1AssetRouter, mintValue]),
4571
+ from: ctx.sender,
4572
+ ...ctx.gasOverrides
4573
+ }
4905
4574
  });
4906
4575
  }
4907
4576
  }
4908
- const req = buildDirectRequestStruct({
4577
+ const requestStruct = buildDirectRequestStruct({
4909
4578
  chainId: ctx.chainIdL2,
4910
4579
  mintValue,
4911
- l2GasLimit: ctx.l2GasLimit,
4580
+ l2GasLimit: l2GasParams.gasLimit,
4912
4581
  gasPerPubdata: ctx.gasPerPubdata,
4913
4582
  refundRecipient: ctx.refundRecipient,
4914
4583
  l2Contract: p.to ?? ctx.sender,
4915
- l2Value
4584
+ l2Value: p.amount
4916
4585
  });
4917
4586
  const data = new ethers.Contract(
4918
4587
  ctx.bridgehub,
4919
4588
  IBridgehub_default,
4920
4589
  ctx.client.l1
4921
- ).interface.encodeFunctionData("requestL2TransactionDirect", [req]);
4922
- const tx = {
4590
+ ).interface.encodeFunctionData("requestL2TransactionDirect", [requestStruct]);
4591
+ const l1TxCandidate = {
4923
4592
  to: ctx.bridgehub,
4924
4593
  data,
4925
4594
  value: 0n,
4926
4595
  // base token is ERC-20 ⇒ msg.value MUST be 0
4927
4596
  from: ctx.sender,
4928
- ...txOverrides
4597
+ ...ctx.gasOverrides
4929
4598
  };
4930
- if (overrideGasLimit != null) {
4931
- tx.gasLimit = overrideGasLimit;
4932
- resolvedL1GasLimit = overrideGasLimit;
4933
- } else {
4934
- try {
4935
- const est = await wrapAs4(
4936
- "RPC",
4937
- OP_DEPOSITS.base.estGas,
4938
- () => ctx.client.l1.estimateGas(tx),
4939
- {
4940
- ctx: { where: "l1.estimateGas", to: ctx.bridgehub },
4941
- message: "Failed to estimate gas for Bridgehub request."
4942
- }
4943
- );
4944
- const buffered = BigInt(est) * 115n / 100n;
4945
- tx.gasLimit = buffered;
4946
- resolvedL1GasLimit = buffered;
4947
- } catch {
4948
- }
4599
+ const l1GasParams = await quoteL1Gas2({
4600
+ ctx,
4601
+ tx: l1TxCandidate,
4602
+ overrides: ctx.gasOverrides,
4603
+ fallbackGasLimit: SAFE_L1_BRIDGE_GAS
4604
+ });
4605
+ if (l1GasParams) {
4606
+ l1TxCandidate.gasLimit = l1GasParams.gasLimit;
4607
+ l1TxCandidate.maxFeePerGas = l1GasParams.maxFeePerGas;
4608
+ l1TxCandidate.maxPriorityFeePerGas = l1GasParams.maxPriorityFeePerGas;
4949
4609
  }
4950
4610
  steps.push({
4951
4611
  key: "bridgehub:direct:erc20-base",
4952
4612
  kind: "bridgehub:direct",
4953
4613
  description: "Bridge base ERC-20 via Bridgehub.requestL2TransactionDirect",
4954
- tx
4614
+ tx: l1TxCandidate
4615
+ });
4616
+ const fees = buildFeeBreakdown({
4617
+ feeToken: baseToken,
4618
+ l1Gas: l1GasParams,
4619
+ l2Gas: l2GasParams,
4620
+ l2BaseCost: baseCost,
4621
+ operatorTip: ctx.operatorTip,
4622
+ mintValue
4955
4623
  });
4956
4624
  return {
4957
4625
  steps,
4958
4626
  approvals,
4959
- quoteExtras: { baseCost, mintValue, l1GasLimit: resolvedL1GasLimit }
4627
+ fees
4960
4628
  };
4961
4629
  }
4962
4630
  };
@@ -4975,37 +4643,19 @@ function createDepositsResource(client) {
4975
4643
  const ctx = await commonCtx(p, client);
4976
4644
  const route = ctx.route;
4977
4645
  await ROUTES[route].preflight?.(p, ctx);
4978
- const { steps, approvals, quoteExtras } = await ROUTES[route].build(p, ctx);
4979
- const { baseCost, mintValue } = quoteExtras;
4980
- const fallbackGasLimit = quoteExtras.l1GasLimit;
4981
- const resolveGasLimit = () => {
4982
- if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
4983
- for (let i = steps.length - 1; i >= 0; i--) {
4984
- const candidate = steps[i].tx.gasLimit;
4985
- if (candidate == null) continue;
4986
- if (typeof candidate === "bigint") return candidate;
4987
- try {
4988
- return BigInt(candidate.toString());
4989
- } catch {
4990
- }
4991
- }
4992
- if (fallbackGasLimit != null) return fallbackGasLimit;
4993
- return ctx.l2GasLimit;
4994
- };
4995
- const gasLimit = resolveGasLimit();
4646
+ const { steps, approvals, fees } = await ROUTES[route].build(p, ctx);
4996
4647
  return {
4997
4648
  route: ctx.route,
4998
4649
  summary: {
4999
4650
  route: ctx.route,
5000
4651
  approvalsNeeded: approvals,
5001
- baseCost,
5002
- mintValue,
5003
- gasPerPubdata: ctx.gasPerPubdata,
5004
- fees: {
5005
- gasLimit,
5006
- maxFeePerGas: ctx.fee.maxFeePerGas,
5007
- maxPriorityFeePerGas: ctx.fee.maxPriorityFeePerGas
5008
- }
4652
+ amounts: {
4653
+ transfer: { token: p.token, amount: p.amount }
4654
+ },
4655
+ fees,
4656
+ // Legacy fields (maintained for backward compatibility)
4657
+ baseCost: fees.l2?.baseCost,
4658
+ mintValue: fees.mintValue
5009
4659
  },
5010
4660
  steps
5011
4661
  };
@@ -5074,7 +4724,7 @@ function createDepositsResource(client) {
5074
4724
  step.tx.maxPriorityFeePerGas = overrides.maxPriorityFeePerGas;
5075
4725
  }
5076
4726
  }
5077
- if (!step.tx.gasLimit) {
4727
+ if (!p.l1TxOverrides?.gasLimit) {
5078
4728
  try {
5079
4729
  const est = await client.l1.estimateGas(step.tx);
5080
4730
  step.tx.gasLimit = BigInt(est) * 115n / 100n;
@@ -5265,7 +4915,7 @@ function normalizeTokenForRouting(token) {
5265
4915
  function pickWithdrawRoute(args) {
5266
4916
  const tokenNorm = normalizeTokenForRouting(args.token);
5267
4917
  const isL2BaseAlias = tokenNorm.toLowerCase() === L2_BASE_TOKEN_ADDRESS.toLowerCase();
5268
- if (isL2BaseAlias) return args.baseIsEth ? "eth-base" : "eth-nonbase";
4918
+ if (isL2BaseAlias) return "base";
5269
4919
  return "erc20-nonbase";
5270
4920
  }
5271
4921
  async function ntvBaseAssetId(l2, ntv) {
@@ -5299,10 +4949,7 @@ async function commonCtx2(p, client) {
5299
4949
  const { chainId } = await client.l2.getNetwork();
5300
4950
  const chainIdL2 = BigInt(chainId);
5301
4951
  const baseIsEth = await isEthBasedChain(client.l2, l2NativeTokenVault);
5302
- const fee = await getL2FeeOverrides(client, p.l2TxOverrides);
5303
- const route = pickWithdrawRoute({ token: p.token, baseIsEth });
5304
- const l2GasLimit = p.l2GasLimit ?? 300000n;
5305
- const gasBufferPct = 15;
4952
+ const route = pickWithdrawRoute({ token: p.token});
5306
4953
  return {
5307
4954
  client,
5308
4955
  bridgehub,
@@ -5315,29 +4962,111 @@ async function commonCtx2(p, client) {
5315
4962
  l2NativeTokenVault,
5316
4963
  l2BaseTokenSystem,
5317
4964
  baseIsEth,
5318
- l2GasLimit,
5319
- gasBufferPct,
5320
- fee
4965
+ gasOverrides: p.l2TxOverrides
4966
+ };
4967
+ }
4968
+
4969
+ // src/core/resources/withdrawals/gas.ts
4970
+ function makeGasQuote2(p) {
4971
+ return {
4972
+ gasLimit: p.gasLimit,
4973
+ maxFeePerGas: p.maxFeePerGas,
4974
+ maxPriorityFeePerGas: p.maxPriorityFeePerGas,
4975
+ maxCost: p.gasLimit * p.maxFeePerGas
4976
+ };
4977
+ }
4978
+ async function fetchFees2(estimator) {
4979
+ try {
4980
+ const fees = await estimator.estimateFeesPerGas();
4981
+ if (fees.maxFeePerGas != null) {
4982
+ return {
4983
+ maxFeePerGas: fees.maxFeePerGas,
4984
+ maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
4985
+ };
4986
+ }
4987
+ if (fees.gasPrice != null) {
4988
+ return {
4989
+ maxFeePerGas: fees.gasPrice,
4990
+ maxPriorityFeePerGas: 0n
4991
+ };
4992
+ }
4993
+ } catch {
4994
+ }
4995
+ try {
4996
+ const gp = await estimator.getGasPrice();
4997
+ return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
4998
+ } catch {
4999
+ return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
5000
+ }
5001
+ }
5002
+ async function quoteL2Gas3(input) {
5003
+ const { estimator, tx, overrides } = input;
5004
+ const market = await fetchFees2(estimator);
5005
+ const o = overrides;
5006
+ const maxFeePerGas = o?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : market.maxFeePerGas);
5007
+ const maxPriorityFeePerGas = o?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : market.maxPriorityFeePerGas);
5008
+ const explicitGasLimit = o?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
5009
+ if (explicitGasLimit != null) {
5010
+ return makeGasQuote2({
5011
+ gasLimit: explicitGasLimit,
5012
+ maxFeePerGas,
5013
+ maxPriorityFeePerGas
5014
+ });
5015
+ }
5016
+ try {
5017
+ const est = await estimator.estimateGas(tx);
5018
+ const buffered = BigInt(est) * (100n + BUFFER) / 100n;
5019
+ return makeGasQuote2({
5020
+ gasLimit: buffered,
5021
+ maxFeePerGas,
5022
+ maxPriorityFeePerGas
5023
+ });
5024
+ } catch (err) {
5025
+ console.warn("Failed to estimate L2 gas for withdrawal.", err);
5026
+ return void 0;
5027
+ }
5028
+ }
5029
+
5030
+ // src/adapters/ethers/resources/withdrawals/services/gas.ts
5031
+ async function quoteL2Gas4(input) {
5032
+ const { ctx, tx } = input;
5033
+ const estimator = ethersToGasEstimator(ctx.client.l2);
5034
+ return quoteL2Gas3({
5035
+ estimator,
5036
+ tx: toCoreTx(tx),
5037
+ overrides: ctx.gasOverrides
5038
+ });
5039
+ }
5040
+
5041
+ // src/adapters/ethers/resources/withdrawals/services/fees.ts
5042
+ function buildFeeBreakdown2(p) {
5043
+ const l2Total = p.l2Gas?.maxCost ?? 0n;
5044
+ const l2 = {
5045
+ total: l2Total,
5046
+ gasLimit: p.l2Gas?.gasLimit ?? 0n,
5047
+ maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
5048
+ maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
5049
+ };
5050
+ return {
5051
+ token: p.feeToken,
5052
+ maxTotal: l2Total,
5053
+ l2
5321
5054
  };
5322
5055
  }
5056
+
5057
+ // src/adapters/ethers/resources/withdrawals/routes/eth.ts
5323
5058
  var { wrapAs: wrapAs5 } = createErrorHandlers("withdrawals");
5324
5059
  function routeEthBase() {
5325
5060
  return {
5326
5061
  async build(p, ctx) {
5327
5062
  const steps = [];
5328
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
5329
- const base = new ethers.Contract(
5330
- L2_BASE_TOKEN_ADDRESS,
5331
- new ethers.Interface(IBaseToken_default),
5332
- ctx.client.l2
5333
- );
5334
- const toL1 = p.to ?? ctx.sender;
5063
+ const base = (await ctx.client.contracts()).l2BaseTokenSystem;
5335
5064
  const data = await wrapAs5(
5336
5065
  "INTERNAL",
5337
5066
  OP_WITHDRAWALS.eth.encodeWithdraw,
5338
- () => Promise.resolve(base.interface.encodeFunctionData("withdraw", [toL1])),
5067
+ () => Promise.resolve(base.interface.encodeFunctionData("withdraw", [p.to ?? ctx.sender])),
5339
5068
  {
5340
- ctx: { where: "L2BaseToken.withdraw", to: toL1 },
5069
+ ctx: { where: "L2BaseToken.withdraw", to: p.to ?? ctx.sender },
5341
5070
  message: "Failed to encode ETH withdraw calldata."
5342
5071
  }
5343
5072
  );
@@ -5345,34 +5074,25 @@ function routeEthBase() {
5345
5074
  to: L2_BASE_TOKEN_ADDRESS,
5346
5075
  data,
5347
5076
  from: ctx.sender,
5348
- value: p.amount,
5349
- maxFeePerGas,
5350
- maxPriorityFeePerGas
5077
+ value: p.amount
5351
5078
  };
5352
- if (overrideGasLimit != null) {
5353
- tx.gasLimit = overrideGasLimit;
5354
- } else {
5355
- try {
5356
- const est = await wrapAs5(
5357
- "RPC",
5358
- OP_WITHDRAWALS.eth.estGas,
5359
- () => ctx.client.l2.estimateGas(tx),
5360
- {
5361
- ctx: { where: "l2.estimateGas", to: L2_BASE_TOKEN_ADDRESS },
5362
- message: "Failed to estimate gas for L2 ETH withdraw."
5363
- }
5364
- );
5365
- tx.gasLimit = BigInt(est) * 115n / 100n;
5366
- } catch {
5367
- }
5368
- }
5079
+ const gas = await quoteL2Gas4({ ctx, tx });
5080
+ if (gas) {
5081
+ tx.gasLimit = gas.gasLimit;
5082
+ tx.maxFeePerGas = gas.maxFeePerGas;
5083
+ tx.maxPriorityFeePerGas = gas.maxPriorityFeePerGas;
5084
+ }
5085
+ const fees = buildFeeBreakdown2({
5086
+ feeToken: L2_BASE_TOKEN_ADDRESS,
5087
+ l2Gas: gas
5088
+ });
5369
5089
  steps.push({
5370
5090
  key: "l2-base-token:withdraw",
5371
5091
  kind: "l2-base-token:withdraw",
5372
5092
  description: "Withdraw ETH via L2 Base Token System",
5373
5093
  tx
5374
5094
  });
5375
- return { steps, approvals: [], quoteExtras: {} };
5095
+ return { steps, approvals: [], fees };
5376
5096
  }
5377
5097
  };
5378
5098
  }
@@ -5385,8 +5105,6 @@ function routeErc20NonBase2() {
5385
5105
  async build(p, ctx) {
5386
5106
  const steps = [];
5387
5107
  const approvals = [];
5388
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
5389
- const txOverrides = overrideGasLimit != null ? { maxFeePerGas, maxPriorityFeePerGas, gasLimit: overrideGasLimit } : { maxFeePerGas, maxPriorityFeePerGas };
5390
5108
  const erc20 = new ethers.Contract(p.token, IERC20_default, ctx.client.getL2Signer());
5391
5109
  const current = await wrapAs6(
5392
5110
  "CONTRACT",
@@ -5408,14 +5126,25 @@ function routeErc20NonBase2() {
5408
5126
  ctx.l2NativeTokenVault,
5409
5127
  p.amount
5410
5128
  ]);
5129
+ const approveTx = {
5130
+ to: p.token,
5131
+ data,
5132
+ from: ctx.sender
5133
+ };
5134
+ const approveGas = await quoteL2Gas4({ ctx, tx: approveTx });
5135
+ if (approveGas) {
5136
+ approveTx.gasLimit = approveGas.gasLimit;
5137
+ approveTx.maxFeePerGas = approveGas.maxFeePerGas;
5138
+ approveTx.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
5139
+ }
5411
5140
  steps.push({
5412
5141
  key: `approve:l2:${p.token}:${ctx.l2NativeTokenVault}`,
5413
5142
  kind: "approve:l2",
5414
5143
  description: `Approve ${p.amount} to NativeTokenVault`,
5415
- tx: { to: p.token, data, from: ctx.sender, ...txOverrides }
5144
+ tx: approveTx
5416
5145
  });
5417
5146
  }
5418
- const ntv = new ethers.Contract(ctx.l2NativeTokenVault, L2NativeTokenVault_default, ctx.client.l2);
5147
+ const ntv = (await ctx.client.contracts()).l2NativeTokenVault;
5419
5148
  const assetId = await wrapAs6(
5420
5149
  "CONTRACT",
5421
5150
  OP_WITHDRAWALS.erc20.ensureRegistered,
@@ -5429,17 +5158,14 @@ function routeErc20NonBase2() {
5429
5158
  "INTERNAL",
5430
5159
  OP_WITHDRAWALS.erc20.encodeAssetData,
5431
5160
  () => Promise.resolve(
5432
- ethers.AbiCoder.defaultAbiCoder().encode(
5433
- ["uint256", "address", "address"],
5434
- [p.amount, p.to ?? ctx.sender, p.token]
5435
- )
5161
+ encodeNativeTokenVaultTransferData(p.amount, p.to ?? ctx.sender, p.token)
5436
5162
  ),
5437
5163
  {
5438
5164
  ctx: { where: "AbiCoder.encode", token: p.token, to: p.to ?? ctx.sender },
5439
5165
  message: "Failed to encode burn/withdraw asset data."
5440
5166
  }
5441
5167
  );
5442
- const l2ar = new ethers.Contract(ctx.l2AssetRouter, IL2AssetRouter_default, ctx.client.l2);
5168
+ const l2ar = (await ctx.client.contracts()).l2AssetRouter;
5443
5169
  const dataWithdraw = await wrapAs6(
5444
5170
  "INTERNAL",
5445
5171
  OP_WITHDRAWALS.erc20.encodeWithdraw,
@@ -5452,81 +5178,25 @@ function routeErc20NonBase2() {
5452
5178
  const withdrawTx = {
5453
5179
  to: ctx.l2AssetRouter,
5454
5180
  data: dataWithdraw,
5455
- from: ctx.sender,
5456
- ...txOverrides
5181
+ from: ctx.sender
5457
5182
  };
5183
+ const withdrawGas = await quoteL2Gas4({ ctx, tx: withdrawTx });
5184
+ if (withdrawGas) {
5185
+ withdrawTx.gasLimit = withdrawGas.gasLimit;
5186
+ withdrawTx.maxFeePerGas = withdrawGas.maxFeePerGas;
5187
+ withdrawTx.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
5188
+ }
5458
5189
  steps.push({
5459
5190
  key: "l2-asset-router:withdraw",
5460
5191
  kind: "l2-asset-router:withdraw",
5461
5192
  description: "Burn on L2 & send L2\u2192L1 message",
5462
5193
  tx: withdrawTx
5463
5194
  });
5464
- return { steps, approvals, quoteExtras: {} };
5465
- }
5466
- };
5467
- }
5468
- var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
5469
- function routeEthNonBase2() {
5470
- return {
5471
- async preflight(p, ctx) {
5472
- await wrapAs7(
5473
- "VALIDATION",
5474
- OP_WITHDRAWALS.ethNonBase.assertNonEthBase,
5475
- () => {
5476
- if (p.token.toLowerCase() !== L2_BASE_TOKEN_ADDRESS.toLowerCase()) {
5477
- throw new Error("eth-nonbase route requires the L2 base-token alias (0x\u2026800A).");
5478
- }
5479
- if (ctx.baseIsEth) {
5480
- throw new Error("eth-nonbase route requires chain base \u2260 ETH.");
5481
- }
5482
- },
5483
- { ctx: { token: p.token, baseIsEth: ctx.baseIsEth } }
5484
- );
5485
- },
5486
- async build(p, ctx) {
5487
- const steps = [];
5488
- const { gasLimit: overrideGasLimit, maxFeePerGas, maxPriorityFeePerGas } = ctx.fee;
5489
- const toL1 = p.to ?? ctx.sender;
5490
- const iface = new ethers.Interface(IBaseToken_default);
5491
- const data = await wrapAs7(
5492
- "INTERNAL",
5493
- OP_WITHDRAWALS.eth.encodeWithdraw,
5494
- // reuse label for base-token system call
5495
- () => Promise.resolve(iface.encodeFunctionData("withdraw", [toL1])),
5496
- { ctx: { where: "L2BaseToken.withdraw", to: toL1 } }
5497
- );
5498
- const tx = {
5499
- to: L2_BASE_TOKEN_ADDRESS,
5500
- data,
5501
- from: ctx.sender,
5502
- value: p.amount,
5503
- maxFeePerGas,
5504
- maxPriorityFeePerGas
5505
- };
5506
- if (overrideGasLimit != null) {
5507
- tx.gasLimit = overrideGasLimit;
5508
- } else {
5509
- try {
5510
- const est = await wrapAs7(
5511
- "RPC",
5512
- OP_WITHDRAWALS.eth.estGas,
5513
- () => ctx.client.l2.estimateGas(tx),
5514
- {
5515
- ctx: { where: "l2.estimateGas", to: L2_BASE_TOKEN_ADDRESS },
5516
- message: "Failed to estimate gas for L2 base-token withdraw."
5517
- }
5518
- );
5519
- tx.gasLimit = BigInt(est) * 115n / 100n;
5520
- } catch {
5521
- }
5522
- }
5523
- steps.push({
5524
- key: "l2-base-token:withdraw",
5525
- kind: "l2-base-token:withdraw",
5526
- description: "Withdraw base token via L2 Base Token System (base \u2260 ETH)",
5527
- tx
5195
+ const fees = buildFeeBreakdown2({
5196
+ feeToken: await ctx.client.baseToken(ctx.chainIdL2),
5197
+ l2Gas: withdrawGas
5528
5198
  });
5529
- return { steps, approvals: [], quoteExtras: {} };
5199
+ return { steps, approvals, fees };
5530
5200
  }
5531
5201
  };
5532
5202
  }
@@ -5564,7 +5234,7 @@ function messengerLogIndex(raw, opts) {
5564
5234
  }
5565
5235
 
5566
5236
  // src/adapters/ethers/resources/withdrawals/services/finalization.ts
5567
- var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
5237
+ var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
5568
5238
  var IL1NullifierMini = [
5569
5239
  "function isWithdrawalFinalized(uint256,uint256,uint256) view returns (bool)"
5570
5240
  ];
@@ -5572,7 +5242,7 @@ function createFinalizationServices(client) {
5572
5242
  const { l1, l2, signer } = client;
5573
5243
  return {
5574
5244
  async fetchFinalizeDepositParams(l2TxHash) {
5575
- const parsed = await wrapAs8(
5245
+ const parsed = await wrapAs7(
5576
5246
  "RPC",
5577
5247
  OP_WITHDRAWALS.finalize.fetchParams.receipt,
5578
5248
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -5589,7 +5259,7 @@ function createFinalizationServices(client) {
5589
5259
  context: { l2TxHash }
5590
5260
  });
5591
5261
  }
5592
- const ev = await wrapAs8(
5262
+ const ev = await wrapAs7(
5593
5263
  "INTERNAL",
5594
5264
  OP_WITHDRAWALS.finalize.fetchParams.findMessage,
5595
5265
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
@@ -5599,7 +5269,7 @@ function createFinalizationServices(client) {
5599
5269
  message: "Failed to locate L1MessageSent event in L2 receipt."
5600
5270
  }
5601
5271
  );
5602
- const message = await wrapAs8(
5272
+ const message = await wrapAs7(
5603
5273
  "INTERNAL",
5604
5274
  OP_WITHDRAWALS.finalize.fetchParams.decodeMessage,
5605
5275
  () => Promise.resolve(ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], ev.data)[0]),
@@ -5608,7 +5278,7 @@ function createFinalizationServices(client) {
5608
5278
  message: "Failed to decode withdrawal message."
5609
5279
  }
5610
5280
  );
5611
- const raw = await wrapAs8(
5281
+ const raw = await wrapAs7(
5612
5282
  "RPC",
5613
5283
  OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
5614
5284
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -5625,7 +5295,7 @@ function createFinalizationServices(client) {
5625
5295
  context: { l2TxHash }
5626
5296
  });
5627
5297
  }
5628
- const idx = await wrapAs8(
5298
+ const idx = await wrapAs7(
5629
5299
  "INTERNAL",
5630
5300
  OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
5631
5301
  () => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
@@ -5634,7 +5304,7 @@ function createFinalizationServices(client) {
5634
5304
  message: "Failed to derive messenger log index."
5635
5305
  }
5636
5306
  );
5637
- const proof = await wrapAs8(
5307
+ const proof = await wrapAs7(
5638
5308
  "RPC",
5639
5309
  OP_WITHDRAWALS.finalize.fetchParams.proof,
5640
5310
  () => client.zks.getL2ToL1LogProof(l2TxHash, idx),
@@ -5643,7 +5313,7 @@ function createFinalizationServices(client) {
5643
5313
  message: "Failed to fetch L2\u2192L1 log proof."
5644
5314
  }
5645
5315
  );
5646
- const { chainId } = await wrapAs8(
5316
+ const { chainId } = await wrapAs7(
5647
5317
  "RPC",
5648
5318
  OP_WITHDRAWALS.finalize.fetchParams.network,
5649
5319
  () => l2.getNetwork(),
@@ -5662,7 +5332,7 @@ function createFinalizationServices(client) {
5662
5332
  message,
5663
5333
  merkleProof: proof.proof
5664
5334
  };
5665
- const { l1Nullifier } = await wrapAs8(
5335
+ const { l1Nullifier } = await wrapAs7(
5666
5336
  "INTERNAL",
5667
5337
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
5668
5338
  () => client.ensureAddresses(),
@@ -5674,7 +5344,7 @@ function createFinalizationServices(client) {
5674
5344
  return { params, nullifier: l1Nullifier };
5675
5345
  },
5676
5346
  async simulateFinalizeReadiness(params) {
5677
- const { l1Nullifier } = await wrapAs8(
5347
+ const { l1Nullifier } = await wrapAs7(
5678
5348
  "INTERNAL",
5679
5349
  OP_WITHDRAWALS.finalize.readiness.ensureAddresses,
5680
5350
  () => client.ensureAddresses(),
@@ -5686,7 +5356,7 @@ function createFinalizationServices(client) {
5686
5356
  const done = await (async () => {
5687
5357
  try {
5688
5358
  const cMini = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
5689
- const isFinalized = await wrapAs8(
5359
+ const isFinalized = await wrapAs7(
5690
5360
  "RPC",
5691
5361
  OP_WITHDRAWALS.finalize.readiness.isFinalized,
5692
5362
  () => cMini.isWithdrawalFinalized(
@@ -5714,7 +5384,7 @@ function createFinalizationServices(client) {
5714
5384
  }
5715
5385
  },
5716
5386
  async isWithdrawalFinalized(key) {
5717
- const { l1Nullifier } = await wrapAs8(
5387
+ const { l1Nullifier } = await wrapAs7(
5718
5388
  "INTERNAL",
5719
5389
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
5720
5390
  () => client.ensureAddresses(),
@@ -5724,7 +5394,7 @@ function createFinalizationServices(client) {
5724
5394
  }
5725
5395
  );
5726
5396
  const c = new ethers.Contract(l1Nullifier, IL1NullifierMini, l1);
5727
- return await wrapAs8(
5397
+ return await wrapAs7(
5728
5398
  "RPC",
5729
5399
  OP_WITHDRAWALS.finalize.isFinalized,
5730
5400
  () => c.isWithdrawalFinalized(key.chainIdL2, key.l2BatchNumber, key.l2MessageIndex),
@@ -5735,7 +5405,7 @@ function createFinalizationServices(client) {
5735
5405
  );
5736
5406
  },
5737
5407
  async estimateFinalization(params) {
5738
- const { l1Nullifier } = await wrapAs8(
5408
+ const { l1Nullifier } = await wrapAs7(
5739
5409
  "INTERNAL",
5740
5410
  OP_WITHDRAWALS.finalize.estimate,
5741
5411
  () => client.ensureAddresses(),
@@ -5746,7 +5416,7 @@ function createFinalizationServices(client) {
5746
5416
  );
5747
5417
  const signer2 = client.getL1Signer();
5748
5418
  const c = new ethers.Contract(l1Nullifier, IL1Nullifier_default, signer2);
5749
- const gasLimit = await wrapAs8(
5419
+ const gasLimit = await wrapAs7(
5750
5420
  "RPC",
5751
5421
  OP_WITHDRAWALS.finalize.estimate,
5752
5422
  () => c.finalizeDeposit.estimateGas(params),
@@ -5761,7 +5431,7 @@ function createFinalizationServices(client) {
5761
5431
  message: "Failed to estimate gas for finalizeDeposit."
5762
5432
  }
5763
5433
  );
5764
- const feeData = await wrapAs8("RPC", OP_WITHDRAWALS.finalize.estimate, () => l1.getFeeData(), {
5434
+ const feeData = await wrapAs7("RPC", OP_WITHDRAWALS.finalize.estimate, () => l1.getFeeData(), {
5765
5435
  ctx: { where: "l1.getFeeData" },
5766
5436
  message: "Failed to estimate fee data for finalizeDeposit."
5767
5437
  });
@@ -5782,7 +5452,7 @@ function createFinalizationServices(client) {
5782
5452
  };
5783
5453
  },
5784
5454
  async finalizeDeposit(params) {
5785
- const { l1Nullifier } = await wrapAs8(
5455
+ const { l1Nullifier } = await wrapAs7(
5786
5456
  "INTERNAL",
5787
5457
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
5788
5458
  () => client.ensureAddresses(),
@@ -5838,10 +5508,8 @@ function createFinalizationServices(client) {
5838
5508
 
5839
5509
  // src/adapters/ethers/resources/withdrawals/index.ts
5840
5510
  var ROUTES2 = {
5841
- "eth-base": routeEthBase(),
5511
+ base: routeEthBase(),
5842
5512
  // BaseTokenSystem.withdraw, chain base = ETH
5843
- "eth-nonbase": routeEthNonBase2(),
5844
- // BaseTokenSystem.withdraw, chain base ≠ ETH
5845
5513
  "erc20-nonbase": routeErc20NonBase2()
5846
5514
  // AssetRouter.withdraw for non-base ERC-20s
5847
5515
  };
@@ -5851,32 +5519,19 @@ function createWithdrawalsResource(client) {
5851
5519
  async function buildPlan(p) {
5852
5520
  const ctx = await commonCtx2(p, client);
5853
5521
  await ROUTES2[ctx.route].preflight?.(p, ctx);
5854
- const { steps, approvals } = await ROUTES2[ctx.route].build(p, ctx);
5855
- const resolveGasLimit = () => {
5856
- if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
5857
- for (let i = steps.length - 1; i >= 0; i--) {
5858
- const candidate = steps[i].tx.gasLimit;
5859
- if (candidate == null) continue;
5860
- if (typeof candidate === "bigint") return candidate;
5861
- try {
5862
- return BigInt(candidate.toString());
5863
- } catch {
5864
- }
5865
- }
5866
- return void 0;
5867
- };
5868
- const gasLimit = resolveGasLimit();
5869
- const summary = {
5522
+ const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
5523
+ return {
5870
5524
  route: ctx.route,
5871
- approvalsNeeded: approvals,
5872
- suggestedL2GasLimit: ctx.l2GasLimit,
5873
- fees: {
5874
- gasLimit,
5875
- maxFeePerGas: ctx.fee.maxFeePerGas,
5876
- maxPriorityFeePerGas: ctx.fee.maxPriorityFeePerGas
5877
- }
5525
+ summary: {
5526
+ route: ctx.route,
5527
+ approvalsNeeded: approvals,
5528
+ amounts: {
5529
+ transfer: { token: p.token, amount: p.amount }
5530
+ },
5531
+ fees
5532
+ },
5533
+ steps
5878
5534
  };
5879
- return { route: ctx.route, summary, steps };
5880
5535
  }
5881
5536
  const finalizeCache = /* @__PURE__ */ new Map();
5882
5537
  const quote = (p) => wrap2(