diff --git a/src/clients/ProfitClient.ts b/src/clients/ProfitClient.ts index e3bf23481..e5eba34b2 100644 --- a/src/clients/ProfitClient.ts +++ b/src/clients/ProfitClient.ts @@ -45,8 +45,9 @@ export const GAS_TOKEN_BY_CHAIN_ID: { [chainId: number]: string } = { // Testnets: 5: WETH, 280: WETH, - 421613: WETH, + 80001: MATIC, 84531: WETH, + 421613: WETH, }; // TODO: Make this dynamic once we support chains with gas tokens that have different decimals. const GAS_TOKEN_DECIMALS = 18; @@ -68,8 +69,9 @@ const QUERY_HANDLERS: { // Testnets: 5: relayFeeCalculator.EthereumQueries, 280: relayFeeCalculator.zkSyncGoerliQueries, - 421613: relayFeeCalculator.ArbitrumQueries, + 80001: relayFeeCalculator.PolygonQueries, 84531: relayFeeCalculator.BaseGoerliQueries, + 421613: relayFeeCalculator.ArbitrumQueries, }; const { PriceClient } = priceClient; diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 8492f3046..12f3e2a6b 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -4,7 +4,7 @@ import { utils } from "@across-protocol/sdk-v2"; // Maximum supported version of the configuration loaded into the Across ConfigStore. // It protects bots from running outdated code against newer version of the on-chain config store. // @dev Incorrectly setting this value may lead to incorrect behaviour and potential loss of funds. -export const CONFIG_STORE_VERSION = 1; +export const CONFIG_STORE_VERSION = 2; // The first version where UBA is in effect. export const { UBA_MIN_CONFIG_STORE_VERSION } = utils; @@ -61,6 +61,7 @@ export const DEFAULT_MIN_DEPOSIT_CONFIRMATIONS = { // Testnets: 5: 0, 280: 0, + 80001: 0, 84531: 0, 421613: 0, }; @@ -76,8 +77,9 @@ export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chain // Testnets: 5: 0, 280: 0, - 421613: 0, + 80001: 0, 84531: 0, + 421613: 0, }, 100: { 1: 16, // Mainnet reorgs are rarely > 4 blocks in depth so this is a very safe buffer @@ -90,6 +92,7 @@ export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chain // Testnets: 5: 0, 280: 0, + 80001: 0, 84531: 0, 421613: 0, }, @@ -114,6 +117,7 @@ export const CHAIN_MAX_BLOCK_LOOKBACK = { // Testnets: 5: 10000, 280: 10000, + 80001: 10000, 84531: 10000, 421613: 10000, }; @@ -129,6 +133,7 @@ export const BUNDLE_END_BLOCK_BUFFERS = { // Testnets: 5: 0, 280: 0, + 80001: 0, 84531: 0, 421613: 0, }; @@ -163,6 +168,7 @@ export const MAX_REORG_DISTANCE: { [chainId: number]: number } = { // Testnets: 5: 0, 280: 0, + 80001: 0, 84531: 0, 421613: 0, }; @@ -192,6 +198,7 @@ export const multicall3Addresses = { 288: "0xcA11bde05977b3631167028862bE2a173976CA11", 8453: "0xcA11bde05977b3631167028862bE2a173976CA11", 42161: "0xcA11bde05977b3631167028862bE2a173976CA11", + 80001: "0xcA11bde05977b3631167028862bE2a173976CA11", 84531: "0xcA11bde05977b3631167028862bE2a173976CA11", 421613: "0xcA11bde05977b3631167028862bE2a173976CA11", }; diff --git a/src/finalizer/index.ts b/src/finalizer/index.ts index c78be8a56..7b931797c 100644 --- a/src/finalizer/index.ts +++ b/src/finalizer/index.ts @@ -1,4 +1,5 @@ import assert from "assert"; +import { typeguards, utils as sdkUtils } from "@across-protocol/sdk-v2"; import { groupBy } from "lodash"; import { Wallet, @@ -28,6 +29,8 @@ import { } from "../common"; import { ChainFinalizer, Withdrawal } from "./types"; +const { isError, isEthersError } = typeguards; + config(); let logger: winston.Logger; @@ -68,12 +71,9 @@ export async function finalize( // input byte length. const multicall2 = getMultisender(hubChainId, hubSigner); const finalizationsToBatch: { - callData: Multicall2Call[]; - withdrawals: Withdrawal[]; - } = { - callData: [], - withdrawals: [], - }; + callData: Multicall2Call; + withdrawal: Withdrawal; + }[] = []; // For each chain, delegate to a handler to look up any TokensBridged events and attempt finalization. for (const chainId of configuredChainIds) { @@ -109,18 +109,41 @@ export async function finalize( ); logger.debug({ at: "finalize", message: `Found ${callData.length} ${network} withdrawals for finalization.` }); - finalizationsToBatch.callData.push(...callData); - finalizationsToBatch.withdrawals.push(...withdrawals); + const txns = callData.map((callData, i) => { + return { callData, withdrawal: withdrawals[i] }; + }); + + finalizationsToBatch.push(...txns); } - if (finalizationsToBatch.callData.length > 0) { + // Ensure each transaction would succeed in isolation. + const finalizations = await sdkUtils.filterAsync(finalizationsToBatch, async (finalization) => { try { - // Note: We might want to slice these up in the future but I don't forsee us including enough events - // to approach the block gas limit. - const txn = await (await multicall2.aggregate(finalizationsToBatch.callData)).wait(); - const { withdrawals = [], proofs = [] } = groupBy(finalizationsToBatch.withdrawals, ({ type }) => { - return type === "withdrawal" ? "withdrawals" : "proofs"; + const { target: to, callData: data } = finalization.callData; + await multicall2.provider.estimateGas({ to, data }); + return true; + } catch (err) { + const { l2ChainId, type, l1TokenSymbol, amount } = finalization.withdrawal; + const network = getNetworkName(l2ChainId); + logger.info({ + at: "finalizer", + message: `Failed to estimate gas for ${network} ${amount} ${l1TokenSymbol} ${type}.`, + reason: isEthersError(err) ? err.reason : isError(err) ? err.message : "unknown error", }); + return false; + } + }); + + if (finalizations.length > 0) { + try { + // Note: If the sum of finalizations approaches the gas limit, consider slicing them up. + const callData = finalizations.map(({ callData }) => callData); + const txn = await (await multicall2.aggregate(callData)).wait(); + + const { withdrawals = [], proofs = [] } = groupBy( + finalizations.map(({ withdrawal }) => withdrawal), + ({ type }) => (type === "withdrawal" ? "withdrawals" : "proofs") + ); proofs.forEach(({ l2ChainId, amount, l1TokenSymbol: symbol }) => { const spokeChain = getNetworkName(l2ChainId); logger.info({ diff --git a/src/utils/NetworkUtils.ts b/src/utils/NetworkUtils.ts index 109a539e0..b25f66213 100644 --- a/src/utils/NetworkUtils.ts +++ b/src/utils/NetworkUtils.ts @@ -1,34 +1,6 @@ -import { PublicNetworks } from "@uma/common"; +import { utils as sdkUtils } from "@across-protocol/sdk-v2"; -export function getNetworkName(networkId: number | string): string { - try { - const networkName = PublicNetworks[Number(networkId)].name; - return networkName.charAt(0).toUpperCase() + networkName.slice(1); - } catch (error) { - if (Number(networkId) == 666) { - return "Hardhat1"; - } - if (Number(networkId) == 1337) { - return "Hardhat2"; - } - if (Number(networkId) == 421613) { - return "ArbitrumGoerli"; - } - if (Number(networkId) == 324) { - return "ZkSync"; - } - if (Number(networkId) == 280) { - return "ZkSync-Goerli"; - } - if (Number(networkId) == 8453) { - return "Base"; - } - if (Number(networkId) == 84531) { - return "BaseGoerli"; - } - return "unknown"; - } -} +export const { getNetworkName } = sdkUtils; export function getNativeTokenSymbol(chainId: number | string): string { if (chainId.toString() === "137" || chainId.toString() === "80001") { diff --git a/yarn.lock b/yarn.lock index 77a2ccdf5..1a2055975 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7273,9 +7273,9 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1"