diff --git a/src/finalizer/utils/arbitrum.ts b/src/finalizer/utils/arbitrum.ts index c6c013129..e3e93f3e4 100644 --- a/src/finalizer/utils/arbitrum.ts +++ b/src/finalizer/utils/arbitrum.ts @@ -11,6 +11,8 @@ import { getRedisCache, getBlockForTimestamp, getL1TokenInfo, + compareAddressesSimple, + TOKEN_SYMBOLS_MAP, } from "../../utils"; import { TokensBridged } from "../../interfaces"; import { HubPoolClient, SpokePoolClient } from "../../clients"; @@ -139,17 +141,24 @@ async function getAllMessageStatuses( // This is important for bridge transactions containing multiple events. const logIndexesForMessage = getUniqueLogIndex(tokensBridged); return ( - await Promise.all( - tokensBridged.map((e, i) => getMessageOutboxStatusAndProof(logger, e, mainnetSigner, logIndexesForMessage[i])) + ( + await Promise.all( + tokensBridged.map((e, i) => getMessageOutboxStatusAndProof(logger, e, mainnetSigner, logIndexesForMessage[i])) + ) ) - ) - .map((result, i) => { - return { - ...result, - info: tokensBridged[i], - }; - }) - .filter((result) => result.message !== undefined); + .map((result, i) => { + return { + ...result, + info: tokensBridged[i], + }; + }) + // USDC withdrawals for Arbitrum should be finalized via the CCTP Finalizer. + .filter( + (result) => + result.message !== undefined && + !compareAddressesSimple(result.info.l2TokenAddress, TOKEN_SYMBOLS_MAP["_USDC"].addresses[CHAIN_ID]) + ) + ); } async function getMessageOutboxStatusAndProof( diff --git a/src/finalizer/utils/linea/l1ToL2.ts b/src/finalizer/utils/linea/l1ToL2.ts index c2575ccc7..18760fe4e 100644 --- a/src/finalizer/utils/linea/l1ToL2.ts +++ b/src/finalizer/utils/linea/l1ToL2.ts @@ -40,9 +40,7 @@ export async function lineaL1ToL2Finalizer( ); // Optimize block range for querying Linea's MessageSent events on L1. - // We want to conservatively query for events that are between 0 and 24 hours old - // because Linea L1->L2 messages are claimable after ~20 mins. - const { fromBlock, toBlock } = await getBlockRangeByHoursOffsets(l1ChainId, 24, 0); + const { fromBlock, toBlock } = await getBlockRangeByHoursOffsets(l1ChainId, 24 * 7, 0); logger.debug({ at: "Finalizer#LineaL1ToL2Finalizer", message: "Linea MessageSent event filter", diff --git a/src/finalizer/utils/linea/l2ToL1.ts b/src/finalizer/utils/linea/l2ToL1.ts index f5affc139..6649b7ba7 100644 --- a/src/finalizer/utils/linea/l2ToL1.ts +++ b/src/finalizer/utils/linea/l2ToL1.ts @@ -27,9 +27,8 @@ export async function lineaL2ToL1Finalizer( const getMessagesWithStatusByTxHash = makeGetMessagesWithStatusByTxHash(l2Contract, l1ClaimingService); // Optimize block range for querying relevant source events on L2. - // We want to conservatively query for events that are between 8 and 72 hours old - // because Linea L2->L1 messages are claimable after 6 - 32 hours - const { fromBlock, toBlock } = await getBlockRangeByHoursOffsets(l2ChainId, 72, 8); + // Linea L2->L1 messages are claimable after 6 - 32 hours + const { fromBlock, toBlock } = await getBlockRangeByHoursOffsets(l2ChainId, 24 * 8, 6); logger.debug({ at: "Finalizer#LineaL2ToL1Finalizer", message: "Linea TokensBridged event filter", diff --git a/src/finalizer/utils/opStack.ts b/src/finalizer/utils/opStack.ts index 60602f01a..adaad61ad 100644 --- a/src/finalizer/utils/opStack.ts +++ b/src/finalizer/utils/opStack.ts @@ -5,7 +5,9 @@ import { HubPoolClient, SpokePoolClient } from "../../clients"; import { TokensBridged } from "../../interfaces"; import { BigNumber, + CHAIN_IDs, chainIsOPStack, + compareAddressesSimple, convertFromWei, getBlockForTimestamp, getCachedProvider, @@ -16,6 +18,7 @@ import { getUniqueLogIndex, groupObjectCountsByProp, Signer, + TOKEN_SYMBOLS_MAP, winston, } from "../../utils"; import { Multicall2Call } from "../../common"; @@ -129,22 +132,31 @@ async function getCrossChainMessages( const logIndexesForMessage = getUniqueLogIndex(tokensBridged); return ( - await Promise.all( - tokensBridged.map( - async (l2Event, i) => - ( - await crossChainMessenger.getMessagesByTransaction(l2Event.transactionHash, { - direction: optimismSDK.MessageDirection.L2_TO_L1, - }) - )[logIndexesForMessage[i]] + ( + await Promise.all( + tokensBridged.map( + async (l2Event, i) => + ( + await crossChainMessenger.getMessagesByTransaction(l2Event.transactionHash, { + direction: optimismSDK.MessageDirection.L2_TO_L1, + }) + )[logIndexesForMessage[i]] + ) ) ) - ).map((message, i) => { - return { - message, - event: tokensBridged[i], - }; - }); + .map((message, i) => { + return { + message, + event: tokensBridged[i], + }; + }) + // USDC withdrawals for Base and Optimism should be finalized via the CCTP Finalizer. + .filter( + (e) => + !compareAddressesSimple(e.event.l2TokenAddress, TOKEN_SYMBOLS_MAP["_USDC"].addresses[_chainId]) || + !(_chainId === CHAIN_IDs.BASE || _chainId === CHAIN_IDs.OPTIMISM) + ) + ); } async function getMessageStatuses( diff --git a/src/finalizer/utils/polygon.ts b/src/finalizer/utils/polygon.ts index 4a616dcc5..c8bf962d4 100644 --- a/src/finalizer/utils/polygon.ts +++ b/src/finalizer/utils/polygon.ts @@ -13,6 +13,8 @@ import { getRedisCache, getBlockForTimestamp, getL1TokenInfo, + compareAddressesSimple, + TOKEN_SYMBOLS_MAP, } from "../../utils"; import { EthersError, TokensBridged } from "../../interfaces"; import { HubPoolClient, SpokePoolClient } from "../../clients"; @@ -110,6 +112,12 @@ async function getFinalizableTransactions( const exitStatus = await Promise.all( checkpointedTokensBridged.map(async (_, i) => { const payload = payloads[i]; + const { chainId, l2TokenAddress } = tokensBridged[i]; + + if (compareAddressesSimple(l2TokenAddress, TOKEN_SYMBOLS_MAP._USDC.addresses[chainId])) { + return { status: "NON_CANONICAL_BRIDGE" }; + } + try { // If we can estimate gas for exit transaction call, then we can exit the burn tx, otherwise its likely // been processed. Note this will capture mislabel some exit txns that fail for other reasons as "exit