Skip to content

Commit

Permalink
Merge branch 'master' into npai/wbtc-excess
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholaspai authored May 20, 2024
2 parents 862aee7 + d15f9aa commit c63776d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 12 deletions.
40 changes: 31 additions & 9 deletions src/monitor/Monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
toBN,
toBNWei,
winston,
TOKEN_SYMBOLS_MAP,
} from "../utils";

import { MonitorClients, updateMonitorClients } from "./MonitorClientHelper";
Expand Down Expand Up @@ -265,18 +266,13 @@ export class Monitor {
// Update current balances of all tokens on each supported chain for each relayer.
async updateCurrentRelayerBalances(relayerBalanceReport: RelayerBalanceReport): Promise<void> {
const { hubPoolClient } = this.clients;
const l1Tokens = hubPoolClient.getL1Tokens();
const _l1Tokens = hubPoolClient.getL1Tokens();
for (const relayer of this.monitorConfig.monitoredRelayers) {
for (const chainId of this.monitorChains) {
const l2ToL1Tokens = Object.fromEntries(
l1Tokens
.filter(({ address: l1Token }) => hubPoolClient.l2TokenEnabledForL1Token(l1Token, chainId))
.map((l1Token) => {
const l2Token = hubPoolClient.getL2TokenForL1TokenAtBlock(l1Token.address, chainId);
return [l2Token, l1Token];
})
const l1Tokens = _l1Tokens.filter(({ address: l1Token }) =>
hubPoolClient.l2TokenEnabledForL1Token(l1Token, chainId)
);

const l2ToL1Tokens = this.getL2ToL1TokenMap(l1Tokens, chainId);
const l2TokenAddresses = Object.keys(l2ToL1Tokens);
const tokenBalances = await this._getBalances(
l2TokenAddresses.map((address) => ({
Expand All @@ -300,6 +296,32 @@ export class Monitor {
}
}

// Returns a dictionary of L2 token addresses on this chain to their mapped L1 token info. For example, this
// will return a dictionary for Optimism including WETH, WBTC, USDC, USDC.e, USDT entries where the key is
// the token's Optimism address and the value is the equivalent L1 token info.
protected getL2ToL1TokenMap(l1Tokens: L1Token[], chainId: number): { [l2TokenAddress: string]: L1Token } {
return Object.fromEntries(
l1Tokens
.map((l1Token) => {
// @dev l2TokenSymbols is a list of all keys in TOKEN_SYMBOLS_MAP where the hub chain address is equal to the
// l1 token address.
const l2TokenSymbols = Object.entries(TOKEN_SYMBOLS_MAP)
.filter(
([, { addresses }]) =>
addresses[this.clients.hubPoolClient.chainId]?.toLowerCase() === l1Token.address.toLowerCase()
)
.map(([symbol]) => symbol);

// Create an entry for all L2 tokens that share a symbol with the L1 token. This includes tokens
// like USDC which has multiple L2 tokens mapped to the same L1 token for a given chain ID.
return l2TokenSymbols
.filter((symbol) => TOKEN_SYMBOLS_MAP[symbol].addresses[chainId] !== undefined)
.map((symbol) => [TOKEN_SYMBOLS_MAP[symbol].addresses[chainId], l1Token]);
})
.flat()
);
}

async checkBalances(): Promise<void> {
const { monitoredBalances } = this.monitorConfig;
const balances = await this._getBalances(monitoredBalances);
Expand Down
40 changes: 37 additions & 3 deletions test/Monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { CrossChainTransferClient } from "../src/clients/bridges";
import { spokePoolClientsToProviders } from "../src/common";
import { Dataworker } from "../src/dataworker/Dataworker";
import { BalanceType, V3DepositWithBlock } from "../src/interfaces";
import { BalanceType, L1Token, V3DepositWithBlock } from "../src/interfaces";
import { ALL_CHAINS_NAME, Monitor, REBALANCE_FINALIZE_GRACE_PERIOD } from "../src/monitor/Monitor";
import { MonitorConfig } from "../src/monitor/MonitorConfig";
import { MAX_UINT_VAL, getNetworkName, toBN } from "../src/utils";
Expand All @@ -31,6 +31,20 @@ import {
toBNWei,
} from "./utils";

type TokenMap = { [l2TokenAddress: string]: L1Token };

class TestMonitor extends Monitor {
private overriddenTokenMap: { [chainId: number]: TokenMap } = {};

setL2ToL1TokenMap(chainId: number, map: TokenMap): void {
this.overriddenTokenMap[chainId] = map;
}
// Override internal function that calls into externally defined and hard-coded TOKEN_SYMBOLS_MAP.
protected getL2ToL1TokenMap(l1Tokens: L1Token[], chainId): TokenMap {
return this.overriddenTokenMap[chainId] ?? super.getL2ToL1TokenMap(l1Tokens, chainId);
}
}

describe("Monitor", async function () {
const TEST_NETWORK_NAMES = ["Hardhat1", "Hardhat2", "unknown", ALL_CHAINS_NAME];
let l1Token: Contract, l2Token: Contract, erc20_2: Contract;
Expand Down Expand Up @@ -154,7 +168,7 @@ describe("Monitor", async function () {
adapterManager = new MockAdapterManager(null, null, null, null);
adapterManager.setSupportedChains(chainIds);
crossChainTransferClient = new CrossChainTransferClient(spyLogger, chainIds, adapterManager);
monitorInstance = new Monitor(spyLogger, monitorConfig, {
monitorInstance = new TestMonitor(spyLogger, monitorConfig, {
bundleDataClient,
configStoreClient,
multiCallerClient,
Expand All @@ -163,7 +177,27 @@ describe("Monitor", async function () {
tokenTransferClient,
crossChainTransferClient,
});

(monitorInstance as TestMonitor).setL2ToL1TokenMap(originChainId, {
[l2Token.address]: {
symbol: "L1Token1",
address: l1Token.address,
decimals: 18,
},
});
(monitorInstance as TestMonitor).setL2ToL1TokenMap(destinationChainId, {
[erc20_2.address]: {
symbol: "L1Token1",
address: l1Token.address,
decimals: 18,
},
});
(monitorInstance as TestMonitor).setL2ToL1TokenMap(hubPoolClient.chainId, {
[l1Token.address]: {
symbol: "L1Token1",
address: l1Token.address,
decimals: 18,
},
});
await updateAllClients();
});

Expand Down

0 comments on commit c63776d

Please sign in to comment.