Skip to content

Commit

Permalink
chore: Update after HubPool Hub <-> Spoke token updates (#1118)
Browse files Browse the repository at this point in the history
This bumps sdk-v2 and constants-v2. The main impact is a change in the 
way token addresses are resolved between SpokePools and the HubPool. No
functional change is intended; I have verified recent bundles locally 
and no regressions were observed.
  • Loading branch information
pxrl authored Jan 3, 2024
1 parent 7d50d21 commit f28382c
Show file tree
Hide file tree
Showing 19 changed files with 101 additions and 81 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"node": ">=16.18.0"
},
"dependencies": {
"@across-protocol/constants-v2": "1.0.7",
"@across-protocol/constants-v2": "1.0.8",
"@across-protocol/contracts-v2": "2.4.7",
"@across-protocol/sdk-v2": "0.18.0",
"@across-protocol/sdk-v2": "0.19.0",
"@arbitrum/sdk": "^3.1.3",
"@defi-wonderland/smock": "^2.3.5",
"@eth-optimism/sdk": "^3.1.0",
Expand Down
13 changes: 7 additions & 6 deletions src/clients/InventoryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class InventoryClient {
}

getDestinationTokenForL1Token(l1Token: string, chainId: number | string): string {
return this.hubPoolClient.getDestinationTokenForL1Token(l1Token, Number(chainId));
return this.hubPoolClient.getL2TokenForL1TokenAtBlock(l1Token, Number(chainId));
}

getEnabledChains(): number[] {
Expand Down Expand Up @@ -184,14 +184,15 @@ export class InventoryClient {
// If this number of more than the target for the designation chain + rebalance overshoot then refund on L1.
// Else, the post fill amount is within the target, so refund on the destination chain.
async determineRefundChainId(deposit: Deposit, l1Token?: string): Promise<number> {
const { amount, destinationChainId } = deposit;
const { originChainId, originToken, amount, destinationChainId } = deposit;
const hubChainId = this.hubPoolClient.chainId;

// Always refund on L1 if the transfer is to L1.
if (!this.isInventoryManagementEnabled() || destinationChainId === this.hubPoolClient.chainId) {
if (!this.isInventoryManagementEnabled() || destinationChainId === hubChainId) {
return destinationChainId;
}

l1Token ??= this.hubPoolClient.getL1TokenForDeposit(deposit);
l1Token ??= this.hubPoolClient.getL1TokenForL2TokenAtBlock(originToken, originChainId);

// If there is no inventory config for this token or this token and destination chain the return the destination chain.
if (
Expand All @@ -214,7 +215,7 @@ export class InventoryClient {
} catch (e) {
// Fallback to getting refunds on Mainnet if calculating bundle refunds goes wrong.
// Inventory management can always rebalance from Mainnet to other chains easily if needed.
return this.hubPoolClient.chainId;
return hubChainId;
}

// Add upcoming refunds going to this destination chain.
Expand All @@ -236,7 +237,7 @@ export class InventoryClient {
// If the post relay allocation, considering funds in transit, is larger than the target threshold then refund on L1
// Else, refund on destination chian to keep funds within the target.
const targetPct = toBN(this.inventoryConfig.tokenConfig[l1Token][destinationChainId].targetPct);
const refundChainId = expectedPostRelayAllocation.gt(targetPct) ? this.hubPoolClient.chainId : destinationChainId;
const refundChainId = expectedPostRelayAllocation.gt(targetPct) ? hubChainId : destinationChainId;

this.log("Evaluated refund Chain", {
chainShortfall,
Expand Down
2 changes: 1 addition & 1 deletion src/clients/ProfitClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ export class ProfitClient {
const destinationToken =
destinationChainId === hubPoolClient.chainId
? hubToken
: hubPoolClient.getDestinationTokenForL1Token(hubToken, destinationChainId);
: hubPoolClient.getL2TokenForL1TokenAtBlock(hubToken, destinationChainId);
assert(isDefined(destinationToken), `Chain ${destinationChainId} SpokePool is not configured for ${testSymbol}`);

const deposit: Deposit = {
Expand Down
4 changes: 2 additions & 2 deletions src/clients/bridges/AdapterManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ export class AdapterManager {
try {
// That the line below is critical. if the hubpoolClient returns the wrong destination token for the L1 token then
// the bot can irrecoverably send the wrong token to the chain and loose money. It should crash if this is detected.
const l2TokenForL1Token = this.hubPoolClient.getDestinationTokenForL1Token(l1Token, chainId);
const l2TokenForL1Token = this.hubPoolClient.getL2TokenForL1TokenAtBlock(l1Token, chainId);
if (!l2TokenForL1Token) {
throw new Error(`No L2 token found for L1 token ${l1Token} on chain ${chainId}`);
}
if (l2TokenForL1Token !== getL2TokenAddresses(l1Token)[chainId]) {
throw new Error("Mismatch tokens!");
throw new Error(`Token address mismatch (${l2TokenForL1Token} != ${getL2TokenAddresses(l1Token)[chainId]})`);
}
return l2TokenForL1Token;
} catch (error) {
Expand Down
9 changes: 3 additions & 6 deletions src/dataworker/DataworkerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ export function _buildRelayerRefundRoot(
// net send amount value if the net send amount is negative.
let amountToReturn = bnZero;
if (!isUBA) {
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenCounterpartAtBlock(
repaymentChainId,
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenForL2TokenAtBlock(
l2TokenAddress,
repaymentChainId,
endBlockForMainnet
);

Expand Down Expand Up @@ -259,10 +259,7 @@ export function _buildRelayerRefundRoot(
return;
}

const l2TokenCounterpart = clients.hubPoolClient.getDestinationTokenForL1Token(
leaf.l1Tokens[index],
leaf.chainId
);
const l2TokenCounterpart = clients.hubPoolClient.getL2TokenForL1TokenAtBlock(leaf.l1Tokens[index], leaf.chainId);
// If we've already seen this leaf, then skip. If UBA, reset the net send amount and then skip.
const existingLeaf = relayerRefundLeaves.find(
(relayerRefundLeaf) =>
Expand Down
20 changes: 10 additions & 10 deletions src/dataworker/PoolRebalanceUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ export function updateRunningBalanceForFill(
fill: interfaces.FillWithBlock,
updateAmount: BigNumber
): void {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
fill.destinationChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
fill.destinationToken,
fill.destinationChainId,
endBlockForMainnet
);
updateRunningBalance(runningBalances, fill.destinationChainId, l1TokenCounterpart, updateAmount);
Expand All @@ -71,9 +71,9 @@ export function updateRunningBalanceForDeposit(
deposit: interfaces.DepositWithBlock,
updateAmount: BigNumber
): void {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
deposit.originChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
deposit.originToken,
deposit.originChainId,
deposit.quoteBlockNumber
);
updateRunningBalance(runningBalances, deposit.originChainId, l1TokenCounterpart, updateAmount);
Expand All @@ -89,9 +89,9 @@ export function updateRunningBalanceForEarlyDeposit(
const originChainId = Number(deposit.args[1].toString());
const originToken = deposit.args[6];

const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
originChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
originToken,
originChainId,
// TODO: this must be handled s.t. it doesn't depend on when this is run.
// For now, tokens do not change their mappings often, so this will work, but
// to keep the system resilient, this must be updated.
Expand Down Expand Up @@ -131,9 +131,9 @@ export function initializeRunningBalancesFromRelayerRepayments(
const repaymentChainId = Number(_repaymentChainId);
Object.entries(fillsForChain).forEach(
([l2TokenAddress, { realizedLpFees: totalRealizedLpFee, totalRefundAmount }]) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
repaymentChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
l2TokenAddress,
repaymentChainId,
latestMainnetBlock
);

Expand All @@ -160,9 +160,9 @@ export function addSlowFillsToRunningBalances(
unfilledDeposits: UnfilledDeposit[]
): void {
unfilledDeposits.forEach((unfilledDeposit) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
unfilledDeposit.deposit.originChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
unfilledDeposit.deposit.originToken,
unfilledDeposit.deposit.originChainId,
latestMainnetBlock
);
updateRunningBalance(
Expand Down
8 changes: 4 additions & 4 deletions src/finalizer/utils/arbitrum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ async function multicallArbitrumFinalizations(
): Promise<{ callData: Multicall2Call[]; withdrawals: Withdrawal[] }> {
const finalizableMessages = await getFinalizableMessages(logger, tokensBridged, hubSigner);
const callData = await Promise.all(finalizableMessages.map((message) => finalizeArbitrum(message.message)));
const withdrawals = finalizableMessages.map((message) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
const withdrawals = finalizableMessages.map(({ info: { l2TokenAddress, amountToReturn } }) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
l2TokenAddress,
CHAIN_ID,
message.info.l2TokenAddress,
hubPoolClient.latestBlockSearched
);
const l1TokenInfo = hubPoolClient.getTokenInfo(1, l1TokenCounterpart);
const amountFromWei = convertFromWei(message.info.amountToReturn.toString(), l1TokenInfo.decimals);
const amountFromWei = convertFromWei(amountToReturn.toString(), l1TokenInfo.decimals);
const withdrawal: Withdrawal = {
l2ChainId: CHAIN_ID,
l1TokenSymbol: l1TokenInfo.symbol,
Expand Down
10 changes: 5 additions & 5 deletions src/finalizer/utils/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,14 @@ async function multicallPolygonFinalizations(
)
);
callData.push(...callDataRetrievals);
const withdrawals = finalizableMessages.map((message) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
const withdrawals = finalizableMessages.map(({ l2TokenAddress, amountToReturn }) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
l2TokenAddress,
CHAIN_ID,
message.l2TokenAddress,
hubPoolClient.latestBlockSearched
);
const l1TokenInfo = hubPoolClient.getTokenInfo(1, l1TokenCounterpart);
const amountFromWei = convertFromWei(message.amountToReturn.toString(), l1TokenInfo.decimals);
const amountFromWei = convertFromWei(amountToReturn.toString(), l1TokenInfo.decimals);
const withdrawal: Withdrawal = {
l2ChainId: CHAIN_ID,
l1TokenSymbol: l1TokenInfo.symbol,
Expand All @@ -208,7 +208,7 @@ async function retrieveTokenFromMainnetTokenBridger(
mainnetSigner: Signer,
hubPoolClient: HubPoolClient
): Promise<Multicall2Call> {
const l1Token = hubPoolClient.getL1TokenCounterpartAtBlock(CHAIN_ID, l2Token, hubPoolClient.latestBlockSearched);
const l1Token = hubPoolClient.getL1TokenForL2TokenAtBlock(l2Token, CHAIN_ID, hubPoolClient.latestBlockSearched);
const mainnetTokenBridger = getMainnetTokenBridger(mainnetSigner);
const callData = await mainnetTokenBridger.populateTransaction.retrieve(l1Token);
return {
Expand Down
3 changes: 1 addition & 2 deletions src/finalizer/utils/zkSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ export async function zkSyncFinalizer(
const txns = await prepareFinalizations(l1ChainId, l2ChainId, withdrawalParams);

const withdrawals = candidates.map(({ l2TokenAddress, amountToReturn }) => {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
l2ChainId,
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
l2TokenAddress,
hubPoolClient.latestBlockSearched
);
Expand Down
35 changes: 28 additions & 7 deletions src/monitor/Monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,17 @@ export class Monitor {
},
])
);
const { hubPoolClient } = this.clients;
const l1Tokens = hubPoolClient.getL1Tokens().map(({ address }) => address);
const tokensPerChain = Object.fromEntries(
this.monitorChains.map((chainId) => {
const l2Tokens = this.clients.hubPoolClient.getDestinationTokensToL1TokensForChainId(chainId);
return [chainId, Object.keys(l2Tokens)];
const l2Tokens = l1Tokens
.filter((l1Token) => hubPoolClient.l2TokenEnabledForL1Token(l1Token, chainId))
.map((l1Token) => {
const l2Token = hubPoolClient.getL2TokenForL1TokenAtBlock(l1Token, chainId);
return l2Token;
});
return [chainId, l2Tokens];
})
);
await this.clients.tokenTransferClient.update(searchConfigs, tokensPerChain);
Expand All @@ -125,7 +132,7 @@ export class Monitor {
return {
l1Token: l1Token.address,
chainId: this.monitorConfig.hubPoolChainId,
poolCollateralSymbol: this.clients.hubPoolClient.getTokenInfoForL1Token(l1Token.address).symbol,
poolCollateralSymbol: l1Token.symbol,
utilization: toBN(utilization.toString()),
};
})
Expand Down Expand Up @@ -286,9 +293,18 @@ 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();
for (const relayer of this.monitorConfig.monitoredRelayers) {
for (const chainId of this.monitorChains) {
const l2ToL1Tokens = this.clients.hubPoolClient.getDestinationTokensToL1TokensForChainId(chainId);
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 l2TokenAddresses = Object.keys(l2ToL1Tokens);
const tokenBalances = await this._getBalances(
Expand Down Expand Up @@ -606,17 +622,22 @@ export class Monitor {
}

updateUnknownTransfers(relayerBalanceReport: RelayerBalanceReport): void {
const hubPoolClient = this.clients.hubPoolClient;
const { hubPoolClient, spokePoolClients } = this.clients;

for (const relayer of this.monitorConfig.monitoredRelayers) {
const report = relayerBalanceReport[relayer];
const transfersPerChain: TransfersByChain = this.clients.tokenTransferClient.getTokenTransfers(relayer);

let mrkdwn = "";
for (const chainId of this.monitorChains) {
const spokePoolClient = this.clients.spokePoolClients[chainId];
const spokePoolClient = spokePoolClients[chainId];
const transfersPerToken: TransfersByTokens = transfersPerChain[chainId];
const l2ToL1Tokens = hubPoolClient.getDestinationTokensToL1TokensForChainId(chainId);
const l2ToL1Tokens = Object.fromEntries(
Object.keys(transfersPerToken).map((l2Token) => [
l2Token,
hubPoolClient.getL1TokenForL2TokenAtBlock(l2Token, chainId, hubPoolClient.latestBlockSearched),
])
);

let currentChainMrkdwn = "";
for (const l2Token of Object.keys(l2ToL1Tokens)) {
Expand Down
17 changes: 7 additions & 10 deletions src/relayer/Relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,21 +590,18 @@ export class Relayer {
destinationToken,
fillAmount: amount,
realizedLpFeePct,
repaymentChainId: chainId,
repaymentChainId,
blockNumber: fillBlock,
} = fill;

const contract = spokePoolClients[chainId].spokePool;
const contract = spokePoolClients[repaymentChainId].spokePool;
const method = "requestRefund";
// @todo: Support specifying max impact against the refund amount (i.e. to mitigate price impact by fills).
const maxCount = ethersConstants.MaxUint256;

// Resolve the refund token from the fill token. The name getDestinationtTokenForDeposit() is a misnomer here.
const refundToken = hubPoolClient.getDestinationTokenForDeposit({
originChainId: destinationChainId,
originToken: destinationToken,
destinationChainId: chainId,
});
// Resolve the refund token from the fill token.
const hubPoolToken = hubPoolClient.getL1TokenForL2TokenAtBlock(destinationToken, destinationChainId);
const refundToken = hubPoolClient.getL2TokenForL1TokenAtBlock(hubPoolToken, repaymentChainId);

const args = [
refundToken,
Expand All @@ -617,11 +614,11 @@ export class Relayer {
maxCount,
];

const message = `Submitted refund request on chain ${getNetworkName(chainId)}.`;
const message = `Submitted refund request on chain ${getNetworkName(repaymentChainId)}.`;
const mrkdwn = this.constructRefundRequestMarkdown(fill);

this.logger.debug({ at: "Relayer::requestRefund", message: "Requesting refund for fill.", fill });
multiCallerClient.enqueueTransaction({ chainId, contract, method, args, message, mrkdwn });
multiCallerClient.enqueueTransaction({ chainId: repaymentChainId, contract, method, args, message, mrkdwn });
}

protected async resolveRepaymentChain(
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/validateRunningBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export async function runScript(_logger: winston.Logger, baseSigner: Signer): Pr

mrkdwn += `\n\tLeaf for chain ID ${leaf.chainId} and token ${tokenInfo.symbol} (${l1Token})`;
const decimals = tokenInfo.decimals;
const l2Token = clients.hubPoolClient.getDestinationTokenForL1Token(l1Token, leaf.chainId);
const l2Token = clients.hubPoolClient.getL2TokenForL1TokenAtBlock(l1Token, leaf.chainId, followingBlockNumber);
const l2TokenContract = new Contract(l2Token, ERC20.abi, await getProvider(leaf.chainId));
const runningBalance = leaf.runningBalances[i];
const netSendAmount = leaf.netSendAmounts[i];
Expand Down
11 changes: 8 additions & 3 deletions src/utils/FillUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ export function getRefundInformationFromFill(
hubPoolClient.chainId,
chainIdListForBundleEvaluationBlockNumbers
)[1];
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
fill.destinationChainId,
// @todo In v3, destination... must be swapped for origin...
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
fill.destinationToken,
fill.destinationChainId,
endBlockForMainnet
);
const repaymentToken = hubPoolClient.getL2TokenForL1TokenAtBlock(
l1TokenCounterpart,
chainToSendRefundTo,
endBlockForMainnet
);
const repaymentToken = hubPoolClient.getDestinationTokenForL1Token(l1TokenCounterpart, chainToSendRefundTo);
return {
chainToSendRefundTo,
repaymentToken,
Expand Down
13 changes: 7 additions & 6 deletions test/AdapterManager.SendTokensCrossChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,8 @@ describe("AdapterManager: Send tokens cross-chain", async function () {
// Throws if there is a misconfiguration between L1 tokens and L2 tokens. This checks that the bot will error out
// if it tries to delete money in the bridge. configure hubpool to return the wrong token for Optimism

hubPoolClient.setL1TokensToDestinationTokens({
// bad config. map USDC on L1 to boba on L2. This is WRONG for chainID 10 and should error.
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": { 10: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8" },
});
// bad config. map USDC on L1 to Arbitrum on L2. This is WRONG for chainID 10 and should error.
hubPoolClient.setTokenMapping(mainnetTokens["usdc"], 10, getL2TokenAddresses(mainnetTokens["usdc"])[42161]);
let thrown2 = false;
try {
await adapterManager.sendTokenCrossChain(relayer.address, CHAIN_IDs.OPTIMISM, mainnetTokens.usdc, amountToSend);
Expand Down Expand Up @@ -291,8 +289,11 @@ describe("AdapterManager: Send tokens cross-chain", async function () {

async function seedMocks() {
const allL1Tokens = Object.values(TOKEN_SYMBOLS_MAP).map((details) => details.addresses[CHAIN_IDs.MAINNET]);
const tokenAddressMapping = Object.fromEntries(allL1Tokens.map((address) => [address, getL2TokenAddresses(address)]));
hubPoolClient.setL1TokensToDestinationTokens(tokenAddressMapping);
allL1Tokens.forEach((address) =>
Object.entries(getL2TokenAddresses(address)).forEach(([chainId, l2Addr]) =>
hubPoolClient.setTokenMapping(address, Number(chainId), l2Addr)
)
);

// Construct fake spoke pool clients. All the adapters need is a signer and a provider on each chain.
for (const chainId of enabledChainIds) {
Expand Down
Loading

0 comments on commit f28382c

Please sign in to comment.