@matterlabs/zksync-js 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1279 -925
- package/dist/adapters/ethers/index.cjs.map +1 -1
- package/dist/adapters/ethers/index.d.ts +1 -0
- package/dist/adapters/ethers/index.js +9 -8
- package/dist/adapters/ethers/resources/contracts/contracts.d.ts +9 -0
- package/dist/adapters/ethers/resources/contracts/index.d.ts +2 -0
- package/dist/adapters/ethers/resources/contracts/types.d.ts +60 -0
- package/dist/adapters/ethers/resources/deposits/context.d.ts +21 -7
- package/dist/adapters/ethers/resources/deposits/index.d.ts +3 -1
- 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 +41 -0
- package/dist/adapters/ethers/resources/tokens/index.d.ts +1 -0
- package/dist/adapters/ethers/resources/tokens/tokens.d.ts +10 -0
- package/dist/adapters/ethers/resources/utils.d.ts +3 -17
- package/dist/adapters/ethers/resources/withdrawals/context.d.ts +15 -7
- package/dist/adapters/ethers/resources/withdrawals/index.d.ts +3 -1
- 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 +1388 -1501
- package/dist/adapters/ethers/sdk.cjs.map +1 -1
- package/dist/adapters/ethers/sdk.d.ts +5 -22
- 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 +1233 -744
- package/dist/adapters/viem/index.cjs.map +1 -1
- package/dist/adapters/viem/index.d.ts +3 -0
- package/dist/adapters/viem/index.js +8 -8
- package/dist/adapters/viem/resources/contracts/contracts.d.ts +9 -0
- package/dist/adapters/viem/resources/contracts/index.d.ts +2 -0
- package/dist/adapters/viem/resources/contracts/types.d.ts +61 -0
- package/dist/adapters/viem/resources/deposits/context.d.ts +21 -7
- package/dist/adapters/viem/resources/deposits/index.d.ts +3 -1
- 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 +37 -0
- package/dist/adapters/viem/resources/tokens/index.d.ts +1 -0
- package/dist/adapters/viem/resources/tokens/tokens.d.ts +3 -0
- package/dist/adapters/viem/resources/utils.d.ts +3 -19
- package/dist/adapters/viem/resources/withdrawals/context.d.ts +14 -9
- package/dist/adapters/viem/resources/withdrawals/index.d.ts +3 -1
- 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 +1225 -699
- package/dist/adapters/viem/sdk.cjs.map +1 -1
- package/dist/adapters/viem/sdk.d.ts +5 -25
- package/dist/adapters/viem/sdk.js +6 -6
- package/dist/{chunk-3LALBFFE.js → chunk-3MRGU4HV.js} +9 -5
- package/dist/{chunk-CGO27P7F.js → chunk-5YWP4CZP.js} +849 -835
- package/dist/{chunk-4HLJJKIY.js → chunk-6K6VJQAL.js} +2 -2
- package/dist/{chunk-6GCT6TLS.js → chunk-F2ENUV3A.js} +13 -1
- package/dist/{chunk-7M4V3FMT.js → chunk-JXUFGIJG.js} +986 -678
- package/dist/chunk-LL3WKCFJ.js +231 -0
- package/dist/{chunk-Y75OMFK6.js → chunk-M5J2MM2U.js} +351 -1
- package/dist/{chunk-263G6636.js → chunk-NCAIVYBR.js} +1 -14
- package/dist/{chunk-DI2CJDPZ.js → chunk-NEC2ZKHI.js} +5 -13
- package/dist/chunk-NTEIA5KA.js +13 -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/codec/ntv.d.ts +48 -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 +4508 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +5 -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/token.d.ts +192 -0
- package/dist/core/types/flows/withdrawals.d.ts +12 -6
- package/dist/core/utils/addr.d.ts +2 -0
- package/dist/index.cjs +4520 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -4
- package/package.json +5 -1
- package/dist/adapters/ethers/resources/token-info.d.ts +0 -31
- package/dist/adapters/ethers/resources/withdrawals/routes/eth-nonbase.d.ts +0 -2
- package/dist/adapters/viem/resources/token-info.d.ts +0 -34
- 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
|
@@ -3645,6 +3645,48 @@ var MailboxABI = [
|
|
|
3645
3645
|
{ type: "error", name: "ZeroGasPriceL1TxZKSyncOS", inputs: [] }
|
|
3646
3646
|
];
|
|
3647
3647
|
var Mailbox_default = MailboxABI;
|
|
3648
|
+
|
|
3649
|
+
// src/adapters/viem/resources/deposits/context.ts
|
|
3650
|
+
async function commonCtx(p, client, tokens, contracts) {
|
|
3651
|
+
const { bridgehub, l1AssetRouter } = await contracts.addresses();
|
|
3652
|
+
const chainId = await client.l2.getChainId();
|
|
3653
|
+
const sender = client.account.address;
|
|
3654
|
+
const gasPerPubdata = p.gasPerPubdata ?? 800n;
|
|
3655
|
+
const operatorTip = p.operatorTip ?? 0n;
|
|
3656
|
+
const refundRecipient = p.refundRecipient ?? sender;
|
|
3657
|
+
const resolvedToken = await tokens.resolve(p.token, { chain: "l1" });
|
|
3658
|
+
const baseTokenAssetId = resolvedToken.baseTokenAssetId;
|
|
3659
|
+
const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
|
|
3660
|
+
const baseIsEth = resolvedToken.isChainEthBased;
|
|
3661
|
+
const route = (() => {
|
|
3662
|
+
if (resolvedToken.kind === "eth") {
|
|
3663
|
+
return baseIsEth ? "eth-base" : "eth-nonbase";
|
|
3664
|
+
}
|
|
3665
|
+
if (resolvedToken.kind === "base") {
|
|
3666
|
+
return baseIsEth ? "eth-base" : "erc20-base";
|
|
3667
|
+
}
|
|
3668
|
+
return "erc20-nonbase";
|
|
3669
|
+
})();
|
|
3670
|
+
return {
|
|
3671
|
+
client,
|
|
3672
|
+
tokens,
|
|
3673
|
+
contracts,
|
|
3674
|
+
resolvedToken,
|
|
3675
|
+
baseTokenAssetId,
|
|
3676
|
+
baseTokenL1,
|
|
3677
|
+
baseIsEth,
|
|
3678
|
+
l1AssetRouter,
|
|
3679
|
+
route,
|
|
3680
|
+
bridgehub,
|
|
3681
|
+
chainIdL2: BigInt(chainId),
|
|
3682
|
+
sender,
|
|
3683
|
+
gasOverrides: p.l1TxOverrides,
|
|
3684
|
+
l2GasLimit: p.l2GasLimit,
|
|
3685
|
+
gasPerPubdata,
|
|
3686
|
+
operatorTip,
|
|
3687
|
+
refundRecipient
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3648
3690
|
var k256hex = (s) => `0x${utils.bytesToHex(sha3.keccak_256(utils.utf8ToBytes(s)))}`.toLowerCase();
|
|
3649
3691
|
var FORMAL_ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
3650
3692
|
var ETH_ADDRESS = "0x0000000000000000000000000000000000000001";
|
|
@@ -3656,123 +3698,14 @@ var TOPIC_L1_MESSAGE_SENT_NEW = k256hex("L1MessageSent(uint256,bytes32,bytes)");
|
|
|
3656
3698
|
var TOPIC_L1_MESSAGE_SENT_LEG = k256hex("L1MessageSent(address,bytes32,bytes)");
|
|
3657
3699
|
var TOPIC_CANONICAL_ASSIGNED = "0x779f441679936c5441b671969f37400b8c3ed0071cb47444431bf985754560df";
|
|
3658
3700
|
var TOPIC_CANONICAL_SUCCESS = "0xe4def01b981193a97a9e81230d7b9f31812ceaf23f864a828a82c687911cb2df";
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
}
|
|
3666
|
-
}
|
|
3667
|
-
function assertPriorityFeeBounds(fees) {
|
|
3668
|
-
if (fees.maxPriorityFeePerGas > fees.maxFeePerGas) {
|
|
3669
|
-
throw new Error("maxPriorityFeePerGas cannot exceed maxFeePerGas.");
|
|
3670
|
-
}
|
|
3671
|
-
}
|
|
3701
|
+
var BUFFER = 20n;
|
|
3702
|
+
var TX_OVERHEAD_GAS = 10000n;
|
|
3703
|
+
var TX_MEMORY_OVERHEAD_GAS = 10n;
|
|
3704
|
+
var DEFAULT_PUBDATA_BYTES = 155n;
|
|
3705
|
+
var DEFAULT_ABI_BYTES = 400n;
|
|
3706
|
+
var SAFE_L1_BRIDGE_GAS = 600000n;
|
|
3672
3707
|
|
|
3673
3708
|
// src/adapters/viem/resources/utils.ts
|
|
3674
|
-
function encodeNativeTokenVaultAssetId(chainId, address) {
|
|
3675
|
-
const encoded = viem.encodeAbiParameters(
|
|
3676
|
-
[
|
|
3677
|
-
{ type: "uint256", name: "originChainId" },
|
|
3678
|
-
{ type: "address", name: "ntv" },
|
|
3679
|
-
{ type: "address", name: "token" }
|
|
3680
|
-
],
|
|
3681
|
-
[chainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, address]
|
|
3682
|
-
);
|
|
3683
|
-
return viem.keccak256(encoded);
|
|
3684
|
-
}
|
|
3685
|
-
async function getFeeOverrides(client, overrides) {
|
|
3686
|
-
assertNoLegacyGas(overrides);
|
|
3687
|
-
let maxFeePerGasFromProvider;
|
|
3688
|
-
let maxPriorityFromProvider;
|
|
3689
|
-
let gasPriceFromProvider;
|
|
3690
|
-
try {
|
|
3691
|
-
const fees = await client.l1.estimateFeesPerGas();
|
|
3692
|
-
const { maxFeePerGas: maxFeePerGas2, maxPriorityFeePerGas: maxPriorityFeePerGas2 } = fees;
|
|
3693
|
-
if (maxFeePerGas2 != null && maxPriorityFeePerGas2 != null) {
|
|
3694
|
-
maxFeePerGasFromProvider = maxFeePerGas2;
|
|
3695
|
-
maxPriorityFromProvider = maxPriorityFeePerGas2;
|
|
3696
|
-
gasPriceFromProvider = fees.gasPrice ?? maxFeePerGas2;
|
|
3697
|
-
} else if (fees.gasPrice != null) {
|
|
3698
|
-
gasPriceFromProvider = fees.gasPrice;
|
|
3699
|
-
}
|
|
3700
|
-
} catch {
|
|
3701
|
-
}
|
|
3702
|
-
if (gasPriceFromProvider == null) {
|
|
3703
|
-
try {
|
|
3704
|
-
gasPriceFromProvider = await client.l1.getGasPrice();
|
|
3705
|
-
} catch {
|
|
3706
|
-
}
|
|
3707
|
-
}
|
|
3708
|
-
const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider;
|
|
3709
|
-
if (maxFeePerGas == null) {
|
|
3710
|
-
throw new Error("L1 provider returned no gas price data");
|
|
3711
|
-
}
|
|
3712
|
-
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
|
|
3713
|
-
assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
|
|
3714
|
-
const gasPriceForBaseCost = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider ?? maxFeePerGas;
|
|
3715
|
-
return {
|
|
3716
|
-
gasLimit: overrides?.gasLimit,
|
|
3717
|
-
maxFeePerGas,
|
|
3718
|
-
maxPriorityFeePerGas,
|
|
3719
|
-
gasPriceForBaseCost
|
|
3720
|
-
};
|
|
3721
|
-
}
|
|
3722
|
-
async function getL2FeeOverrides(client, overrides) {
|
|
3723
|
-
assertNoLegacyGas(overrides);
|
|
3724
|
-
let maxFeePerGasFromProvider;
|
|
3725
|
-
let maxPriorityFromProvider;
|
|
3726
|
-
let gasPriceFromProvider;
|
|
3727
|
-
try {
|
|
3728
|
-
const fees = await client.l2.estimateFeesPerGas();
|
|
3729
|
-
if (fees?.maxFeePerGas != null && fees.maxPriorityFeePerGas != null) {
|
|
3730
|
-
maxFeePerGasFromProvider = fees.maxFeePerGas;
|
|
3731
|
-
maxPriorityFromProvider = fees.maxPriorityFeePerGas;
|
|
3732
|
-
gasPriceFromProvider = fees.gasPrice ?? fees.maxFeePerGas;
|
|
3733
|
-
} else if (fees?.gasPrice != null) {
|
|
3734
|
-
gasPriceFromProvider = fees.gasPrice;
|
|
3735
|
-
}
|
|
3736
|
-
} catch {
|
|
3737
|
-
}
|
|
3738
|
-
if (gasPriceFromProvider == null) {
|
|
3739
|
-
try {
|
|
3740
|
-
gasPriceFromProvider = await client.l2.getGasPrice();
|
|
3741
|
-
} catch {
|
|
3742
|
-
}
|
|
3743
|
-
}
|
|
3744
|
-
const maxFeePerGas = overrides?.maxFeePerGas ?? maxFeePerGasFromProvider ?? gasPriceFromProvider;
|
|
3745
|
-
if (maxFeePerGas == null) {
|
|
3746
|
-
throw new Error("provider returned no gas price data");
|
|
3747
|
-
}
|
|
3748
|
-
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? maxPriorityFromProvider ?? maxFeePerGas;
|
|
3749
|
-
assertPriorityFeeBounds({ maxFeePerGas, maxPriorityFeePerGas });
|
|
3750
|
-
return {
|
|
3751
|
-
gasLimit: overrides?.gasLimit,
|
|
3752
|
-
maxFeePerGas,
|
|
3753
|
-
maxPriorityFeePerGas
|
|
3754
|
-
};
|
|
3755
|
-
}
|
|
3756
|
-
function buildViemFeeOverrides(fees) {
|
|
3757
|
-
return {
|
|
3758
|
-
maxFeePerGas: fees.maxFeePerGas,
|
|
3759
|
-
maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
|
|
3760
|
-
gas: fees.gasLimit
|
|
3761
|
-
};
|
|
3762
|
-
}
|
|
3763
|
-
function buildDirectRequestStruct(args) {
|
|
3764
|
-
return {
|
|
3765
|
-
chainId: args.chainId,
|
|
3766
|
-
l2Contract: args.l2Contract,
|
|
3767
|
-
mintValue: args.mintValue,
|
|
3768
|
-
l2Value: args.l2Value,
|
|
3769
|
-
l2Calldata: "0x",
|
|
3770
|
-
l2GasLimit: args.l2GasLimit,
|
|
3771
|
-
l2GasPerPubdataByteLimit: args.gasPerPubdata,
|
|
3772
|
-
factoryDeps: [],
|
|
3773
|
-
refundRecipient: args.refundRecipient
|
|
3774
|
-
};
|
|
3775
|
-
}
|
|
3776
3709
|
function encodeSecondBridgeArgs(token, amount, l2Receiver) {
|
|
3777
3710
|
return viem.encodeAbiParameters(
|
|
3778
3711
|
[
|
|
@@ -3789,58 +3722,17 @@ function encodeSecondBridgeErc20Args(token, amount, l2Receiver) {
|
|
|
3789
3722
|
function encodeSecondBridgeEthArgs(amount, l2Receiver, ethToken = ETH_ADDRESS) {
|
|
3790
3723
|
return encodeSecondBridgeArgs(ethToken, amount, l2Receiver);
|
|
3791
3724
|
}
|
|
3792
|
-
|
|
3793
|
-
// src/core/utils/addr.ts
|
|
3794
|
-
var isHash66 = (x) => !!x && x.startsWith("0x") && x.length === 66;
|
|
3795
|
-
function isAddressEq(a, b) {
|
|
3796
|
-
return a.toLowerCase() === b.toLowerCase();
|
|
3797
|
-
}
|
|
3798
|
-
function isETH(token) {
|
|
3799
|
-
return isAddressEq(token, FORMAL_ETH_ADDRESS) || isAddressEq(token, L2_BASE_TOKEN_ADDRESS) || isAddressEq(token, ETH_ADDRESS);
|
|
3800
|
-
}
|
|
3801
|
-
function normalizeAddrEq(a, b) {
|
|
3802
|
-
if (!a || !b) return false;
|
|
3803
|
-
const normalize = (s) => {
|
|
3804
|
-
const hasPrefix = s.slice(0, 2).toLowerCase() === "0x";
|
|
3805
|
-
const body = hasPrefix ? s.slice(2) : s;
|
|
3806
|
-
return `0x${body.toLowerCase()}`;
|
|
3807
|
-
};
|
|
3808
|
-
return normalize(a) === normalize(b);
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
// src/core/resources/deposits/route.ts
|
|
3812
|
-
async function pickDepositRoute(client, chainIdL2, token) {
|
|
3813
|
-
if (isETH(token)) {
|
|
3814
|
-
const base2 = await client.baseToken(chainIdL2);
|
|
3815
|
-
return isETH(base2) ? "eth-base" : "eth-nonbase";
|
|
3816
|
-
}
|
|
3817
|
-
const base = await client.baseToken(chainIdL2);
|
|
3818
|
-
return normalizeAddrEq(token, base) ? "erc20-base" : "erc20-nonbase";
|
|
3819
|
-
}
|
|
3820
|
-
|
|
3821
|
-
// src/adapters/viem/resources/deposits/context.ts
|
|
3822
|
-
async function commonCtx(p, client) {
|
|
3823
|
-
const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
|
|
3824
|
-
const chainId = await client.l2.getChainId();
|
|
3825
|
-
const sender = client.account.address;
|
|
3826
|
-
const fee = await getFeeOverrides(client, p.l1TxOverrides);
|
|
3827
|
-
const l2GasLimit = p.l2GasLimit ?? 300000n;
|
|
3828
|
-
const gasPerPubdata = p.gasPerPubdata ?? 800n;
|
|
3829
|
-
const operatorTip = p.operatorTip ?? 0n;
|
|
3830
|
-
const refundRecipient = p.refundRecipient ?? sender;
|
|
3831
|
-
const route = await pickDepositRoute(client, BigInt(chainId), p.token);
|
|
3725
|
+
function buildDirectRequestStruct(args) {
|
|
3832
3726
|
return {
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
operatorTip,
|
|
3843
|
-
refundRecipient
|
|
3727
|
+
chainId: args.chainId,
|
|
3728
|
+
l2Contract: args.l2Contract,
|
|
3729
|
+
mintValue: args.mintValue,
|
|
3730
|
+
l2Value: args.l2Value,
|
|
3731
|
+
l2Calldata: "0x",
|
|
3732
|
+
l2GasLimit: args.l2GasLimit,
|
|
3733
|
+
l2GasPerPubdataByteLimit: args.gasPerPubdata,
|
|
3734
|
+
factoryDeps: [],
|
|
3735
|
+
refundRecipient: args.refundRecipient
|
|
3844
3736
|
};
|
|
3845
3737
|
}
|
|
3846
3738
|
|
|
@@ -4055,27 +3947,21 @@ var OP_DEPOSITS = {
|
|
|
4055
3947
|
base: {
|
|
4056
3948
|
assertErc20Asset: "deposits.erc20-base:assertErc20Asset",
|
|
4057
3949
|
assertMatchesBase: "deposits.erc20-base:assertMatchesBase",
|
|
4058
|
-
baseToken: "deposits.erc20-base:baseToken",
|
|
4059
3950
|
allowance: "deposits.erc20-base:allowance",
|
|
4060
|
-
baseCost: "deposits.erc20-base:l2TransactionBaseCost",
|
|
4061
3951
|
estGas: "deposits.erc20-base:estimateGas"
|
|
4062
3952
|
},
|
|
4063
3953
|
nonbase: {
|
|
4064
|
-
baseToken: "deposits.erc20-nonbase:baseToken",
|
|
4065
3954
|
assertNotEthAsset: "deposits.erc20-nonbase:assertNotEthAsset",
|
|
4066
|
-
allowance: "deposits.erc20-nonbase:allowance",
|
|
4067
|
-
allowanceFees: "deposits.erc20-nonbase:allowanceFeesBaseToken",
|
|
4068
|
-
baseCost: "deposits.erc20-nonbase:l2TransactionBaseCost",
|
|
4069
3955
|
encodeCalldata: "deposits.erc20-nonbase:encodeSecondBridgeErc20Args",
|
|
4070
3956
|
estGas: "deposits.erc20-nonbase:estimateGas",
|
|
4071
|
-
assertNonBaseToken: "deposits.erc20-nonbase:assertNonBaseToken"
|
|
3957
|
+
assertNonBaseToken: "deposits.erc20-nonbase:assertNonBaseToken",
|
|
3958
|
+
allowanceToken: "deposits.erc20-nonbase:allowanceToken",
|
|
3959
|
+
allowanceBase: "deposits.erc20-nonbase:allowanceBase"
|
|
3960
|
+
},
|
|
4072
3961
|
eth: {
|
|
4073
|
-
baseCost: "deposits.eth:l2TransactionBaseCost",
|
|
4074
3962
|
estGas: "deposits.eth:estimateGas"
|
|
4075
3963
|
},
|
|
4076
3964
|
ethNonBase: {
|
|
4077
|
-
baseToken: "deposits.eth-nonbase:baseToken",
|
|
4078
|
-
baseCost: "deposits.eth-nonbase:l2TransactionBaseCost",
|
|
4079
3965
|
allowanceBase: "deposits.eth-nonbase:allowanceBaseToken",
|
|
4080
3966
|
ethBalance: "deposits.eth-nonbase:getEthBalance",
|
|
4081
3967
|
encodeCalldata: "deposits.eth-nonbase:encodeSecondBridgeEthArgs",
|
|
@@ -4313,7 +4199,7 @@ function createErrorHandlers(resource) {
|
|
|
4313
4199
|
function wrap2(operation, fn, opts) {
|
|
4314
4200
|
return run("INTERNAL", operation, fn, opts);
|
|
4315
4201
|
}
|
|
4316
|
-
function
|
|
4202
|
+
function wrapAs10(kind, operation, fn, opts) {
|
|
4317
4203
|
return run(kind, operation, fn, opts);
|
|
4318
4204
|
}
|
|
4319
4205
|
async function toResult2(operation, fn, opts) {
|
|
@@ -4334,44 +4220,358 @@ function createErrorHandlers(resource) {
|
|
|
4334
4220
|
return { ok: false, error: shaped };
|
|
4335
4221
|
}
|
|
4336
4222
|
}
|
|
4337
|
-
return { wrap: wrap2, wrapAs:
|
|
4223
|
+
return { wrap: wrap2, wrapAs: wrapAs10, toResult: toResult2 };
|
|
4338
4224
|
}
|
|
4339
4225
|
|
|
4340
|
-
// src/
|
|
4226
|
+
// src/core/resources/deposits/gas.ts
|
|
4227
|
+
function makeGasQuote(p) {
|
|
4228
|
+
const maxPriorityFeePerGas = p.maxPriorityFeePerGas ?? 0n;
|
|
4229
|
+
return {
|
|
4230
|
+
gasLimit: p.gasLimit,
|
|
4231
|
+
maxFeePerGas: p.maxFeePerGas,
|
|
4232
|
+
maxPriorityFeePerGas,
|
|
4233
|
+
gasPerPubdata: p.gasPerPubdata,
|
|
4234
|
+
maxCost: p.gasLimit * p.maxFeePerGas
|
|
4235
|
+
};
|
|
4236
|
+
}
|
|
4237
|
+
async function fetchFees(estimator) {
|
|
4238
|
+
try {
|
|
4239
|
+
const fees = await estimator.estimateFeesPerGas();
|
|
4240
|
+
if (fees.maxFeePerGas != null) {
|
|
4241
|
+
return {
|
|
4242
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
4243
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
|
|
4244
|
+
};
|
|
4245
|
+
}
|
|
4246
|
+
if (fees.gasPrice != null) {
|
|
4247
|
+
return {
|
|
4248
|
+
maxFeePerGas: fees.gasPrice,
|
|
4249
|
+
maxPriorityFeePerGas: 0n
|
|
4250
|
+
};
|
|
4251
|
+
}
|
|
4252
|
+
} catch {
|
|
4253
|
+
}
|
|
4254
|
+
try {
|
|
4255
|
+
const gp = await estimator.getGasPrice();
|
|
4256
|
+
return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
|
|
4257
|
+
} catch {
|
|
4258
|
+
return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
async function quoteL1Gas(input) {
|
|
4262
|
+
const { estimator, tx, overrides, fallbackGasLimit } = input;
|
|
4263
|
+
let market;
|
|
4264
|
+
const getMarket = async () => {
|
|
4265
|
+
if (market) return market;
|
|
4266
|
+
market = await fetchFees(estimator);
|
|
4267
|
+
return market;
|
|
4268
|
+
};
|
|
4269
|
+
const maxFeePerGas = overrides?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : (await getMarket()).maxFeePerGas);
|
|
4270
|
+
const maxPriorityFeePerGas = overrides?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : (await getMarket()).maxPriorityFeePerGas);
|
|
4271
|
+
const explicitGasLimit = overrides?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
|
|
4272
|
+
if (explicitGasLimit != null) {
|
|
4273
|
+
return makeGasQuote({ gasLimit: explicitGasLimit, maxFeePerGas, maxPriorityFeePerGas });
|
|
4274
|
+
}
|
|
4275
|
+
try {
|
|
4276
|
+
const est = await estimator.estimateGas(tx);
|
|
4277
|
+
const buffered = BigInt(est) * (100n + BUFFER) / 100n;
|
|
4278
|
+
return makeGasQuote({ gasLimit: buffered, maxFeePerGas, maxPriorityFeePerGas });
|
|
4279
|
+
} catch (err) {
|
|
4280
|
+
if (fallbackGasLimit != null) {
|
|
4281
|
+
return makeGasQuote({ gasLimit: fallbackGasLimit, maxFeePerGas, maxPriorityFeePerGas });
|
|
4282
|
+
}
|
|
4283
|
+
console.warn("L1 gas estimation failed", err);
|
|
4284
|
+
return void 0;
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4287
|
+
async function quoteL2Gas(input) {
|
|
4288
|
+
const { estimator, route, tx, gasPerPubdata, l2GasLimit, overrideGasLimit, stateOverrides } = input;
|
|
4289
|
+
const market = await fetchFees(estimator);
|
|
4290
|
+
const maxFeePerGas = market.maxFeePerGas || market.maxPriorityFeePerGas || 0n;
|
|
4291
|
+
const txGasLimit = tx?.gasLimit != null ? BigInt(tx.gasLimit) : void 0;
|
|
4292
|
+
const explicit = overrideGasLimit ?? txGasLimit;
|
|
4293
|
+
if (explicit != null) {
|
|
4294
|
+
return makeGasQuote({
|
|
4295
|
+
gasLimit: explicit,
|
|
4296
|
+
maxFeePerGas,
|
|
4297
|
+
gasPerPubdata
|
|
4298
|
+
});
|
|
4299
|
+
}
|
|
4300
|
+
if (!tx) {
|
|
4301
|
+
return makeGasQuote({
|
|
4302
|
+
gasLimit: l2GasLimit ?? 0n,
|
|
4303
|
+
maxFeePerGas,
|
|
4304
|
+
gasPerPubdata
|
|
4305
|
+
});
|
|
4306
|
+
}
|
|
4307
|
+
try {
|
|
4308
|
+
const execEstimate = await estimator.estimateGas(tx, stateOverrides);
|
|
4309
|
+
const memoryBytes = route === "erc20-nonbase" ? 500n : DEFAULT_ABI_BYTES;
|
|
4310
|
+
const pubdataBytes = route === "erc20-nonbase" ? 200n : DEFAULT_PUBDATA_BYTES;
|
|
4311
|
+
const pp = gasPerPubdata ?? 800n;
|
|
4312
|
+
const memoryOverhead = memoryBytes * TX_MEMORY_OVERHEAD_GAS;
|
|
4313
|
+
const pubdataOverhead = pubdataBytes * pp;
|
|
4314
|
+
let total = BigInt(execEstimate) + TX_OVERHEAD_GAS + memoryOverhead + pubdataOverhead;
|
|
4315
|
+
total = total * (100n + BUFFER) / 100n;
|
|
4316
|
+
return makeGasQuote({
|
|
4317
|
+
gasLimit: total,
|
|
4318
|
+
maxFeePerGas,
|
|
4319
|
+
gasPerPubdata: pp
|
|
4320
|
+
});
|
|
4321
|
+
} catch (err) {
|
|
4322
|
+
console.warn("L2 gas estimation failed", err);
|
|
4323
|
+
return makeGasQuote({
|
|
4324
|
+
gasLimit: l2GasLimit ?? 0n,
|
|
4325
|
+
maxFeePerGas,
|
|
4326
|
+
gasPerPubdata
|
|
4327
|
+
});
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
|
|
4331
|
+
// src/adapters/viem/estimator.ts
|
|
4332
|
+
function toCoreTx(tx) {
|
|
4333
|
+
return {
|
|
4334
|
+
to: tx.to,
|
|
4335
|
+
from: tx.from,
|
|
4336
|
+
data: tx.data,
|
|
4337
|
+
value: tx.value,
|
|
4338
|
+
gasLimit: tx.gas,
|
|
4339
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
4340
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
4341
|
+
};
|
|
4342
|
+
}
|
|
4343
|
+
function viemToGasEstimator(client) {
|
|
4344
|
+
return {
|
|
4345
|
+
async estimateGas(tx, stateOverrides) {
|
|
4346
|
+
if (stateOverrides) {
|
|
4347
|
+
try {
|
|
4348
|
+
const result = await client.request({
|
|
4349
|
+
method: "eth_estimateGas",
|
|
4350
|
+
params: [
|
|
4351
|
+
{
|
|
4352
|
+
from: tx.from,
|
|
4353
|
+
to: tx.to,
|
|
4354
|
+
data: tx.data,
|
|
4355
|
+
value: tx.value,
|
|
4356
|
+
gas: tx.gasLimit,
|
|
4357
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
4358
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
4359
|
+
},
|
|
4360
|
+
"latest",
|
|
4361
|
+
stateOverrides
|
|
4362
|
+
]
|
|
4363
|
+
});
|
|
4364
|
+
return BigInt(result);
|
|
4365
|
+
} catch (error) {
|
|
4366
|
+
console.warn(
|
|
4367
|
+
"Failed to estimate gas with state overrides, falling back to standard estimation:",
|
|
4368
|
+
error
|
|
4369
|
+
);
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
return await client.estimateGas({
|
|
4373
|
+
account: tx.from,
|
|
4374
|
+
to: tx.to,
|
|
4375
|
+
data: tx.data,
|
|
4376
|
+
value: tx.value,
|
|
4377
|
+
gas: tx.gasLimit,
|
|
4378
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
4379
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas
|
|
4380
|
+
});
|
|
4381
|
+
},
|
|
4382
|
+
async estimateFeesPerGas() {
|
|
4383
|
+
try {
|
|
4384
|
+
const fees = await client.estimateFeesPerGas();
|
|
4385
|
+
return {
|
|
4386
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
4387
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas
|
|
4388
|
+
};
|
|
4389
|
+
} catch {
|
|
4390
|
+
}
|
|
4391
|
+
try {
|
|
4392
|
+
const gp = await client.getGasPrice();
|
|
4393
|
+
return { gasPrice: gp };
|
|
4394
|
+
} catch {
|
|
4395
|
+
return {};
|
|
4396
|
+
}
|
|
4397
|
+
},
|
|
4398
|
+
async getGasPrice() {
|
|
4399
|
+
return await client.getGasPrice();
|
|
4400
|
+
},
|
|
4401
|
+
async call(tx) {
|
|
4402
|
+
const res = await client.call({
|
|
4403
|
+
to: tx.to,
|
|
4404
|
+
data: tx.data,
|
|
4405
|
+
value: tx.value,
|
|
4406
|
+
account: tx.from
|
|
4407
|
+
});
|
|
4408
|
+
return res.data ?? "0x";
|
|
4409
|
+
}
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
// src/adapters/viem/resources/deposits/services/gas.ts
|
|
4414
|
+
async function quoteL1Gas2(input) {
|
|
4415
|
+
const { ctx, tx, overrides, fallbackGasLimit } = input;
|
|
4416
|
+
const estimator = viemToGasEstimator(ctx.client.l1);
|
|
4417
|
+
return quoteL1Gas({
|
|
4418
|
+
estimator,
|
|
4419
|
+
tx: toCoreTx(tx),
|
|
4420
|
+
overrides,
|
|
4421
|
+
fallbackGasLimit
|
|
4422
|
+
});
|
|
4423
|
+
}
|
|
4424
|
+
async function quoteL2Gas2(input) {
|
|
4425
|
+
const { ctx, route, l2TxForModeling, overrideGasLimit } = input;
|
|
4426
|
+
const estimator = viemToGasEstimator(ctx.client.l2);
|
|
4427
|
+
return quoteL2Gas({
|
|
4428
|
+
estimator,
|
|
4429
|
+
route,
|
|
4430
|
+
tx: l2TxForModeling ? toCoreTx(l2TxForModeling) : void 0,
|
|
4431
|
+
gasPerPubdata: ctx.gasPerPubdata,
|
|
4432
|
+
l2GasLimit: ctx.l2GasLimit,
|
|
4433
|
+
// TODO: investigate if this should be passed here; weird viem quirk
|
|
4434
|
+
overrideGasLimit,
|
|
4435
|
+
stateOverrides: input.stateOverrides
|
|
4436
|
+
});
|
|
4437
|
+
}
|
|
4438
|
+
async function determineErc20L2Gas(input) {
|
|
4439
|
+
const { ctx, l1Token } = input;
|
|
4440
|
+
const DEFAULT_SAFE_L2_GAS_LIMIT = 3000000n;
|
|
4441
|
+
if (ctx.l2GasLimit != null) {
|
|
4442
|
+
return quoteL2Gas2({
|
|
4443
|
+
ctx,
|
|
4444
|
+
route: "erc20-nonbase",
|
|
4445
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
4446
|
+
});
|
|
4447
|
+
}
|
|
4448
|
+
try {
|
|
4449
|
+
const l2TokenAddress = ctx.tokens ? await ctx.tokens.toL2Address(l1Token) : await (await ctx.contracts.l2NativeTokenVault()).read.l2TokenAddress([l1Token]);
|
|
4450
|
+
if (l2TokenAddress === viem.zeroAddress) {
|
|
4451
|
+
return quoteL2Gas2({
|
|
4452
|
+
ctx,
|
|
4453
|
+
route: "erc20-nonbase",
|
|
4454
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
4455
|
+
});
|
|
4456
|
+
}
|
|
4457
|
+
const modelTx = {
|
|
4458
|
+
to: input.modelTx?.to ?? ctx.sender,
|
|
4459
|
+
from: input.modelTx?.from ?? ctx.sender,
|
|
4460
|
+
data: input.modelTx?.data ?? "0x",
|
|
4461
|
+
value: input.modelTx?.value ?? 0n
|
|
4462
|
+
};
|
|
4463
|
+
const gas = await quoteL2Gas2({
|
|
4464
|
+
ctx,
|
|
4465
|
+
route: "erc20-nonbase",
|
|
4466
|
+
l2TxForModeling: modelTx
|
|
4467
|
+
});
|
|
4468
|
+
if (!gas) {
|
|
4469
|
+
return quoteL2Gas2({
|
|
4470
|
+
ctx,
|
|
4471
|
+
route: "erc20-nonbase",
|
|
4472
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
4473
|
+
});
|
|
4474
|
+
}
|
|
4475
|
+
return gas;
|
|
4476
|
+
} catch (err) {
|
|
4477
|
+
console.warn("Failed to determine ERC20 L2 gas; defaulting to safe gas limit.", err);
|
|
4478
|
+
return quoteL2Gas2({
|
|
4479
|
+
ctx,
|
|
4480
|
+
route: "erc20-nonbase",
|
|
4481
|
+
overrideGasLimit: DEFAULT_SAFE_L2_GAS_LIMIT
|
|
4482
|
+
});
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
|
|
4486
|
+
// src/adapters/viem/resources/deposits/services/fee.ts
|
|
4341
4487
|
var { wrapAs } = createErrorHandlers("deposits");
|
|
4488
|
+
async function quoteL2BaseCost(input) {
|
|
4489
|
+
const { ctx, l2GasLimit } = input;
|
|
4490
|
+
const estimator = viemToGasEstimator(ctx.client.l1);
|
|
4491
|
+
const fees = await estimator.estimateFeesPerGas();
|
|
4492
|
+
const gasPrice = fees.maxFeePerGas ?? fees.gasPrice ?? await estimator.getGasPrice();
|
|
4493
|
+
return wrapAs(
|
|
4494
|
+
"RPC",
|
|
4495
|
+
"deposits.fees.l2BaseCost",
|
|
4496
|
+
async () => {
|
|
4497
|
+
return await ctx.client.l1.readContract({
|
|
4498
|
+
address: ctx.bridgehub,
|
|
4499
|
+
abi: IBridgehub_default,
|
|
4500
|
+
functionName: "l2TransactionBaseCost",
|
|
4501
|
+
args: [ctx.chainIdL2, gasPrice, l2GasLimit, ctx.gasPerPubdata]
|
|
4502
|
+
});
|
|
4503
|
+
},
|
|
4504
|
+
{ ctx: { chainIdL2: ctx.chainIdL2 } }
|
|
4505
|
+
);
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4508
|
+
// src/core/resources/deposits/fee.ts
|
|
4509
|
+
function buildFeeBreakdown(p) {
|
|
4510
|
+
const l1MaxTotal = p.l1Gas?.maxCost ?? 0n;
|
|
4511
|
+
const l2Total = p.l2BaseCost + p.operatorTip;
|
|
4512
|
+
const l1 = {
|
|
4513
|
+
gasLimit: p.l1Gas?.gasLimit ?? 0n,
|
|
4514
|
+
maxFeePerGas: p.l1Gas?.maxFeePerGas ?? 0n,
|
|
4515
|
+
maxPriorityFeePerGas: p.l1Gas?.maxPriorityFeePerGas,
|
|
4516
|
+
maxTotal: l1MaxTotal
|
|
4517
|
+
};
|
|
4518
|
+
const l2 = {
|
|
4519
|
+
total: l2Total,
|
|
4520
|
+
baseCost: p.l2BaseCost,
|
|
4521
|
+
operatorTip: p.operatorTip,
|
|
4522
|
+
gasLimit: p.l2Gas?.gasLimit ?? 0n,
|
|
4523
|
+
maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
|
|
4524
|
+
maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas,
|
|
4525
|
+
gasPerPubdata: p.l2Gas?.gasPerPubdata ?? 0n
|
|
4526
|
+
};
|
|
4527
|
+
return {
|
|
4528
|
+
token: p.feeToken,
|
|
4529
|
+
maxTotal: l1MaxTotal + l2Total,
|
|
4530
|
+
mintValue: p.mintValue,
|
|
4531
|
+
l1,
|
|
4532
|
+
l2
|
|
4533
|
+
};
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
// src/adapters/viem/resources/deposits/routes/eth.ts
|
|
4537
|
+
var { wrapAs: wrapAs2 } = createErrorHandlers("deposits");
|
|
4342
4538
|
function routeEthDirect() {
|
|
4343
4539
|
return {
|
|
4344
4540
|
async build(p, ctx) {
|
|
4345
|
-
const
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
"
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
{
|
|
4357
|
-
ctx: {
|
|
4358
|
-
|
|
4541
|
+
const l2TxModel = {
|
|
4542
|
+
to: p.to ?? ctx.sender,
|
|
4543
|
+
from: ctx.sender,
|
|
4544
|
+
data: "0x",
|
|
4545
|
+
value: p.amount
|
|
4546
|
+
};
|
|
4547
|
+
const l2GasParams = await quoteL2Gas2({
|
|
4548
|
+
ctx,
|
|
4549
|
+
route: "eth-base",
|
|
4550
|
+
l2TxForModeling: l2TxModel,
|
|
4551
|
+
overrideGasLimit: ctx.l2GasLimit,
|
|
4552
|
+
stateOverrides: {
|
|
4553
|
+
[ctx.sender]: {
|
|
4554
|
+
balance: "0xffffffffffffffffffff"
|
|
4555
|
+
}
|
|
4359
4556
|
}
|
|
4360
|
-
);
|
|
4361
|
-
|
|
4557
|
+
});
|
|
4558
|
+
if (!l2GasParams) {
|
|
4559
|
+
throw new Error("Failed to estimate L2 gas for deposit.");
|
|
4560
|
+
}
|
|
4561
|
+
const baseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2GasParams.gasLimit });
|
|
4362
4562
|
const l2Contract = p.to ?? ctx.sender;
|
|
4363
4563
|
const l2Value = p.amount;
|
|
4364
4564
|
const mintValue = baseCost + ctx.operatorTip + l2Value;
|
|
4365
4565
|
const req = buildDirectRequestStruct({
|
|
4366
4566
|
chainId: ctx.chainIdL2,
|
|
4367
4567
|
mintValue,
|
|
4368
|
-
l2GasLimit:
|
|
4568
|
+
l2GasLimit: l2GasParams.gasLimit,
|
|
4369
4569
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
4370
4570
|
refundRecipient: ctx.refundRecipient,
|
|
4371
4571
|
l2Contract,
|
|
4372
4572
|
l2Value
|
|
4373
4573
|
});
|
|
4374
|
-
const sim = await
|
|
4574
|
+
const sim = await wrapAs2(
|
|
4375
4575
|
"RPC",
|
|
4376
4576
|
OP_DEPOSITS.eth.estGas,
|
|
4377
4577
|
() => ctx.client.l1.simulateContract({
|
|
@@ -4387,120 +4587,138 @@ function routeEthDirect() {
|
|
|
4387
4587
|
message: "Failed to simulate Bridgehub.requestL2TransactionDirect."
|
|
4388
4588
|
}
|
|
4389
4589
|
);
|
|
4390
|
-
const
|
|
4590
|
+
const data = viem.encodeFunctionData({
|
|
4591
|
+
abi: sim.request.abi,
|
|
4592
|
+
functionName: sim.request.functionName,
|
|
4593
|
+
args: sim.request.args
|
|
4594
|
+
});
|
|
4595
|
+
const l1TxCandidate = {
|
|
4596
|
+
to: ctx.bridgehub,
|
|
4597
|
+
data,
|
|
4598
|
+
value: mintValue,
|
|
4599
|
+
from: ctx.sender,
|
|
4600
|
+
...ctx.gasOverrides
|
|
4601
|
+
};
|
|
4602
|
+
const l1Gas = await quoteL1Gas2({
|
|
4603
|
+
ctx,
|
|
4604
|
+
tx: l1TxCandidate,
|
|
4605
|
+
overrides: ctx.gasOverrides
|
|
4606
|
+
});
|
|
4391
4607
|
const steps = [
|
|
4392
4608
|
{
|
|
4393
4609
|
key: "bridgehub:direct",
|
|
4394
4610
|
kind: "bridgehub:direct",
|
|
4395
4611
|
description: "Bridge ETH via Bridgehub.requestL2TransactionDirect",
|
|
4396
|
-
tx: { ...sim.request, ...
|
|
4612
|
+
tx: { ...sim.request, ...l1Gas }
|
|
4397
4613
|
}
|
|
4398
4614
|
];
|
|
4615
|
+
const fees = buildFeeBreakdown({
|
|
4616
|
+
feeToken: ETH_ADDRESS,
|
|
4617
|
+
l1Gas,
|
|
4618
|
+
l2Gas: l2GasParams,
|
|
4619
|
+
l2BaseCost: baseCost,
|
|
4620
|
+
operatorTip: ctx.operatorTip,
|
|
4621
|
+
mintValue
|
|
4622
|
+
});
|
|
4399
4623
|
return {
|
|
4400
4624
|
steps,
|
|
4401
4625
|
approvals: [],
|
|
4402
|
-
|
|
4626
|
+
fees
|
|
4403
4627
|
};
|
|
4404
4628
|
}
|
|
4405
4629
|
};
|
|
4406
4630
|
}
|
|
4407
4631
|
|
|
4632
|
+
// src/core/utils/addr.ts
|
|
4633
|
+
var isHash66 = (x) => !!x && x.startsWith("0x") && x.length === 66;
|
|
4634
|
+
function isAddressEq(a, b) {
|
|
4635
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
4636
|
+
}
|
|
4637
|
+
function isETH(token) {
|
|
4638
|
+
return isAddressEq(token, FORMAL_ETH_ADDRESS) || isAddressEq(token, L2_BASE_TOKEN_ADDRESS) || isAddressEq(token, ETH_ADDRESS);
|
|
4639
|
+
}
|
|
4640
|
+
function normalizeAddrEq(a, b) {
|
|
4641
|
+
if (!a || !b) return false;
|
|
4642
|
+
const normalize = (s) => {
|
|
4643
|
+
const hasPrefix = s.slice(0, 2).toLowerCase() === "0x";
|
|
4644
|
+
const body = hasPrefix ? s.slice(2) : s;
|
|
4645
|
+
return `0x${body.toLowerCase()}`;
|
|
4646
|
+
};
|
|
4647
|
+
return normalize(a) === normalize(b);
|
|
4648
|
+
}
|
|
4649
|
+
var hexEq = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
4650
|
+
var normalizeL1Token = (token) => isAddressEq(token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : token;
|
|
4651
|
+
|
|
4408
4652
|
// src/adapters/viem/resources/deposits/routes/erc20-nonbase.ts
|
|
4409
|
-
var { wrapAs:
|
|
4410
|
-
var BASE_COST_BUFFER_BPS = 100n;
|
|
4411
|
-
var BPS = 10000n;
|
|
4412
|
-
var withBuffer = (x) => x * (BPS + BASE_COST_BUFFER_BPS) / BPS;
|
|
4653
|
+
var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
|
|
4413
4654
|
function routeErc20NonBase() {
|
|
4414
4655
|
return {
|
|
4656
|
+
// TODO: do we even need these validations?
|
|
4415
4657
|
async preflight(p, ctx) {
|
|
4416
|
-
await
|
|
4658
|
+
await wrapAs3(
|
|
4417
4659
|
"VALIDATION",
|
|
4418
4660
|
OP_DEPOSITS.nonbase.assertNotEthAsset,
|
|
4419
4661
|
() => {
|
|
4420
|
-
if (isETH(p.token)) {
|
|
4662
|
+
if (ctx.resolvedToken?.kind === "eth" || isETH(p.token)) {
|
|
4421
4663
|
throw new Error("erc20-nonbase route requires an ERC-20 token (not ETH).");
|
|
4422
4664
|
}
|
|
4423
4665
|
},
|
|
4424
4666
|
{ ctx: { token: p.token } }
|
|
4425
4667
|
);
|
|
4426
|
-
const baseToken = await
|
|
4427
|
-
|
|
4428
|
-
OP_DEPOSITS.nonbase.baseToken,
|
|
4429
|
-
() => ctx.client.l1.readContract({
|
|
4430
|
-
address: ctx.bridgehub,
|
|
4431
|
-
abi: IBridgehub_default,
|
|
4432
|
-
functionName: "baseToken",
|
|
4433
|
-
args: [ctx.chainIdL2]
|
|
4434
|
-
}),
|
|
4435
|
-
{ ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 } }
|
|
4436
|
-
);
|
|
4437
|
-
await wrapAs2(
|
|
4668
|
+
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
4669
|
+
await wrapAs3(
|
|
4438
4670
|
"VALIDATION",
|
|
4439
4671
|
OP_DEPOSITS.nonbase.assertNonBaseToken,
|
|
4440
4672
|
() => {
|
|
4441
|
-
if (normalizeAddrEq(baseToken, p.token)) {
|
|
4673
|
+
if (ctx.resolvedToken?.kind === "base" || normalizeAddrEq(baseToken, p.token)) {
|
|
4442
4674
|
throw new Error("erc20-nonbase route requires a non-base ERC-20 deposit token.");
|
|
4443
4675
|
}
|
|
4444
4676
|
},
|
|
4445
4677
|
{ ctx: { depositToken: p.token, baseToken } }
|
|
4446
4678
|
);
|
|
4447
|
-
return;
|
|
4448
4679
|
},
|
|
4449
4680
|
async build(p, ctx) {
|
|
4450
|
-
const
|
|
4451
|
-
const
|
|
4452
|
-
const
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
);
|
|
4463
|
-
|
|
4464
|
-
const
|
|
4465
|
-
const
|
|
4466
|
-
"CONTRACT",
|
|
4467
|
-
OP_DEPOSITS.nonbase.baseCost,
|
|
4468
|
-
() => ctx.client.l1.readContract({
|
|
4469
|
-
address: ctx.bridgehub,
|
|
4470
|
-
abi: IBridgehub_default,
|
|
4471
|
-
functionName: "l2TransactionBaseCost",
|
|
4472
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, l2GasLimitUsed, ctx.gasPerPubdata]
|
|
4473
|
-
}),
|
|
4474
|
-
{ ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 } }
|
|
4475
|
-
);
|
|
4476
|
-
const baseCost = rawBaseCost;
|
|
4477
|
-
const mintValue = withBuffer(baseCost + ctx.operatorTip);
|
|
4681
|
+
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
4682
|
+
const baseIsEth = ctx.baseIsEth ?? isETH(baseToken);
|
|
4683
|
+
const assetRouter = ctx.l1AssetRouter;
|
|
4684
|
+
const l2Gas = await determineErc20L2Gas({
|
|
4685
|
+
ctx,
|
|
4686
|
+
l1Token: p.token,
|
|
4687
|
+
modelTx: {
|
|
4688
|
+
to: p.to ?? ctx.sender,
|
|
4689
|
+
from: ctx.sender,
|
|
4690
|
+
data: "0x",
|
|
4691
|
+
value: 0n
|
|
4692
|
+
}
|
|
4693
|
+
});
|
|
4694
|
+
if (!l2Gas) throw new Error("Failed to establish L2 gas parameters.");
|
|
4695
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
4696
|
+
const mintValue = l2BaseCost + ctx.operatorTip;
|
|
4478
4697
|
const approvals = [];
|
|
4479
4698
|
const steps = [];
|
|
4480
|
-
const depositAllowance = await
|
|
4699
|
+
const depositAllowance = await wrapAs3(
|
|
4481
4700
|
"CONTRACT",
|
|
4482
|
-
OP_DEPOSITS.nonbase.
|
|
4701
|
+
OP_DEPOSITS.nonbase.allowanceToken,
|
|
4483
4702
|
() => ctx.client.l1.readContract({
|
|
4484
4703
|
address: p.token,
|
|
4485
4704
|
abi: IERC20_default,
|
|
4486
4705
|
functionName: "allowance",
|
|
4487
|
-
args: [ctx.sender,
|
|
4706
|
+
args: [ctx.sender, assetRouter]
|
|
4488
4707
|
}),
|
|
4489
4708
|
{
|
|
4490
|
-
ctx: { where: "erc20.allowance", token: p.token, spender:
|
|
4491
|
-
message: "Failed to read
|
|
4709
|
+
ctx: { where: "erc20.allowance", token: p.token, spender: assetRouter },
|
|
4710
|
+
message: "Failed to read deposit-token allowance."
|
|
4492
4711
|
}
|
|
4493
4712
|
);
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
const approveDepReq = await wrapAs2(
|
|
4713
|
+
if (depositAllowance < p.amount) {
|
|
4714
|
+
const approveSim = await wrapAs3(
|
|
4497
4715
|
"CONTRACT",
|
|
4498
4716
|
OP_DEPOSITS.nonbase.estGas,
|
|
4499
4717
|
() => ctx.client.l1.simulateContract({
|
|
4500
4718
|
address: p.token,
|
|
4501
4719
|
abi: IERC20_default,
|
|
4502
4720
|
functionName: "approve",
|
|
4503
|
-
args: [
|
|
4721
|
+
args: [assetRouter, p.amount],
|
|
4504
4722
|
account: ctx.client.account
|
|
4505
4723
|
}),
|
|
4506
4724
|
{
|
|
@@ -4508,60 +4726,55 @@ function routeErc20NonBase() {
|
|
|
4508
4726
|
message: "Failed to simulate deposit token approve."
|
|
4509
4727
|
}
|
|
4510
4728
|
);
|
|
4511
|
-
approvals.push({ token: p.token, spender:
|
|
4729
|
+
approvals.push({ token: p.token, spender: assetRouter, amount: p.amount });
|
|
4512
4730
|
steps.push({
|
|
4513
|
-
key: `approve:${p.token}:${
|
|
4731
|
+
key: `approve:${p.token}:${assetRouter}`,
|
|
4514
4732
|
kind: "approve",
|
|
4515
4733
|
description: `Approve deposit token for amount`,
|
|
4516
|
-
tx: { ...
|
|
4734
|
+
tx: { ...approveSim.request }
|
|
4517
4735
|
});
|
|
4518
4736
|
}
|
|
4519
|
-
const baseIsEth = isETH(baseToken);
|
|
4520
|
-
let msgValue = 0n;
|
|
4521
4737
|
if (!baseIsEth) {
|
|
4522
|
-
const baseAllowance = await
|
|
4738
|
+
const baseAllowance = await wrapAs3(
|
|
4523
4739
|
"CONTRACT",
|
|
4524
|
-
OP_DEPOSITS.nonbase.
|
|
4740
|
+
OP_DEPOSITS.nonbase.allowanceBase,
|
|
4525
4741
|
() => ctx.client.l1.readContract({
|
|
4526
4742
|
address: baseToken,
|
|
4527
4743
|
abi: IERC20_default,
|
|
4528
4744
|
functionName: "allowance",
|
|
4529
|
-
args: [ctx.sender,
|
|
4745
|
+
args: [ctx.sender, assetRouter]
|
|
4530
4746
|
}),
|
|
4531
4747
|
{
|
|
4532
|
-
ctx: { where: "erc20.allowance", token: baseToken, spender:
|
|
4748
|
+
ctx: { where: "erc20.allowance", token: baseToken, spender: assetRouter },
|
|
4533
4749
|
message: "Failed to read base-token allowance."
|
|
4534
4750
|
}
|
|
4535
4751
|
);
|
|
4536
4752
|
if (baseAllowance < mintValue) {
|
|
4537
|
-
const
|
|
4753
|
+
const approveBaseSim = await wrapAs3(
|
|
4538
4754
|
"CONTRACT",
|
|
4539
4755
|
OP_DEPOSITS.nonbase.estGas,
|
|
4540
4756
|
() => ctx.client.l1.simulateContract({
|
|
4541
4757
|
address: baseToken,
|
|
4542
4758
|
abi: IERC20_default,
|
|
4543
4759
|
functionName: "approve",
|
|
4544
|
-
args: [
|
|
4760
|
+
args: [assetRouter, mintValue],
|
|
4545
4761
|
account: ctx.client.account
|
|
4546
4762
|
}),
|
|
4547
4763
|
{
|
|
4548
4764
|
ctx: { where: "l1.simulateContract", to: baseToken },
|
|
4549
|
-
message: "Failed to simulate base
|
|
4765
|
+
message: "Failed to simulate base token approve."
|
|
4550
4766
|
}
|
|
4551
4767
|
);
|
|
4552
|
-
approvals.push({ token: baseToken, spender:
|
|
4768
|
+
approvals.push({ token: baseToken, spender: assetRouter, amount: mintValue });
|
|
4553
4769
|
steps.push({
|
|
4554
|
-
key: `approve:${baseToken}:${
|
|
4770
|
+
key: `approve:${baseToken}:${assetRouter}`,
|
|
4555
4771
|
kind: "approve",
|
|
4556
4772
|
description: `Approve base token for mintValue`,
|
|
4557
|
-
tx: { ...
|
|
4773
|
+
tx: { ...approveBaseSim.request }
|
|
4558
4774
|
});
|
|
4559
4775
|
}
|
|
4560
|
-
msgValue = 0n;
|
|
4561
|
-
} else {
|
|
4562
|
-
msgValue = mintValue;
|
|
4563
4776
|
}
|
|
4564
|
-
const secondBridgeCalldata = await
|
|
4777
|
+
const secondBridgeCalldata = await wrapAs3(
|
|
4565
4778
|
"INTERNAL",
|
|
4566
4779
|
OP_DEPOSITS.nonbase.encodeCalldata,
|
|
4567
4780
|
() => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, p.to ?? ctx.sender)),
|
|
@@ -4570,44 +4783,60 @@ function routeErc20NonBase() {
|
|
|
4570
4783
|
where: "encodeSecondBridgeErc20Args",
|
|
4571
4784
|
token: p.token,
|
|
4572
4785
|
amount: p.amount.toString()
|
|
4573
|
-
}
|
|
4786
|
+
},
|
|
4787
|
+
message: "Failed to encode bridging calldata."
|
|
4574
4788
|
}
|
|
4575
4789
|
);
|
|
4576
|
-
const
|
|
4790
|
+
const requestStruct = {
|
|
4577
4791
|
chainId: ctx.chainIdL2,
|
|
4578
4792
|
mintValue,
|
|
4579
4793
|
l2Value: 0n,
|
|
4580
|
-
l2GasLimit:
|
|
4794
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
4581
4795
|
l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
|
|
4582
4796
|
refundRecipient: ctx.refundRecipient,
|
|
4583
|
-
secondBridgeAddress:
|
|
4797
|
+
secondBridgeAddress: assetRouter,
|
|
4584
4798
|
secondBridgeValue: 0n,
|
|
4585
4799
|
secondBridgeCalldata
|
|
4586
4800
|
};
|
|
4801
|
+
const msgValue = baseIsEth ? mintValue : 0n;
|
|
4802
|
+
const calldata = viem.encodeFunctionData({
|
|
4803
|
+
abi: IBridgehub_default,
|
|
4804
|
+
functionName: "requestL2TransactionTwoBridges",
|
|
4805
|
+
args: [requestStruct]
|
|
4806
|
+
});
|
|
4807
|
+
const l1TxCandidate = {
|
|
4808
|
+
to: ctx.bridgehub,
|
|
4809
|
+
data: calldata,
|
|
4810
|
+
value: msgValue,
|
|
4811
|
+
from: ctx.sender,
|
|
4812
|
+
...ctx.gasOverrides
|
|
4813
|
+
};
|
|
4814
|
+
const l1Gas = await quoteL1Gas2({
|
|
4815
|
+
ctx,
|
|
4816
|
+
tx: l1TxCandidate,
|
|
4817
|
+
overrides: ctx.gasOverrides,
|
|
4818
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
4819
|
+
});
|
|
4587
4820
|
const approvalsNeeded = approvals.length > 0;
|
|
4588
4821
|
let bridgeTx;
|
|
4589
|
-
let resolvedL1GasLimit;
|
|
4590
|
-
const gasOverride = txFeeOverrides.gas;
|
|
4591
4822
|
if (approvalsNeeded) {
|
|
4592
4823
|
bridgeTx = {
|
|
4593
4824
|
address: ctx.bridgehub,
|
|
4594
4825
|
abi: IBridgehub_default,
|
|
4595
4826
|
functionName: "requestL2TransactionTwoBridges",
|
|
4596
|
-
args: [
|
|
4827
|
+
args: [requestStruct],
|
|
4597
4828
|
value: msgValue,
|
|
4598
|
-
account: ctx.client.account
|
|
4599
|
-
...txFeeOverrides
|
|
4829
|
+
account: ctx.client.account
|
|
4600
4830
|
};
|
|
4601
|
-
resolvedL1GasLimit = gasOverride ?? ctx.l2GasLimit;
|
|
4602
4831
|
} else {
|
|
4603
|
-
const sim = await
|
|
4832
|
+
const sim = await wrapAs3(
|
|
4604
4833
|
"CONTRACT",
|
|
4605
4834
|
OP_DEPOSITS.nonbase.estGas,
|
|
4606
4835
|
() => ctx.client.l1.simulateContract({
|
|
4607
4836
|
address: ctx.bridgehub,
|
|
4608
4837
|
abi: IBridgehub_default,
|
|
4609
4838
|
functionName: "requestL2TransactionTwoBridges",
|
|
4610
|
-
args: [
|
|
4839
|
+
args: [requestStruct],
|
|
4611
4840
|
value: msgValue,
|
|
4612
4841
|
account: ctx.client.account
|
|
4613
4842
|
}),
|
|
@@ -4616,67 +4845,64 @@ function routeErc20NonBase() {
|
|
|
4616
4845
|
message: "Failed to simulate two-bridges request."
|
|
4617
4846
|
}
|
|
4618
4847
|
);
|
|
4619
|
-
bridgeTx = { ...sim.request
|
|
4620
|
-
|
|
4848
|
+
bridgeTx = { ...sim.request };
|
|
4849
|
+
}
|
|
4850
|
+
if (l1Gas) {
|
|
4851
|
+
bridgeTx = {
|
|
4852
|
+
...bridgeTx,
|
|
4853
|
+
gas: l1Gas.gasLimit,
|
|
4854
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
4855
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
4856
|
+
};
|
|
4621
4857
|
}
|
|
4622
4858
|
steps.push({
|
|
4623
|
-
key: "bridgehub:two-bridges:nonbase",
|
|
4859
|
+
key: "bridgehub:two-bridges:erc20-nonbase",
|
|
4624
4860
|
kind: "bridgehub:two-bridges",
|
|
4625
4861
|
description: baseIsEth ? "Bridge ERC-20 (fees in ETH) via Bridgehub.requestL2TransactionTwoBridges" : "Bridge ERC-20 (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
|
|
4626
4862
|
tx: bridgeTx
|
|
4627
4863
|
});
|
|
4864
|
+
const fees = buildFeeBreakdown({
|
|
4865
|
+
feeToken: baseToken,
|
|
4866
|
+
l1Gas,
|
|
4867
|
+
l2Gas,
|
|
4868
|
+
l2BaseCost,
|
|
4869
|
+
operatorTip: ctx.operatorTip,
|
|
4870
|
+
mintValue
|
|
4871
|
+
});
|
|
4628
4872
|
return {
|
|
4629
4873
|
steps,
|
|
4630
4874
|
approvals,
|
|
4631
|
-
|
|
4875
|
+
fees
|
|
4632
4876
|
};
|
|
4633
4877
|
}
|
|
4634
4878
|
};
|
|
4635
4879
|
}
|
|
4636
|
-
|
|
4637
|
-
// src/adapters/viem/resources/deposits/routes/eth-nonbase.ts
|
|
4638
|
-
var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
|
|
4639
|
-
var BASE_COST_BUFFER_BPS2 = 100n;
|
|
4640
|
-
var BPS2 = 10000n;
|
|
4641
|
-
var withBuffer2 = (x) => x * (BPS2 + BASE_COST_BUFFER_BPS2) / BPS2;
|
|
4880
|
+
var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
|
|
4642
4881
|
function routeEthNonBase() {
|
|
4643
4882
|
return {
|
|
4883
|
+
// TODO: do we even need these validations?
|
|
4644
4884
|
async preflight(p, ctx) {
|
|
4645
|
-
await
|
|
4885
|
+
await wrapAs4(
|
|
4646
4886
|
"VALIDATION",
|
|
4647
4887
|
OP_DEPOSITS.ethNonBase.assertEthAsset,
|
|
4648
4888
|
() => {
|
|
4649
|
-
if (!isETH(p.token)) {
|
|
4889
|
+
if (ctx.resolvedToken?.kind !== "eth" && !isETH(p.token)) {
|
|
4650
4890
|
throw new Error("eth-nonbase route requires ETH as the deposit asset.");
|
|
4651
4891
|
}
|
|
4652
4892
|
},
|
|
4653
4893
|
{ ctx: { token: p.token } }
|
|
4654
4894
|
);
|
|
4655
|
-
|
|
4656
|
-
"CONTRACT",
|
|
4657
|
-
OP_DEPOSITS.ethNonBase.baseToken,
|
|
4658
|
-
() => ctx.client.l1.readContract({
|
|
4659
|
-
address: ctx.bridgehub,
|
|
4660
|
-
abi: IBridgehub_default,
|
|
4661
|
-
functionName: "baseToken",
|
|
4662
|
-
args: [ctx.chainIdL2]
|
|
4663
|
-
}),
|
|
4664
|
-
{
|
|
4665
|
-
ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
|
|
4666
|
-
message: "Failed to read base token."
|
|
4667
|
-
}
|
|
4668
|
-
);
|
|
4669
|
-
await wrapAs3(
|
|
4895
|
+
await wrapAs4(
|
|
4670
4896
|
"VALIDATION",
|
|
4671
4897
|
OP_DEPOSITS.ethNonBase.assertNonEthBase,
|
|
4672
4898
|
() => {
|
|
4673
|
-
if (
|
|
4899
|
+
if (ctx.baseIsEth) {
|
|
4674
4900
|
throw new Error("eth-nonbase route requires target chain base token \u2260 ETH.");
|
|
4675
4901
|
}
|
|
4676
4902
|
},
|
|
4677
|
-
{ ctx: {
|
|
4903
|
+
{ ctx: { baseIsEth: ctx.baseIsEth, chainIdL2: ctx.chainIdL2 } }
|
|
4678
4904
|
);
|
|
4679
|
-
const ethBal = await
|
|
4905
|
+
const ethBal = await wrapAs4(
|
|
4680
4906
|
"RPC",
|
|
4681
4907
|
OP_DEPOSITS.ethNonBase.ethBalance,
|
|
4682
4908
|
() => ctx.client.l1.getBalance({ address: ctx.sender }),
|
|
@@ -4685,7 +4911,7 @@ function routeEthNonBase() {
|
|
|
4685
4911
|
message: "Failed to read L1 ETH balance."
|
|
4686
4912
|
}
|
|
4687
4913
|
);
|
|
4688
|
-
await
|
|
4914
|
+
await wrapAs4(
|
|
4689
4915
|
"VALIDATION",
|
|
4690
4916
|
OP_DEPOSITS.ethNonBase.assertEthBalance,
|
|
4691
4917
|
() => {
|
|
@@ -4695,45 +4921,27 @@ function routeEthNonBase() {
|
|
|
4695
4921
|
},
|
|
4696
4922
|
{ ctx: { required: p.amount.toString(), balance: ethBal.toString() } }
|
|
4697
4923
|
);
|
|
4698
|
-
return;
|
|
4699
4924
|
},
|
|
4700
4925
|
async build(p, ctx) {
|
|
4701
|
-
const
|
|
4702
|
-
const
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
const rawBaseCost = await wrapAs3(
|
|
4718
|
-
"CONTRACT",
|
|
4719
|
-
OP_DEPOSITS.ethNonBase.baseCost,
|
|
4720
|
-
() => ctx.client.l1.readContract({
|
|
4721
|
-
address: ctx.bridgehub,
|
|
4722
|
-
abi: IBridgehub_default,
|
|
4723
|
-
functionName: "l2TransactionBaseCost",
|
|
4724
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, ctx.l2GasLimit, ctx.gasPerPubdata]
|
|
4725
|
-
}),
|
|
4726
|
-
{
|
|
4727
|
-
ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
|
|
4728
|
-
message: "Could not fetch L2 base cost."
|
|
4729
|
-
}
|
|
4730
|
-
);
|
|
4731
|
-
const baseCost = BigInt(rawBaseCost);
|
|
4732
|
-
const mintValueRaw = baseCost + ctx.operatorTip;
|
|
4733
|
-
const mintValue = withBuffer2(mintValueRaw);
|
|
4926
|
+
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
4927
|
+
const l2TxModel = {
|
|
4928
|
+
to: p.to ?? ctx.sender,
|
|
4929
|
+
from: ctx.sender,
|
|
4930
|
+
data: "0x",
|
|
4931
|
+
value: 0n
|
|
4932
|
+
};
|
|
4933
|
+
const l2Gas = await quoteL2Gas2({
|
|
4934
|
+
ctx,
|
|
4935
|
+
route: "eth-nonbase",
|
|
4936
|
+
l2TxForModeling: l2TxModel,
|
|
4937
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
4938
|
+
});
|
|
4939
|
+
if (!l2Gas) throw new Error("Failed to estimate L2 gas parameters.");
|
|
4940
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
4941
|
+
const mintValue = l2BaseCost + ctx.operatorTip;
|
|
4734
4942
|
const approvals = [];
|
|
4735
4943
|
const steps = [];
|
|
4736
|
-
const allowance = await
|
|
4944
|
+
const allowance = await wrapAs4(
|
|
4737
4945
|
"CONTRACT",
|
|
4738
4946
|
OP_DEPOSITS.ethNonBase.allowanceBase,
|
|
4739
4947
|
() => ctx.client.l1.readContract({
|
|
@@ -4749,7 +4957,7 @@ function routeEthNonBase() {
|
|
|
4749
4957
|
);
|
|
4750
4958
|
const needsApprove = allowance < mintValue;
|
|
4751
4959
|
if (needsApprove) {
|
|
4752
|
-
const approveSim = await
|
|
4960
|
+
const approveSim = await wrapAs4(
|
|
4753
4961
|
"CONTRACT",
|
|
4754
4962
|
OP_DEPOSITS.ethNonBase.estGas,
|
|
4755
4963
|
() => ctx.client.l1.simulateContract({
|
|
@@ -4768,11 +4976,11 @@ function routeEthNonBase() {
|
|
|
4768
4976
|
steps.push({
|
|
4769
4977
|
key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
|
|
4770
4978
|
kind: "approve",
|
|
4771
|
-
description: `Approve base token for mintValue`,
|
|
4979
|
+
description: `Approve base token for fees (mintValue)`,
|
|
4772
4980
|
tx: { ...approveSim.request }
|
|
4773
4981
|
});
|
|
4774
4982
|
}
|
|
4775
|
-
const secondBridgeCalldata = await
|
|
4983
|
+
const secondBridgeCalldata = await wrapAs4(
|
|
4776
4984
|
"INTERNAL",
|
|
4777
4985
|
OP_DEPOSITS.ethNonBase.encodeCalldata,
|
|
4778
4986
|
() => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, p.to ?? ctx.sender)),
|
|
@@ -4785,11 +4993,11 @@ function routeEthNonBase() {
|
|
|
4785
4993
|
message: "Failed to encode ETH bridging calldata."
|
|
4786
4994
|
}
|
|
4787
4995
|
);
|
|
4788
|
-
const
|
|
4996
|
+
const requestStruct = {
|
|
4789
4997
|
chainId: ctx.chainIdL2,
|
|
4790
4998
|
mintValue,
|
|
4791
|
-
l2Value:
|
|
4792
|
-
l2GasLimit:
|
|
4999
|
+
l2Value: p.amount,
|
|
5000
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
4793
5001
|
l2GasPerPubdataByteLimit: ctx.gasPerPubdata,
|
|
4794
5002
|
refundRecipient: ctx.refundRecipient,
|
|
4795
5003
|
secondBridgeAddress: ctx.l1AssetRouter,
|
|
@@ -4797,29 +5005,32 @@ function routeEthNonBase() {
|
|
|
4797
5005
|
secondBridgeCalldata
|
|
4798
5006
|
};
|
|
4799
5007
|
let bridgeTx;
|
|
4800
|
-
let
|
|
5008
|
+
let calldata;
|
|
4801
5009
|
if (needsApprove) {
|
|
4802
5010
|
bridgeTx = {
|
|
4803
5011
|
address: ctx.bridgehub,
|
|
4804
5012
|
abi: IBridgehub_default,
|
|
4805
5013
|
functionName: "requestL2TransactionTwoBridges",
|
|
4806
|
-
args: [
|
|
5014
|
+
args: [requestStruct],
|
|
4807
5015
|
value: p.amount,
|
|
4808
5016
|
// base ≠ ETH ⇒ msg.value == secondBridgeValue
|
|
4809
5017
|
account: ctx.client.account
|
|
4810
5018
|
};
|
|
4811
|
-
|
|
5019
|
+
calldata = viem.encodeFunctionData({
|
|
5020
|
+
abi: IBridgehub_default,
|
|
5021
|
+
functionName: "requestL2TransactionTwoBridges",
|
|
5022
|
+
args: [requestStruct]
|
|
5023
|
+
});
|
|
4812
5024
|
} else {
|
|
4813
|
-
const
|
|
5025
|
+
const sim = await wrapAs4(
|
|
4814
5026
|
"CONTRACT",
|
|
4815
5027
|
OP_DEPOSITS.ethNonBase.estGas,
|
|
4816
5028
|
() => ctx.client.l1.simulateContract({
|
|
4817
5029
|
address: ctx.bridgehub,
|
|
4818
5030
|
abi: IBridgehub_default,
|
|
4819
5031
|
functionName: "requestL2TransactionTwoBridges",
|
|
4820
|
-
args: [
|
|
5032
|
+
args: [requestStruct],
|
|
4821
5033
|
value: p.amount,
|
|
4822
|
-
// base ≠ ETH ⇒ msg.value == secondBridgeValue
|
|
4823
5034
|
account: ctx.client.account
|
|
4824
5035
|
}),
|
|
4825
5036
|
{
|
|
@@ -4827,8 +5038,33 @@ function routeEthNonBase() {
|
|
|
4827
5038
|
message: "Failed to simulate Bridgehub two-bridges request."
|
|
4828
5039
|
}
|
|
4829
5040
|
);
|
|
4830
|
-
|
|
4831
|
-
|
|
5041
|
+
calldata = viem.encodeFunctionData({
|
|
5042
|
+
abi: sim.request.abi,
|
|
5043
|
+
functionName: sim.request.functionName,
|
|
5044
|
+
args: sim.request.args
|
|
5045
|
+
});
|
|
5046
|
+
bridgeTx = { ...sim.request };
|
|
5047
|
+
}
|
|
5048
|
+
const l1TxCandidate = {
|
|
5049
|
+
to: ctx.bridgehub,
|
|
5050
|
+
data: calldata,
|
|
5051
|
+
value: p.amount,
|
|
5052
|
+
from: ctx.sender,
|
|
5053
|
+
...ctx.gasOverrides
|
|
5054
|
+
};
|
|
5055
|
+
const l1Gas = await quoteL1Gas2({
|
|
5056
|
+
ctx,
|
|
5057
|
+
tx: l1TxCandidate,
|
|
5058
|
+
overrides: ctx.gasOverrides,
|
|
5059
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
5060
|
+
});
|
|
5061
|
+
if (l1Gas) {
|
|
5062
|
+
bridgeTx = {
|
|
5063
|
+
...bridgeTx,
|
|
5064
|
+
gas: l1Gas.gasLimit,
|
|
5065
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
5066
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
5067
|
+
};
|
|
4832
5068
|
}
|
|
4833
5069
|
steps.push({
|
|
4834
5070
|
key: "bridgehub:two-bridges:eth-nonbase",
|
|
@@ -4836,48 +5072,38 @@ function routeEthNonBase() {
|
|
|
4836
5072
|
description: "Bridge ETH (fees in base ERC-20) via Bridgehub.requestL2TransactionTwoBridges",
|
|
4837
5073
|
tx: bridgeTx
|
|
4838
5074
|
});
|
|
5075
|
+
const fees = buildFeeBreakdown({
|
|
5076
|
+
feeToken: baseToken,
|
|
5077
|
+
l1Gas,
|
|
5078
|
+
l2Gas,
|
|
5079
|
+
l2BaseCost,
|
|
5080
|
+
operatorTip: ctx.operatorTip,
|
|
5081
|
+
mintValue
|
|
5082
|
+
});
|
|
4839
5083
|
return {
|
|
4840
5084
|
steps,
|
|
4841
5085
|
approvals,
|
|
4842
|
-
|
|
5086
|
+
fees
|
|
4843
5087
|
};
|
|
4844
5088
|
}
|
|
4845
5089
|
};
|
|
4846
5090
|
}
|
|
4847
|
-
|
|
4848
|
-
// src/adapters/viem/resources/deposits/routes/erc20-base.ts
|
|
4849
|
-
var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
|
|
4850
|
-
var BASE_COST_BUFFER_BPS3 = 100n;
|
|
4851
|
-
var BPS3 = 10000n;
|
|
4852
|
-
var withBuffer3 = (x) => x * (BPS3 + BASE_COST_BUFFER_BPS3) / BPS3;
|
|
5091
|
+
var { wrapAs: wrapAs5 } = createErrorHandlers("deposits");
|
|
4853
5092
|
function routeErc20Base() {
|
|
4854
5093
|
return {
|
|
4855
5094
|
async preflight(p, ctx) {
|
|
4856
|
-
await
|
|
5095
|
+
await wrapAs5(
|
|
4857
5096
|
"VALIDATION",
|
|
4858
5097
|
OP_DEPOSITS.base.assertErc20Asset,
|
|
4859
5098
|
() => {
|
|
4860
|
-
if (isETH(p.token)) {
|
|
5099
|
+
if (ctx.resolvedToken?.kind === "eth" || isETH(p.token)) {
|
|
4861
5100
|
throw new Error("erc20-base route requires an ERC-20 token (not ETH).");
|
|
4862
|
-
}
|
|
4863
|
-
},
|
|
4864
|
-
{ ctx: { token: p.token } }
|
|
4865
|
-
);
|
|
4866
|
-
const baseToken = await wrapAs4(
|
|
4867
|
-
"CONTRACT",
|
|
4868
|
-
OP_DEPOSITS.base.baseToken,
|
|
4869
|
-
() => ctx.client.l1.readContract({
|
|
4870
|
-
address: ctx.bridgehub,
|
|
4871
|
-
abi: IBridgehub_default,
|
|
4872
|
-
functionName: "baseToken",
|
|
4873
|
-
args: [ctx.chainIdL2]
|
|
4874
|
-
}),
|
|
4875
|
-
{
|
|
4876
|
-
ctx: { where: "bridgehub.baseToken", chainIdL2: ctx.chainIdL2 },
|
|
4877
|
-
message: "Failed to read base token."
|
|
4878
|
-
}
|
|
5101
|
+
}
|
|
5102
|
+
},
|
|
5103
|
+
{ ctx: { token: p.token } }
|
|
4879
5104
|
);
|
|
4880
|
-
await
|
|
5105
|
+
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
5106
|
+
await wrapAs5(
|
|
4881
5107
|
"VALIDATION",
|
|
4882
5108
|
OP_DEPOSITS.base.assertMatchesBase,
|
|
4883
5109
|
() => {
|
|
@@ -4887,45 +5113,27 @@ function routeErc20Base() {
|
|
|
4887
5113
|
},
|
|
4888
5114
|
{ ctx: { baseToken, provided: p.token, chainIdL2: ctx.chainIdL2 } }
|
|
4889
5115
|
);
|
|
4890
|
-
return;
|
|
4891
5116
|
},
|
|
4892
5117
|
async build(p, ctx) {
|
|
4893
|
-
const
|
|
4894
|
-
const
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
"
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
const
|
|
4911
|
-
|
|
4912
|
-
OP_DEPOSITS.base.baseCost,
|
|
4913
|
-
() => ctx.client.l1.readContract({
|
|
4914
|
-
address: ctx.bridgehub,
|
|
4915
|
-
abi: IBridgehub_default,
|
|
4916
|
-
functionName: "l2TransactionBaseCost",
|
|
4917
|
-
args: [ctx.chainIdL2, gasPriceForBaseCost, ctx.l2GasLimit, ctx.gasPerPubdata]
|
|
4918
|
-
}),
|
|
4919
|
-
{
|
|
4920
|
-
ctx: { where: "l2TransactionBaseCost", chainIdL2: ctx.chainIdL2 },
|
|
4921
|
-
message: "Could not fetch L2 base cost from Bridgehub."
|
|
4922
|
-
}
|
|
4923
|
-
);
|
|
4924
|
-
const baseCost = rawBaseCost;
|
|
4925
|
-
const l2Value = p.amount;
|
|
4926
|
-
const rawMintValue = baseCost + ctx.operatorTip + l2Value;
|
|
4927
|
-
const mintValue = withBuffer3(rawMintValue);
|
|
4928
|
-
const allowance = await wrapAs4(
|
|
5118
|
+
const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
|
|
5119
|
+
const l2TxModel = {
|
|
5120
|
+
to: p.to ?? ctx.sender,
|
|
5121
|
+
from: ctx.sender,
|
|
5122
|
+
data: "0x",
|
|
5123
|
+
value: 0n
|
|
5124
|
+
};
|
|
5125
|
+
const l2Gas = await quoteL2Gas2({
|
|
5126
|
+
ctx,
|
|
5127
|
+
route: "erc20-base",
|
|
5128
|
+
l2TxForModeling: l2TxModel,
|
|
5129
|
+
overrideGasLimit: ctx.l2GasLimit
|
|
5130
|
+
});
|
|
5131
|
+
if (!l2Gas) throw new Error("Failed to estimate L2 gas parameters.");
|
|
5132
|
+
const l2BaseCost = await quoteL2BaseCost({ ctx, l2GasLimit: l2Gas.gasLimit });
|
|
5133
|
+
const mintValue = l2BaseCost + ctx.operatorTip + p.amount;
|
|
5134
|
+
const approvals = [];
|
|
5135
|
+
const steps = [];
|
|
5136
|
+
const allowance = await wrapAs5(
|
|
4929
5137
|
"CONTRACT",
|
|
4930
5138
|
OP_DEPOSITS.base.allowance,
|
|
4931
5139
|
() => ctx.client.l1.readContract({
|
|
@@ -4939,11 +5147,9 @@ function routeErc20Base() {
|
|
|
4939
5147
|
message: "Failed to read base-token allowance."
|
|
4940
5148
|
}
|
|
4941
5149
|
);
|
|
4942
|
-
const approvals = [];
|
|
4943
|
-
const steps = [];
|
|
4944
5150
|
const needsApprove = allowance < mintValue;
|
|
4945
5151
|
if (needsApprove) {
|
|
4946
|
-
const approveSim = await
|
|
5152
|
+
const approveSim = await wrapAs5(
|
|
4947
5153
|
"CONTRACT",
|
|
4948
5154
|
OP_DEPOSITS.base.estGas,
|
|
4949
5155
|
() => ctx.client.l1.simulateContract({
|
|
@@ -4963,20 +5169,20 @@ function routeErc20Base() {
|
|
|
4963
5169
|
key: `approve:${baseToken}:${ctx.l1AssetRouter}`,
|
|
4964
5170
|
kind: "approve",
|
|
4965
5171
|
description: "Approve base token for mintValue",
|
|
4966
|
-
tx: { ...approveSim.request
|
|
5172
|
+
tx: { ...approveSim.request }
|
|
4967
5173
|
});
|
|
4968
5174
|
}
|
|
4969
5175
|
const req = buildDirectRequestStruct({
|
|
4970
5176
|
chainId: ctx.chainIdL2,
|
|
4971
5177
|
mintValue,
|
|
4972
|
-
l2GasLimit:
|
|
5178
|
+
l2GasLimit: l2Gas.gasLimit,
|
|
4973
5179
|
gasPerPubdata: ctx.gasPerPubdata,
|
|
4974
5180
|
refundRecipient: ctx.refundRecipient,
|
|
4975
5181
|
l2Contract: p.to ?? ctx.sender,
|
|
4976
|
-
l2Value
|
|
5182
|
+
l2Value: p.amount
|
|
4977
5183
|
});
|
|
4978
5184
|
let bridgeTx;
|
|
4979
|
-
let
|
|
5185
|
+
let calldata;
|
|
4980
5186
|
if (needsApprove) {
|
|
4981
5187
|
bridgeTx = {
|
|
4982
5188
|
address: ctx.bridgehub,
|
|
@@ -4984,13 +5190,16 @@ function routeErc20Base() {
|
|
|
4984
5190
|
functionName: "requestL2TransactionDirect",
|
|
4985
5191
|
args: [req],
|
|
4986
5192
|
value: 0n,
|
|
4987
|
-
// base is ERC-20 ⇒ msg.value MUST be 0
|
|
4988
|
-
account: ctx.client.account
|
|
4989
|
-
...txFeeOverrides
|
|
5193
|
+
// base token is ERC-20 ⇒ msg.value MUST be 0
|
|
5194
|
+
account: ctx.client.account
|
|
4990
5195
|
};
|
|
4991
|
-
|
|
5196
|
+
calldata = viem.encodeFunctionData({
|
|
5197
|
+
abi: IBridgehub_default,
|
|
5198
|
+
functionName: "requestL2TransactionDirect",
|
|
5199
|
+
args: [req]
|
|
5200
|
+
});
|
|
4992
5201
|
} else {
|
|
4993
|
-
const sim = await
|
|
5202
|
+
const sim = await wrapAs5(
|
|
4994
5203
|
"RPC",
|
|
4995
5204
|
OP_DEPOSITS.base.estGas,
|
|
4996
5205
|
() => ctx.client.l1.simulateContract({
|
|
@@ -5006,8 +5215,33 @@ function routeErc20Base() {
|
|
|
5006
5215
|
message: "Failed to simulate Bridgehub.requestL2TransactionDirect."
|
|
5007
5216
|
}
|
|
5008
5217
|
);
|
|
5009
|
-
|
|
5010
|
-
|
|
5218
|
+
calldata = viem.encodeFunctionData({
|
|
5219
|
+
abi: sim.request.abi,
|
|
5220
|
+
functionName: sim.request.functionName,
|
|
5221
|
+
args: sim.request.args
|
|
5222
|
+
});
|
|
5223
|
+
bridgeTx = { ...sim.request };
|
|
5224
|
+
}
|
|
5225
|
+
const l1TxCandidate = {
|
|
5226
|
+
to: ctx.bridgehub,
|
|
5227
|
+
data: calldata,
|
|
5228
|
+
value: 0n,
|
|
5229
|
+
from: ctx.sender,
|
|
5230
|
+
...ctx.gasOverrides
|
|
5231
|
+
};
|
|
5232
|
+
const l1Gas = await quoteL1Gas2({
|
|
5233
|
+
ctx,
|
|
5234
|
+
tx: l1TxCandidate,
|
|
5235
|
+
overrides: ctx.gasOverrides,
|
|
5236
|
+
fallbackGasLimit: SAFE_L1_BRIDGE_GAS
|
|
5237
|
+
});
|
|
5238
|
+
if (l1Gas) {
|
|
5239
|
+
bridgeTx = {
|
|
5240
|
+
...bridgeTx,
|
|
5241
|
+
gas: l1Gas.gasLimit,
|
|
5242
|
+
maxFeePerGas: l1Gas.maxFeePerGas,
|
|
5243
|
+
maxPriorityFeePerGas: l1Gas.maxPriorityFeePerGas
|
|
5244
|
+
};
|
|
5011
5245
|
}
|
|
5012
5246
|
steps.push({
|
|
5013
5247
|
key: "bridgehub:direct:erc20-base",
|
|
@@ -5015,10 +5249,18 @@ function routeErc20Base() {
|
|
|
5015
5249
|
description: "Bridge base ERC-20 via Bridgehub.requestL2TransactionDirect",
|
|
5016
5250
|
tx: bridgeTx
|
|
5017
5251
|
});
|
|
5252
|
+
const fees = buildFeeBreakdown({
|
|
5253
|
+
feeToken: baseToken,
|
|
5254
|
+
l1Gas,
|
|
5255
|
+
l2Gas,
|
|
5256
|
+
l2BaseCost,
|
|
5257
|
+
operatorTip: ctx.operatorTip,
|
|
5258
|
+
mintValue
|
|
5259
|
+
});
|
|
5018
5260
|
return {
|
|
5019
5261
|
steps,
|
|
5020
5262
|
approvals,
|
|
5021
|
-
|
|
5263
|
+
fees
|
|
5022
5264
|
};
|
|
5023
5265
|
}
|
|
5024
5266
|
};
|
|
@@ -5099,6 +5341,276 @@ async function waitForL2ExecutionFromL1Tx(l1, l2, l1TxHash) {
|
|
|
5099
5341
|
return { l2Receipt, l2TxHash };
|
|
5100
5342
|
}
|
|
5101
5343
|
|
|
5344
|
+
// src/core/codec/ntv.ts
|
|
5345
|
+
function createNTVCodec(deps) {
|
|
5346
|
+
function encodeAssetId(originChainId, ntvAddress, tokenAddress) {
|
|
5347
|
+
const encoded = deps.encode(
|
|
5348
|
+
["uint256", "address", "address"],
|
|
5349
|
+
[originChainId, ntvAddress, tokenAddress]
|
|
5350
|
+
);
|
|
5351
|
+
return deps.keccak256(encoded);
|
|
5352
|
+
}
|
|
5353
|
+
return {
|
|
5354
|
+
encodeAssetId
|
|
5355
|
+
};
|
|
5356
|
+
}
|
|
5357
|
+
|
|
5358
|
+
// src/adapters/viem/resources/tokens/tokens.ts
|
|
5359
|
+
var { wrapAs: wrapAs6 } = createErrorHandlers("tokens");
|
|
5360
|
+
var ntvCodec = createNTVCodec({
|
|
5361
|
+
encode: (types, values) => viem.encodeAbiParameters(
|
|
5362
|
+
types.map((t, i) => ({ type: t, name: `arg${i}` })),
|
|
5363
|
+
values
|
|
5364
|
+
),
|
|
5365
|
+
keccak256: (data) => viem.keccak256(data)
|
|
5366
|
+
});
|
|
5367
|
+
function createTokensResource(client) {
|
|
5368
|
+
let l2NtvL1ChainIdPromise = null;
|
|
5369
|
+
let baseTokenAssetIdPromise = null;
|
|
5370
|
+
let wethL1Promise = null;
|
|
5371
|
+
let wethL2Promise = null;
|
|
5372
|
+
async function getL1ChainId() {
|
|
5373
|
+
if (!l2NtvL1ChainIdPromise) {
|
|
5374
|
+
l2NtvL1ChainIdPromise = wrapAs6("INTERNAL", "getL1ChainId", async () => {
|
|
5375
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5376
|
+
return await l2NativeTokenVault.read.L1_CHAIN_ID();
|
|
5377
|
+
});
|
|
5378
|
+
}
|
|
5379
|
+
return l2NtvL1ChainIdPromise;
|
|
5380
|
+
}
|
|
5381
|
+
async function getBaseTokenAssetId() {
|
|
5382
|
+
if (!baseTokenAssetIdPromise) {
|
|
5383
|
+
baseTokenAssetIdPromise = wrapAs6("INTERNAL", "baseTokenAssetId", async () => {
|
|
5384
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5385
|
+
const assetId = await l2NativeTokenVault.read.BASE_TOKEN_ASSET_ID();
|
|
5386
|
+
return assetId;
|
|
5387
|
+
});
|
|
5388
|
+
}
|
|
5389
|
+
return baseTokenAssetIdPromise;
|
|
5390
|
+
}
|
|
5391
|
+
async function getWethL1() {
|
|
5392
|
+
if (!wethL1Promise) {
|
|
5393
|
+
wethL1Promise = wrapAs6("INTERNAL", "wethL1", async () => {
|
|
5394
|
+
const { l1NativeTokenVault } = await client.contracts();
|
|
5395
|
+
const weth = await l1NativeTokenVault.read.WETH_TOKEN();
|
|
5396
|
+
return weth;
|
|
5397
|
+
});
|
|
5398
|
+
}
|
|
5399
|
+
return wethL1Promise;
|
|
5400
|
+
}
|
|
5401
|
+
async function getWethL2() {
|
|
5402
|
+
if (!wethL2Promise) {
|
|
5403
|
+
wethL2Promise = wrapAs6("INTERNAL", "wethL2", async () => {
|
|
5404
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5405
|
+
const weth = await l2NativeTokenVault.read.WETH_TOKEN();
|
|
5406
|
+
return weth;
|
|
5407
|
+
});
|
|
5408
|
+
}
|
|
5409
|
+
return wethL2Promise;
|
|
5410
|
+
}
|
|
5411
|
+
async function toL2Address(l1Token) {
|
|
5412
|
+
return wrapAs6("CONTRACT", "tokens.toL2Address", async () => {
|
|
5413
|
+
const normalized = normalizeL1Token(l1Token);
|
|
5414
|
+
const chainId = BigInt(await client.l2.getChainId());
|
|
5415
|
+
const baseToken = await client.baseToken(chainId);
|
|
5416
|
+
if (isAddressEq(normalized, baseToken)) {
|
|
5417
|
+
return L2_BASE_TOKEN_ADDRESS;
|
|
5418
|
+
}
|
|
5419
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5420
|
+
const l2Token = await l2NativeTokenVault.read.l2TokenAddress([normalized]);
|
|
5421
|
+
return l2Token;
|
|
5422
|
+
});
|
|
5423
|
+
}
|
|
5424
|
+
async function toL1Address(l2Token) {
|
|
5425
|
+
return wrapAs6("CONTRACT", "tokens.toL1Address", async () => {
|
|
5426
|
+
if (isAddressEq(l2Token, ETH_ADDRESS)) return ETH_ADDRESS;
|
|
5427
|
+
if (isAddressEq(l2Token, L2_BASE_TOKEN_ADDRESS)) {
|
|
5428
|
+
const chainId = BigInt(await client.l2.getChainId());
|
|
5429
|
+
return await client.baseToken(chainId);
|
|
5430
|
+
}
|
|
5431
|
+
const { l2AssetRouter } = await client.contracts();
|
|
5432
|
+
const l1Token = await l2AssetRouter.read.l1TokenAddress([l2Token]);
|
|
5433
|
+
return l1Token;
|
|
5434
|
+
});
|
|
5435
|
+
}
|
|
5436
|
+
async function assetIdOfL1(l1Token) {
|
|
5437
|
+
return wrapAs6("CONTRACT", "tokens.assetIdOfL1", async () => {
|
|
5438
|
+
const normalized = normalizeL1Token(l1Token);
|
|
5439
|
+
const { l1NativeTokenVault } = await client.contracts();
|
|
5440
|
+
return await l1NativeTokenVault.read.assetId([normalized]);
|
|
5441
|
+
});
|
|
5442
|
+
}
|
|
5443
|
+
async function assetIdOfL2(l2Token) {
|
|
5444
|
+
return wrapAs6("CONTRACT", "tokens.assetIdOfL2", async () => {
|
|
5445
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5446
|
+
return await l2NativeTokenVault.read.assetId([l2Token]);
|
|
5447
|
+
});
|
|
5448
|
+
}
|
|
5449
|
+
async function l2TokenFromAssetId(assetId) {
|
|
5450
|
+
return wrapAs6("CONTRACT", "tokens.l2TokenFromAssetId", async () => {
|
|
5451
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5452
|
+
return await l2NativeTokenVault.read.tokenAddress([assetId]);
|
|
5453
|
+
});
|
|
5454
|
+
}
|
|
5455
|
+
async function l1TokenFromAssetId(assetId) {
|
|
5456
|
+
return wrapAs6("CONTRACT", "tokens.l1TokenFromAssetId", async () => {
|
|
5457
|
+
const { l1NativeTokenVault } = await client.contracts();
|
|
5458
|
+
return await l1NativeTokenVault.read.tokenAddress([assetId]);
|
|
5459
|
+
});
|
|
5460
|
+
}
|
|
5461
|
+
async function originChainId(assetId) {
|
|
5462
|
+
return wrapAs6("CONTRACT", "tokens.originChainId", async () => {
|
|
5463
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5464
|
+
return await l2NativeTokenVault.read.originChainId([assetId]);
|
|
5465
|
+
});
|
|
5466
|
+
}
|
|
5467
|
+
async function baseTokenAssetId() {
|
|
5468
|
+
return getBaseTokenAssetId();
|
|
5469
|
+
}
|
|
5470
|
+
async function isChainEthBased() {
|
|
5471
|
+
return wrapAs6("CONTRACT", "tokens.isChainEthBased", async () => {
|
|
5472
|
+
const baseAssetId = await getBaseTokenAssetId();
|
|
5473
|
+
const l1ChainId = await getL1ChainId();
|
|
5474
|
+
const ethAssetId = ntvCodec.encodeAssetId(
|
|
5475
|
+
l1ChainId,
|
|
5476
|
+
L2_NATIVE_TOKEN_VAULT_ADDRESS,
|
|
5477
|
+
ETH_ADDRESS
|
|
5478
|
+
);
|
|
5479
|
+
return hexEq(baseAssetId, ethAssetId);
|
|
5480
|
+
});
|
|
5481
|
+
}
|
|
5482
|
+
async function wethL1() {
|
|
5483
|
+
return getWethL1();
|
|
5484
|
+
}
|
|
5485
|
+
async function wethL2() {
|
|
5486
|
+
return getWethL2();
|
|
5487
|
+
}
|
|
5488
|
+
async function computeL2BridgedAddress(args) {
|
|
5489
|
+
return wrapAs6("CONTRACT", "tokens.computeL2BridgedAddress", async () => {
|
|
5490
|
+
const normalized = normalizeL1Token(args.l1Token);
|
|
5491
|
+
const { l2NativeTokenVault } = await client.contracts();
|
|
5492
|
+
const predicted = await l2NativeTokenVault.read.calculateCreate2TokenAddress([
|
|
5493
|
+
args.originChainId,
|
|
5494
|
+
normalized
|
|
5495
|
+
]);
|
|
5496
|
+
return predicted;
|
|
5497
|
+
});
|
|
5498
|
+
}
|
|
5499
|
+
async function resolve(ref, opts) {
|
|
5500
|
+
return wrapAs6("CONTRACT", "tokens.resolve", async () => {
|
|
5501
|
+
let chain;
|
|
5502
|
+
let address;
|
|
5503
|
+
if (typeof ref === "string") {
|
|
5504
|
+
chain = opts?.chain ?? "l1";
|
|
5505
|
+
address = ref;
|
|
5506
|
+
} else {
|
|
5507
|
+
chain = ref.chain;
|
|
5508
|
+
address = ref.address;
|
|
5509
|
+
}
|
|
5510
|
+
let l1;
|
|
5511
|
+
let l2;
|
|
5512
|
+
if (chain === "l1") {
|
|
5513
|
+
l1 = normalizeL1Token(address);
|
|
5514
|
+
l2 = await toL2Address(address);
|
|
5515
|
+
} else {
|
|
5516
|
+
l2 = address;
|
|
5517
|
+
l1 = await toL1Address(address);
|
|
5518
|
+
}
|
|
5519
|
+
const assetId = await assetIdOfL1(l1);
|
|
5520
|
+
const originChainIdVal = await originChainId(assetId);
|
|
5521
|
+
const [baseAssetId, wethL1Addr, wethL2Addr, ethBased] = await Promise.all([
|
|
5522
|
+
baseTokenAssetId(),
|
|
5523
|
+
wethL1(),
|
|
5524
|
+
wethL2(),
|
|
5525
|
+
isChainEthBased()
|
|
5526
|
+
]);
|
|
5527
|
+
let kind;
|
|
5528
|
+
if (isAddressEq(l1, ETH_ADDRESS)) {
|
|
5529
|
+
kind = "eth";
|
|
5530
|
+
} else if (hexEq(assetId, baseAssetId)) {
|
|
5531
|
+
kind = "base";
|
|
5532
|
+
} else {
|
|
5533
|
+
kind = "erc20";
|
|
5534
|
+
}
|
|
5535
|
+
return {
|
|
5536
|
+
kind,
|
|
5537
|
+
l1,
|
|
5538
|
+
l2,
|
|
5539
|
+
assetId,
|
|
5540
|
+
originChainId: originChainIdVal,
|
|
5541
|
+
isChainEthBased: ethBased,
|
|
5542
|
+
baseTokenAssetId: baseAssetId,
|
|
5543
|
+
wethL1: wethL1Addr,
|
|
5544
|
+
wethL2: wethL2Addr
|
|
5545
|
+
};
|
|
5546
|
+
});
|
|
5547
|
+
}
|
|
5548
|
+
return {
|
|
5549
|
+
resolve,
|
|
5550
|
+
toL2Address,
|
|
5551
|
+
toL1Address,
|
|
5552
|
+
assetIdOfL1,
|
|
5553
|
+
assetIdOfL2,
|
|
5554
|
+
l2TokenFromAssetId,
|
|
5555
|
+
l1TokenFromAssetId,
|
|
5556
|
+
originChainId,
|
|
5557
|
+
baseTokenAssetId,
|
|
5558
|
+
isChainEthBased,
|
|
5559
|
+
wethL1,
|
|
5560
|
+
wethL2,
|
|
5561
|
+
computeL2BridgedAddress
|
|
5562
|
+
};
|
|
5563
|
+
}
|
|
5564
|
+
|
|
5565
|
+
// src/adapters/viem/resources/contracts/contracts.ts
|
|
5566
|
+
function createContractsResource(client) {
|
|
5567
|
+
async function addresses() {
|
|
5568
|
+
return client.ensureAddresses();
|
|
5569
|
+
}
|
|
5570
|
+
async function instances() {
|
|
5571
|
+
return client.contracts();
|
|
5572
|
+
}
|
|
5573
|
+
async function bridgehub() {
|
|
5574
|
+
const { bridgehub: bridgehub2 } = await instances();
|
|
5575
|
+
return bridgehub2;
|
|
5576
|
+
}
|
|
5577
|
+
async function l1AssetRouter() {
|
|
5578
|
+
const { l1AssetRouter: l1AssetRouter2 } = await instances();
|
|
5579
|
+
return l1AssetRouter2;
|
|
5580
|
+
}
|
|
5581
|
+
async function l1NativeTokenVault() {
|
|
5582
|
+
const { l1NativeTokenVault: l1NativeTokenVault2 } = await instances();
|
|
5583
|
+
return l1NativeTokenVault2;
|
|
5584
|
+
}
|
|
5585
|
+
async function l1Nullifier() {
|
|
5586
|
+
const { l1Nullifier: l1Nullifier2 } = await instances();
|
|
5587
|
+
return l1Nullifier2;
|
|
5588
|
+
}
|
|
5589
|
+
async function l2AssetRouter() {
|
|
5590
|
+
const { l2AssetRouter: l2AssetRouter2 } = await instances();
|
|
5591
|
+
return l2AssetRouter2;
|
|
5592
|
+
}
|
|
5593
|
+
async function l2NativeTokenVault() {
|
|
5594
|
+
const { l2NativeTokenVault: l2NativeTokenVault2 } = await instances();
|
|
5595
|
+
return l2NativeTokenVault2;
|
|
5596
|
+
}
|
|
5597
|
+
async function l2BaseTokenSystem() {
|
|
5598
|
+
const { l2BaseTokenSystem: l2BaseTokenSystem2 } = await instances();
|
|
5599
|
+
return l2BaseTokenSystem2;
|
|
5600
|
+
}
|
|
5601
|
+
return {
|
|
5602
|
+
addresses,
|
|
5603
|
+
instances,
|
|
5604
|
+
bridgehub,
|
|
5605
|
+
l1AssetRouter,
|
|
5606
|
+
l1NativeTokenVault,
|
|
5607
|
+
l1Nullifier,
|
|
5608
|
+
l2AssetRouter,
|
|
5609
|
+
l2NativeTokenVault,
|
|
5610
|
+
l2BaseTokenSystem
|
|
5611
|
+
};
|
|
5612
|
+
}
|
|
5613
|
+
|
|
5102
5614
|
// src/adapters/viem/resources/deposits/index.ts
|
|
5103
5615
|
var { wrap, toResult } = createErrorHandlers("deposits");
|
|
5104
5616
|
var ROUTES = {
|
|
@@ -5107,37 +5619,26 @@ var ROUTES = {
|
|
|
5107
5619
|
"erc20-nonbase": routeErc20NonBase(),
|
|
5108
5620
|
"erc20-base": routeErc20Base()
|
|
5109
5621
|
};
|
|
5110
|
-
function createDepositsResource(client) {
|
|
5622
|
+
function createDepositsResource(client, tokens, contracts) {
|
|
5623
|
+
const tokensResource = tokens ?? createTokensResource(client);
|
|
5624
|
+
const contractsResource = contracts ?? createContractsResource(client);
|
|
5111
5625
|
async function buildPlan(p) {
|
|
5112
|
-
const ctx = await commonCtx(p, client);
|
|
5626
|
+
const ctx = await commonCtx(p, client, tokensResource, contractsResource);
|
|
5113
5627
|
const route = ctx.route;
|
|
5114
5628
|
await ROUTES[route].preflight?.(p, ctx);
|
|
5115
|
-
const { steps, approvals,
|
|
5116
|
-
const { baseCost, mintValue } = quoteExtras;
|
|
5117
|
-
const fallbackGasLimit = quoteExtras.l1GasLimit;
|
|
5118
|
-
const resolveGasLimit = () => {
|
|
5119
|
-
if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
|
|
5120
|
-
for (let i = steps.length - 1; i >= 0; i--) {
|
|
5121
|
-
const candidate = steps[i].tx.gas;
|
|
5122
|
-
if (candidate != null) return candidate;
|
|
5123
|
-
}
|
|
5124
|
-
if (fallbackGasLimit != null) return fallbackGasLimit;
|
|
5125
|
-
return ctx.l2GasLimit;
|
|
5126
|
-
};
|
|
5127
|
-
const gasLimit = resolveGasLimit();
|
|
5629
|
+
const { steps, approvals, fees } = await ROUTES[route].build(p, ctx);
|
|
5128
5630
|
return {
|
|
5129
5631
|
route: ctx.route,
|
|
5130
5632
|
summary: {
|
|
5131
5633
|
route: ctx.route,
|
|
5132
5634
|
approvalsNeeded: approvals,
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
fees
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
}
|
|
5635
|
+
amounts: {
|
|
5636
|
+
transfer: { token: p.token, amount: p.amount }
|
|
5637
|
+
},
|
|
5638
|
+
fees,
|
|
5639
|
+
// Legacy fields (maintained for backward compatibility)
|
|
5640
|
+
baseCost: fees.l2?.baseCost,
|
|
5641
|
+
mintValue: fees.mintValue
|
|
5141
5642
|
},
|
|
5142
5643
|
steps
|
|
5143
5644
|
};
|
|
@@ -5212,7 +5713,7 @@ function createDepositsResource(client) {
|
|
|
5212
5713
|
step.tx.gas = overrides.gasLimit;
|
|
5213
5714
|
}
|
|
5214
5715
|
}
|
|
5215
|
-
if (
|
|
5716
|
+
if (!p.l1TxOverrides?.gasLimit) {
|
|
5216
5717
|
try {
|
|
5217
5718
|
const feePart = step.tx.maxFeePerGas != null && step.tx.maxPriorityFeePerGas != null ? {
|
|
5218
5719
|
maxFeePerGas: step.tx.maxFeePerGas,
|
|
@@ -5435,36 +5936,12 @@ function normalizeTokenForRouting(token) {
|
|
|
5435
5936
|
function pickWithdrawRoute(args) {
|
|
5436
5937
|
const tokenNorm = normalizeTokenForRouting(args.token);
|
|
5437
5938
|
const isL2BaseAlias = tokenNorm.toLowerCase() === L2_BASE_TOKEN_ADDRESS.toLowerCase();
|
|
5438
|
-
if (isL2BaseAlias) return
|
|
5939
|
+
if (isL2BaseAlias) return "base";
|
|
5439
5940
|
return "erc20-nonbase";
|
|
5440
5941
|
}
|
|
5441
5942
|
|
|
5442
|
-
// src/adapters/viem/resources/token-info.ts
|
|
5443
|
-
async function ntvBaseAssetId(l2, ntv) {
|
|
5444
|
-
return l2.readContract({
|
|
5445
|
-
address: ntv,
|
|
5446
|
-
abi: L2NativeTokenVault_default,
|
|
5447
|
-
functionName: "BASE_TOKEN_ASSET_ID"
|
|
5448
|
-
});
|
|
5449
|
-
}
|
|
5450
|
-
async function ntvL1ChainId(l2, ntv) {
|
|
5451
|
-
return l2.readContract({
|
|
5452
|
-
address: ntv,
|
|
5453
|
-
abi: L2NativeTokenVault_default,
|
|
5454
|
-
functionName: "L1_CHAIN_ID"
|
|
5455
|
-
});
|
|
5456
|
-
}
|
|
5457
|
-
async function isEthBasedChain(l2, ntv) {
|
|
5458
|
-
const [baseAssetId, l1ChainId] = await Promise.all([
|
|
5459
|
-
ntvBaseAssetId(l2, ntv),
|
|
5460
|
-
ntvL1ChainId(l2, ntv)
|
|
5461
|
-
]);
|
|
5462
|
-
const ethAssetId = encodeNativeTokenVaultAssetId(l1ChainId, ETH_ADDRESS);
|
|
5463
|
-
return baseAssetId.toLowerCase() === ethAssetId.toLowerCase();
|
|
5464
|
-
}
|
|
5465
|
-
|
|
5466
5943
|
// src/adapters/viem/resources/withdrawals/context.ts
|
|
5467
|
-
async function commonCtx2(p, client) {
|
|
5944
|
+
async function commonCtx2(p, client, tokens, contracts) {
|
|
5468
5945
|
const sender = client.account.address;
|
|
5469
5946
|
const {
|
|
5470
5947
|
bridgehub,
|
|
@@ -5473,18 +5950,20 @@ async function commonCtx2(p, client) {
|
|
|
5473
5950
|
l2AssetRouter,
|
|
5474
5951
|
l2NativeTokenVault,
|
|
5475
5952
|
l2BaseTokenSystem
|
|
5476
|
-
} = await
|
|
5953
|
+
} = await contracts.addresses();
|
|
5477
5954
|
const chainIdL2 = BigInt(await client.l2.getChainId());
|
|
5478
|
-
const
|
|
5479
|
-
const
|
|
5480
|
-
const
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
});
|
|
5484
|
-
const l2GasLimit = p.l2GasLimit ?? 300000n;
|
|
5485
|
-
const gasBufferPct = 15;
|
|
5955
|
+
const resolvedToken = await tokens.resolve(p.token, { chain: "l2" });
|
|
5956
|
+
const baseTokenAssetId = resolvedToken.baseTokenAssetId;
|
|
5957
|
+
const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
|
|
5958
|
+
const baseIsEth = resolvedToken.isChainEthBased;
|
|
5959
|
+
const route = pickWithdrawRoute({ token: p.token});
|
|
5486
5960
|
return {
|
|
5487
5961
|
client,
|
|
5962
|
+
tokens,
|
|
5963
|
+
contracts,
|
|
5964
|
+
resolvedToken,
|
|
5965
|
+
baseTokenAssetId,
|
|
5966
|
+
baseTokenL1,
|
|
5488
5967
|
bridgehub,
|
|
5489
5968
|
chainIdL2,
|
|
5490
5969
|
sender,
|
|
@@ -5495,56 +5974,162 @@ async function commonCtx2(p, client) {
|
|
|
5495
5974
|
l2NativeTokenVault,
|
|
5496
5975
|
l2BaseTokenSystem,
|
|
5497
5976
|
baseIsEth,
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5977
|
+
gasOverrides: p.l2TxOverrides
|
|
5978
|
+
};
|
|
5979
|
+
}
|
|
5980
|
+
|
|
5981
|
+
// src/core/resources/withdrawals/gas.ts
|
|
5982
|
+
function makeGasQuote2(p) {
|
|
5983
|
+
return {
|
|
5984
|
+
gasLimit: p.gasLimit,
|
|
5985
|
+
maxFeePerGas: p.maxFeePerGas,
|
|
5986
|
+
maxPriorityFeePerGas: p.maxPriorityFeePerGas,
|
|
5987
|
+
maxCost: p.gasLimit * p.maxFeePerGas
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
async function fetchFees2(estimator) {
|
|
5991
|
+
try {
|
|
5992
|
+
const fees = await estimator.estimateFeesPerGas();
|
|
5993
|
+
if (fees.maxFeePerGas != null) {
|
|
5994
|
+
return {
|
|
5995
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
5996
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? 0n
|
|
5997
|
+
};
|
|
5998
|
+
}
|
|
5999
|
+
if (fees.gasPrice != null) {
|
|
6000
|
+
return {
|
|
6001
|
+
maxFeePerGas: fees.gasPrice,
|
|
6002
|
+
maxPriorityFeePerGas: 0n
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
} catch {
|
|
6006
|
+
}
|
|
6007
|
+
try {
|
|
6008
|
+
const gp = await estimator.getGasPrice();
|
|
6009
|
+
return { maxFeePerGas: gp, maxPriorityFeePerGas: 0n };
|
|
6010
|
+
} catch {
|
|
6011
|
+
return { maxFeePerGas: 0n, maxPriorityFeePerGas: 0n };
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
async function quoteL2Gas3(input) {
|
|
6015
|
+
const { estimator, tx, overrides } = input;
|
|
6016
|
+
const market = await fetchFees2(estimator);
|
|
6017
|
+
const o = overrides;
|
|
6018
|
+
const maxFeePerGas = o?.maxFeePerGas ?? (tx.maxFeePerGas != null ? BigInt(tx.maxFeePerGas) : market.maxFeePerGas);
|
|
6019
|
+
const maxPriorityFeePerGas = o?.maxPriorityFeePerGas ?? (tx.maxPriorityFeePerGas != null ? BigInt(tx.maxPriorityFeePerGas) : market.maxPriorityFeePerGas);
|
|
6020
|
+
const explicitGasLimit = o?.gasLimit ?? (tx.gasLimit != null ? BigInt(tx.gasLimit) : void 0);
|
|
6021
|
+
if (explicitGasLimit != null) {
|
|
6022
|
+
return makeGasQuote2({
|
|
6023
|
+
gasLimit: explicitGasLimit,
|
|
6024
|
+
maxFeePerGas,
|
|
6025
|
+
maxPriorityFeePerGas
|
|
6026
|
+
});
|
|
6027
|
+
}
|
|
6028
|
+
try {
|
|
6029
|
+
const est = await estimator.estimateGas(tx);
|
|
6030
|
+
const buffered = BigInt(est) * (100n + BUFFER) / 100n;
|
|
6031
|
+
return makeGasQuote2({
|
|
6032
|
+
gasLimit: buffered,
|
|
6033
|
+
maxFeePerGas,
|
|
6034
|
+
maxPriorityFeePerGas
|
|
6035
|
+
});
|
|
6036
|
+
} catch (err) {
|
|
6037
|
+
console.warn("Failed to estimate L2 gas for withdrawal.", err);
|
|
6038
|
+
return void 0;
|
|
6039
|
+
}
|
|
6040
|
+
}
|
|
6041
|
+
|
|
6042
|
+
// src/adapters/viem/resources/withdrawals/services/gas.ts
|
|
6043
|
+
async function quoteL2Gas4(input) {
|
|
6044
|
+
const { ctx, tx } = input;
|
|
6045
|
+
const estimator = viemToGasEstimator(ctx.client.l2);
|
|
6046
|
+
return quoteL2Gas3({
|
|
6047
|
+
estimator,
|
|
6048
|
+
tx: toCoreTx(tx),
|
|
6049
|
+
overrides: ctx.gasOverrides
|
|
6050
|
+
});
|
|
6051
|
+
}
|
|
6052
|
+
|
|
6053
|
+
// src/adapters/viem/resources/withdrawals/services/fee.ts
|
|
6054
|
+
function buildFeeBreakdown2(p) {
|
|
6055
|
+
const l2Total = p.l2Gas?.maxCost ?? 0n;
|
|
6056
|
+
const l2 = {
|
|
6057
|
+
total: l2Total,
|
|
6058
|
+
gasLimit: p.l2Gas?.gasLimit ?? 0n,
|
|
6059
|
+
maxFeePerGas: p.l2Gas?.maxFeePerGas ?? 0n,
|
|
6060
|
+
maxPriorityFeePerGas: p.l2Gas?.maxPriorityFeePerGas
|
|
6061
|
+
};
|
|
6062
|
+
return {
|
|
6063
|
+
token: p.feeToken,
|
|
6064
|
+
maxTotal: l2Total,
|
|
6065
|
+
l2
|
|
5501
6066
|
};
|
|
5502
6067
|
}
|
|
5503
6068
|
|
|
5504
6069
|
// src/adapters/viem/resources/withdrawals/routes/eth.ts
|
|
5505
|
-
var { wrapAs:
|
|
6070
|
+
var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
|
|
5506
6071
|
function routeEthBase() {
|
|
5507
6072
|
return {
|
|
5508
6073
|
async build(p, ctx) {
|
|
5509
|
-
const
|
|
5510
|
-
const
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
account: ctx.client.account,
|
|
5521
|
-
...txFeeOverrides
|
|
5522
|
-
}),
|
|
6074
|
+
const steps = [];
|
|
6075
|
+
const data = await wrapAs7(
|
|
6076
|
+
"INTERNAL",
|
|
6077
|
+
OP_WITHDRAWALS.eth.encodeWithdraw,
|
|
6078
|
+
() => Promise.resolve(
|
|
6079
|
+
viem.encodeFunctionData({
|
|
6080
|
+
abi: IBaseToken_default,
|
|
6081
|
+
functionName: "withdraw",
|
|
6082
|
+
args: [p.to ?? ctx.sender]
|
|
6083
|
+
})
|
|
6084
|
+
),
|
|
5523
6085
|
{
|
|
5524
|
-
ctx: { where: "
|
|
5525
|
-
message: "Failed to
|
|
6086
|
+
ctx: { where: "L2BaseToken.withdraw", to: p.to ?? ctx.sender },
|
|
6087
|
+
message: "Failed to encode ETH withdraw calldata."
|
|
5526
6088
|
}
|
|
5527
6089
|
);
|
|
5528
|
-
const
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
6090
|
+
const L2tx = {
|
|
6091
|
+
to: L2_BASE_TOKEN_ADDRESS,
|
|
6092
|
+
data,
|
|
6093
|
+
value: p.amount,
|
|
6094
|
+
from: ctx.sender
|
|
6095
|
+
};
|
|
6096
|
+
const l2Gas = await quoteL2Gas4({ ctx, tx: L2tx });
|
|
6097
|
+
if (l2Gas) {
|
|
6098
|
+
L2tx.gas = l2Gas.gasLimit;
|
|
6099
|
+
L2tx.maxFeePerGas = l2Gas.maxFeePerGas;
|
|
6100
|
+
L2tx.maxPriorityFeePerGas = l2Gas.maxPriorityFeePerGas;
|
|
6101
|
+
}
|
|
6102
|
+
const tx = {
|
|
6103
|
+
address: L2_BASE_TOKEN_ADDRESS,
|
|
6104
|
+
abi: IBaseToken_default,
|
|
6105
|
+
functionName: "withdraw",
|
|
6106
|
+
args: [p.to ?? ctx.sender],
|
|
6107
|
+
value: p.amount,
|
|
6108
|
+
account: ctx.client.account,
|
|
6109
|
+
...l2Gas
|
|
6110
|
+
};
|
|
6111
|
+
const fees = buildFeeBreakdown2({
|
|
6112
|
+
feeToken: L2_BASE_TOKEN_ADDRESS,
|
|
6113
|
+
l2Gas
|
|
6114
|
+
});
|
|
6115
|
+
steps.push({
|
|
6116
|
+
key: "l2-base-token:withdraw",
|
|
6117
|
+
kind: "l2-base-token:withdraw",
|
|
6118
|
+
description: "Withdraw ETH via L2 Base Token System",
|
|
6119
|
+
tx
|
|
6120
|
+
});
|
|
6121
|
+
return { steps, approvals: [], fees };
|
|
5537
6122
|
}
|
|
5538
6123
|
};
|
|
5539
6124
|
}
|
|
5540
|
-
var { wrapAs:
|
|
6125
|
+
var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
|
|
5541
6126
|
function routeErc20NonBase2() {
|
|
5542
6127
|
return {
|
|
5543
6128
|
// TODO: add preflight validations here
|
|
5544
6129
|
async build(p, ctx) {
|
|
5545
|
-
const
|
|
5546
|
-
const
|
|
5547
|
-
const current = await
|
|
6130
|
+
const steps = [];
|
|
6131
|
+
const approvals = [];
|
|
6132
|
+
const current = await wrapAs8(
|
|
5548
6133
|
"CONTRACT",
|
|
5549
6134
|
OP_WITHDRAWALS.erc20.allowance,
|
|
5550
6135
|
() => ctx.client.l2.readContract({
|
|
@@ -5564,12 +6149,26 @@ function routeErc20NonBase2() {
|
|
|
5564
6149
|
message: "Failed to read L2 ERC-20 allowance."
|
|
5565
6150
|
}
|
|
5566
6151
|
);
|
|
5567
|
-
|
|
5568
|
-
const steps = [];
|
|
5569
|
-
const approvals = [];
|
|
5570
|
-
if (needsApprove) {
|
|
6152
|
+
if (current < p.amount) {
|
|
5571
6153
|
approvals.push({ token: p.token, spender: ctx.l2NativeTokenVault, amount: p.amount });
|
|
5572
|
-
const
|
|
6154
|
+
const data = viem.encodeFunctionData({
|
|
6155
|
+
abi: IERC20_default,
|
|
6156
|
+
functionName: "approve",
|
|
6157
|
+
args: [ctx.l2NativeTokenVault, p.amount]
|
|
6158
|
+
});
|
|
6159
|
+
const approveTxCandidate = {
|
|
6160
|
+
to: p.token,
|
|
6161
|
+
data,
|
|
6162
|
+
value: 0n,
|
|
6163
|
+
from: ctx.sender
|
|
6164
|
+
};
|
|
6165
|
+
const approveGas = await quoteL2Gas4({ ctx, tx: approveTxCandidate });
|
|
6166
|
+
if (approveGas) {
|
|
6167
|
+
approveTxCandidate.gas = approveGas.gasLimit;
|
|
6168
|
+
approveTxCandidate.maxFeePerGas = approveGas.maxFeePerGas;
|
|
6169
|
+
approveTxCandidate.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
|
|
6170
|
+
}
|
|
6171
|
+
const approveSim = await wrapAs8(
|
|
5573
6172
|
"CONTRACT",
|
|
5574
6173
|
OP_WITHDRAWALS.erc20.estGas,
|
|
5575
6174
|
() => ctx.client.l2.simulateContract({
|
|
@@ -5578,21 +6177,26 @@ function routeErc20NonBase2() {
|
|
|
5578
6177
|
functionName: "approve",
|
|
5579
6178
|
args: [ctx.l2NativeTokenVault, p.amount],
|
|
5580
6179
|
account: ctx.client.account,
|
|
5581
|
-
...
|
|
6180
|
+
...approveGas
|
|
5582
6181
|
}),
|
|
5583
6182
|
{
|
|
5584
6183
|
ctx: { where: "l2.simulateContract", to: p.token },
|
|
5585
6184
|
message: "Failed to simulate L2 ERC-20 approve."
|
|
5586
6185
|
}
|
|
5587
6186
|
);
|
|
6187
|
+
const { ...approveRequest } = approveSim.request;
|
|
6188
|
+
const approveTx = {
|
|
6189
|
+
...approveRequest
|
|
6190
|
+
};
|
|
5588
6191
|
steps.push({
|
|
5589
6192
|
key: `approve:l2:${p.token}:${ctx.l2NativeTokenVault}`,
|
|
5590
6193
|
kind: "approve:l2",
|
|
5591
6194
|
description: `Approve ${p.amount} to NativeTokenVault`,
|
|
5592
|
-
tx:
|
|
6195
|
+
tx: approveTx
|
|
5593
6196
|
});
|
|
5594
6197
|
}
|
|
5595
|
-
const
|
|
6198
|
+
const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l2" }) : void 0);
|
|
6199
|
+
const assetId = resolved?.assetId ?? (await wrapAs8(
|
|
5596
6200
|
"CONTRACT",
|
|
5597
6201
|
OP_WITHDRAWALS.erc20.ensureRegistered,
|
|
5598
6202
|
() => ctx.client.l2.simulateContract({
|
|
@@ -5606,28 +6210,44 @@ function routeErc20NonBase2() {
|
|
|
5606
6210
|
ctx: { where: "L2NativeTokenVault.ensureTokenIsRegistered", token: p.token },
|
|
5607
6211
|
message: "Failed to ensure token is registered in L2NativeTokenVault."
|
|
5608
6212
|
}
|
|
5609
|
-
);
|
|
5610
|
-
const assetId = ensure.result;
|
|
6213
|
+
)).result;
|
|
5611
6214
|
const assetData = viem.encodeAbiParameters(
|
|
5612
6215
|
[
|
|
5613
6216
|
{ type: "uint256", name: "amount" },
|
|
5614
6217
|
{ type: "address", name: "l1Receiver" },
|
|
5615
6218
|
{ type: "address", name: "l2Token" }
|
|
5616
6219
|
],
|
|
5617
|
-
[p.amount,
|
|
6220
|
+
[p.amount, p.to ?? ctx.sender, p.token]
|
|
5618
6221
|
);
|
|
6222
|
+
const withdrawCalldata = viem.encodeFunctionData({
|
|
6223
|
+
abi: IL2AssetRouter_default,
|
|
6224
|
+
functionName: "withdraw",
|
|
6225
|
+
args: [assetId, assetData]
|
|
6226
|
+
});
|
|
6227
|
+
const withdrawTxCandidate = {
|
|
6228
|
+
to: ctx.l2AssetRouter,
|
|
6229
|
+
data: withdrawCalldata,
|
|
6230
|
+
value: 0n,
|
|
6231
|
+
from: ctx.sender
|
|
6232
|
+
};
|
|
6233
|
+
const withdrawGas = await quoteL2Gas4({ ctx, tx: withdrawTxCandidate });
|
|
6234
|
+
if (withdrawGas) {
|
|
6235
|
+
withdrawTxCandidate.gas = withdrawGas.gasLimit;
|
|
6236
|
+
withdrawTxCandidate.maxFeePerGas = withdrawGas.maxFeePerGas;
|
|
6237
|
+
withdrawTxCandidate.maxPriorityFeePerGas = withdrawGas.maxPriorityFeePerGas;
|
|
6238
|
+
}
|
|
5619
6239
|
let withdrawTx;
|
|
5620
|
-
if (
|
|
6240
|
+
if (current < p.amount) {
|
|
5621
6241
|
withdrawTx = {
|
|
5622
6242
|
address: ctx.l2AssetRouter,
|
|
5623
6243
|
abi: IL2AssetRouter_default,
|
|
5624
6244
|
functionName: "withdraw",
|
|
5625
6245
|
args: [assetId, assetData],
|
|
5626
6246
|
account: ctx.client.account,
|
|
5627
|
-
...
|
|
6247
|
+
...withdrawGas
|
|
5628
6248
|
};
|
|
5629
6249
|
} else {
|
|
5630
|
-
const sim = await
|
|
6250
|
+
const sim = await wrapAs8(
|
|
5631
6251
|
"CONTRACT",
|
|
5632
6252
|
OP_WITHDRAWALS.erc20.estGas,
|
|
5633
6253
|
() => ctx.client.l2.simulateContract({
|
|
@@ -5636,14 +6256,18 @@ function routeErc20NonBase2() {
|
|
|
5636
6256
|
functionName: "withdraw",
|
|
5637
6257
|
args: [assetId, assetData],
|
|
5638
6258
|
account: ctx.client.account,
|
|
5639
|
-
...
|
|
6259
|
+
...withdrawGas
|
|
5640
6260
|
}),
|
|
5641
6261
|
{
|
|
5642
6262
|
ctx: { where: "l2.simulateContract", to: ctx.l2AssetRouter },
|
|
5643
6263
|
message: "Failed to simulate L2 ERC-20 withdraw."
|
|
5644
6264
|
}
|
|
5645
6265
|
);
|
|
5646
|
-
|
|
6266
|
+
const { ...withdrawRequest } = sim.request;
|
|
6267
|
+
withdrawTx = {
|
|
6268
|
+
...withdrawRequest,
|
|
6269
|
+
...withdrawGas
|
|
6270
|
+
};
|
|
5647
6271
|
}
|
|
5648
6272
|
steps.push({
|
|
5649
6273
|
key: "l2-asset-router:withdraw",
|
|
@@ -5651,59 +6275,11 @@ function routeErc20NonBase2() {
|
|
|
5651
6275
|
description: "Burn on L2 & send L2\u2192L1 message",
|
|
5652
6276
|
tx: withdrawTx
|
|
5653
6277
|
});
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
}
|
|
5658
|
-
|
|
5659
|
-
// src/adapters/viem/resources/withdrawals/routes/eth-nonbase.ts
|
|
5660
|
-
var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
|
|
5661
|
-
function routeEthNonBase2() {
|
|
5662
|
-
return {
|
|
5663
|
-
async preflight(p, ctx) {
|
|
5664
|
-
await wrapAs7(
|
|
5665
|
-
"VALIDATION",
|
|
5666
|
-
OP_WITHDRAWALS.ethNonBase.assertNonEthBase,
|
|
5667
|
-
() => {
|
|
5668
|
-
if (p.token.toLowerCase() !== L2_BASE_TOKEN_ADDRESS.toLowerCase()) {
|
|
5669
|
-
throw new Error("eth-nonbase route requires the L2 base-token alias (0x\u2026800A).");
|
|
5670
|
-
}
|
|
5671
|
-
if (ctx.baseIsEth) {
|
|
5672
|
-
throw new Error("eth-nonbase route requires chain base \u2260 ETH.");
|
|
5673
|
-
}
|
|
5674
|
-
},
|
|
5675
|
-
{ ctx: { token: p.token, baseIsEth: ctx.baseIsEth } }
|
|
5676
|
-
);
|
|
5677
|
-
},
|
|
5678
|
-
async build(p, ctx) {
|
|
5679
|
-
const toL1 = p.to ?? ctx.sender;
|
|
5680
|
-
const txFeeOverrides = buildViemFeeOverrides(ctx.fee);
|
|
5681
|
-
const sim = await wrapAs7(
|
|
5682
|
-
"CONTRACT",
|
|
5683
|
-
OP_WITHDRAWALS.ethNonBase.estGas,
|
|
5684
|
-
() => ctx.client.l2.simulateContract({
|
|
5685
|
-
address: L2_BASE_TOKEN_ADDRESS,
|
|
5686
|
-
abi: IBaseToken_default,
|
|
5687
|
-
functionName: "withdraw",
|
|
5688
|
-
args: [toL1],
|
|
5689
|
-
value: p.amount,
|
|
5690
|
-
account: ctx.client.account,
|
|
5691
|
-
...txFeeOverrides
|
|
5692
|
-
}),
|
|
5693
|
-
{
|
|
5694
|
-
ctx: { where: "l2.simulateContract", to: L2_BASE_TOKEN_ADDRESS },
|
|
5695
|
-
message: "Failed to simulate L2 base-token withdraw."
|
|
5696
|
-
}
|
|
5697
|
-
);
|
|
5698
|
-
const steps = [
|
|
5699
|
-
{
|
|
5700
|
-
key: "l2-base-token:withdraw",
|
|
5701
|
-
kind: "l2-base-token:withdraw",
|
|
5702
|
-
description: "Withdraw base token via L2 Base Token System (base \u2260 ETH)",
|
|
5703
|
-
tx: { ...sim.request, ...txFeeOverrides }
|
|
5704
|
-
}
|
|
5705
|
-
];
|
|
5706
|
-
return { steps, approvals: [], quoteExtras: {} };
|
|
6278
|
+
const fees = buildFeeBreakdown2({
|
|
6279
|
+
feeToken: ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2),
|
|
6280
|
+
l2Gas: withdrawGas
|
|
6281
|
+
});
|
|
6282
|
+
return { steps, approvals, fees };
|
|
5707
6283
|
}
|
|
5708
6284
|
};
|
|
5709
6285
|
}
|
|
@@ -5739,7 +6315,7 @@ function messengerLogIndex(raw, opts) {
|
|
|
5739
6315
|
}
|
|
5740
6316
|
return (hits[index] ?? hits[0]).i;
|
|
5741
6317
|
}
|
|
5742
|
-
var { wrapAs:
|
|
6318
|
+
var { wrapAs: wrapAs9 } = createErrorHandlers("withdrawals");
|
|
5743
6319
|
var IL1NullifierMini = [
|
|
5744
6320
|
{
|
|
5745
6321
|
type: "function",
|
|
@@ -5756,7 +6332,7 @@ var IL1NullifierMini = [
|
|
|
5756
6332
|
function createFinalizationServices(client) {
|
|
5757
6333
|
return {
|
|
5758
6334
|
async fetchFinalizeDepositParams(l2TxHash) {
|
|
5759
|
-
const parsed = await
|
|
6335
|
+
const parsed = await wrapAs9(
|
|
5760
6336
|
"RPC",
|
|
5761
6337
|
OP_WITHDRAWALS.finalize.fetchParams.receipt,
|
|
5762
6338
|
() => client.zks.getReceiptWithL2ToL1(l2TxHash),
|
|
@@ -5773,7 +6349,7 @@ function createFinalizationServices(client) {
|
|
|
5773
6349
|
context: { l2TxHash }
|
|
5774
6350
|
});
|
|
5775
6351
|
}
|
|
5776
|
-
const ev = await
|
|
6352
|
+
const ev = await wrapAs9(
|
|
5777
6353
|
"INTERNAL",
|
|
5778
6354
|
OP_WITHDRAWALS.finalize.fetchParams.findMessage,
|
|
5779
6355
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
|
@@ -5783,7 +6359,7 @@ function createFinalizationServices(client) {
|
|
|
5783
6359
|
message: "Failed to locate L1MessageSent event in L2 receipt."
|
|
5784
6360
|
}
|
|
5785
6361
|
);
|
|
5786
|
-
const message = await
|
|
6362
|
+
const message = await wrapAs9(
|
|
5787
6363
|
"INTERNAL",
|
|
5788
6364
|
OP_WITHDRAWALS.finalize.fetchParams.decodeMessage,
|
|
5789
6365
|
() => {
|
|
@@ -5795,7 +6371,7 @@ function createFinalizationServices(client) {
|
|
|
5795
6371
|
message: "Failed to decode withdrawal message."
|
|
5796
6372
|
}
|
|
5797
6373
|
);
|
|
5798
|
-
const raw = await
|
|
6374
|
+
const raw = await wrapAs9(
|
|
5799
6375
|
"RPC",
|
|
5800
6376
|
OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
|
|
5801
6377
|
() => client.zks.getReceiptWithL2ToL1(l2TxHash),
|
|
@@ -5812,7 +6388,7 @@ function createFinalizationServices(client) {
|
|
|
5812
6388
|
context: { l2TxHash }
|
|
5813
6389
|
});
|
|
5814
6390
|
}
|
|
5815
|
-
const idx = await
|
|
6391
|
+
const idx = await wrapAs9(
|
|
5816
6392
|
"INTERNAL",
|
|
5817
6393
|
OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
|
|
5818
6394
|
() => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
|
|
@@ -5821,7 +6397,7 @@ function createFinalizationServices(client) {
|
|
|
5821
6397
|
message: "Failed to derive messenger log index."
|
|
5822
6398
|
}
|
|
5823
6399
|
);
|
|
5824
|
-
const proof = await
|
|
6400
|
+
const proof = await wrapAs9(
|
|
5825
6401
|
"RPC",
|
|
5826
6402
|
OP_WITHDRAWALS.finalize.fetchParams.proof,
|
|
5827
6403
|
() => client.zks.getL2ToL1LogProof(l2TxHash, idx),
|
|
@@ -5830,7 +6406,7 @@ function createFinalizationServices(client) {
|
|
|
5830
6406
|
message: "Failed to fetch L2\u2192L1 log proof."
|
|
5831
6407
|
}
|
|
5832
6408
|
);
|
|
5833
|
-
const chainId = await
|
|
6409
|
+
const chainId = await wrapAs9(
|
|
5834
6410
|
"RPC",
|
|
5835
6411
|
OP_WITHDRAWALS.finalize.fetchParams.network,
|
|
5836
6412
|
() => client.l2.getChainId(),
|
|
@@ -5846,7 +6422,7 @@ function createFinalizationServices(client) {
|
|
|
5846
6422
|
message,
|
|
5847
6423
|
merkleProof: proof.proof
|
|
5848
6424
|
};
|
|
5849
|
-
const { l1Nullifier } = await
|
|
6425
|
+
const { l1Nullifier } = await wrapAs9(
|
|
5850
6426
|
"INTERNAL",
|
|
5851
6427
|
OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
|
|
5852
6428
|
() => client.ensureAddresses(),
|
|
@@ -5858,7 +6434,7 @@ function createFinalizationServices(client) {
|
|
|
5858
6434
|
return { params, nullifier: l1Nullifier };
|
|
5859
6435
|
},
|
|
5860
6436
|
async simulateFinalizeReadiness(params) {
|
|
5861
|
-
const { l1Nullifier } = await
|
|
6437
|
+
const { l1Nullifier } = await wrapAs9(
|
|
5862
6438
|
"INTERNAL",
|
|
5863
6439
|
OP_WITHDRAWALS.finalize.readiness.ensureAddresses,
|
|
5864
6440
|
() => client.ensureAddresses(),
|
|
@@ -5869,7 +6445,7 @@ function createFinalizationServices(client) {
|
|
|
5869
6445
|
);
|
|
5870
6446
|
const done = await (async () => {
|
|
5871
6447
|
try {
|
|
5872
|
-
const result = await
|
|
6448
|
+
const result = await wrapAs9(
|
|
5873
6449
|
"RPC",
|
|
5874
6450
|
OP_WITHDRAWALS.finalize.readiness.isFinalized,
|
|
5875
6451
|
() => client.l1.readContract({
|
|
@@ -5903,7 +6479,7 @@ function createFinalizationServices(client) {
|
|
|
5903
6479
|
}
|
|
5904
6480
|
},
|
|
5905
6481
|
async isWithdrawalFinalized(key) {
|
|
5906
|
-
const { l1Nullifier } = await
|
|
6482
|
+
const { l1Nullifier } = await wrapAs9(
|
|
5907
6483
|
"INTERNAL",
|
|
5908
6484
|
OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
|
|
5909
6485
|
() => client.ensureAddresses(),
|
|
@@ -5912,7 +6488,7 @@ function createFinalizationServices(client) {
|
|
|
5912
6488
|
message: "Failed to ensure L1 Nullifier address."
|
|
5913
6489
|
}
|
|
5914
6490
|
);
|
|
5915
|
-
return await
|
|
6491
|
+
return await wrapAs9(
|
|
5916
6492
|
"RPC",
|
|
5917
6493
|
OP_WITHDRAWALS.finalize.isFinalized,
|
|
5918
6494
|
() => client.l1.readContract({
|
|
@@ -5928,7 +6504,7 @@ function createFinalizationServices(client) {
|
|
|
5928
6504
|
);
|
|
5929
6505
|
},
|
|
5930
6506
|
async estimateFinalization(params) {
|
|
5931
|
-
const { l1Nullifier } = await
|
|
6507
|
+
const { l1Nullifier } = await wrapAs9(
|
|
5932
6508
|
"INTERNAL",
|
|
5933
6509
|
OP_WITHDRAWALS.finalize.estimate,
|
|
5934
6510
|
() => client.ensureAddresses(),
|
|
@@ -5937,7 +6513,7 @@ function createFinalizationServices(client) {
|
|
|
5937
6513
|
message: "Failed to ensure L1 Nullifier address."
|
|
5938
6514
|
}
|
|
5939
6515
|
);
|
|
5940
|
-
const gasLimit = await
|
|
6516
|
+
const gasLimit = await wrapAs9(
|
|
5941
6517
|
"RPC",
|
|
5942
6518
|
OP_WITHDRAWALS.finalize.estimate,
|
|
5943
6519
|
() => client.l1.estimateContractGas({
|
|
@@ -5961,7 +6537,7 @@ function createFinalizationServices(client) {
|
|
|
5961
6537
|
let maxFeePerGas;
|
|
5962
6538
|
let maxPriorityFeePerGas;
|
|
5963
6539
|
try {
|
|
5964
|
-
const fee = await
|
|
6540
|
+
const fee = await wrapAs9(
|
|
5965
6541
|
"RPC",
|
|
5966
6542
|
OP_WITHDRAWALS.finalize.estimate,
|
|
5967
6543
|
() => client.l1.estimateFeesPerGas(),
|
|
@@ -5980,7 +6556,7 @@ function createFinalizationServices(client) {
|
|
|
5980
6556
|
})();
|
|
5981
6557
|
maxPriorityFeePerGas = fee.maxPriorityFeePerGas ?? 0n;
|
|
5982
6558
|
} catch {
|
|
5983
|
-
const gasPrice = await
|
|
6559
|
+
const gasPrice = await wrapAs9(
|
|
5984
6560
|
"RPC",
|
|
5985
6561
|
OP_WITHDRAWALS.finalize.estimate,
|
|
5986
6562
|
() => client.l1.getGasPrice(),
|
|
@@ -5999,7 +6575,7 @@ function createFinalizationServices(client) {
|
|
|
5999
6575
|
};
|
|
6000
6576
|
},
|
|
6001
6577
|
async finalizeDeposit(params) {
|
|
6002
|
-
const { l1Nullifier } = await
|
|
6578
|
+
const { l1Nullifier } = await wrapAs9(
|
|
6003
6579
|
"INTERNAL",
|
|
6004
6580
|
OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
|
|
6005
6581
|
() => client.ensureAddresses(),
|
|
@@ -6058,40 +6634,32 @@ function createFinalizationServices(client) {
|
|
|
6058
6634
|
|
|
6059
6635
|
// src/adapters/viem/resources/withdrawals/index.ts
|
|
6060
6636
|
var ROUTES2 = {
|
|
6061
|
-
|
|
6637
|
+
base: routeEthBase(),
|
|
6062
6638
|
// BaseTokenSystem.withdraw, chain base = ETH
|
|
6063
|
-
"eth-nonbase": routeEthNonBase2(),
|
|
6064
|
-
// BaseTokenSystem.withdraw, chain base ≠ ETH
|
|
6065
6639
|
"erc20-nonbase": routeErc20NonBase2()
|
|
6066
6640
|
// AssetRouter.withdraw for non-base ERC-20s
|
|
6067
6641
|
};
|
|
6068
|
-
function createWithdrawalsResource(client) {
|
|
6642
|
+
function createWithdrawalsResource(client, tokens, contracts) {
|
|
6069
6643
|
const svc = createFinalizationServices(client);
|
|
6070
6644
|
const { wrap: wrap2, toResult: toResult2 } = createErrorHandlers("withdrawals");
|
|
6645
|
+
const tokensResource = tokens ?? createTokensResource(client);
|
|
6646
|
+
const contractsResource = contracts ?? createContractsResource(client);
|
|
6071
6647
|
async function buildPlan(p) {
|
|
6072
|
-
const ctx = await commonCtx2(p, client);
|
|
6648
|
+
const ctx = await commonCtx2(p, client, tokensResource, contractsResource);
|
|
6073
6649
|
await ROUTES2[ctx.route].preflight?.(p, ctx);
|
|
6074
|
-
const { steps, approvals } = await ROUTES2[ctx.route].build(p, ctx);
|
|
6075
|
-
|
|
6076
|
-
if (ctx.fee.gasLimit != null) return ctx.fee.gasLimit;
|
|
6077
|
-
for (let i = steps.length - 1; i >= 0; i--) {
|
|
6078
|
-
const candidate = steps[i].tx.gas;
|
|
6079
|
-
if (candidate != null) return candidate;
|
|
6080
|
-
}
|
|
6081
|
-
return void 0;
|
|
6082
|
-
};
|
|
6083
|
-
const gasLimit = resolveGasLimit();
|
|
6084
|
-
const summary = {
|
|
6650
|
+
const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
|
|
6651
|
+
return {
|
|
6085
6652
|
route: ctx.route,
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6653
|
+
summary: {
|
|
6654
|
+
route: ctx.route,
|
|
6655
|
+
approvalsNeeded: approvals,
|
|
6656
|
+
amounts: {
|
|
6657
|
+
transfer: { token: p.token, amount: p.amount }
|
|
6658
|
+
},
|
|
6659
|
+
fees
|
|
6660
|
+
},
|
|
6661
|
+
steps
|
|
6093
6662
|
};
|
|
6094
|
-
return { route: ctx.route, summary, steps };
|
|
6095
6663
|
}
|
|
6096
6664
|
const finalizeCache = /* @__PURE__ */ new Map();
|
|
6097
6665
|
const quote = (p) => wrap2(OP_WITHDRAWALS.quote, async () => (await buildPlan(p)).summary, {
|
|
@@ -6125,7 +6693,7 @@ function createWithdrawalsResource(client) {
|
|
|
6125
6693
|
}
|
|
6126
6694
|
if (overrides.gasLimit != null) step.tx.gas = overrides.gasLimit;
|
|
6127
6695
|
}
|
|
6128
|
-
if (
|
|
6696
|
+
if (!p.l2TxOverrides?.gasLimit) {
|
|
6129
6697
|
try {
|
|
6130
6698
|
const feePart = step.tx.maxFeePerGas != null && step.tx.maxPriorityFeePerGas != null ? {
|
|
6131
6699
|
maxFeePerGas: step.tx.maxFeePerGas,
|
|
@@ -6424,55 +6992,13 @@ function createWithdrawalsResource(client) {
|
|
|
6424
6992
|
|
|
6425
6993
|
// src/adapters/viem/sdk.ts
|
|
6426
6994
|
function createViemSdk(client) {
|
|
6995
|
+
const tokens = createTokensResource(client);
|
|
6996
|
+
const contracts = createContractsResource(client);
|
|
6427
6997
|
return {
|
|
6428
|
-
deposits: createDepositsResource(client),
|
|
6429
|
-
withdrawals: createWithdrawalsResource(client),
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
contracts: () => client.contracts(),
|
|
6433
|
-
async l1AssetRouter() {
|
|
6434
|
-
const { l1AssetRouter } = await client.contracts();
|
|
6435
|
-
return l1AssetRouter;
|
|
6436
|
-
},
|
|
6437
|
-
async l1NativeTokenVault() {
|
|
6438
|
-
const { l1NativeTokenVault } = await client.contracts();
|
|
6439
|
-
return l1NativeTokenVault;
|
|
6440
|
-
},
|
|
6441
|
-
async l1Nullifier() {
|
|
6442
|
-
const { l1Nullifier } = await client.contracts();
|
|
6443
|
-
return l1Nullifier;
|
|
6444
|
-
},
|
|
6445
|
-
async baseToken(chainId) {
|
|
6446
|
-
const id = chainId ?? BigInt(await client.l2.getChainId());
|
|
6447
|
-
return client.baseToken(id);
|
|
6448
|
-
},
|
|
6449
|
-
async l2TokenAddress(l1Token) {
|
|
6450
|
-
if (isAddressEq(l1Token, FORMAL_ETH_ADDRESS)) {
|
|
6451
|
-
return ETH_ADDRESS;
|
|
6452
|
-
}
|
|
6453
|
-
const base = await client.baseToken(BigInt(await client.l2.getChainId()));
|
|
6454
|
-
if (isAddressEq(l1Token, base)) {
|
|
6455
|
-
return L2_BASE_TOKEN_ADDRESS;
|
|
6456
|
-
}
|
|
6457
|
-
const { l2NativeTokenVault } = await client.contracts();
|
|
6458
|
-
const addr = await l2NativeTokenVault.read.l2TokenAddress([l1Token]);
|
|
6459
|
-
return addr;
|
|
6460
|
-
},
|
|
6461
|
-
async l1TokenAddress(l2Token) {
|
|
6462
|
-
if (isAddressEq(l2Token, FORMAL_ETH_ADDRESS)) {
|
|
6463
|
-
return FORMAL_ETH_ADDRESS;
|
|
6464
|
-
}
|
|
6465
|
-
const { l2AssetRouter } = await client.contracts();
|
|
6466
|
-
const addr = await l2AssetRouter.read.l1TokenAddress([l2Token]);
|
|
6467
|
-
return addr;
|
|
6468
|
-
},
|
|
6469
|
-
async assetId(l1Token) {
|
|
6470
|
-
const norm = isAddressEq(l1Token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : l1Token;
|
|
6471
|
-
const { l1NativeTokenVault } = await client.contracts();
|
|
6472
|
-
const id = await l1NativeTokenVault.read.assetId([norm]);
|
|
6473
|
-
return id;
|
|
6474
|
-
}
|
|
6475
|
-
}
|
|
6998
|
+
deposits: createDepositsResource(client, tokens, contracts),
|
|
6999
|
+
withdrawals: createWithdrawalsResource(client, tokens, contracts),
|
|
7000
|
+
tokens,
|
|
7001
|
+
contracts
|
|
6476
7002
|
};
|
|
6477
7003
|
}
|
|
6478
7004
|
|