From 13ec536217c69923b9d5e99f109162e6401b8ed0 Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Sun, 19 May 2024 17:10:02 -0400 Subject: [PATCH] fix(Finalizer): Dedup transaction hash list when creating list of transactions to query for CCTP l2->l1 transactions (#1535) --- src/finalizer/utils/arbitrum.ts | 2 +- src/finalizer/utils/cctp/l1ToL2.ts | 4 +--- src/finalizer/utils/cctp/l2ToL1.ts | 27 +++++++++++++++++++-------- src/finalizer/utils/opStack.ts | 2 +- src/finalizer/utils/polygon.ts | 2 +- src/finalizer/utils/zkSync.ts | 2 +- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/finalizer/utils/arbitrum.ts b/src/finalizer/utils/arbitrum.ts index 2f7e178d6..c6c013129 100644 --- a/src/finalizer/utils/arbitrum.ts +++ b/src/finalizer/utils/arbitrum.ts @@ -30,7 +30,7 @@ export async function arbitrumOneFinalizer( // Arbitrum takes 7 days to finalize withdrawals, so don't look up events younger than that. const redis = await getRedisCache(logger); const [fromBlock, toBlock] = await Promise.all([ - getBlockForTimestamp(chainId, getCurrentTime() - 9 * 60 * 60 * 24, undefined, redis), + getBlockForTimestamp(chainId, getCurrentTime() - 14 * 60 * 60 * 24, undefined, redis), getBlockForTimestamp(chainId, getCurrentTime() - 7 * 60 * 60 * 24, undefined, redis), ]); logger.debug({ diff --git a/src/finalizer/utils/cctp/l1ToL2.ts b/src/finalizer/utils/cctp/l1ToL2.ts index 3f012a557..e9769f398 100644 --- a/src/finalizer/utils/cctp/l1ToL2.ts +++ b/src/finalizer/utils/cctp/l1ToL2.ts @@ -32,9 +32,7 @@ export async function cctpL1toL2Finalizer( spokePoolClient: SpokePoolClient, l1ToL2AddressesToFinalize: string[] ): Promise { - // Let's just assume for now CCTP transfers don't take longer than 1 day and can - // happen very quickly. - const lookback = getCurrentTime() - 60 * 60 * 24; + const lookback = getCurrentTime() - 60 * 60 * 24 * 7; const redis = await getRedisCache(logger); const fromBlock = await getBlockForTimestamp(hubPoolClient.chainId, lookback, undefined, redis); logger.debug({ diff --git a/src/finalizer/utils/cctp/l2ToL1.ts b/src/finalizer/utils/cctp/l2ToL1.ts index 878340ddc..b7f0bd535 100644 --- a/src/finalizer/utils/cctp/l2ToL1.ts +++ b/src/finalizer/utils/cctp/l2ToL1.ts @@ -6,7 +6,9 @@ import { CONTRACT_ADDRESSES, Multicall2Call, chainIdsToCctpDomains } from "../.. import { Contract, Signer, + TOKEN_SYMBOLS_MAP, assert, + compareAddressesSimple, getBlockForTimestamp, getCurrentTime, getNetworkName, @@ -24,9 +26,7 @@ export async function cctpL2toL1Finalizer( hubPoolClient: HubPoolClient, spokePoolClient: SpokePoolClient ): Promise { - // Let's just assume for now CCTP transfers don't take longer than 1 day and can - // happen very quickly. - const lookback = getCurrentTime() - 60 * 60 * 24; + const lookback = getCurrentTime() - 60 * 60 * 24 * 7; const redis = await getRedisCache(logger); const fromBlock = await getBlockForTimestamp(hubPoolClient.chainId, lookback, undefined, redis); logger.debug({ @@ -67,14 +67,25 @@ async function resolveRelatedTxnReceipts( targetDestinationChainId: number, latestBlockToFinalize: number ): Promise { + const sourceChainId = client.chainId; + // Dedup the txnReceipt list because there might be multiple tokens bridged events in the same txn hash. + + const uniqueTxnHashes = new Set(); + client + .getTokensBridged() + .filter( + (bridgeEvent) => + bridgeEvent.blockNumber >= latestBlockToFinalize && + compareAddressesSimple(bridgeEvent.l2TokenAddress, TOKEN_SYMBOLS_MAP._USDC.addresses[sourceChainId]) + ) + .forEach((bridgeEvent) => uniqueTxnHashes.add(bridgeEvent.transactionHash)); + // Resolve the receipts to all collected txns const txnReceipts = await Promise.all( - client - .getTokensBridged() - .filter((bridgeEvent) => bridgeEvent.blockNumber >= latestBlockToFinalize) - .map((bridgeEvent) => client.spokePool.provider.getTransactionReceipt(bridgeEvent.transactionHash)) + Array.from(uniqueTxnHashes).map((hash) => client.spokePool.provider.getTransactionReceipt(hash)) ); - return resolveCCTPRelatedTxns(txnReceipts, client.chainId, targetDestinationChainId); + + return resolveCCTPRelatedTxns(txnReceipts, sourceChainId, targetDestinationChainId); } /** diff --git a/src/finalizer/utils/opStack.ts b/src/finalizer/utils/opStack.ts index 1865bde3c..60602f01a 100644 --- a/src/finalizer/utils/opStack.ts +++ b/src/finalizer/utils/opStack.ts @@ -53,8 +53,8 @@ export async function opStackFinalizer( // - Don't try to withdraw tokens that are not past the 7 day challenge period const redis = await getRedisCache(logger); const [earliestBlockToFinalize, latestBlockToProve] = await Promise.all([ + getBlockForTimestamp(chainId, getCurrentTime() - 14 * 60 * 60 * 24, undefined, redis), getBlockForTimestamp(chainId, getCurrentTime() - 7 * 60 * 60 * 24, undefined, redis), - getBlockForTimestamp(chainId, getCurrentTime() - 60 * 60 * 24, undefined, redis), ]); const { recentTokensBridgedEvents = [], olderTokensBridgedEvents = [] } = groupBy( spokePoolClient.getTokensBridged(), diff --git a/src/finalizer/utils/polygon.ts b/src/finalizer/utils/polygon.ts index 5b6212278..4a616dcc5 100644 --- a/src/finalizer/utils/polygon.ts +++ b/src/finalizer/utils/polygon.ts @@ -46,7 +46,7 @@ export async function polygonFinalizer( const { chainId } = spokePoolClient; const posClient = await getPosClient(signer); - const lookback = getCurrentTime() - 60 * 60 * 24; + const lookback = getCurrentTime() - 60 * 60 * 24 * 7; const redis = await getRedisCache(logger); const fromBlock = await getBlockForTimestamp(chainId, lookback, undefined, redis); diff --git a/src/finalizer/utils/zkSync.ts b/src/finalizer/utils/zkSync.ts index 7326f6f15..88305d9c5 100644 --- a/src/finalizer/utils/zkSync.ts +++ b/src/finalizer/utils/zkSync.ts @@ -47,7 +47,7 @@ export async function zkSyncFinalizer( // older than 2 days and earlier than 1 day. const redis = await getRedisCache(logger); const [fromBlock, toBlock] = await Promise.all([ - getBlockForTimestamp(l2ChainId, getCurrentTime() - 2 * 60 * 60 * 24, undefined, redis), + getBlockForTimestamp(l2ChainId, getCurrentTime() - 8 * 60 * 60 * 24, undefined, redis), getBlockForTimestamp(l2ChainId, getCurrentTime() - 1 * 60 * 60 * 24, undefined, redis), ]); logger.debug({