diff --git a/src/monitor/Monitor.ts b/src/monitor/Monitor.ts index d1dd769165..5cf38541be 100644 --- a/src/monitor/Monitor.ts +++ b/src/monitor/Monitor.ts @@ -109,7 +109,8 @@ export class Monitor { readonly monitorConfig: MonitorConfig, readonly clients: MonitorClients ) { - this.crossChainAdapterSupportedChains = clients.crossChainTransferClient.adapterManager.supportedChains(); + // Both clients have the same supported chains. Use either. + this.crossChainAdapterSupportedChains = clients.protocolTransferClient.adapterManager.supportedChains(); this.monitorChains = Object.values(clients.spokePoolClients).map(({ chainId }) => chainId); for (const chainId of this.monitorChains) { this.spokePoolsBlocks[chainId] = { startingBlock: undefined, endingBlock: undefined }; @@ -1009,7 +1010,7 @@ export class Monitor { // But this should be okay as we should address any stuck transactions immediately so realistically no transfers // should stay unstuck for longer than one bundle. async checkStuckRebalances(): Promise { - const { crossChainTransferClient, hubPoolClient, spokePoolClients } = this.clients; + const { protocolTransferClient, hubPoolClient, spokePoolClients } = this.clients; const { currentTime, latestHeightSearched } = hubPoolClient; const lastFullyExecutedBundle = hubPoolClient.getLatestFullyExecutedRootBundle(latestHeightSearched); // This case shouldn't happen outside of tests as Across V2 has already launched. @@ -1075,17 +1076,15 @@ export class Monitor { // Outstanding transfers are mapped to either the spoke pool or the hub pool, depending on which // chain events are queried. Some only allow us to index on the fromAddress, the L1 originator or the // HubPool, while others only allow us to index on the toAddress, the L2 recipient or the SpokePool. - const transferBalance = crossChainTransferClient + const transferBalance = protocolTransferClient .getOutstandingCrossChainTransferAmount(spokePoolAddress, chainId, l1Token.address) - .add( - crossChainTransferClient.getOutstandingCrossChainTransferAmount(hubPoolAddress, chainId, l1Token.address) - ); + .add(protocolTransferClient.getOutstandingCrossChainTransferAmount(hubPoolAddress, chainId, l1Token.address)); const outstandingDepositTxs = blockExplorerLinks( - crossChainTransferClient.getOutstandingCrossChainTransferTxs(spokePoolAddress, chainId, l1Token.address), + protocolTransferClient.getOutstandingCrossChainTransferTxs(spokePoolAddress, chainId, l1Token.address), hubPoolClient.chainId ).concat( blockExplorerLinks( - crossChainTransferClient.getOutstandingCrossChainTransferTxs(hubPoolAddress, chainId, l1Token.address), + protocolTransferClient.getOutstandingCrossChainTransferTxs(hubPoolAddress, chainId, l1Token.address), hubPoolClient.chainId ) ); @@ -1238,7 +1237,7 @@ export class Monitor { } updateCrossChainTransfers(relayer: Address, relayerBalanceTable: RelayerBalanceTable): void { - const { crossChainTransferClient } = this.clients; + const { relayerTransferClient } = this.clients; const allL1Tokens = this.getL1TokensForRelayerBalancesReport(); const supportedChains = this.crossChainAdapterSupportedChains.filter((chainId) => this.monitorChains.includes(chainId) @@ -1249,7 +1248,7 @@ export class Monitor { for (const l2Token of l2TokenAddresses) { const tokenInfo = l2ToL1Tokens[l2Token]; - const bridgedTransferBalance = crossChainTransferClient.getOutstandingCrossChainTransferAmount( + const bridgedTransferBalance = relayerTransferClient.getOutstandingCrossChainTransferAmount( relayer, chainId, tokenInfo.address, @@ -1267,7 +1266,7 @@ export class Monitor { } async updatePendingL2Withdrawals(relayer: Address, relayerBalanceTable: RelayerBalanceTable): Promise { - const { adapterManager } = this.clients.crossChainTransferClient; + const { adapterManager } = this.clients.relayerTransferClient; const allL1Tokens = this.getL1TokensForRelayerBalancesReport(); const supportedChains = this.crossChainAdapterSupportedChains.filter( (chainId) => this.monitorChains.includes(chainId) && chainId !== CHAIN_IDs.BSC // @todo temporarily skip BSC as the following diff --git a/src/monitor/MonitorClientHelper.ts b/src/monitor/MonitorClientHelper.ts index 32bc457621..e83eb5d375 100644 --- a/src/monitor/MonitorClientHelper.ts +++ b/src/monitor/MonitorClientHelper.ts @@ -1,5 +1,5 @@ import { MonitorConfig } from "./MonitorConfig"; -import { Signer, winston, assert, isEVMSpokePoolClient, toAddressType } from "../utils"; +import { EvmAddress, Signer, winston, assert, isEVMSpokePoolClient } from "../utils"; import { BundleDataClient, HubPoolClient, TokenTransferClient } from "../clients"; import { Clients, @@ -15,8 +15,9 @@ import { RebalancerClient } from "../rebalancer/utils/interfaces"; export interface MonitorClients extends Clients { bundleDataClient: BundleDataClient; - crossChainTransferClient: CrossChainTransferClient; hubPoolClient: HubPoolClient; + protocolTransferClient: CrossChainTransferClient; + relayerTransferClient: CrossChainTransferClient; rebalancerClient?: RebalancerClient; spokePoolClients: SpokePoolClientsByChain; tokenTransferClient: TokenTransferClient; @@ -59,13 +60,18 @@ export async function constructMonitorClients( // Need to update HubPoolClient to get latest tokens. const spokePoolAddresses = Object.values(spokePoolClients).map((client) => client.spokePoolAddress); - // Cross-chain transfers will originate from the HubPool's address and target SpokePool addresses, so - // track both. - const adapterManager = new AdapterManager(logger, spokePoolClients, hubPoolClient, [ - toAddressType(signerAddr, hubPoolClient.chainId), - toAddressType(hubPoolClient.hubPool.address, hubPoolClient.chainId), + const hubPoolAddress = EvmAddress.from(hubPoolClient.hubPool.address); + const signerAddress = EvmAddress.from(signerAddr); + + // Protocol: tracks HubPool -> SpokePool rebalances. + const protocolAdapterManager = new AdapterManager(logger, spokePoolClients, hubPoolClient, [ + hubPoolAddress, ...spokePoolAddresses, ]); + + // Relayer: tracks EOA cross-chain transfers. + const relayerAdapterManager = new AdapterManager(logger, spokePoolClients, hubPoolClient, [signerAddress]); + const spokePoolChains = Object.keys(spokePoolClients).map((chainId) => Number(chainId)); const providerPerChain = Object.fromEntries( spokePoolChains @@ -79,23 +85,21 @@ export async function constructMonitorClients( const tokenTransferClient = new TokenTransferClient(logger, providerPerChain, config.monitoredRelayers); // The CrossChainTransferClient is dependent on having adapters for all passed in chains - // so we need to filter out any chains that don't have adapters. This means limiting the chains we keep in - // `providerPerChain` when constructing the TokenTransferClient and limiting `spokePoolChains` when constructing - // the CrossChainTransferClient. - const crossChainAdapterSupportedChains = adapterManager.supportedChains(); - const crossChainTransferClient = new CrossChainTransferClient( - logger, - spokePoolChains.filter((chainId) => crossChainAdapterSupportedChains.includes(chainId)), - adapterManager + // so we need to filter out any chains that don't have adapters. + const filteredChains = spokePoolChains.filter((chainId) => + protocolAdapterManager.supportedChains().includes(chainId) ); + const protocolTransferClient = new CrossChainTransferClient(logger, filteredChains, protocolAdapterManager); + const relayerTransferClient = new CrossChainTransferClient(logger, filteredChains, relayerAdapterManager); // Load RebalancerClient in view only mode so that getPendingRebalances() can get called. const rebalancerClient = await constructReadOnlyRebalancerClient(logger, baseSigner); return { ...commonClients, bundleDataClient, - crossChainTransferClient, + protocolTransferClient, rebalancerClient, + relayerTransferClient, spokePoolClients, tokenTransferClient, }; @@ -110,5 +114,8 @@ export async function updateMonitorClients(clients: MonitorClients): Promise l1Token.address); - await clients.crossChainTransferClient.update(allL1Tokens); + await Promise.all([ + clients.protocolTransferClient.update(allL1Tokens), + clients.relayerTransferClient.update(allL1Tokens), + ]); } diff --git a/test/Monitor.ts b/test/Monitor.ts index 26055a1268..49e71b9743 100644 --- a/test/Monitor.ts +++ b/test/Monitor.ts @@ -90,8 +90,10 @@ describe("Monitor", async function () { let tokenTransferClient: TokenTransferClient; let monitorInstance: Monitor; let spokePoolClients: { [chainId: number]: SpokePoolClient }; - let crossChainTransferClient: CrossChainTransferClient; - let adapterManager: MockAdapterManager; + let protocolTransferClient: CrossChainTransferClient; + let relayerTransferClient: CrossChainTransferClient; + let protocolAdapterManager: MockAdapterManager; + let relayerAdapterManager: MockAdapterManager; let defaultMonitorEnvVars: Record; let updateAllClients: () => Promise; let relayerAddress; @@ -201,9 +203,14 @@ describe("Monitor", async function () { ); tokenTransferClient = new TokenTransferClient(spyLogger, providers, [relayerAddress]); - adapterManager = new MockAdapterManager(null, null, null, null); - adapterManager.setSupportedChains(chainIds); - crossChainTransferClient = new CrossChainTransferClient(spyLogger, chainIds, adapterManager); + protocolAdapterManager = new MockAdapterManager(null, null, null, null); + protocolAdapterManager.setSupportedChains(chainIds); + protocolTransferClient = new CrossChainTransferClient(spyLogger, chainIds, protocolAdapterManager); + + relayerAdapterManager = new MockAdapterManager(null, null, null, null); + relayerAdapterManager.setSupportedChains(chainIds); + relayerTransferClient = new CrossChainTransferClient(spyLogger, chainIds, relayerAdapterManager); + monitorInstance = new TestMonitor(spyLogger, monitorConfig, { bundleDataClient, configStoreClient, @@ -211,7 +218,8 @@ describe("Monitor", async function () { hubPoolClient, spokePoolClients, tokenTransferClient, - crossChainTransferClient, + protocolTransferClient, + relayerTransferClient, }); (monitorInstance as TestMonitor).setL2ToL1TokenMap(originChainId, { [l2Token.address]: { @@ -306,7 +314,7 @@ describe("Monitor", async function () { ); // Simulate some pending cross chain transfers. - crossChainTransferClient.increaseOutstandingTransfer( + relayerTransferClient.increaseOutstandingTransfer( relayerAddress, toAddressType(l1Token.address, hubPoolClient.chainId), toAddressType(erc20_2.address, destinationChainId), @@ -379,7 +387,7 @@ describe("Monitor", async function () { await hubPool.setCurrentTime(Number(await hubPool.getCurrentTime()) + REBALANCE_FINALIZE_GRACE_PERIOD + 1); // Simulate some pending cross chain transfers to SpokePools. - adapterManager.setMockedOutstandingCrossChainTransfers( + protocolAdapterManager.setMockedOutstandingCrossChainTransfers( originChainId, toAddressType(spokePool_1.address, originChainId), toAddressType(l1Token.address, hubPoolClient.chainId),