From 4d42f7f5963c1e4bfe79a8d2fb467747d0fe79ca Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:27:08 -0400 Subject: [PATCH] improve(relayer): Clear out token data explicitly and log token balances (#983) * improve(relayer): Clear out token data explicitly and log token balances Based on an issue we're seeing where L1 to L2 rebalances are still getting duplicated, even after wrapping ETH, perhaps suggesting that the `tokenClient` is using stale data the logic written [here](https://github.com/across-protocol/relayer-v2/blob/master/src/relayer/RelayerClientHelper.ts#L159) should be reading updated balances post-ETH-unwrap but it may not. This PR adds more logs we can use to better debug * Update InventoryClient.ts * Update RelayerConfig.ts --- src/clients/InventoryClient.ts | 4 +++- src/clients/TokenClient.ts | 19 ++++++++++++++++++- src/clients/bridges/ArbitrumAdapter.ts | 7 +++++++ src/clients/bridges/ZKSyncAdapter.ts | 7 +++++++ .../bridges/op-stack/OpStackAdapter.ts | 7 +++++++ src/relayer/RelayerClientHelper.ts | 1 + src/relayer/RelayerConfig.ts | 2 +- 7 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/clients/InventoryClient.ts b/src/clients/InventoryClient.ts index 95d078442..ffca512bc 100644 --- a/src/clients/InventoryClient.ts +++ b/src/clients/InventoryClient.ts @@ -634,7 +634,9 @@ export class InventoryClient { } async wrapL2EthIfAboveThreshold(): Promise { - if (!this.isInventoryManagementEnabled()) { + // If inventoryConfig is defined, there will be a default wrapEtherTarget and wrapEtherThreshold + // set by RelayerConfig.ts + if (!this?.inventoryConfig) { return; } this.log("Checking ETH->WETH Wrap status"); diff --git a/src/clients/TokenClient.ts b/src/clients/TokenClient.ts index ffaec0934..0ae198946 100644 --- a/src/clients/TokenClient.ts +++ b/src/clients/TokenClient.ts @@ -123,6 +123,10 @@ export class TokenClient { this.tokenShortfall = {}; } + clearTokenData(): void { + this.tokenData = {}; + } + async setOriginTokenApprovals(): Promise { const tokensToApprove: { chainId: number; token: string }[] = []; Object.entries(this.tokenData).forEach(([_chainId, tokenMap]) => { @@ -191,7 +195,20 @@ export class TokenClient { } } - this.logger.debug({ at: "TokenBalanceClient", message: "TokenBalance client updated!" }); + // Remove allowance from token data when logging. + const balanceData = Object.fromEntries( + Object.entries(this.tokenData).map(([chainId, tokenData]) => { + return [ + chainId, + Object.fromEntries( + Object.entries(tokenData).map(([token, { balance }]) => { + return [token, balance]; + }) + ), + ]; + }) + ); + this.logger.debug({ at: "TokenBalanceClient", message: "TokenBalance client updated!", balanceData }); } async fetchTokenData(spokePoolClient: SpokePoolClient): Promise<{ diff --git a/src/clients/bridges/ArbitrumAdapter.ts b/src/clients/bridges/ArbitrumAdapter.ts index 68598f5aa..be533f377 100644 --- a/src/clients/bridges/ArbitrumAdapter.ts +++ b/src/clients/bridges/ArbitrumAdapter.ts @@ -214,6 +214,13 @@ export class ArbitrumAdapter extends BaseAdapter { const value = ethBalance.sub(target); this.logger.debug({ at: this.getName(), message: "Wrapping ETH", threshold, target, value, ethBalance }); return await this._wrapEthIfAboveThreshold(threshold, contract, value, simMode); + } else { + this.logger.debug({ + at: this.getName(), + message: "ETH balance below threhsold", + threshold, + ethBalance, + }); } return null; } diff --git a/src/clients/bridges/ZKSyncAdapter.ts b/src/clients/bridges/ZKSyncAdapter.ts index 9a6214005..a796a5291 100644 --- a/src/clients/bridges/ZKSyncAdapter.ts +++ b/src/clients/bridges/ZKSyncAdapter.ts @@ -246,6 +246,13 @@ export class ZKSyncAdapter extends BaseAdapter { const value = ethBalance.sub(target); this.logger.debug({ at: this.getName(), message: "Wrapping ETH", threshold, target, value, ethBalance }); return await this._wrapEthIfAboveThreshold(threshold, contract, value, simMode); + } else { + this.logger.debug({ + at: this.getName(), + message: "ETH balance below threhsold", + threshold, + ethBalance, + }); } return null; } diff --git a/src/clients/bridges/op-stack/OpStackAdapter.ts b/src/clients/bridges/op-stack/OpStackAdapter.ts index c5f2fe268..dcf2c6abf 100644 --- a/src/clients/bridges/op-stack/OpStackAdapter.ts +++ b/src/clients/bridges/op-stack/OpStackAdapter.ts @@ -154,6 +154,13 @@ export class OpStackAdapter extends BaseAdapter { const value = ethBalance.sub(target); this.logger.debug({ at: this.getName(), message: "Wrapping ETH", threshold, target, value, ethBalance }); return await this._wrapEthIfAboveThreshold(threshold, contract, value, simMode); + } else { + this.logger.debug({ + at: this.getName(), + message: "ETH balance below threhsold", + threshold, + ethBalance, + }); } return null; } diff --git a/src/relayer/RelayerClientHelper.ts b/src/relayer/RelayerClientHelper.ts index b995a9d8f..3b956667e 100644 --- a/src/relayer/RelayerClientHelper.ts +++ b/src/relayer/RelayerClientHelper.ts @@ -158,6 +158,7 @@ export async function updateRelayerClients(clients: RelayerClients, config: Rela // Update the token client after the inventory client has done its wrapping of L2 ETH to ensure latest WETH ballance. // The token client needs route data, so wait for update before checking approvals. + clients.tokenClient.clearTokenData(); await clients.tokenClient.update(); if (config.sendingRelaysEnabled) { await clients.tokenClient.setOriginTokenApprovals(); diff --git a/src/relayer/RelayerConfig.ts b/src/relayer/RelayerConfig.ts index d569ff863..32de7fedb 100644 --- a/src/relayer/RelayerConfig.ts +++ b/src/relayer/RelayerConfig.ts @@ -108,7 +108,7 @@ export class RelayerConfig extends CommonConfig { ); } }); - Object.keys(this.inventoryConfig.tokenConfig).forEach((l1Token) => { + Object.keys(this.inventoryConfig?.tokenConfig ?? {}).forEach((l1Token) => { Object.keys(this.inventoryConfig.tokenConfig[l1Token]).forEach((chainId) => { const { targetPct, thresholdPct, unwrapWethThreshold, unwrapWethTarget } = this.inventoryConfig.tokenConfig[l1Token][chainId];