@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.
- package/README.md +12 -12
- package/dist/adapters/ethers/client.cjs +642 -1
- package/dist/adapters/ethers/client.cjs.map +1 -1
- package/dist/adapters/ethers/client.js +6 -5
- package/dist/adapters/ethers/estimator.d.ts +4 -0
- package/dist/adapters/ethers/index.cjs +934 -801
- package/dist/adapters/ethers/index.cjs.map +1 -1
- package/dist/adapters/ethers/index.js +9 -8
- package/dist/adapters/ethers/resources/deposits/context.d.ts +5 -5
- package/dist/adapters/ethers/resources/deposits/routes/types.d.ts +2 -6
- package/dist/adapters/ethers/resources/deposits/services/fee.d.ts +6 -0
- package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +40 -0
- package/dist/adapters/ethers/resources/utils.d.ts +4 -15
- package/dist/adapters/ethers/resources/withdrawals/context.d.ts +4 -4
- package/dist/adapters/ethers/resources/withdrawals/routes/types.d.ts +2 -2
- package/dist/adapters/ethers/resources/withdrawals/services/fees.d.ts +14 -0
- package/dist/adapters/ethers/resources/withdrawals/services/gas.d.ts +12 -0
- package/dist/adapters/ethers/sdk.cjs +947 -1292
- package/dist/adapters/ethers/sdk.cjs.map +1 -1
- package/dist/adapters/ethers/sdk.js +7 -6
- package/dist/adapters/viem/client.cjs.map +1 -1
- package/dist/adapters/viem/client.d.ts +1 -1
- package/dist/adapters/viem/client.js +4 -5
- package/dist/adapters/viem/estimator.d.ts +4 -0
- package/dist/adapters/viem/index.cjs +944 -662
- package/dist/adapters/viem/index.cjs.map +1 -1
- package/dist/adapters/viem/index.js +8 -8
- package/dist/adapters/viem/resources/deposits/context.d.ts +5 -5
- package/dist/adapters/viem/resources/deposits/routes/types.d.ts +2 -6
- package/dist/adapters/viem/resources/deposits/services/fee.d.ts +6 -0
- package/dist/adapters/viem/resources/deposits/services/gas.d.ts +36 -0
- package/dist/adapters/viem/resources/utils.d.ts +3 -16
- package/dist/adapters/viem/resources/withdrawals/context.d.ts +3 -6
- package/dist/adapters/viem/resources/withdrawals/routes/types.d.ts +12 -2
- package/dist/adapters/viem/resources/withdrawals/services/fee.d.ts +17 -0
- package/dist/adapters/viem/resources/withdrawals/services/gas.d.ts +12 -0
- package/dist/adapters/viem/sdk.cjs +877 -563
- package/dist/adapters/viem/sdk.cjs.map +1 -1
- package/dist/adapters/viem/sdk.d.ts +1 -1
- package/dist/adapters/viem/sdk.js +6 -6
- package/dist/{chunk-3LALBFFE.js → chunk-3MRGU4HV.js} +9 -5
- package/dist/{chunk-4HLJJKIY.js → chunk-6K6VJQAL.js} +2 -2
- package/dist/{chunk-CGO27P7F.js → chunk-BCCKWWOX.js} +540 -741
- package/dist/{chunk-6GCT6TLS.js → chunk-F2ENUV3A.js} +13 -1
- package/dist/{chunk-DI2CJDPZ.js → chunk-HLUANWGN.js} +2 -2
- package/dist/{chunk-Y75OMFK6.js → chunk-M5J2MM2U.js} +351 -1
- package/dist/{chunk-263G6636.js → chunk-NCAIVYBR.js} +1 -14
- package/dist/{chunk-7M4V3FMT.js → chunk-OC6ZVLSP.js} +669 -559
- package/dist/chunk-QJS6ETEE.js +217 -0
- package/dist/chunk-XRE7H466.js +157 -0
- package/dist/{chunk-BD2LUO5T.js → chunk-YUK547UF.js} +3 -3
- package/dist/core/abi.d.ts +9 -0
- package/dist/core/adapters/interfaces.d.ts +25 -0
- package/dist/core/constants.cjs +12 -0
- package/dist/core/constants.cjs.map +1 -1
- package/dist/core/constants.d.ts +6 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/index.cjs +4504 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +4 -4
- package/dist/core/resources/deposits/fee.d.ts +15 -0
- package/dist/core/resources/deposits/gas.d.ts +38 -0
- package/dist/core/resources/withdrawals/gas.d.ts +14 -0
- package/dist/core/types/errors.d.ts +1 -1
- package/dist/core/types/fees.d.ts +40 -0
- package/dist/core/types/flows/base.d.ts +0 -10
- package/dist/core/types/flows/deposits.d.ts +20 -6
- package/dist/core/types/flows/route.d.ts +2 -3
- package/dist/core/types/flows/withdrawals.d.ts +12 -6
- package/dist/index.cjs +4516 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/package.json +5 -1
- package/dist/adapters/ethers/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
- package/dist/adapters/viem/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
- package/dist/chunk-B77GWPO5.js +0 -339
- package/dist/core/internal/abi-registry.d.ts +0 -9
- package/dist/core/utils/gas.d.ts +0 -13
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { findL1MessageSentLog, messengerLogIndex, isAddressEq, isHash66, pickDepositRoute, isETH, normalizeAddrEq, pickWithdrawRoute } from './chunk-
|
|
3
|
-
import {
|
|
4
|
-
import { isZKsyncError, createError, shapeCause, OP_WITHDRAWALS, OP_DEPOSITS, isReceiptNotFound } from './chunk-
|
|
5
|
-
import { ETH_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS,
|
|
6
|
-
import { encodeAbiParameters, keccak256, concat, decodeErrorResult, decodeAbiParameters, decodeEventLog } from 'viem';
|
|
1
|
+
import { buildFeeBreakdown, quoteL2Gas, quoteL1Gas, quoteL2Gas2 } from './chunk-QJS6ETEE.js';
|
|
2
|
+
import { findL1MessageSentLog, messengerLogIndex, isAddressEq, isHash66, pickDepositRoute, isETH, normalizeAddrEq, pickWithdrawRoute } from './chunk-HLUANWGN.js';
|
|
3
|
+
import { REVERT_TO_READINESS } from './chunk-NCAIVYBR.js';
|
|
4
|
+
import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, isZKsyncError, createError, shapeCause, OP_WITHDRAWALS, OP_DEPOSITS, isReceiptNotFound, IBridgehub_default, IL2AssetRouter_default, IBaseToken_default } from './chunk-M5J2MM2U.js';
|
|
5
|
+
import { ETH_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L1_MESSENGER_ADDRESS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS, L2_BASE_TOKEN_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, SAFE_L1_BRIDGE_GAS } from './chunk-F2ENUV3A.js';
|
|
6
|
+
import { encodeAbiParameters, keccak256, concat, decodeErrorResult, decodeAbiParameters, decodeEventLog, encodeFunctionData, zeroAddress } from 'viem';
|
|
7
7
|
|
|
8
|
+
// src/adapters/viem/resources/deposits/context.ts
|
|
9
|
+
async function commonCtx(p, client) {
|
|
10
|
+
const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
|
|
11
|
+
const chainId = await client.l2.getChainId();
|
|
12
|
+
const sender = client.account.address;
|
|
13
|
+
const gasPerPubdata = p.gasPerPubdata ?? 800n;
|
|
14
|
+
const operatorTip = p.operatorTip ?? 0n;
|
|
15
|
+
const refundRecipient = p.refundRecipient ?? sender;
|
|
16
|
+
const route = await pickDepositRoute(client, BigInt(chainId), p.token);
|
|
17
|
+
return {
|
|
18
|
+
client,
|
|
19
|
+
l1AssetRouter,
|
|
20
|
+
route,
|
|
21
|
+
bridgehub,
|
|
22
|
+
chainIdL2: BigInt(chainId),
|
|
23
|
+
sender,
|
|
24
|
+
gasOverrides: p.l1TxOverrides,
|
|
25
|
+
l2GasLimit: p.l2GasLimit,
|
|
26
|
+
gasPerPubdata,
|
|
27
|
+
operatorTip,
|
|
28
|
+
refundRecipient
|
|
29
|
+
};
|
|
30
|
+
}
|
|
8
31
|
function encodeNativeTokenVaultAssetId(chainId, address) {
|
|
9
32
|
const encoded = encodeAbiParameters(
|
|
10
33
|
[
|
|
@@ -38,121 +61,6 @@ function encodeSecondBridgeDataV1(assetId, transferData) {
|
|
|
38
61
|
}
|
|
39
62
|
var encodeNTVAssetId = encodeNativeTokenVaultAssetId;
|
|
40
63
|
var encodeNTVTransferData = encodeNativeTokenVaultTransferData;
|
|
41
|
-
function scaleGasLimit(gasLimit) {
|
|
42
|
-
return gasLimit * BigInt(L1_FEE_ESTIMATION_COEF_NUMERATOR) / BigInt(L1_FEE_ESTIMATION_COEF_DENOMINATOR);
|
|
43
|
-
}
|
|
44
|
-
async function checkBaseCost(baseCost, value) {
|
|
45
|
-
const resolved = await value;
|
|
46
|
-
if (baseCost > resolved) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`The base cost of performing the priority operation is higher than the provided value parameter for the transaction: baseCost: ${String(baseCost)}, provided value: ${String(resolved)}!`
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function getFeeOverrides(client, overrides) {
|
|
53
|
-
assertNoLegacyGas(overrides);
|
|
54
|
-
let maxFeePerGasFromProvider;
|
|
55
|
-
let maxPriorityFromProvider;
|
|
56
|
-
let gasPriceFromProvider;
|
|
57
|
-
try {
|
|
58
|
-
const fees = await client.l1.estimateFeesPerGas();
|
|
59
|
-
const { maxFeePerGas: maxFeePerGas2, maxPriorityFeePerGas: maxPriorityFeePerGas2 } = fees;
|
|
60
|
-
if (maxFeePerGas2 != null && maxPriorityFeePerGas2 != null) {
|
|
61
|
-
maxFeePerGasFromProvider = maxFeePerGas2;
|
|
62
|
-
maxPriorityFromProvider = maxPriorityFeePerGas2;
|
|
63
|
-
gasPriceFromProvider = fees.gasPrice ?? maxFeePerGas2;
|
|
64
|
-
} else if (fees.gasPrice != null) {
|
|
65
|
-
gasPriceFromProvider = fees.gasPrice;
|
|
66
|
-
}
|
|
67
|
-
} catch {
|
|
68
|
-
}
|
|
69
|
-
if (gasPriceFromProvider == null) {
|
|
70
|
-
try {
|
|
71
|
-
gasPriceFromProvider = await client.l1.getGasPrice();
|
|
72
|
-
} catch {
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider;
|
|
76
|
-
if (maxFeePerGas == null) {
|
|
77
|
-
throw new Error("L1 provider returned no gas price data");
|
|
78
|
-
}
|
|
79
|
-
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
|
|
80
|
-
assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
|
|
81
|
-
const gasPriceForBaseCost = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider ?? maxFeePerGas;
|
|
82
|
-
return {
|
|
83
|
-
gasLimit: overrides?.gasLimit,
|
|
84
|
-
maxFeePerGas,
|
|
85
|
-
maxPriorityFeePerGas,
|
|
86
|
-
gasPriceForBaseCost
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
async function getL2FeeOverrides(client, overrides) {
|
|
90
|
-
assertNoLegacyGas(overrides);
|
|
91
|
-
let maxFeePerGasFromProvider;
|
|
92
|
-
let maxPriorityFromProvider;
|
|
93
|
-
let gasPriceFromProvider;
|
|
94
|
-
try {
|
|
95
|
-
const fees = await client.l2.estimateFeesPerGas();
|
|
96
|
-
if (fees?.maxFeePerGas != null && fees.maxPriorityFeePerGas != null) {
|
|
97
|
-
maxFeePerGasFromProvider = fees.maxFeePerGas;
|
|
98
|
-
maxPriorityFromProvider = fees.maxPriorityFeePerGas;
|
|
99
|
-
gasPriceFromProvider = fees.gasPrice ?? fees.maxFeePerGas;
|
|
100
|
-
} else if (fees?.gasPrice != null) {
|
|
101
|
-
gasPriceFromProvider = fees.gasPrice;
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
if (gasPriceFromProvider == null) {
|
|
106
|
-
try {
|
|
107
|
-
gasPriceFromProvider = await client.l2.getGasPrice();
|
|
108
|
-
} catch {
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider;
|
|
112
|
-
if (maxFeePerGas == null) {
|
|
113
|
-
throw new Error("provider returned no gas price data");
|
|
114
|
-
}
|
|
115
|
-
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
|
|
116
|
-
assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
|
|
117
|
-
return {
|
|
118
|
-
gasLimit: overrides?.gasLimit,
|
|
119
|
-
maxFeePerGas,
|
|
120
|
-
maxPriorityFeePerGas
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
function buildViemFeeOverrides(fees) {
|
|
124
|
-
return {
|
|
125
|
-
maxFeePerGas: fees.maxFeePerGas,
|
|
126
|
-
maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
|
|
127
|
-
gas: fees.gasLimit
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
async function getGasPriceWei(client) {
|
|
131
|
-
try {
|
|
132
|
-
const gp = await client.l1.getGasPrice();
|
|
133
|
-
if (gp != null) return gp;
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
try {
|
|
137
|
-
const fees = await client.l1.estimateFeesPerGas();
|
|
138
|
-
if (fees?.maxFeePerGas != null) return fees.maxFeePerGas;
|
|
139
|
-
} catch {
|
|
140
|
-
}
|
|
141
|
-
throw new Error("provider returned no gas price data");
|
|
142
|
-
}
|
|
143
|
-
function buildDirectRequestStruct(args) {
|
|
144
|
-
return {
|
|
145
|
-
chainId: args.chainId,
|
|
146
|
-
l2Contract: args.l2Contract,
|
|
147
|
-
mintValue: args.mintValue,
|
|
148
|
-
l2Value: args.l2Value,
|
|
149
|
-
l2Calldata: "0x",
|
|
150
|
-
l2GasLimit: args.l2GasLimit,
|
|
151
|
-
l2GasPerPubdataByteLimit: args.gasPerPubdata,
|
|
152
|
-
factoryDeps: [],
|
|
153
|
-
refundRecipient: args.refundRecipient
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
64
|
function encodeSecondBridgeArgs(token, amount, l2Receiver) {
|
|
157
65
|
return encodeAbiParameters(
|
|
158
66
|
[
|
|
@@ -169,30 +77,17 @@ function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
|
|
|
169
77
|
function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
|
|
170
78
|
return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
|
|
171
79
|
}
|
|
172
|
-
|
|
173
|
-
// src/adapters/viem/resources/deposits/context.ts
|
|
174
|
-
async function commonCtx(p, client) {
|
|
175
|
-
const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
|
|
176
|
-
const chainId = await client.l2.getChainId();
|
|
177
|
-
const sender = client.account.address;
|
|
178
|
-
const fee = await getFeeOverrides(client, p.l1TxOverrides);
|
|
179
|
-
const l2GasLimit = p.l2GasLimit ?? 300000n;
|
|
180
|
-
const gasPerPubdata = p.gasPerPubdata ?? 800n;
|
|
181
|
-
const operatorTip = p.operatorTip ?? 0n;
|
|
182
|
-
const refundRecipient = p.refundRecipient ?? sender;
|
|
183
|
-
const route = await pickDepositRoute(client, BigInt(chainId), p.token);
|
|
80
|
+
function buildDirectRequestStruct(args) {
|
|
184
81
|
return {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
operatorTip,
|
|
195
|
-
refundRecipient
|
|
82
|
+
chainId: args.chainId,
|
|
83
|
+
l2Contract: args.l2Contract,
|
|
84
|
+
mintValue: args.mintValue,
|
|
85
|
+
l2Value: args.l2Value,
|
|
86
|
+
l2Calldata: "0x",
|
|
87
|
+
l2GasLimit: args.l2GasLimit,
|
|
88
|
+
l2GasPerPubdataByteLimit: args.gasPerPubdata,
|
|
89
|
+
factoryDeps: [],
|
|
90
|
+
refundRecipient: args.refundRecipient
|
|
196
91
|
};
|
|
197
92
|
}
|
|
198
93
|
var ERROR_ABIS = [];
|
|
@@ -347,41 +242,228 @@ function createErrorHandlers(resource) {
|
|
|
347
242
|
return { wrap: wrap2, wrapAs: wrapAs9, toResult: toResult2 };
|
|
348
243
|
}
|
|
349
244
|
|
|
350
|
-
// src/adapters/viem/
|
|
245
|
+
// src/adapters/viem/estimator.ts
|
|
246
|
+
function toCoreTx(tx) {
|
|
247
|
+
return {
|
|
248
|
+
to: tx.to,
|
|
249
|
+
from: tx.from,
|
|
250
|
+
data: tx.data,
|
|
251
|
+
value: tx.value,
|
|
252
|
+
gasLimit: tx.gas,
|
|
253
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
254
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function viemToGasEstimator(client) {
|
|
258
|
+
return {
|
|
259
|
+
async estimateGas(tx, stateOverrides) {
|
|
260
|
+
if (stateOverrides) {
|
|
261
|
+
try {
|
|
262
|
+
const result = await client.request({
|
|
263
|
+
method: "eth_estimateGas",
|
|
264
|
+
params: [
|
|
265
|
+
{
|
|
266
|
+
from: tx.from,
|
|
267
|
+
to: tx.to,
|
|
268
|
+
data: tx.data,
|
|
269
|
+
value: tx.value,
|
|
270
|
+
gas: tx.gasLimit,
|
|
271
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
272
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
273
|
+
},
|
|
274
|
+
"latest",
|
|
275
|
+
stateOverrides
|
|
276
|
+
]
|
|
277
|
+
});
|
|
278
|
+
return BigInt(result);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.warn(
|
|
281
|
+
"Failed to estimate gas with state overrides, falling back to standard estimation:",
|
|
282
|
+
error
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return await client.estimateGas({
|
|
287
|
+
account: tx.from,
|
|
288
|
+
to: tx.to,
|
|
289
|
+
data: tx.data,
|
|
290
|
+
value: tx.value,
|
|
291
|
+
gas: tx.gasLimit,
|
|
292
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
293
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
294
|
+
});
|
|
295
|
+
},
|
|
296
|
+
async estimateFeesPerGas() {
|
|
297
|
+
try {
|
|
298
|
+
const fees = await client.estimateFeesPerGas();
|
|
299
|
+
return {
|
|
300
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
301
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas
|
|
302
|
+
};
|
|
303
|
+
} catch {
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const gp = await client.getGasPrice();
|
|
307
|
+
return { gasPrice: gp };
|
|
308
|
+
} catch {
|
|
309
|
+
return {};
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
async getGasPrice() {
|
|
313
|
+
return await client.getGasPrice();
|
|
314
|
+
},
|
|
315
|
+
async call(tx) {
|
|
316
|
+
const res = await client.call({
|
|
317
|
+
to: tx.to,
|
|
318
|
+
data: tx.data,
|
|
319
|
+
value: tx.value,
|
|
320
|
+
account: tx.from
|
|
321
|
+
});
|
|
322
|
+
return res.data ?? "0x";
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/adapters/viem/resources/deposits/services/gas.ts
|
|
328
|
+
async function quoteL1Gas2(input) {
|
|
329
|
+
const { ctx, tx, overrides, fallbackGasLimit } = input;
|
|
330
|
+
const estimator = viemToGasEstimator(ctx.client.l1);
|
|
331
|
+
return quoteL1Gas({
|
|
332
|
+
estimator,
|
|
333
|
+
tx: toCoreTx(tx),
|
|
334
|
+
overrides,
|
|
335
|
+
fallbackGasLimit
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async function quoteL2Gas3(input) {
|
|
339
|
+
const { ctx, route, l2TxForModeling, overrideGasLimit } = input;
|
|
340
|
+
const estimator = viemToGasEstimator(ctx.client.l2);
|
|
341
|
+
return quoteL2Gas({
|
|
342
|
+
estimator,
|
|
343
|
+
route,
|
|
344
|
+
tx: l2TxForModeling ? toCoreTx(l2TxForModeling) : void 0,
|
|
345
|
+
gasPerPubdata: ctx.gasPerPubdata,
|
|
346
|
+
l2GasLimit: ctx.l2GasLimit,
|
|
347
|
+
// TODO: investigate if this should be passed here; weird viem quirk
|
|
348
|
+
overrideGasLimit,
|
|
349
|
+
stateOverrides: input.stateOverrides
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
async function determineErc20L2Gas(input) {
|
|
353
|
+
const { ctx, l1Token } = input;
|
|
354
|
+
const DEFAULT_SAFE_L2_GAS_LIMIT = 3000000n;
|
|
355
|
+
if (ctx.l2GasLimit != null) {
|
|
356
|
+
return quoteL2Gas3({
|
|
357
|
+
ctx,
|
|
358
|
+
route: "erc20-nonbase",
|
|
359
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
const l2NativeTokenVault = (await ctx.client.contracts()).l2NativeTokenVault;
|
|
364
|
+
const l2TokenAddress = await ctx.client.l2.readContract({
|
|
365
|
+
address: l2NativeTokenVault.address,
|
|
366
|
+
abi: l2NativeTokenVault.abi,
|
|
367
|
+
functionName: "l2TokenAddress",
|
|
368
|
+
args: [l1Token]
|
|
369
|
+
});
|
|
370
|
+
if (l2TokenAddress === zeroAddress) {
|
|
371
|
+
return quoteL2Gas3({
|
|
372
|
+
ctx,
|
|
373
|
+
route: "erc20-nonbase",
|
|
374
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
const modelTx = {
|
|
378
|
+
to: input.modelTx?.to ?? ctx.sender,
|
|
379
|
+
from: input.modelTx?.from ?? ctx.sender,
|
|
380
|
+
data: input.modelTx?.data ?? "0x",
|
|
381
|
+
value: input.modelTx?.value ?? 0n
|
|
382
|
+
};
|
|
383
|
+
const gas = await quoteL2Gas3({
|
|
384
|
+
ctx,
|
|
385
|
+
route: "erc20-nonbase",
|
|
386
|
+
l2TxForModeling: modelTx
|
|
387
|
+
});
|
|
388
|
+
if (!gas) {
|
|
389
|
+
return quoteL2Gas3({
|
|
390
|
+
ctx,
|
|
391
|
+
route: "erc20-nonbase",
|
|
392
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
return gas;
|
|
396
|
+
} catch (err) {
|
|
397
|
+
console.warn("Failed to determine ERC20 L2 gas; defaulting to safe gas limit.", err);
|
|
398
|
+
return quoteL2Gas3({
|
|
399
|
+
ctx,
|
|
400
|
+
route: "erc20-nonbase",
|
|
401
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/adapters/viem/resources/deposits/services/fee.ts
|
|
351
407
|
var { wrapAs } = createErrorHandlers("deposits");
|
|
408
|
+
async function quoteL2BaseCost(input) {
|
|
409
|
+
const { ctx, l2GasLimit } = input;
|
|
410
|
+
const estimator = viemToGasEstimator(ctx.client.l1);
|
|
411
|
+
const fees = await estimator.estimateFeesPerGas();
|
|
412
|
+
const gasPrice = fees.maxFeePerGas ?? fees.gasPrice ?? await estimator.getGasPrice();
|
|
413
|
+
return wrapAs(
|
|
414
|
+
"RPC",
|
|
415
|
+
"deposits.fees.l2BaseCost",
|
|
416
|
+
async () => {
|
|
417
|
+
return await ctx.client.l1.readContract({
|
|
418
|
+
address: ctx.bridgehub,
|
|
419
|
+
abi: IBridgehub_default,
|
|
420
|
+
functionName: "l2TransactionBaseCost",
|
|
421
|
+
args: [ctx.chainIdL2, gasPrice, l2GasLimit, ctx.gasPerPubdata]
|
|
422
|
+
});
|
|
423
|
+
},
|
|
424
|
+
{ ctx: { chainIdL2: ctx.chainIdL2 } }
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/adapters/viem/resources/deposits/routes/eth.ts
|
|
429
|
+
var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
|
|
352
430
|
function routeEthDirect() {
|
|
353
431
|
return {
|
|
354
432
|
async build(p, ctx) {
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
"
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
{
|
|
367
|
-
ctx: {
|
|
368
|
-
|
|
433
|
+
const l2TxModel = {
|
|
434
|
+
to: p.to ?? ctx.sender,
|
|
435
|
+
from: ctx.sender,
|
|
436
|
+
data: "0x",
|
|
437
|
+
value: p.amount
|
|
438
|
+
};
|
|
439
|
+
const l2GasParams = await quoteL2Gas3({
|
|
440
|
+
ctx,
|
|
441
|
+
route: "eth-base",
|
|
442
|
+
l2TxForModeling: l2TxModel,
|
|
443
|
+
overrideGasLimit: ctx.l2GasLimit,
|
|
444
|
+
stateOverrides: {
|
|
445
|
+
[ctx.sender]: {
|
|
446
|
+
balance: "0xffffffffffffffffffff"
|
|
447
|
+
}
|
|
369
448
|
}
|
|
370
|
-
);
|
|
371
|
-
|
|
449
|
+
});
|
|
450
|
+
if (!l2GasParams) {
|
|
451
|
+
throw new Error("Failed to estimate L2 gas for deposit.");
|
|
452
|
+
}
|
|
453
|
+
const baseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2GasParams.gasLimit });
|
|
372
454
|
const l2Contract = p.to ?? ctx.sender;
|
|
373
455
|
const l2Value = p.amount;
|
|
374
456
|
const mintValue = baseCost + ctx.operatorTip + l2Value;
|
|
375
457
|
const req = buildDirectRequestStruct({
|
|
376
458
|
chainId: ctx.chainIdL2,
|
|
377
459
|
mintValue,
|
|
378
|
-
l2GasLimit:
|
|
460
|
+
l2GasLimit: l2GasParams.gasLimit,
|
|
379
461
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
380
462
|
refundRecipient: ctx.refundRecipient,
|
|
381
463
|
l2Contract,
|
|
382
464
|
l2Value
|
|
383
465
|
});
|
|
384
|
-
const sim = await
|
|
466
|
+
const sim = await wrapAs2(
|
|
385
467
|
"RPC",
|
|
386
468
|
OP_DEPOSITS.eth.estGas,
|
|
387
469
|
() => ctx.client.l1.simulateContract({
|
|
@@ -397,33 +479,53 @@ function routeEthDirect() {
|
|
|
397
479
|
message: "Failed to simulate Bridgehub.requestL2TransactionDirect."
|
|
398
480
|
}
|
|
399
481
|
);
|
|
400
|
-
const
|
|
482
|
+
const data = encodeFunctionData({
|
|
483
|
+
abi: sim.request.abi,
|
|
484
|
+
functionName: sim.request.functionName,
|
|
485
|
+
args: sim.request.args
|
|
486
|
+
});
|
|
487
|
+
const l1TxCandidate = {
|
|
488
|
+
to: ctx.bridgehub,
|
|
489
|
+
data,
|
|
490
|
+
value: mintValue,
|
|
491
|
+
from: ctx.sender,
|
|
492
|
+
...ctx.gasOverrides
|
|
493
|
+
};
|
|
494
|
+
const l1Gas = await quoteL1Gas2({
|
|
495
|
+
ctx,
|
|
496
|
+
tx: l1TxCandidate,
|
|
497
|
+
overrides: ctx.gasOverrides
|
|
498
|
+
});
|
|
401
499
|
const steps = [
|
|
402
500
|
{
|
|
403
501
|
key: "bridgehub:direct",
|
|
404
502
|
kind: "bridgehub:direct",
|
|
405
503
|
description: "Bridge ETH via Bridgehub.requestL2TransactionDirect",
|
|
406
|
-
tx: { ...sim.request, ...
|
|
504
|
+
tx: { ...sim.request, ...l1Gas }
|
|
407
505
|
}
|
|
408
506
|
];
|
|
507
|
+
const fees = buildFeeBreakdown({
|
|
508
|
+
feeToken: ETH_ADDRESS,
|
|
509
|
+
l1Gas,
|
|
510
|
+
l2Gas: l2GasParams,
|
|
511
|
+
l2BaseCost: baseCost,
|
|
512
|
+
operatorTip: ctx.operatorTip,
|
|
513
|
+
mintValue
|
|
514
|
+
});
|
|
409
515
|
return {
|
|
410
516
|
steps,
|
|
411
517
|
approvals: [],
|
|
412
|
-
|
|
518
|
+
fees
|
|
413
519
|
};
|
|
414
520
|
}
|
|
415
521
|
};
|
|
416
522
|
}
|
|
417
|
-
|
|
418
|
-
// src/adapters/viem/resources/deposits/routes/erc20-nonbase.ts
|
|
419
|
-
var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
|
|
420
|
-
var BASE_COST_BUFFER_BPS = 100n;
|
|
421
|
-
var BPS = 10000n;
|
|
422
|
-
var withBuffer = (x) => x * (BPS + BASE_COST_BUFFER_BPS) / BPS;
|
|
523
|
+
var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
|
|
423
524
|
function routeErc20NonBase() {
|
|
424
525
|
return {
|
|
526
|
+
// TODO: do we even need these validations?
|
|
425
527
|
async preflight(p, ctx) {
|
|
426
|
-
await
|
|
528
|
+
await wrapAs3(
|
|
427
529
|
"VALIDATION",
|
|
428
530
|
OP_DEPOSITS.nonbase.assertNotEthAsset,
|
|
429
531
|
() => {
|
|
@@ -433,18 +535,8 @@ function routeErc20NonBase() {
|
|
|
433
535
|
},
|
|
434
536
|
{ ctx: { token: p.token } }
|
|
435
537
|
);
|
|
436
|
-
const baseToken = await
|
|
437
|
-
|
|
438
|
-
OP_DEPOSITS.nonbase.baseToken,
|
|
439
|
-
() => ctx.client.l1.readContract({
|
|
440
|
-
address: ctx.bridgehub,
|
|
441
|
-
abi: IBridgehub_default,
|
|
442
|
-
functionName: "baseToken",
|
|
443
|
-
args: [ctx.chainIdL2]
|
|
444
|
-
}),
|
|
445
|
-
{ ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 } }
|
|
446
|
-
);
|
|
447
|
-
await wrapAs2(
|
|
538
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
539
|
+
await wrapAs3(
|
|
448
540
|
"VALIDATION",
|
|
449
541
|
OP_DEPOSITS.nonbase.assertNonBaseToken,
|
|
450
542
|
() => {
|
|
@@ -454,63 +546,49 @@ function routeErc20NonBase() {
|
|
|
454
546
|
},
|
|
455
547
|
{ ctx: { depositToken: p.token, baseToken } }
|
|
456
548
|
);
|
|
457
|
-
return;
|
|
458
549
|
},
|
|
459
550
|
async build(p, ctx) {
|
|
460
|
-
const
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
const
|
|
475
|
-
const
|
|
476
|
-
"CONTRACT",
|
|
477
|
-
OP_DEPOSITS.nonbase.baseCost,
|
|
478
|
-
() => ctx.client.l1.readContract({
|
|
479
|
-
address: ctx.bridgehub,
|
|
480
|
-
abi: IBridgehub_default,
|
|
481
|
-
functionName: "l2TransactionBaseCost",
|
|
482
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, l2GasLimitUsed, ctx.gasPerPubdata]
|
|
483
|
-
}),
|
|
484
|
-
{ ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 } }
|
|
485
|
-
);
|
|
486
|
-
const baseCost = rawBaseCost;
|
|
487
|
-
const mintValue = withBuffer(baseCost + ctx.operatorTip);
|
|
551
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
552
|
+
const baseIsEth = isETH(baseToken);
|
|
553
|
+
const assetRouter = ctx.l1AssetRouter;
|
|
554
|
+
const l2Gas = await determineErc20L2Gas({
|
|
555
|
+
ctx,
|
|
556
|
+
l1Token: p.token,
|
|
557
|
+
modelTx: {
|
|
558
|
+
to: p.to ?? ctx.sender,
|
|
559
|
+
from: ctx.sender,
|
|
560
|
+
data: "0x",
|
|
561
|
+
value: 0n
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
if (!l2Gas) throw new Error("Failed to establish L2 gas parameters.");
|
|
565
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
566
|
+
const mintValue = l2BaseCost + ctx.operatorTip;
|
|
488
567
|
const approvals = [];
|
|
489
568
|
const steps = [];
|
|
490
|
-
const depositAllowance = await
|
|
569
|
+
const depositAllowance = await wrapAs3(
|
|
491
570
|
"CONTRACT",
|
|
492
|
-
OP_DEPOSITS.nonbase.
|
|
571
|
+
OP_DEPOSITS.nonbase.allowanceToken,
|
|
493
572
|
() => ctx.client.l1.readContract({
|
|
494
573
|
address: p.token,
|
|
495
574
|
abi: IERC20_default,
|
|
496
575
|
functionName: "allowance",
|
|
497
|
-
args: [ctx.sender,
|
|
576
|
+
args: [ctx.sender, assetRouter]
|
|
498
577
|
}),
|
|
499
578
|
{
|
|
500
|
-
ctx: { where: "erc20.allowance", token: p.token, spender:
|
|
501
|
-
message: "Failed to read
|
|
579
|
+
ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
|
|
580
|
+
message: "Failed to read deposit-token allowance."
|
|
502
581
|
}
|
|
503
582
|
);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const approveDepReq = await wrapAs2(
|
|
583
|
+
if (depositAllowance < p.amount) {
|
|
584
|
+
const approveSim = await wrapAs3(
|
|
507
585
|
"CONTRACT",
|
|
508
586
|
OP_DEPOSITS.nonbase.estGas,
|
|
509
587
|
() => ctx.client.l1.simulateContract({
|
|
510
588
|
address: p.token,
|
|
511
589
|
abi: IERC20_default,
|
|
512
590
|
functionName: "approve",
|
|
513
|
-
args: [
|
|
591
|
+
args: [assetRouter, p.amount],
|
|
514
592
|
account: ctx.client.account
|
|
515
593
|
}),
|
|
516
594
|
{
|
|
@@ -518,60 +596,55 @@ function routeErc20NonBase() {
|
|
|
518
596
|
message: "Failed to simulate deposit token approve."
|
|
519
597
|
}
|
|
520
598
|
);
|
|
521
|
-
approvals.push({ token: p.token, spender:
|
|
599
|
+
approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
|
|
522
600
|
steps.push({
|
|
523
|
-
key: `approve:${p.token}:${
|
|
601
|
+
key: `approve:${p.token}:${assetRouter}`,
|
|
524
602
|
kind: "approve",
|
|
525
603
|
description: `Approve deposit token for amount`,
|
|
526
|
-
tx: { ...
|
|
604
|
+
tx: { ...approveSim.request }
|
|
527
605
|
});
|
|
528
606
|
}
|
|
529
|
-
const baseIsEth = isETH(baseToken);
|
|
530
|
-
let msgValue = 0n;
|
|
531
607
|
if (!baseIsEth) {
|
|
532
|
-
const baseAllowance = await
|
|
608
|
+
const baseAllowance = await wrapAs3(
|
|
533
609
|
"CONTRACT",
|
|
534
|
-
OP_DEPOSITS.nonbase.
|
|
610
|
+
OP_DEPOSITS.nonbase.allowanceBase,
|
|
535
611
|
() => ctx.client.l1.readContract({
|
|
536
612
|
address: baseToken,
|
|
537
613
|
abi: IERC20_default,
|
|
538
614
|
functionName: "allowance",
|
|
539
|
-
args: [ctx.sender,
|
|
615
|
+
args: [ctx.sender, assetRouter]
|
|
540
616
|
}),
|
|
541
617
|
{
|
|
542
|
-
ctx: { where: "erc20.allowance", token: baseToken, spender:
|
|
618
|
+
ctx: { where: "erc20.allowance", token: baseToken, spender: assetRouter },
|
|
543
619
|
message: "Failed to read base-token allowance."
|
|
544
620
|
}
|
|
545
621
|
);
|
|
546
622
|
if (baseAllowance < mintValue) {
|
|
547
|
-
const
|
|
623
|
+
const approveBaseSim = await wrapAs3(
|
|
548
624
|
"CONTRACT",
|
|
549
625
|
OP_DEPOSITS.nonbase.estGas,
|
|
550
626
|
() => ctx.client.l1.simulateContract({
|
|
551
627
|
address: baseToken,
|
|
552
628
|
abi: IERC20_default,
|
|
553
629
|
functionName: "approve",
|
|
554
|
-
args: [
|
|
630
|
+
args: [assetRouter, mintValue],
|
|
555
631
|
account: ctx.client.account
|
|
556
632
|
}),
|
|
557
633
|
{
|
|
558
634
|
ctx: { where: "l1.simulateContract", to: baseToken },
|
|
559
|
-
message: "Failed to simulate base
|
|
635
|
+
message: "Failed to simulate base token approve."
|
|
560
636
|
}
|
|
561
637
|
);
|
|
562
|
-
approvals.push({ token: baseToken, spender:
|
|
638
|
+
approvals.push({ token: baseToken, spender: assetRouter, amount: mintValue });
|
|
563
639
|
steps.push({
|
|
564
|
-
key: `approve:${baseToken}:${
|
|
640
|
+
key: `approve:${baseToken}:${assetRouter}`,
|
|
565
641
|
kind: "approve",
|
|
566
642
|
description: `Approve base token for mintValue`,
|
|
567
|
-
tx: { ...
|
|
643
|
+
tx: { ...approveBaseSim.request }
|
|
568
644
|
});
|
|
569
645
|
}
|
|
570
|
-
msgValue = 0n;
|
|
571
|
-
} else {
|
|
572
|
-
msgValue = mintValue;
|
|
573
646
|
}
|
|
574
|
-
const secondBridgeCalldata = await
|
|
647
|
+
const secondBridgeCalldata = await wrapAs3(
|
|
575
648
|
"INTERNAL",
|
|
576
649
|
OP_DEPOSITS.nonbase.encodeCalldata,
|
|
577
650
|
() => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, p.to ?? ctx.sender)),
|
|
@@ -580,44 +653,60 @@ function routeErc20NonBase() {
|
|
|
580
653
|
where: "encodeSecondBridgeErc20Args",
|
|
581
654
|
token: p.token,
|
|
582
655
|
amount: p.amount.toString()
|
|
583
|
-
}
|
|
656
|
+
},
|
|
657
|
+
message: "Failed to encode bridging calldata."
|
|
584
658
|
}
|
|
585
659
|
);
|
|
586
|
-
const
|
|
660
|
+
const requestStruct = {
|
|
587
661
|
chainId: ctx.chainIdL2,
|
|
588
662
|
mintValue,
|
|
589
663
|
l2Value: 0n,
|
|
590
|
-
l2GasLimit:
|
|
664
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
591
665
|
l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
|
|
592
666
|
refundRecipient: ctx.refundRecipient,
|
|
593
|
-
secondBridgeAddress:
|
|
667
|
+
secondBridgeAddress: assetRouter,
|
|
594
668
|
secondBridgeValue: 0n,
|
|
595
669
|
secondBridgeCalldata
|
|
596
670
|
};
|
|
671
|
+
const msgValue = baseIsEth ? mintValue : 0n;
|
|
672
|
+
const calldata = encodeFunctionData({
|
|
673
|
+
abi: IBridgehub_default,
|
|
674
|
+
functionName: "requestL2TransactionTwoBridges",
|
|
675
|
+
args: [requestStruct]
|
|
676
|
+
});
|
|
677
|
+
const l1TxCandidate = {
|
|
678
|
+
to: ctx.bridgehub,
|
|
679
|
+
data: calldata,
|
|
680
|
+
value: msgValue,
|
|
681
|
+
from: ctx.sender,
|
|
682
|
+
...ctx.gasOverrides
|
|
683
|
+
};
|
|
684
|
+
const l1Gas = await quoteL1Gas2({
|
|
685
|
+
ctx,
|
|
686
|
+
tx: l1TxCandidate,
|
|
687
|
+
overrides: ctx.gasOverrides,
|
|
688
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
689
|
+
});
|
|
597
690
|
const approvalsNeeded = approvals.length > 0;
|
|
598
691
|
let bridgeTx;
|
|
599
|
-
let resolvedL1GasLimit;
|
|
600
|
-
const gasOverride = txFeeOverrides.gas;
|
|
601
692
|
if (approvalsNeeded) {
|
|
602
693
|
bridgeTx = {
|
|
603
694
|
address: ctx.bridgehub,
|
|
604
695
|
abi: IBridgehub_default,
|
|
605
696
|
functionName: "requestL2TransactionTwoBridges",
|
|
606
|
-
args: [
|
|
697
|
+
args: [requestStruct],
|
|
607
698
|
value: msgValue,
|
|
608
|
-
account: ctx.client.account
|
|
609
|
-
...txFeeOverrides
|
|
699
|
+
account: ctx.client.account
|
|
610
700
|
};
|
|
611
|
-
resolvedL1GasLimit = gasOverride ?? ctx.l2GasLimit;
|
|
612
701
|
} else {
|
|
613
|
-
const sim = await
|
|
702
|
+
const sim = await wrapAs3(
|
|
614
703
|
"CONTRACT",
|
|
615
704
|
OP_DEPOSITS.nonbase.estGas,
|
|
616
705
|
() => ctx.client.l1.simulateContract({
|
|
617
706
|
address: ctx.bridgehub,
|
|
618
707
|
abi: IBridgehub_default,
|
|
619
708
|
functionName: "requestL2TransactionTwoBridges",
|
|
620
|
-
args: [
|
|
709
|
+
args: [requestStruct],
|
|
621
710
|
value: msgValue,
|
|
622
711
|
account: ctx.client.account
|
|
623
712
|
}),
|
|
@@ -626,33 +715,44 @@ function routeErc20NonBase() {
|
|
|
626
715
|
message: "Failed to simulate two-bridges request."
|
|
627
716
|
}
|
|
628
717
|
);
|
|
629
|
-
bridgeTx = { ...sim.request
|
|
630
|
-
|
|
718
|
+
bridgeTx = { ...sim.request };
|
|
719
|
+
}
|
|
720
|
+
if (l1Gas) {
|
|
721
|
+
bridgeTx = {
|
|
722
|
+
...bridgeTx,
|
|
723
|
+
gas: l1Gas.gasLimit,
|
|
724
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
725
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
726
|
+
};
|
|
631
727
|
}
|
|
632
728
|
steps.push({
|
|
633
|
-
key: "bridgehub:two-bridges:nonbase",
|
|
729
|
+
key: "bridgehub:two-bridges:erc20-nonbase",
|
|
634
730
|
kind: "bridgehub:two-bridges",
|
|
635
731
|
description: baseIsEth ? "Bridge ERC-20 (fees in ETH) via Bridgehub.requestL2TransactionTwoBridges" : "Bridge ERC-20 (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
|
|
636
732
|
tx: bridgeTx
|
|
637
733
|
});
|
|
734
|
+
const fees = buildFeeBreakdown({
|
|
735
|
+
feeToken: baseToken,
|
|
736
|
+
l1Gas,
|
|
737
|
+
l2Gas,
|
|
738
|
+
l2BaseCost,
|
|
739
|
+
operatorTip: ctx.operatorTip,
|
|
740
|
+
mintValue
|
|
741
|
+
});
|
|
638
742
|
return {
|
|
639
743
|
steps,
|
|
640
744
|
approvals,
|
|
641
|
-
|
|
745
|
+
fees
|
|
642
746
|
};
|
|
643
747
|
}
|
|
644
748
|
};
|
|
645
749
|
}
|
|
646
|
-
|
|
647
|
-
// src/adapters/viem/resources/deposits/routes/eth-nonbase.ts
|
|
648
|
-
var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
|
|
649
|
-
var BASE_COST_BUFFER_BPS2 = 100n;
|
|
650
|
-
var BPS2 = 10000n;
|
|
651
|
-
var withBuffer2 = (x) => x * (BPS2 + BASE_COST_BUFFER_BPS2) / BPS2;
|
|
750
|
+
var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
|
|
652
751
|
function routeEthNonBase() {
|
|
653
752
|
return {
|
|
753
|
+
// TODO: do we even need these validations?
|
|
654
754
|
async preflight(p, ctx) {
|
|
655
|
-
await
|
|
755
|
+
await wrapAs4(
|
|
656
756
|
"VALIDATION",
|
|
657
757
|
OP_DEPOSITS.ethNonBase.assertEthAsset,
|
|
658
758
|
() => {
|
|
@@ -662,21 +762,8 @@ function routeEthNonBase() {
|
|
|
662
762
|
},
|
|
663
763
|
{ ctx: { token: p.token } }
|
|
664
764
|
);
|
|
665
|
-
const baseToken = await
|
|
666
|
-
|
|
667
|
-
OP_DEPOSITS.ethNonBase.baseToken,
|
|
668
|
-
() => ctx.client.l1.readContract({
|
|
669
|
-
address: ctx.bridgehub,
|
|
670
|
-
abi: IBridgehub_default,
|
|
671
|
-
functionName: "baseToken",
|
|
672
|
-
args: [ctx.chainIdL2]
|
|
673
|
-
}),
|
|
674
|
-
{
|
|
675
|
-
ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
|
|
676
|
-
message: "Failed to read base token."
|
|
677
|
-
}
|
|
678
|
-
);
|
|
679
|
-
await wrapAs3(
|
|
765
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
766
|
+
await wrapAs4(
|
|
680
767
|
"VALIDATION",
|
|
681
768
|
OP_DEPOSITS.ethNonBase.assertNonEthBase,
|
|
682
769
|
() => {
|
|
@@ -686,7 +773,7 @@ function routeEthNonBase() {
|
|
|
686
773
|
},
|
|
687
774
|
{ ctx: { baseToken, chainIdL2: ctx.chainIdL2 } }
|
|
688
775
|
);
|
|
689
|
-
const ethBal = await
|
|
776
|
+
const ethBal = await wrapAs4(
|
|
690
777
|
"RPC",
|
|
691
778
|
OP_DEPOSITS.ethNonBase.ethBalance,
|
|
692
779
|
() => ctx.client.l1.getBalance({ address: ctx.sender }),
|
|
@@ -695,7 +782,7 @@ function routeEthNonBase() {
|
|
|
695
782
|
message: "Failed to read L1 ETH balance."
|
|
696
783
|
}
|
|
697
784
|
);
|
|
698
|
-
await
|
|
785
|
+
await wrapAs4(
|
|
699
786
|
"VALIDATION",
|
|
700
787
|
OP_DEPOSITS.ethNonBase.assertEthBalance,
|
|
701
788
|
() => {
|
|
@@ -705,45 +792,27 @@ function routeEthNonBase() {
|
|
|
705
792
|
},
|
|
706
793
|
{ ctx: { required: p.amount.toString(), balance: ethBal.toString() } }
|
|
707
794
|
);
|
|
708
|
-
return;
|
|
709
795
|
},
|
|
710
796
|
async build(p, ctx) {
|
|
711
|
-
const
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
const rawBaseCost = await wrapAs3(
|
|
728
|
-
"CONTRACT",
|
|
729
|
-
OP_DEPOSITS.ethNonBase.baseCost,
|
|
730
|
-
() => ctx.client.l1.readContract({
|
|
731
|
-
address: ctx.bridgehub,
|
|
732
|
-
abi: IBridgehub_default,
|
|
733
|
-
functionName: "l2TransactionBaseCost",
|
|
734
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, ctx.l2GasLimit, ctx.gasPerPubdata]
|
|
735
|
-
}),
|
|
736
|
-
{
|
|
737
|
-
ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
|
|
738
|
-
message: "Could not fetch L2 base cost."
|
|
739
|
-
}
|
|
740
|
-
);
|
|
741
|
-
const baseCost = BigInt(rawBaseCost);
|
|
742
|
-
const mintValueRaw = baseCost + ctx.operatorTip;
|
|
743
|
-
const mintValue = withBuffer2(mintValueRaw);
|
|
797
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
798
|
+
const l2TxModel = {
|
|
799
|
+
to: p.to ?? ctx.sender,
|
|
800
|
+
from: ctx.sender,
|
|
801
|
+
data: "0x",
|
|
802
|
+
value: 0n
|
|
803
|
+
};
|
|
804
|
+
const l2Gas = await quoteL2Gas3({
|
|
805
|
+
ctx,
|
|
806
|
+
route: "eth-nonbase",
|
|
807
|
+
l2TxForModeling: l2TxModel,
|
|
808
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
809
|
+
});
|
|
810
|
+
if (!l2Gas) throw new Error("Failed to estimate L2 gas parameters.");
|
|
811
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
812
|
+
const mintValue = l2BaseCost + ctx.operatorTip;
|
|
744
813
|
const approvals = [];
|
|
745
814
|
const steps = [];
|
|
746
|
-
const allowance = await
|
|
815
|
+
const allowance = await wrapAs4(
|
|
747
816
|
"CONTRACT",
|
|
748
817
|
OP_DEPOSITS.ethNonBase.allowanceBase,
|
|
749
818
|
() => ctx.client.l1.readContract({
|
|
@@ -759,7 +828,7 @@ function routeEthNonBase() {
|
|
|
759
828
|
);
|
|
760
829
|
const needsApprove = allowance < mintValue;
|
|
761
830
|
if (needsApprove) {
|
|
762
|
-
const approveSim = await
|
|
831
|
+
const approveSim = await wrapAs4(
|
|
763
832
|
"CONTRACT",
|
|
764
833
|
OP_DEPOSITS.ethNonBase.estGas,
|
|
765
834
|
() => ctx.client.l1.simulateContract({
|
|
@@ -778,11 +847,11 @@ function routeEthNonBase() {
|
|
|
778
847
|
steps.push({
|
|
779
848
|
key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
|
|
780
849
|
kind: "approve",
|
|
781
|
-
description: `Approve base token for mintValue`,
|
|
850
|
+
description: `Approve base token for fees (mintValue)`,
|
|
782
851
|
tx: { ...approveSim.request }
|
|
783
852
|
});
|
|
784
853
|
}
|
|
785
|
-
const secondBridgeCalldata = await
|
|
854
|
+
const secondBridgeCalldata = await wrapAs4(
|
|
786
855
|
"INTERNAL",
|
|
787
856
|
OP_DEPOSITS.ethNonBase.encodeCalldata,
|
|
788
857
|
() => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, p.to ?? ctx.sender)),
|
|
@@ -795,11 +864,11 @@ function routeEthNonBase() {
|
|
|
795
864
|
message: "Failed to encode ETH bridging calldata."
|
|
796
865
|
}
|
|
797
866
|
);
|
|
798
|
-
const
|
|
867
|
+
const requestStruct = {
|
|
799
868
|
chainId: ctx.chainIdL2,
|
|
800
869
|
mintValue,
|
|
801
|
-
l2Value:
|
|
802
|
-
l2GasLimit:
|
|
870
|
+
l2Value: p.amount,
|
|
871
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
803
872
|
l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
|
|
804
873
|
refundRecipient: ctx.refundRecipient,
|
|
805
874
|
secondBridgeAddress: ctx.l1AssetRouter,
|
|
@@ -807,29 +876,32 @@ function routeEthNonBase() {
|
|
|
807
876
|
secondBridgeCalldata
|
|
808
877
|
};
|
|
809
878
|
let bridgeTx;
|
|
810
|
-
let
|
|
879
|
+
let calldata;
|
|
811
880
|
if (needsApprove) {
|
|
812
881
|
bridgeTx = {
|
|
813
882
|
address: ctx.bridgehub,
|
|
814
883
|
abi: IBridgehub_default,
|
|
815
884
|
functionName: "requestL2TransactionTwoBridges",
|
|
816
|
-
args: [
|
|
885
|
+
args: [requestStruct],
|
|
817
886
|
value: p.amount,
|
|
818
887
|
// base ≠ ETH ⇒ msg.value == secondBridgeValue
|
|
819
888
|
account: ctx.client.account
|
|
820
889
|
};
|
|
821
|
-
|
|
890
|
+
calldata = encodeFunctionData({
|
|
891
|
+
abi: IBridgehub_default,
|
|
892
|
+
functionName: "requestL2TransactionTwoBridges",
|
|
893
|
+
args: [requestStruct]
|
|
894
|
+
});
|
|
822
895
|
} else {
|
|
823
|
-
const
|
|
896
|
+
const sim = await wrapAs4(
|
|
824
897
|
"CONTRACT",
|
|
825
898
|
OP_DEPOSITS.ethNonBase.estGas,
|
|
826
899
|
() => ctx.client.l1.simulateContract({
|
|
827
900
|
address: ctx.bridgehub,
|
|
828
901
|
abi: IBridgehub_default,
|
|
829
902
|
functionName: "requestL2TransactionTwoBridges",
|
|
830
|
-
args: [
|
|
903
|
+
args: [requestStruct],
|
|
831
904
|
value: p.amount,
|
|
832
|
-
// base ≠ ETH ⇒ msg.value == secondBridgeValue
|
|
833
905
|
account: ctx.client.account
|
|
834
906
|
}),
|
|
835
907
|
{
|
|
@@ -837,8 +909,33 @@ function routeEthNonBase() {
|
|
|
837
909
|
message: "Failed to simulate Bridgehub two-bridges request."
|
|
838
910
|
}
|
|
839
911
|
);
|
|
840
|
-
|
|
841
|
-
|
|
912
|
+
calldata = encodeFunctionData({
|
|
913
|
+
abi: sim.request.abi,
|
|
914
|
+
functionName: sim.request.functionName,
|
|
915
|
+
args: sim.request.args
|
|
916
|
+
});
|
|
917
|
+
bridgeTx = { ...sim.request };
|
|
918
|
+
}
|
|
919
|
+
const l1TxCandidate = {
|
|
920
|
+
to: ctx.bridgehub,
|
|
921
|
+
data: calldata,
|
|
922
|
+
value: p.amount,
|
|
923
|
+
from: ctx.sender,
|
|
924
|
+
...ctx.gasOverrides
|
|
925
|
+
};
|
|
926
|
+
const l1Gas = await quoteL1Gas2({
|
|
927
|
+
ctx,
|
|
928
|
+
tx: l1TxCandidate,
|
|
929
|
+
overrides: ctx.gasOverrides,
|
|
930
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
931
|
+
});
|
|
932
|
+
if (l1Gas) {
|
|
933
|
+
bridgeTx = {
|
|
934
|
+
...bridgeTx,
|
|
935
|
+
gas: l1Gas.gasLimit,
|
|
936
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
937
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
938
|
+
};
|
|
842
939
|
}
|
|
843
940
|
steps.push({
|
|
844
941
|
key: "bridgehub:two-bridges:eth-nonbase",
|
|
@@ -846,24 +943,27 @@ function routeEthNonBase() {
|
|
|
846
943
|
description: "Bridge ETH (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
|
|
847
944
|
tx: bridgeTx
|
|
848
945
|
});
|
|
946
|
+
const fees = buildFeeBreakdown({
|
|
947
|
+
feeToken: baseToken,
|
|
948
|
+
l1Gas,
|
|
949
|
+
l2Gas,
|
|
950
|
+
l2BaseCost,
|
|
951
|
+
operatorTip: ctx.operatorTip,
|
|
952
|
+
mintValue
|
|
953
|
+
});
|
|
849
954
|
return {
|
|
850
955
|
steps,
|
|
851
956
|
approvals,
|
|
852
|
-
|
|
957
|
+
fees
|
|
853
958
|
};
|
|
854
959
|
}
|
|
855
960
|
};
|
|
856
961
|
}
|
|
857
|
-
|
|
858
|
-
// src/adapters/viem/resources/deposits/routes/erc20-base.ts
|
|
859
|
-
var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
|
|
860
|
-
var BASE_COST_BUFFER_BPS3 = 100n;
|
|
861
|
-
var BPS3 = 10000n;
|
|
862
|
-
var withBuffer3 = (x) => x * (BPS3 + BASE_COST_BUFFER_BPS3) / BPS3;
|
|
962
|
+
var { wrapAs: wrapAs5 } = createErrorHandlers("deposits");
|
|
863
963
|
function routeErc20Base() {
|
|
864
964
|
return {
|
|
865
965
|
async preflight(p, ctx) {
|
|
866
|
-
await
|
|
966
|
+
await wrapAs5(
|
|
867
967
|
"VALIDATION",
|
|
868
968
|
OP_DEPOSITS.base.assertErc20Asset,
|
|
869
969
|
() => {
|
|
@@ -873,21 +973,8 @@ function routeErc20Base() {
|
|
|
873
973
|
},
|
|
874
974
|
{ ctx: { token: p.token } }
|
|
875
975
|
);
|
|
876
|
-
const baseToken = await
|
|
877
|
-
|
|
878
|
-
OP_DEPOSITS.base.baseToken,
|
|
879
|
-
() => ctx.client.l1.readContract({
|
|
880
|
-
address: ctx.bridgehub,
|
|
881
|
-
abi: IBridgehub_default,
|
|
882
|
-
functionName: "baseToken",
|
|
883
|
-
args: [ctx.chainIdL2]
|
|
884
|
-
}),
|
|
885
|
-
{
|
|
886
|
-
ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
|
|
887
|
-
message: "Failed to read base token."
|
|
888
|
-
}
|
|
889
|
-
);
|
|
890
|
-
await wrapAs4(
|
|
976
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
977
|
+
await wrapAs5(
|
|
891
978
|
"VALIDATION",
|
|
892
979
|
OP_DEPOSITS.base.assertMatchesBase,
|
|
893
980
|
() => {
|
|
@@ -897,45 +984,27 @@ function routeErc20Base() {
|
|
|
897
984
|
},
|
|
898
985
|
{ ctx: { baseToken, provided: p.token, chainIdL2: ctx.chainIdL2 } }
|
|
899
986
|
);
|
|
900
|
-
return;
|
|
901
987
|
},
|
|
902
988
|
async build(p, ctx) {
|
|
903
|
-
const
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
"
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
OP_DEPOSITS.base.baseCost,
|
|
923
|
-
() => ctx.client.l1.readContract({
|
|
924
|
-
address: ctx.bridgehub,
|
|
925
|
-
abi: IBridgehub_default,
|
|
926
|
-
functionName: "l2TransactionBaseCost",
|
|
927
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, ctx.l2GasLimit, ctx.gasPerPubdata]
|
|
928
|
-
}),
|
|
929
|
-
{
|
|
930
|
-
ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
|
|
931
|
-
message: "Could not fetch L2 base cost from Bridgehub."
|
|
932
|
-
}
|
|
933
|
-
);
|
|
934
|
-
const baseCost = rawBaseCost;
|
|
935
|
-
const l2Value = p.amount;
|
|
936
|
-
const rawMintValue = baseCost + ctx.operatorTip + l2Value;
|
|
937
|
-
const mintValue = withBuffer3(rawMintValue);
|
|
938
|
-
const allowance = await wrapAs4(
|
|
989
|
+
const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
|
|
990
|
+
const l2TxModel = {
|
|
991
|
+
to: p.to ?? ctx.sender,
|
|
992
|
+
from: ctx.sender,
|
|
993
|
+
data: "0x",
|
|
994
|
+
value: 0n
|
|
995
|
+
};
|
|
996
|
+
const l2Gas = await quoteL2Gas3({
|
|
997
|
+
ctx,
|
|
998
|
+
route: "erc20-base",
|
|
999
|
+
l2TxForModeling: l2TxModel,
|
|
1000
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
1001
|
+
});
|
|
1002
|
+
if (!l2Gas) throw new Error("Failed to estimate L2 gas parameters.");
|
|
1003
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
1004
|
+
const mintValue = l2BaseCost + ctx.operatorTip + p.amount;
|
|
1005
|
+
const approvals = [];
|
|
1006
|
+
const steps = [];
|
|
1007
|
+
const allowance = await wrapAs5(
|
|
939
1008
|
"CONTRACT",
|
|
940
1009
|
OP_DEPOSITS.base.allowance,
|
|
941
1010
|
() => ctx.client.l1.readContract({
|
|
@@ -949,11 +1018,9 @@ function routeErc20Base() {
|
|
|
949
1018
|
message: "Failed to read base-token allowance."
|
|
950
1019
|
}
|
|
951
1020
|
);
|
|
952
|
-
const approvals = [];
|
|
953
|
-
const steps = [];
|
|
954
1021
|
const needsApprove = allowance < mintValue;
|
|
955
1022
|
if (needsApprove) {
|
|
956
|
-
const approveSim = await
|
|
1023
|
+
const approveSim = await wrapAs5(
|
|
957
1024
|
"CONTRACT",
|
|
958
1025
|
OP_DEPOSITS.base.estGas,
|
|
959
1026
|
() => ctx.client.l1.simulateContract({
|
|
@@ -973,20 +1040,20 @@ function routeErc20Base() {
|
|
|
973
1040
|
key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
|
|
974
1041
|
kind: "approve",
|
|
975
1042
|
description: "Approve base token for mintValue",
|
|
976
|
-
tx: { ...approveSim.request
|
|
1043
|
+
tx: { ...approveSim.request }
|
|
977
1044
|
});
|
|
978
1045
|
}
|
|
979
1046
|
const req = buildDirectRequestStruct({
|
|
980
1047
|
chainId: ctx.chainIdL2,
|
|
981
1048
|
mintValue,
|
|
982
|
-
l2GasLimit:
|
|
1049
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
983
1050
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
984
1051
|
refundRecipient: ctx.refundRecipient,
|
|
985
1052
|
l2Contract: p.to ?? ctx.sender,
|
|
986
|
-
l2Value
|
|
1053
|
+
l2Value: p.amount
|
|
987
1054
|
});
|
|
988
1055
|
let bridgeTx;
|
|
989
|
-
let
|
|
1056
|
+
let calldata;
|
|
990
1057
|
if (needsApprove) {
|
|
991
1058
|
bridgeTx = {
|
|
992
1059
|
address: ctx.bridgehub,
|
|
@@ -994,13 +1061,16 @@ function routeErc20Base() {
|
|
|
994
1061
|
functionName: "requestL2TransactionDirect",
|
|
995
1062
|
args: [req],
|
|
996
1063
|
value: 0n,
|
|
997
|
-
// base is ERC-20 ⇒ msg.value MUST be 0
|
|
998
|
-
account: ctx.client.account
|
|
999
|
-
...txFeeOverrides
|
|
1064
|
+
// base token is ERC-20 ⇒ msg.value MUST be 0
|
|
1065
|
+
account: ctx.client.account
|
|
1000
1066
|
};
|
|
1001
|
-
|
|
1067
|
+
calldata = encodeFunctionData({
|
|
1068
|
+
abi: IBridgehub_default,
|
|
1069
|
+
functionName: "requestL2TransactionDirect",
|
|
1070
|
+
args: [req]
|
|
1071
|
+
});
|
|
1002
1072
|
} else {
|
|
1003
|
-
const sim = await
|
|
1073
|
+
const sim = await wrapAs5(
|
|
1004
1074
|
"RPC",
|
|
1005
1075
|
OP_DEPOSITS.base.estGas,
|
|
1006
1076
|
() => ctx.client.l1.simulateContract({
|
|
@@ -1016,8 +1086,33 @@ function routeErc20Base() {
|
|
|
1016
1086
|
message: "Failed to simulate Bridgehub.requestL2TransactionDirect."
|
|
1017
1087
|
}
|
|
1018
1088
|
);
|
|
1019
|
-
|
|
1020
|
-
|
|
1089
|
+
calldata = encodeFunctionData({
|
|
1090
|
+
abi: sim.request.abi,
|
|
1091
|
+
functionName: sim.request.functionName,
|
|
1092
|
+
args: sim.request.args
|
|
1093
|
+
});
|
|
1094
|
+
bridgeTx = { ...sim.request };
|
|
1095
|
+
}
|
|
1096
|
+
const l1TxCandidate = {
|
|
1097
|
+
to: ctx.bridgehub,
|
|
1098
|
+
data: calldata,
|
|
1099
|
+
value: 0n,
|
|
1100
|
+
from: ctx.sender,
|
|
1101
|
+
...ctx.gasOverrides
|
|
1102
|
+
};
|
|
1103
|
+
const l1Gas = await quoteL1Gas2({
|
|
1104
|
+
ctx,
|
|
1105
|
+
tx: l1TxCandidate,
|
|
1106
|
+
overrides: ctx.gasOverrides,
|
|
1107
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
1108
|
+
});
|
|
1109
|
+
if (l1Gas) {
|
|
1110
|
+
bridgeTx = {
|
|
1111
|
+
...bridgeTx,
|
|
1112
|
+
gas: l1Gas.gasLimit,
|
|
1113
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
1114
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
1115
|
+
};
|
|
1021
1116
|
}
|
|
1022
1117
|
steps.push({
|
|
1023
1118
|
key: "bridgehub:direct:erc20-base",
|
|
@@ -1025,10 +1120,18 @@ function routeErc20Base() {
|
|
|
1025
1120
|
description: "Bridge base ERC-20 via Bridgehub.requestL2TransactionDirect",
|
|
1026
1121
|
tx: bridgeTx
|
|
1027
1122
|
});
|
|
1123
|
+
const fees = buildFeeBreakdown({
|
|
1124
|
+
feeToken: baseToken,
|
|
1125
|
+
l1Gas,
|
|
1126
|
+
l2Gas,
|
|
1127
|
+
l2BaseCost,
|
|
1128
|
+
operatorTip: ctx.operatorTip,
|
|
1129
|
+
mintValue
|
|
1130
|
+
});
|
|
1028
1131
|
return {
|
|
1029
1132
|
steps,
|
|
1030
1133
|
approvals,
|
|
1031
|
-
|
|
1134
|
+
fees
|
|
1032
1135
|
};
|
|
1033
1136
|
}
|
|
1034
1137
|
};
|
|
@@ -1122,32 +1225,19 @@ function createDepositsResource(client) {
|
|
|
1122
1225
|
const ctx = await commonCtx(p, client);
|
|
1123
1226
|
const route = ctx.route;
|
|
1124
1227
|
await ROUTES[route].preflight?.(p, ctx);
|
|
1125
|
-
const { steps, approvals,
|
|
1126
|
-
const { baseCost, mintValue } = quoteExtras;
|
|
1127
|
-
const fallbackGasLimit = quoteExtras.l1GasLimit;
|
|
1128
|
-
const resolveGasLimit = () => {
|
|
1129
|
-
if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
|
|
1130
|
-
for (let i = steps.length - 1; i >= 0; i--) {
|
|
1131
|
-
const candidate = steps[i].tx.gas;
|
|
1132
|
-
if (candidate != null) return candidate;
|
|
1133
|
-
}
|
|
1134
|
-
if (fallbackGasLimit != null) return fallbackGasLimit;
|
|
1135
|
-
return ctx.l2GasLimit;
|
|
1136
|
-
};
|
|
1137
|
-
const gasLimit = resolveGasLimit();
|
|
1228
|
+
const { steps, approvals, fees } = await ROUTES[route].build(p, ctx);
|
|
1138
1229
|
return {
|
|
1139
1230
|
route: ctx.route,
|
|
1140
1231
|
summary: {
|
|
1141
1232
|
route: ctx.route,
|
|
1142
1233
|
approvalsNeeded: approvals,
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
fees
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
}
|
|
1234
|
+
amounts: {
|
|
1235
|
+
transfer: { token: p.token, amount: p.amount }
|
|
1236
|
+
},
|
|
1237
|
+
fees,
|
|
1238
|
+
// Legacy fields (maintained for backward compatibility)
|
|
1239
|
+
baseCost: fees.l2?.baseCost,
|
|
1240
|
+
mintValue: fees.mintValue
|
|
1151
1241
|
},
|
|
1152
1242
|
steps
|
|
1153
1243
|
};
|
|
@@ -1222,7 +1312,7 @@ function createDepositsResource(client) {
|
|
|
1222
1312
|
step.tx.gas = overrides.gasLimit;
|
|
1223
1313
|
}
|
|
1224
1314
|
}
|
|
1225
|
-
if (
|
|
1315
|
+
if (!p.l1TxOverrides?.gasLimit) {
|
|
1226
1316
|
try {
|
|
1227
1317
|
const feePart = step.tx.maxFeePerGas != null && step.tx.maxPriorityFeePerGas != null ? {
|
|
1228
1318
|
maxFeePerGas: step.tx.maxFeePerGas,
|
|
@@ -1473,13 +1563,7 @@ async function commonCtx2(p, client) {
|
|
|
1473
1563
|
} = await client.ensureAddresses();
|
|
1474
1564
|
const chainIdL2 = BigInt(await client.l2.getChainId());
|
|
1475
1565
|
const baseIsEth = await isEthBasedChain(client.l2, l2NativeTokenVault);
|
|
1476
|
-
const
|
|
1477
|
-
const route = pickWithdrawRoute({
|
|
1478
|
-
token: p.token,
|
|
1479
|
-
baseIsEth
|
|
1480
|
-
});
|
|
1481
|
-
const l2GasLimit = p.l2GasLimit ?? 300000n;
|
|
1482
|
-
const gasBufferPct = 15;
|
|
1566
|
+
const route = pickWithdrawRoute({ token: p.token, baseIsEth });
|
|
1483
1567
|
return {
|
|
1484
1568
|
client,
|
|
1485
1569
|
bridgehub,
|
|
@@ -1492,56 +1576,101 @@ async function commonCtx2(p, client) {
|
|
|
1492
1576
|
l2NativeTokenVault,
|
|
1493
1577
|
l2BaseTokenSystem,
|
|
1494
1578
|
baseIsEth,
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1579
|
+
gasOverrides: p.l2TxOverrides
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// src/adapters/viem/resources/withdrawals/services/gas.ts
|
|
1584
|
+
async function quoteL2Gas4(input) {
|
|
1585
|
+
const { ctx, tx } = input;
|
|
1586
|
+
const estimator = viemToGasEstimator(ctx.client.l2);
|
|
1587
|
+
return quoteL2Gas2({
|
|
1588
|
+
estimator,
|
|
1589
|
+
tx: toCoreTx(tx),
|
|
1590
|
+
overrides: ctx.gasOverrides
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
// src/adapters/viem/resources/withdrawals/services/fee.ts
|
|
1595
|
+
function buildFeeBreakdown2(p) {
|
|
1596
|
+
const l2Total = p.l2Gas?.maxCost ?? 0n;
|
|
1597
|
+
const l2 = {
|
|
1598
|
+
total: l2Total,
|
|
1599
|
+
gasLimit: p.l2Gas?.gasLimit ?? 0n,
|
|
1600
|
+
maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
|
|
1601
|
+
maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
|
|
1602
|
+
};
|
|
1603
|
+
return {
|
|
1604
|
+
token: p.feeToken,
|
|
1605
|
+
maxTotal: l2Total,
|
|
1606
|
+
l2
|
|
1498
1607
|
};
|
|
1499
1608
|
}
|
|
1500
1609
|
|
|
1501
1610
|
// src/adapters/viem/resources/withdrawals/routes/eth.ts
|
|
1502
|
-
var { wrapAs:
|
|
1611
|
+
var { wrapAs: wrapAs6 } = createErrorHandlers("withdrawals");
|
|
1503
1612
|
function routeEthBase() {
|
|
1504
1613
|
return {
|
|
1505
1614
|
async build(p, ctx) {
|
|
1506
|
-
const
|
|
1507
|
-
const
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
account: ctx.client.account,
|
|
1518
|
-
...txFeeOverrides
|
|
1519
|
-
}),
|
|
1615
|
+
const steps = [];
|
|
1616
|
+
const data = await wrapAs6(
|
|
1617
|
+
"INTERNAL",
|
|
1618
|
+
OP_WITHDRAWALS.eth.encodeWithdraw,
|
|
1619
|
+
() => Promise.resolve(
|
|
1620
|
+
encodeFunctionData({
|
|
1621
|
+
abi: IBaseToken_default,
|
|
1622
|
+
functionName: "withdraw",
|
|
1623
|
+
args: [p.to ?? ctx.sender]
|
|
1624
|
+
})
|
|
1625
|
+
),
|
|
1520
1626
|
{
|
|
1521
|
-
ctx: { where: "
|
|
1522
|
-
message: "Failed to
|
|
1627
|
+
ctx: { where: "L2BaseToken.withdraw", to: p.to ?? ctx.sender },
|
|
1628
|
+
message: "Failed to encode ETH withdraw calldata."
|
|
1523
1629
|
}
|
|
1524
1630
|
);
|
|
1525
|
-
const
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1631
|
+
const L2tx = {
|
|
1632
|
+
to: L2_BASE_TOKEN_ADDRESS,
|
|
1633
|
+
data,
|
|
1634
|
+
value: p.amount,
|
|
1635
|
+
from: ctx.sender
|
|
1636
|
+
};
|
|
1637
|
+
const l2Gas = await quoteL2Gas4({ ctx, tx: L2tx });
|
|
1638
|
+
if (l2Gas) {
|
|
1639
|
+
L2tx.gas = l2Gas.gasLimit;
|
|
1640
|
+
L2tx.maxFeePerGas = l2Gas.maxFeePerGas;
|
|
1641
|
+
L2tx.maxPriorityFeePerGas = l2Gas.maxPriorityFeePerGas;
|
|
1642
|
+
}
|
|
1643
|
+
const tx = {
|
|
1644
|
+
address: L2_BASE_TOKEN_ADDRESS,
|
|
1645
|
+
abi: IBaseToken_default,
|
|
1646
|
+
functionName: "withdraw",
|
|
1647
|
+
args: [p.to ?? ctx.sender],
|
|
1648
|
+
value: p.amount,
|
|
1649
|
+
account: ctx.client.account,
|
|
1650
|
+
...l2Gas
|
|
1651
|
+
};
|
|
1652
|
+
const fees = buildFeeBreakdown2({
|
|
1653
|
+
feeToken: L2_BASE_TOKEN_ADDRESS,
|
|
1654
|
+
l2Gas
|
|
1655
|
+
});
|
|
1656
|
+
steps.push({
|
|
1657
|
+
key: "l2-base-token:withdraw",
|
|
1658
|
+
kind: "l2-base-token:withdraw",
|
|
1659
|
+
description: "Withdraw ETH via L2 Base Token System",
|
|
1660
|
+
tx
|
|
1661
|
+
});
|
|
1662
|
+
return { steps, approvals: [], fees };
|
|
1534
1663
|
}
|
|
1535
1664
|
};
|
|
1536
1665
|
}
|
|
1537
|
-
var { wrapAs:
|
|
1666
|
+
var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
|
|
1538
1667
|
function routeErc20NonBase2() {
|
|
1539
1668
|
return {
|
|
1540
1669
|
// TODO: add preflight validations here
|
|
1541
1670
|
async build(p, ctx) {
|
|
1542
|
-
const
|
|
1543
|
-
const
|
|
1544
|
-
const current = await
|
|
1671
|
+
const steps = [];
|
|
1672
|
+
const approvals = [];
|
|
1673
|
+
const current = await wrapAs7(
|
|
1545
1674
|
"CONTRACT",
|
|
1546
1675
|
OP_WITHDRAWALS.erc20.allowance,
|
|
1547
1676
|
() => ctx.client.l2.readContract({
|
|
@@ -1561,12 +1690,26 @@ function routeErc20NonBase2() {
|
|
|
1561
1690
|
message: "Failed to read L2 ERC-20 allowance."
|
|
1562
1691
|
}
|
|
1563
1692
|
);
|
|
1564
|
-
|
|
1565
|
-
const steps = [];
|
|
1566
|
-
const approvals = [];
|
|
1567
|
-
if (needsApprove) {
|
|
1693
|
+
if (current < p.amount) {
|
|
1568
1694
|
approvals.push({ token: p.token, spender: ctx.l2NativeTokenVault, amount: p.amount });
|
|
1569
|
-
const
|
|
1695
|
+
const data = encodeFunctionData({
|
|
1696
|
+
abi: IERC20_default,
|
|
1697
|
+
functionName: "approve",
|
|
1698
|
+
args: [ctx.l2NativeTokenVault, p.amount]
|
|
1699
|
+
});
|
|
1700
|
+
const approveTxCandidate = {
|
|
1701
|
+
to: p.token,
|
|
1702
|
+
data,
|
|
1703
|
+
value: 0n,
|
|
1704
|
+
from: ctx.sender
|
|
1705
|
+
};
|
|
1706
|
+
const approveGas = await quoteL2Gas4({ ctx, tx: approveTxCandidate });
|
|
1707
|
+
if (approveGas) {
|
|
1708
|
+
approveTxCandidate.gas = approveGas.gasLimit;
|
|
1709
|
+
approveTxCandidate.maxFeePerGas = approveGas.maxFeePerGas;
|
|
1710
|
+
approveTxCandidate.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
|
|
1711
|
+
}
|
|
1712
|
+
const approveSim = await wrapAs7(
|
|
1570
1713
|
"CONTRACT",
|
|
1571
1714
|
OP_WITHDRAWALS.erc20.estGas,
|
|
1572
1715
|
() => ctx.client.l2.simulateContract({
|
|
@@ -1575,21 +1718,25 @@ function routeErc20NonBase2() {
|
|
|
1575
1718
|
functionName: "approve",
|
|
1576
1719
|
args: [ctx.l2NativeTokenVault, p.amount],
|
|
1577
1720
|
account: ctx.client.account,
|
|
1578
|
-
...
|
|
1721
|
+
...approveGas
|
|
1579
1722
|
}),
|
|
1580
1723
|
{
|
|
1581
1724
|
ctx: { where: "l2.simulateContract", to: p.token },
|
|
1582
1725
|
message: "Failed to simulate L2 ERC-20 approve."
|
|
1583
1726
|
}
|
|
1584
1727
|
);
|
|
1728
|
+
const { ...approveRequest } = approveSim.request;
|
|
1729
|
+
const approveTx = {
|
|
1730
|
+
...approveRequest
|
|
1731
|
+
};
|
|
1585
1732
|
steps.push({
|
|
1586
1733
|
key: `approve:l2:${p.token}:${ctx.l2NativeTokenVault}`,
|
|
1587
1734
|
kind: "approve:l2",
|
|
1588
1735
|
description: `Approve ${p.amount} to NativeTokenVault`,
|
|
1589
|
-
tx:
|
|
1736
|
+
tx: approveTx
|
|
1590
1737
|
});
|
|
1591
1738
|
}
|
|
1592
|
-
const ensure = await
|
|
1739
|
+
const ensure = await wrapAs7(
|
|
1593
1740
|
"CONTRACT",
|
|
1594
1741
|
OP_WITHDRAWALS.erc20.ensureRegistered,
|
|
1595
1742
|
() => ctx.client.l2.simulateContract({
|
|
@@ -1611,20 +1758,37 @@ function routeErc20NonBase2() {
|
|
|
1611
1758
|
{ type: "address", name: "l1Receiver" },
|
|
1612
1759
|
{ type: "address", name: "l2Token" }
|
|
1613
1760
|
],
|
|
1614
|
-
[p.amount,
|
|
1761
|
+
[p.amount, p.to ?? ctx.sender, p.token]
|
|
1615
1762
|
);
|
|
1763
|
+
const withdrawCalldata = encodeFunctionData({
|
|
1764
|
+
abi: IL2AssetRouter_default,
|
|
1765
|
+
functionName: "withdraw",
|
|
1766
|
+
args: [assetId, assetData]
|
|
1767
|
+
});
|
|
1768
|
+
const withdrawTxCandidate = {
|
|
1769
|
+
to: ctx.l2AssetRouter,
|
|
1770
|
+
data: withdrawCalldata,
|
|
1771
|
+
value: 0n,
|
|
1772
|
+
from: ctx.sender
|
|
1773
|
+
};
|
|
1774
|
+
const withdrawGas = await quoteL2Gas4({ ctx, tx: withdrawTxCandidate });
|
|
1775
|
+
if (withdrawGas) {
|
|
1776
|
+
withdrawTxCandidate.gas = withdrawGas.gasLimit;
|
|
1777
|
+
withdrawTxCandidate.maxFeePerGas = withdrawGas.maxFeePerGas;
|
|
1778
|
+
withdrawTxCandidate.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
|
|
1779
|
+
}
|
|
1616
1780
|
let withdrawTx;
|
|
1617
|
-
if (
|
|
1781
|
+
if (current < p.amount) {
|
|
1618
1782
|
withdrawTx = {
|
|
1619
1783
|
address: ctx.l2AssetRouter,
|
|
1620
1784
|
abi: IL2AssetRouter_default,
|
|
1621
1785
|
functionName: "withdraw",
|
|
1622
1786
|
args: [assetId, assetData],
|
|
1623
1787
|
account: ctx.client.account,
|
|
1624
|
-
...
|
|
1788
|
+
...withdrawGas
|
|
1625
1789
|
};
|
|
1626
1790
|
} else {
|
|
1627
|
-
const sim = await
|
|
1791
|
+
const sim = await wrapAs7(
|
|
1628
1792
|
"CONTRACT",
|
|
1629
1793
|
OP_WITHDRAWALS.erc20.estGas,
|
|
1630
1794
|
() => ctx.client.l2.simulateContract({
|
|
@@ -1633,14 +1797,18 @@ function routeErc20NonBase2() {
|
|
|
1633
1797
|
functionName: "withdraw",
|
|
1634
1798
|
args: [assetId, assetData],
|
|
1635
1799
|
account: ctx.client.account,
|
|
1636
|
-
...
|
|
1800
|
+
...withdrawGas
|
|
1637
1801
|
}),
|
|
1638
1802
|
{
|
|
1639
1803
|
ctx: { where: "l2.simulateContract", to: ctx.l2AssetRouter },
|
|
1640
1804
|
message: "Failed to simulate L2 ERC-20 withdraw."
|
|
1641
1805
|
}
|
|
1642
1806
|
);
|
|
1643
|
-
|
|
1807
|
+
const { ...withdrawRequest } = sim.request;
|
|
1808
|
+
withdrawTx = {
|
|
1809
|
+
...withdrawRequest,
|
|
1810
|
+
...withdrawGas
|
|
1811
|
+
};
|
|
1644
1812
|
}
|
|
1645
1813
|
steps.push({
|
|
1646
1814
|
key: "l2-asset-router:withdraw",
|
|
@@ -1648,59 +1816,11 @@ function routeErc20NonBase2() {
|
|
|
1648
1816
|
description: "Burn on L2 & send L2\u2192L1 message",
|
|
1649
1817
|
tx: withdrawTx
|
|
1650
1818
|
});
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
// src/adapters/viem/resources/withdrawals/routes/eth-nonbase.ts
|
|
1657
|
-
var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
|
|
1658
|
-
function routeEthNonBase2() {
|
|
1659
|
-
return {
|
|
1660
|
-
async preflight(p, ctx) {
|
|
1661
|
-
await wrapAs7(
|
|
1662
|
-
"VALIDATION",
|
|
1663
|
-
OP_WITHDRAWALS.ethNonBase.assertNonEthBase,
|
|
1664
|
-
() => {
|
|
1665
|
-
if (p.token.toLowerCase() !== L2_BASE_TOKEN_ADDRESS.toLowerCase()) {
|
|
1666
|
-
throw new Error("eth-nonbase route requires the L2 base-token alias (0x\u2026800A).");
|
|
1667
|
-
}
|
|
1668
|
-
if (ctx.baseIsEth) {
|
|
1669
|
-
throw new Error("eth-nonbase route requires chain base \u2260 ETH.");
|
|
1670
|
-
}
|
|
1671
|
-
},
|
|
1672
|
-
{ ctx: { token: p.token, baseIsEth: ctx.baseIsEth } }
|
|
1673
|
-
);
|
|
1674
|
-
},
|
|
1675
|
-
async build(p, ctx) {
|
|
1676
|
-
const toL1 = p.to ?? ctx.sender;
|
|
1677
|
-
const txFeeOverrides = buildViemFeeOverrides(ctx.fee);
|
|
1678
|
-
const sim = await wrapAs7(
|
|
1679
|
-
"CONTRACT",
|
|
1680
|
-
OP_WITHDRAWALS.ethNonBase.estGas,
|
|
1681
|
-
() => ctx.client.l2.simulateContract({
|
|
1682
|
-
address: L2_BASE_TOKEN_ADDRESS,
|
|
1683
|
-
abi: IBaseToken_default,
|
|
1684
|
-
functionName: "withdraw",
|
|
1685
|
-
args: [toL1],
|
|
1686
|
-
value: p.amount,
|
|
1687
|
-
account: ctx.client.account,
|
|
1688
|
-
...txFeeOverrides
|
|
1689
|
-
}),
|
|
1690
|
-
{
|
|
1691
|
-
ctx: { where: "l2.simulateContract", to: L2_BASE_TOKEN_ADDRESS },
|
|
1692
|
-
message: "Failed to simulate L2 base-token withdraw."
|
|
1693
|
-
}
|
|
1694
|
-
);
|
|
1695
|
-
const steps = [
|
|
1696
|
-
{
|
|
1697
|
-
key: "l2-base-token:withdraw",
|
|
1698
|
-
kind: "l2-base-token:withdraw",
|
|
1699
|
-
description: "Withdraw base token via L2 Base Token System (base \u2260 ETH)",
|
|
1700
|
-
tx: { ...sim.request, ...txFeeOverrides }
|
|
1701
|
-
}
|
|
1702
|
-
];
|
|
1703
|
-
return { steps, approvals: [], quoteExtras: {} };
|
|
1819
|
+
const fees = buildFeeBreakdown2({
|
|
1820
|
+
feeToken: await ctx.client.baseToken(ctx.chainIdL2),
|
|
1821
|
+
l2Gas: withdrawGas
|
|
1822
|
+
});
|
|
1823
|
+
return { steps, approvals, fees };
|
|
1704
1824
|
}
|
|
1705
1825
|
};
|
|
1706
1826
|
}
|
|
@@ -2023,10 +2143,8 @@ function createFinalizationServices(client) {
|
|
|
2023
2143
|
|
|
2024
2144
|
// src/adapters/viem/resources/withdrawals/index.ts
|
|
2025
2145
|
var ROUTES2 = {
|
|
2026
|
-
|
|
2146
|
+
base: routeEthBase(),
|
|
2027
2147
|
// BaseTokenSystem.withdraw, chain base = ETH
|
|
2028
|
-
"eth-nonbase": routeEthNonBase2(),
|
|
2029
|
-
// BaseTokenSystem.withdraw, chain base ≠ ETH
|
|
2030
2148
|
"erc20-nonbase": routeErc20NonBase2()
|
|
2031
2149
|
// AssetRouter.withdraw for non-base ERC-20s
|
|
2032
2150
|
};
|
|
@@ -2036,27 +2154,19 @@ function createWithdrawalsResource(client) {
|
|
|
2036
2154
|
async function buildPlan(p) {
|
|
2037
2155
|
const ctx = await commonCtx2(p, client);
|
|
2038
2156
|
await ROUTES2[ctx.route].preflight?.(p, ctx);
|
|
2039
|
-
const { steps, approvals } = await ROUTES2[ctx.route].build(p, ctx);
|
|
2040
|
-
|
|
2041
|
-
if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
|
|
2042
|
-
for (let i = steps.length - 1; i >= 0; i--) {
|
|
2043
|
-
const candidate = steps[i].tx.gas;
|
|
2044
|
-
if (candidate != null) return candidate;
|
|
2045
|
-
}
|
|
2046
|
-
return void 0;
|
|
2047
|
-
};
|
|
2048
|
-
const gasLimit = resolveGasLimit();
|
|
2049
|
-
const summary = {
|
|
2157
|
+
const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
|
|
2158
|
+
return {
|
|
2050
2159
|
route: ctx.route,
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2160
|
+
summary: {
|
|
2161
|
+
route: ctx.route,
|
|
2162
|
+
approvalsNeeded: approvals,
|
|
2163
|
+
amounts: {
|
|
2164
|
+
transfer: { token: p.token, amount: p.amount }
|
|
2165
|
+
},
|
|
2166
|
+
fees
|
|
2167
|
+
},
|
|
2168
|
+
steps
|
|
2058
2169
|
};
|
|
2059
|
-
return { route: ctx.route, summary, steps };
|
|
2060
2170
|
}
|
|
2061
2171
|
const finalizeCache = /* @__PURE__ */ new Map();
|
|
2062
2172
|
const quote = (p) => wrap2(OP_WITHDRAWALS.quote, async () => (await buildPlan(p)).summary, {
|
|
@@ -2090,7 +2200,7 @@ function createWithdrawalsResource(client) {
|
|
|
2090
2200
|
}
|
|
2091
2201
|
if (overrides.gasLimit != null) step.tx.gas = overrides.gasLimit;
|
|
2092
2202
|
}
|
|
2093
|
-
if (
|
|
2203
|
+
if (!p.l2TxOverrides?.gasLimit) {
|
|
2094
2204
|
try {
|
|
2095
2205
|
const feePart = step.tx.maxFeePerGas != null && step.tx.maxPriorityFeePerGas != null ? {
|
|
2096
2206
|
maxFeePerGas: step.tx.maxFeePerGas,
|
|
@@ -2441,4 +2551,4 @@ function createViemSdk(client) {
|
|
|
2441
2551
|
};
|
|
2442
2552
|
}
|
|
2443
2553
|
|
|
2444
|
-
export { buildDirectRequestStruct,
|
|
2554
|
+
export { buildDirectRequestStruct, classifyReadinessFromRevert, createDepositsResource, createErrorHandlers, createFinalizationServices, createViemSdk, createWithdrawalsResource, decodeRevert, encodeNTVAssetId, encodeNTVTransferData, encodeNativeTokenVaultAssetId, encodeNativeTokenVaultTransferData, encodeSecondBridgeArgs, encodeSecondBridgeDataV1, encodeSecondBridgeErc20Args, encodeSecondBridgeEthArgs, registerErrorAbi, toZKsyncError };
|