Skip to content

Commit

Permalink
Merge across repo (#13)
Browse files Browse the repository at this point in the history
### What was the problem?

Merge from latest across repo

---------

Signed-off-by: dependabot[bot] <[email protected]>
Signed-off-by: bennett <[email protected]>
Co-authored-by: Paul <[email protected]>
Co-authored-by: finaltrip <[email protected]>
Co-authored-by: omahs <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: bmzig <[email protected]>
  • Loading branch information
6 people authored Jul 17, 2024
1 parent 42c3894 commit 3fa21ee
Show file tree
Hide file tree
Showing 16 changed files with 994 additions and 809 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Check out [this guide](https://docs.across.to/relayers/running-a-relayer) for de

## Prerequisites

After installing dependencies and building the repository, be sure to [install RedisDB](https://redis.io/docs/getting-started/installation/), an in-memory storage layer that is required to make the bots work. The bots query blockchain RPCs for a lot of smart contract events so its important that the bot
After installing dependencies and building the repository, be sure to [install RedisDB](https://redis.io/docs/getting-started/installation/), an in-memory storage layer that is required to make the bots work. The bots query blockchain RPCs for a lot of smart contract events so it's important that the bot
cache some of this data in order to maintain its speed.

The first time that the bot runs, it might be slower than usual as the Redis DB fills up. This slowdown should disappear on subsequent runs.
Expand Down
3 changes: 2 additions & 1 deletion src/clients/AcrossAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
bnZero,
winston,
BigNumber,
dedupArray,
getCurrentTime,
TOKEN_SYMBOLS_MAP,
CHAIN_IDs,
Expand Down Expand Up @@ -37,7 +38,7 @@ export class AcrossApiClient {
const hubChainId = hubPoolClient.chainId;
this.endpoint = `https://${hubChainId === CHAIN_IDs.MAINNET ? "app.across.to" : "testnet.across.to"}/api`;
if (Object.keys(tokensQuery).length === 0) {
this.tokensQuery = Object.values(TOKEN_SYMBOLS_MAP).map(({ addresses }) => addresses[hubChainId]);
this.tokensQuery = dedupArray(Object.values(TOKEN_SYMBOLS_MAP).map(({ addresses }) => addresses[hubChainId]));
}

this.chainIds = chainIds.filter((chainId) => chainId !== hubChainId);
Expand Down
39 changes: 24 additions & 15 deletions src/clients/InventoryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export type Rebalance = {
};

const { CHAIN_IDs } = constants;
const LITE_CHAIN_OVERAGE = toBNWei("1");
const DEFAULT_CHAIN_OVERAGE = toBNWei("1.5");

export class InventoryClient {
private logDisabledManagement = false;
Expand Down Expand Up @@ -476,15 +478,17 @@ export class InventoryClient {
chainsToEvaluate.push(originChainId);
}

const liteChainIds = this.hubPoolClient.configStoreClient.getLiteChainIdIndicesForBlock();

const eligibleRefundChains: number[] = [];
// At this point, all chains to evaluate have defined token configs and are sorted in order of
// highest priority to take repayment on, assuming the chain is under-allocated.
for (const _chain of chainsToEvaluate) {
assert(this._l1TokenEnabledForChain(l1Token, _chain), `Token ${l1Token} not enabled for chain ${_chain}`);
for (const chainId of chainsToEvaluate) {
assert(this._l1TokenEnabledForChain(l1Token, chainId), `Token ${l1Token} not enabled for chain ${chainId}`);
// Destination chain:
const repaymentToken = this.getRepaymentTokenForL1Token(l1Token, _chain);
const chainShortfall = this.tokenClient.getShortfallTotalRequirement(_chain, repaymentToken);
const chainVirtualBalance = this.getBalanceOnChain(_chain, l1Token, repaymentToken);
const repaymentToken = this.getRepaymentTokenForL1Token(l1Token, chainId);
const chainShortfall = this.tokenClient.getShortfallTotalRequirement(chainId, repaymentToken);
const chainVirtualBalance = this.getBalanceOnChain(chainId, l1Token, repaymentToken);
const chainVirtualBalanceWithShortfall = chainVirtualBalance.sub(chainShortfall);
let cumulativeVirtualBalanceWithShortfall = cumulativeVirtualBalance.sub(chainShortfall);
// @dev No need to factor in outputAmount when computing origin chain balance since funds only leave relayer
Expand All @@ -493,14 +497,14 @@ export class InventoryClient {
// This is possible when the output token is USDC.e and the input token is USDC which would still cause
// validateOutputToken() to return true above.
let chainVirtualBalanceWithShortfallPostRelay =
_chain === destinationChainId &&
chainId === destinationChainId &&
this.hubPoolClient.areTokensEquivalent(inputToken, originChainId, outputToken, destinationChainId)
? chainVirtualBalanceWithShortfall.sub(outputAmount)
: chainVirtualBalanceWithShortfall;

// Add upcoming refunds:
chainVirtualBalanceWithShortfallPostRelay = chainVirtualBalanceWithShortfallPostRelay.add(
totalRefundsPerChain[_chain] ?? bnZero
totalRefundsPerChain[chainId] ?? bnZero
);
// To correctly compute the allocation % for this destination chain, we need to add all upcoming refunds for the
// equivalents of l1Token on all chains.
Expand All @@ -514,18 +518,23 @@ export class InventoryClient {
.div(cumulativeVirtualBalanceWithShortfallPostRelay);

// Consider configured buffer for target to allow relayer to support slight overages.
const tokenConfig = this.getTokenConfig(l1Token, _chain, repaymentToken);
const tokenConfig = this.getTokenConfig(l1Token, chainId, repaymentToken);
assert(
isDefined(tokenConfig),
`No ${outputToken} tokenConfig in the Inventory Config for ${l1Token} on ${_chain} with a repaymentToken of ${repaymentToken}.`
`No ${outputToken} tokenConfig for ${l1Token} on ${chainId} with a repaymentToken ${repaymentToken}.`
);
const thresholdPct = toBN(tokenConfig.targetPct)
.mul(tokenConfig.targetOverageBuffer ?? toBNWei("1"))
.div(fixedPointAdjustment);

// It's undesirable to accrue excess balances on a Lite chain because the relayer relies on additional deposits
// destined for that chain in order to offload its excess. In anticipation of most Lite chains tending to be
// exit-heavy, drop the default buffer to 1x.
const targetOverage =
tokenConfig.targetOverageBuffer ?? liteChainIds.includes(chainId) ? LITE_CHAIN_OVERAGE : DEFAULT_CHAIN_OVERAGE;
const thresholdPct = tokenConfig.targetPct.mul(targetOverage).div(fixedPointAdjustment);

this.log(
`Evaluated taking repayment on ${
_chain === originChainId ? "origin" : _chain === destinationChainId ? "destination" : "slow withdrawal"
} chain ${_chain} for deposit ${deposit.depositId}: ${
chainId === originChainId ? "origin" : chainId === destinationChainId ? "destination" : "slow withdrawal"
} chain ${chainId} for deposit ${deposit.depositId}: ${
expectedPostRelayAllocation.lte(thresholdPct) ? "UNDERALLOCATED ✅" : "OVERALLOCATED ❌"
}`,
{
Expand All @@ -546,7 +555,7 @@ export class InventoryClient {
}
);
if (expectedPostRelayAllocation.lte(thresholdPct)) {
eligibleRefundChains.push(_chain);
eligibleRefundChains.push(chainId);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/clients/bridges/PolygonAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,6 @@ export class PolygonAdapter extends CCTPAdapter {
}

async wrapEthIfAboveThreshold(): Promise<TransactionResponse | null> {
throw new Error("Unneccessary to wrap ETH on Polygon");
throw new Error("Unnecessary to wrap ETH on Polygon");
}
}
100 changes: 42 additions & 58 deletions src/common/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,88 +40,52 @@ export const FINALIZER_TOKENBRIDGE_LOOKBACK = 14 * 24 * 60 * 60;
// block. This would cause the relayer to unintentionally send an invalid fill and not refunded. The tradeoff is that
// the larger the follow distance, the slower the relayer will be to fulfill deposits. Therefore, the following
// configuration allows the user to set higher follow distances for higher deposit amounts.
// The Key of the following dictionary is used as the USD threshold to determine the MDC:
// The key of the following dictionary is used as the USD threshold to determine the MDC:
// - Searching from highest USD threshold to lowest
// - If the key value is >= deposited USD amount, then use the MDC associated with the key for the origin chain
// - If no key values are >= depostied USD amount, use the "default" value for the origin chain
// - For example, a deposit on Polygon worth $90 would use the MDC associated with the 100 key and chain
// 137, so it would use a follow distance of 80 blocks, while a deposit on Polygon for $110 would use 1000
// key. A deposit of $1100 would use the "default" key

// - If the key is >= deposited USD amount, then use the MDC associated with the key for the origin chain
// - If no keys are >= depostied USD amount, ignore the deposit.
// To see the latest block reorg events go to:
// - Ethereum: https://etherscan.io/blocks_forked
// - Polygon: https://polygonscan.com/blocks_forked

// Optimistic Rollups are currently centrally serialized and are not expected to reorg. Technically a block on an
// ORU will not be finalized until after 7 days, so there is little difference in following behind 0 blocks versus
// anything under 7 days.
export const DEFAULT_MIN_DEPOSIT_CONFIRMATIONS = {
[CHAIN_IDs.ARBITRUM]: 0,
[CHAIN_IDs.BASE]: 120,
[CHAIN_IDs.BLAST]: 120,
[CHAIN_IDs.BOBA]: 0,
[CHAIN_IDs.LINEA]: 30,
[CHAIN_IDs.LISK]: 120, // Same as other OVM. Hard finality is 1800 blocks
[CHAIN_IDs.MAINNET]: 64, // Finalized block: https://www.alchemy.com/overviews/ethereum-commitment-levels
[CHAIN_IDs.MODE]: 120,
[CHAIN_IDs.OPTIMISM]: 120,
[CHAIN_IDs.POLYGON]: 128, // Commonly used finality level for CEX's that accept Polygon deposits
[CHAIN_IDs.ZK_SYNC]: 120,
// Testnets:
[CHAIN_IDs.ARBITRUM_SEPOLIA]: 0,
[CHAIN_IDs.BASE_SEPOLIA]: 0,
[CHAIN_IDs.BLAST_SEPOLIA]: 0,
[CHAIN_IDs.LISK_SEPOLIA]: 0,
[CHAIN_IDs.MODE_SEPOLIA]: 0,
[CHAIN_IDs.OPTIMISM_SEPOLIA]: 0,
[CHAIN_IDs.POLYGON_AMOY]: 0,
[CHAIN_IDs.SEPOLIA]: 0,
};

export const MIN_DEPOSIT_CONFIRMATIONS: { [threshold: number | string]: { [chainId: number]: number } } = {
10000: {
[CHAIN_IDs.ARBITRUM]: 0,
[CHAIN_IDs.BASE]: 120,
[CHAIN_IDs.BLAST]: 120,
[CHAIN_IDs.LINEA]: 30,
[CHAIN_IDs.LISK]: 120,
[CHAIN_IDs.MAINNET]: 64, // Finalized block: https://www.alchemy.com/overviews/ethereum-commitment-levels
[CHAIN_IDs.MODE]: 120,
[CHAIN_IDs.OPTIMISM]: 120,
[CHAIN_IDs.POLYGON]: 128, // Commonly used finality level for CEX's that accept Polygon deposits
[CHAIN_IDs.ZK_SYNC]: 120,
},
1000: {
[CHAIN_IDs.ARBITRUM]: 0,
[CHAIN_IDs.BASE]: 60,
[CHAIN_IDs.BLAST]: 60,
[CHAIN_IDs.BOBA]: 0,
[CHAIN_IDs.LINEA]: 1,
[CHAIN_IDs.LISK]: 60,
[CHAIN_IDs.MAINNET]: 32, // Justified block
[CHAIN_IDs.MODE]: 60,
[CHAIN_IDs.OPTIMISM]: 60,
[CHAIN_IDs.POLYGON]: 100, // Probabilistically safe level based on historic Polygon reorgs
[CHAIN_IDs.ZK_SYNC]: 0,
// Testnets:
[CHAIN_IDs.ARBITRUM_SEPOLIA]: 0,
[CHAIN_IDs.BASE_SEPOLIA]: 0,
[CHAIN_IDs.BLAST_SEPOLIA]: 0,
[CHAIN_IDs.LISK_SEPOLIA]: 60,
[CHAIN_IDs.MODE_SEPOLIA]: 0,
[CHAIN_IDs.OPTIMISM_SEPOLIA]: 0,
[CHAIN_IDs.POLYGON_AMOY]: 0,
[CHAIN_IDs.SEPOLIA]: 0,
},
100: {
[CHAIN_IDs.ARBITRUM]: 0,
[CHAIN_IDs.BASE]: 60,
[CHAIN_IDs.BLAST]: 60,
[CHAIN_IDs.BOBA]: 0,
[CHAIN_IDs.LINEA]: 1,
[CHAIN_IDs.LISK]: 60,
[CHAIN_IDs.MAINNET]: 16, // Mainnet reorgs are rarely > 4 blocks in depth so this is a very safe buffer
[CHAIN_IDs.MODE]: 60,
[CHAIN_IDs.OPTIMISM]: 60,
[CHAIN_IDs.POLYGON]: 80,
[CHAIN_IDs.ZK_SYNC]: 0,
// Testnets:
[CHAIN_IDs.ARBITRUM_SEPOLIA]: 0,
[CHAIN_IDs.BASE_SEPOLIA]: 0,
[CHAIN_IDs.BLAST_SEPOLIA]: 0,
[CHAIN_IDs.LISK_SEPOLIA]: 0,
[CHAIN_IDs.MODE_SEPOLIA]: 0,
[CHAIN_IDs.OPTIMISM_SEPOLIA]: 0,
[CHAIN_IDs.POLYGON_AMOY]: 0,
[CHAIN_IDs.SEPOLIA]: 0,
},
};

Expand All @@ -134,15 +98,15 @@ export const REDIS_URL_DEFAULT = "redis://localhost:6379";
// Quicknode for example.
export const CHAIN_MAX_BLOCK_LOOKBACK = {
[CHAIN_IDs.ARBITRUM]: 10000,
[CHAIN_IDs.BASE]: 1500,
[CHAIN_IDs.BLAST]: 1500,
[CHAIN_IDs.BASE]: 10000,
[CHAIN_IDs.BLAST]: 10000,
[CHAIN_IDs.BOBA]: 4990,
[CHAIN_IDs.LINEA]: 5000,
[CHAIN_IDs.LISK]: 1500,
[CHAIN_IDs.LISK]: 10000,
[CHAIN_IDs.MAINNET]: 10000,
[CHAIN_IDs.MODE]: 1500,
[CHAIN_IDs.MODE]: 10000,
[CHAIN_IDs.OPTIMISM]: 10000, // Quick
[CHAIN_IDs.POLYGON]: 3490,
[CHAIN_IDs.POLYGON]: 10000,
[CHAIN_IDs.ZK_SYNC]: 10000,
// Testnets:
[CHAIN_IDs.ARBITRUM_SEPOLIA]: 10000,
Expand Down Expand Up @@ -295,7 +259,7 @@ export type Multicall2Call = {
target: string;
};

// These are the spokes that can hold both ETH and WETH, so they should be added together when caclulating whether
// These are the spokes that can hold both ETH and WETH, so they should be added together when calculating whether
// a bundle execution is possible with the funds in the pool.
export const spokesThatHoldEthAndWeth = [
CHAIN_IDs.BASE,
Expand Down Expand Up @@ -368,7 +332,8 @@ export const RELAYER_DEFAULT_SPOKEPOOL_INDEXER = "./dist/src/libexec/RelayerSpok
export const DEFAULT_ARWEAVE_GATEWAY = { url: "arweave.net", port: 443, protocol: "https" };

// Chains with slow (> 2 day liveness) canonical L2-->L1 bridges that we prioritize taking repayment on.
// This does not include all 7-day withdrawal chains because we don't necessarily prefer being repaid on some of these 7-day chains, like Mode.
// This does not include all 7-day withdrawal chains because we don't necessarily prefer being repaid on some of these 7-day chains, like Mode.
// This list should generally exclude Lite chains because the relayer ignores HubPool liquidity in that case.
export const SLOW_WITHDRAWAL_CHAINS = [CHAIN_IDs.ARBITRUM, CHAIN_IDs.BASE, CHAIN_IDs.OPTIMISM];

// Expected worst-case time for message from L1 to propogate to L2 in seconds
Expand All @@ -385,6 +350,25 @@ export const EXPECTED_L1_TO_L2_MESSAGE_TIME = {
};

export const OPSTACK_CONTRACT_OVERRIDES = {
[CHAIN_IDs.BLAST]: {
l1: {
AddressManager: "0xE064B565Cf2A312a3e66Fe4118890583727380C0",
L1CrossDomainMessenger: "0x5D4472f31Bd9385709ec61305AFc749F0fA8e9d0",
L1StandardBridge: "0x697402166Fbf2F22E970df8a6486Ef171dbfc524",
StateCommitmentChain: "0x0000000000000000000000000000000000000000",
CanonicalTransactionChain: "0x0000000000000000000000000000000000000000",
BondManager: "0x0000000000000000000000000000000000000000",
OptimismPortal: "0x0Ec68c5B10F21EFFb74f2A5C61DFe6b08C0Db6Cb",
L2OutputOracle: "0x826D1B0D4111Ad9146Eb8941D7Ca2B6a44215c76",
OptimismPortal2: "0x0000000000000000000000000000000000000000",
DisputeGameFactory: "0x0000000000000000000000000000000000000000",
},
// https://github.com/blast-io/blast/blob/master/blast-optimism/op-bindings/predeploys/addresses.go
l2: {
...DEFAULT_L2_CONTRACT_ADDRESSES,
WETH: TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.BLAST],
},
},
[CHAIN_IDs.LISK]: {
l1: {
AddressManager: "0x2dF7057d3F25212E51aFEA8dA628668229Ea423f",
Expand Down
2 changes: 1 addition & 1 deletion src/common/ContractAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const CONTRACT_ADDRESSES: {
address: "0x39Ea01a0298C315d149a490E34B59Dbf2EC7e48F",
abi: SNX_OPTIMISM_BRIDGE_L1_ABI,
},
// OVM, ZkSync, Linea, and Polygon cant deposit WETH directly so we use an atomic depositor contract that unwraps WETH and
// OVM, ZkSync, Linea, and Polygon can't deposit WETH directly so we use an atomic depositor contract that unwraps WETH and
// bridges ETH other the canonical bridge.
atomicDepositor: {
address: "0xfa52a9DCF51695EA2777E6908d6401481850c391",
Expand Down
2 changes: 1 addition & 1 deletion src/dataworker/PoolRebalanceUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ export function generateMarkdownForRootBundle(
` ${getNetworkName(leaf.relayData.originChainId)} depositId ${leaf.relayData.depositId}`
);

// @todo: When v2 types are removed, update the slowFill definition to be more precise about the memebr fields.
// @todo: When v2 types are removed, update the slowFill definition to be more precise about the member fields.
const slowFill = {
// Shorten select keys for ease of reading from Slack.
depositor: shortenHexString(leaf.relayData.depositor),
Expand Down
Loading

0 comments on commit 3fa21ee

Please sign in to comment.