diff --git a/package.json b/package.json index 3ad929ad..06e9701a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@balancer-labs/sor", - "version": "4.1.1-beta.1", + "version": "4.1.1-beta.2", "license": "GPL-3.0-only", "main": "dist/index.js", "module": "dist/index.esm.js", diff --git a/src/routeProposal/filtering.ts b/src/routeProposal/filtering.ts index da507f71..5af17cbe 100644 --- a/src/routeProposal/filtering.ts +++ b/src/routeProposal/filtering.ts @@ -158,10 +158,9 @@ export function producePaths( // Nodes are tokens and edges are triads: [pool.id, tokenIn, tokenOut]. // The current criterion for including a pool into this graph is the following: // (a) We include every linear pool. -// (b) Among phantom pools, we include those that contain the pool token of a linear pool. -// (c) Among every pool, we include those that contain the pool token of -// a pool from the previous step. -// (d) We include connections of tokenIn and tokenOut to WETH (only highest liquidity for each). +// (b) Among preminted BPT pools and weighted pools, we include those that contain the pool token of a linear pool. +// (c) Among every pool, we include those that contain the pool token of a pool from the previous step. +// (d) We include connections of tokenIn and tokenOut to list of tokens from `connectingTokens` (only highest liquidity for each). // (e) When tokenIn or tokenOut are tokens offered at an LBP, we also include // the LBPs and the corresponding highest liquidity connections of the raising tokens with WETH. // (f) We include the pool weth/wsteth @@ -182,30 +181,34 @@ export function getBoostedGraph( poolsAllDict: PoolDictionary, config: SorConfig ): edgeDict { + // This should contain all pools in the Graph const graphPoolsSet: Set = new Set(); - const linearPools: PoolBase[] = []; - const phantomPools: PoolBase[] = []; + const allLinearPoolAddresses: string[] = []; + const poolsToCheckForLinearBpt: PoolBase[] = []; const connectingTokens = config.connectingTokens ? config.connectingTokens.map( (connectingToken) => connectingToken.address ) : []; - // Here we add all linear pools, take note of phantom pools, - // add LBP pools with tokenIn or tokenOut and their corresponding - // highest liquidity WETH connections + // Add all LinearPools (see step a) + // Create a list of pools that should be checked for Linear BPT (for step b) + // Add LBP pools with tokenIn or tokenOut and their corresponding highest liquidity connections for (const id in poolsAllDict) { const pool = poolsAllDict[id]; if (pool.poolType == PoolTypes.Linear) { - linearPools.push(pool); + allLinearPoolAddresses.push(pool.address); graphPoolsSet.add(pool); } else { - // Here we asssume that phantom pools are exactly those that - // are not linear and have their pool token in their tokensList. const tokensList = pool.tokensList.map((address) => address.toLowerCase() ); if (tokensList.includes(pool.address)) { - phantomPools.push(pool); + // Here we asssume that preminted pools are exactly those that + // are not linear and have their pool token in their tokensList. + poolsToCheckForLinearBpt.push(pool); + } else if (pool.poolType === PoolTypes.Weighted) { + // We want to consider Weighted Pools with Linear Bpt tokens + poolsToCheckForLinearBpt.push(pool); } if (config.lbpRaisingTokens && pool.isLBP) { handleLBPCase( @@ -220,6 +223,8 @@ export function getBoostedGraph( } } } + if (allLinearPoolAddresses.length == 0) return {}; + // add best pools tokenIn -> connectingToken and connectingToken -> tokenOut // these can be part of a longer path so do not rely on being directly connected for (const connectingToken of connectingTokens) { @@ -236,30 +241,26 @@ export function getBoostedGraph( graphPoolsSet ); } - if (linearPools.length == 0) return {}; - const linearPoolsAddresses = linearPools.map((pool) => pool.address); - const secondStepPoolsSet: Set = new Set(); - for (const pool of phantomPools) { - for (const linearPoolAddress of linearPoolsAddresses) { - if (pool.tokensList.includes(linearPoolAddress)) { - graphPoolsSet.add(pool); - secondStepPoolsSet.add(pool); - } + // As per step b - Among preminted BPT pools and weighted pools, we include those that contain the pool token of a linear pool. + const poolsWithLinearTokens: Set = new Set(); + for (const pool of poolsToCheckForLinearBpt) { + if ( + pool.tokensList.some((token) => + allLinearPoolAddresses.includes(token) + ) + ) { + graphPoolsSet.add(pool); + poolsWithLinearTokens.add(pool.address); } } - const secondStepPoolsAddresses = [...secondStepPoolsSet].map( - (pool) => pool.address - ); - // Here we include every pool that has a pool token from the previous step + // As per step c - We include every pool that has a pool token from the previous step for (const id in poolsAllDict) { const pool = poolsAllDict[id]; - for (const secondStepPoolAddress of secondStepPoolsAddresses) { - if (pool.tokensList.includes(secondStepPoolAddress)) { - graphPoolsSet.add(pool); - } + if (pool.tokensList.some((token) => poolsWithLinearTokens.has(token))) { + graphPoolsSet.add(pool); } } - // add pool weth/wsteth when it exists + // Step f - add pool weth/wsteth when it exists if (config.wETHwstETH && poolsAllDict[config.wETHwstETH.id]) { graphPoolsSet.add(poolsAllDict[config.wETHwstETH.id]); } diff --git a/src/types.ts b/src/types.ts index 7f3802bf..a1e383fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -180,14 +180,23 @@ export enum PoolFilter { LBP = 'LiquidityBootstrapping', Investment = 'Investment', Element = 'Element', - AaveLinear = 'AaveLinear', StablePhantom = 'StablePhantom', - ERC4626Linear = 'ERC4626Linear', ComposableStable = 'ComposableStable', Gyro2 = 'Gyro2', Gyro3 = 'Gyro3', GyroE = 'GyroE', + // Linear Pools defined below all operate the same mathematically but have different factories and names in Subgraph + AaveLinear = 'AaveLinear', + Linear = 'Linear', EulerLinear = 'EulerLinear', + ERC4626Linear = 'ERC4626Linear', + BeefyLinear = 'BeefyLinear', + GearboxLinear = 'GearboxLinear', + MidasLinear = 'MidasLinear', + ReaperLinear = 'ReaperLinear', + SiloLinear = 'SiloLinear', + TetuLinear = 'TetuLinear', + YearnLinear = 'YearnLinear', } export interface PoolBase { diff --git a/test/testScripts/constants.ts b/test/testScripts/constants.ts index 76f6e72e..45729bd2 100644 --- a/test/testScripts/constants.ts +++ b/test/testScripts/constants.ts @@ -24,6 +24,10 @@ export const SOR_CONFIG: Record = { symbol: 'DOLA', address: '0x865377367054516e17014CcdED1e7d814EDC9ce4', }, + { + symbol: 'wstEth', + address: '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0', + }, ], wETHwstETH: { id: '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080', @@ -258,6 +262,21 @@ export const ADDRESSES = { decimals: 18, symbol: 'DBR', }, + APE: { + address: '0x4d224452801aced8b2f0aebe155379bb5d594381', + decimals: 18, + symbol: 'APE', + }, + sAPE: { + address: '0x7966c5bae631294d7cffcea5430b78c2f76db6fa', + decimals: 18, + symbol: 'sAPE', + }, + bbtAPE: { + address: '0x126e7643235ec0ab9c103c507642dC3F4cA23C66'.toLowerCase(), + decimals: 18, + symbol: 'bbtAPE', + }, }, [Network.KOVAN]: { // Visit https://balancer-faucet.on.fleek.co/#/faucet for test tokens diff --git a/test/testScripts/swapExample.ts b/test/testScripts/swapExample.ts index 5aa5ae5d..e848480b 100644 --- a/test/testScripts/swapExample.ts +++ b/test/testScripts/swapExample.ts @@ -65,10 +65,10 @@ export async function swap(): Promise { const gasPrice = BigNumber.from('14000000000'); // This determines the max no of pools the SOR will use to swap. const maxPools = 4; - const tokenIn = ADDRESSES[networkId].USDC; - const tokenOut = ADDRESSES[networkId].DAI; + const tokenIn = ADDRESSES[networkId].sAPE; + const tokenOut = ADDRESSES[networkId].WETH; const swapType: SwapTypes = SwapTypes.SwapExactIn; - const swapAmount = parseFixed('200', 6); + const swapAmount = parseFixed('2000', 18); const sor = setUp(networkId, provider);