From 23ebfce2dd69e943de148e435c4b9a992816dd6c Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Thu, 17 Aug 2023 18:38:12 -0300 Subject: [PATCH 1/5] Update StablePhantom generalisedExit to go through the non-proportional flow --- balancer-js/src/modules/exits/exits.module.ts | 41 ++++++------------- balancer-js/src/modules/graph/graph.ts | 2 +- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/balancer-js/src/modules/exits/exits.module.ts b/balancer-js/src/modules/exits/exits.module.ts index e377f24dd..7a4ce1f11 100644 --- a/balancer-js/src/modules/exits/exits.module.ts +++ b/balancer-js/src/modules/exits/exits.module.ts @@ -676,35 +676,18 @@ export class Exit { break; } case 'batchSwap': { - if (node.children.length === 1) { - const { modelRequest, encodedCall, assets, amounts } = - this.createSwap( - node, - exitChild as Node, - i, - minAmountOut, - sender, - recipient - ); - modelRequests.push(modelRequest); - calls.push(encodedCall); - this.updateDeltas(deltas, assets, amounts); - } else { - const exitChildren = node.children.map((n) => n); - // TODO - is it correct to use minAmountsOutProportional? - const { modelRequest, encodedCall, assets, amounts } = - this.createBatchSwap( - node, - exitChildren, - i, - minAmountsOutProportional, - sender, - recipient - ); - modelRequests.push(modelRequest); - calls.push(encodedCall); - this.updateDeltas(deltas, assets, amounts); - } + const { modelRequest, encodedCall, assets, amounts } = + this.createSwap( + node, + exitChild as Node, + i, + minAmountOut, + sender, + recipient + ); + modelRequests.push(modelRequest); + calls.push(encodedCall); + this.updateDeltas(deltas, assets, amounts); break; } case 'exitPool': { diff --git a/balancer-js/src/modules/graph/graph.ts b/balancer-js/src/modules/graph/graph.ts index 24e8b88a4..69a087079 100644 --- a/balancer-js/src/modules/graph/graph.ts +++ b/balancer-js/src/modules/graph/graph.ts @@ -392,7 +392,7 @@ export class PoolGraph { */ static isProportionalPools(nodes: Node[]): boolean { return nodes.every((node) => { - if (node.exitAction === 'exitPool') return node.isProportionalExit; + if (node.children.length > 1) return node.isProportionalExit; else return true; }); } From c00570519e68758caa5309c52a6c4318920e5129 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Thu, 17 Aug 2023 18:41:17 -0300 Subject: [PATCH 2/5] Refactor tests so we're able to hold pool state between them when necessary --- .../exits.module.integration-mainnet.spec.ts | 205 ++++++++++-------- balancer-js/src/modules/exits/testHelper.ts | 15 +- 2 files changed, 115 insertions(+), 105 deletions(-) diff --git a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts index 6ec4335db..687a0d72e 100644 --- a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts +++ b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts @@ -1,48 +1,97 @@ // yarn test:only ./src/modules/exits/exits.module.integration-mainnet.spec.ts import dotenv from 'dotenv'; import { expect } from 'chai'; -import { Network } from '@/.'; +import { BalancerSDK, Network, PoolWithMethods } from '@/.'; import { BigNumber, parseFixed } from '@ethersproject/bignumber'; import { accuracy } from '@/test/lib/utils'; import { ADDRESSES, TEST_BLOCK } from '@/test/lib/constants'; -import { testFlow } from './testHelper'; +import { setUpForkAndSdk, testFlow } from './testHelper'; +import { JsonRpcSigner } from '@ethersproject/providers'; dotenv.config(); -const TEST_BBAUSD3 = true; +describe('generalised exit execution', async function () { + let unwrappingTokensAmountsOut: string[]; + let unwrappingTokensGasUsed: BigNumber; + let mainTokensAmountsOut: string[]; + let mainTokensGasUsed: BigNumber; + let pool: { id: string; address: string; slot: number; decimals: number }; + let unwrapExitAmount: BigNumber; + let mainExitAmount: BigNumber; + let amountRatio: number; + let sdk: BalancerSDK; + let signer: JsonRpcSigner; -const blockNo = TEST_BLOCK[Network.MAINNET]; + const network = Network.MAINNET; + const blockNo = TEST_BLOCK[Network.MAINNET]; + const poolAddresses = Object.values(ADDRESSES[network]).map( + (address) => address.address + ); + const slippage = '10'; // 10 bps = 0.1% -describe('generalised exit execution', async function () { - this.timeout(120000); // Sets timeout for all tests within this scope to 2 minutes - context('aaveLinear V1 - bbausd', async () => { - const network = Network.MAINNET; - const pool = ADDRESSES[network].bbausd; - const slippage = '10'; // 10 bps = 0.1% - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; - const poolAddresses = Object.values(ADDRESSES[network]).map( - (address) => address.address + beforeEach(async () => { + const setup = await setUpForkAndSdk( + network, + blockNo, + poolAddresses, + [pool.address], + [pool.slot], + [parseFixed('120000000', 18).toString()] ); + sdk = setup.sdk; + signer = setup.signer; + }); - const amountRatio = 10; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - const unwrapExitAmount = parseFixed('1273000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - const mainExitAmount = unwrapExitAmount.div(amountRatio); + this.timeout(120000); // Sets timeout for all tests within this scope to 2 minutes + context.only('aaveLinear V1 - bbausd', async () => { + before(async () => { + pool = ADDRESSES[network].bbausd; + amountRatio = 2; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + unwrapExitAmount = parseFixed('2000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + mainExitAmount = unwrapExitAmount.div(amountRatio); + }); + + beforeEach(async () => { + // prepare pool to have more wrapped than main tokens + await testFlow( + pool, + slippage, + parseFixed('1270000', 18).toString(), + [], + sdk, + signer + ); + }); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { + const parentPool = (await sdk.pools.find(pool.id)) as PoolWithMethods; + const childPool0 = (await sdk.pools.findBy( + 'address', + parentPool.tokensList[0] + )) as PoolWithMethods; + const childPool1 = (await sdk.pools.findBy( + 'address', + parentPool.tokensList[1] + )) as PoolWithMethods; + const childPool2 = (await sdk.pools.findBy( + 'address', + parentPool.tokensList[2] + )) as PoolWithMethods; + // log pool state to see if it's persisting between tests + console.log('childPool0', childPool0.tokens); + console.log('childPool1', childPool1.tokens); + console.log('childPool2', childPool2.tokens); + const { expectedAmountsOut, gasUsed } = await testFlow( pool, slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - network, - blockNo, - poolAddresses + sdk, + signer ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -56,9 +105,8 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - network, - blockNo, - poolAddresses + sdk, + signer ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -83,23 +131,14 @@ describe('generalised exit execution', async function () { }); context('ERC4626 - bbausd3', async () => { - if (!TEST_BBAUSD3) return true; - const network = Network.MAINNET; - const pool = ADDRESSES[network].bbausd3; - const slippage = '10'; // 10 bps = 0.1% - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; - const poolAddresses = Object.values(ADDRESSES[network]).map( - (address) => address.address - ); - - const amountRatio = 10; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - const unwrapExitAmount = parseFixed('10000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - const mainExitAmount = unwrapExitAmount.div(amountRatio); + before(async () => { + pool = ADDRESSES[network].bbausd3; + amountRatio = 10; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + unwrapExitAmount = parseFixed('10000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + mainExitAmount = unwrapExitAmount.div(amountRatio); + }); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -108,9 +147,8 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - network, - blockNo, - poolAddresses + sdk, + signer ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -124,9 +162,8 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - network, - blockNo, - poolAddresses + sdk, + signer ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -151,22 +188,15 @@ describe('generalised exit execution', async function () { }); context('GearboxLinear - bbgusd', async () => { - const network = Network.MAINNET; - const pool = ADDRESSES[network].bbgusd; - const slippage = '10'; // 10 bps = 0.1% - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; - const poolAddresses = Object.values(ADDRESSES[network]).map( - (address) => address.address - ); + before(async () => { + pool = ADDRESSES[network].bbgusd; - const amountRatio = 100000; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - const unwrapExitAmount = parseFixed('1000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - const mainExitAmount = unwrapExitAmount.div(amountRatio); + amountRatio = 100000; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + unwrapExitAmount = parseFixed('1000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + mainExitAmount = unwrapExitAmount.div(amountRatio); + }); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -175,9 +205,8 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].USDC.address], - network, - blockNo, - poolAddresses + sdk, + signer ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -191,9 +220,8 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - network, - blockNo, - poolAddresses + sdk, + signer ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -217,23 +245,16 @@ describe('generalised exit execution', async function () { }); }); - context('AaveLinear - bbausd', async () => { - const network = Network.MAINNET; - const pool = ADDRESSES[network].bbausd2; - const slippage = '10'; // 10 bps = 0.1% - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; - const poolAddresses = Object.values(ADDRESSES[network]).map( - (address) => address.address - ); + context('AaveLinear - bbausd2', async () => { + before(async () => { + pool = ADDRESSES[network].bbausd2; - const amountRatio = 1000; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - const unwrapExitAmount = parseFixed('3000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - const mainExitAmount = unwrapExitAmount.div(amountRatio); + amountRatio = 1000; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + unwrapExitAmount = parseFixed('3000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + mainExitAmount = unwrapExitAmount.div(amountRatio); + }); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -242,9 +263,8 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - network, - blockNo, - poolAddresses + sdk, + signer ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -258,9 +278,8 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - network, - blockNo, - poolAddresses + sdk, + signer ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; diff --git a/balancer-js/src/modules/exits/testHelper.ts b/balancer-js/src/modules/exits/testHelper.ts index bb073fb73..e7f7b77dc 100644 --- a/balancer-js/src/modules/exits/testHelper.ts +++ b/balancer-js/src/modules/exits/testHelper.ts @@ -32,21 +32,12 @@ export const testFlow = async ( slippage: string, exitAmount: string, expectToUnwrap: string[], - network: Network, - blockNumber: number, - poolAddressesToConsider: string[] + sdk: BalancerSDK, + signer: JsonRpcSigner ): Promise<{ expectedAmountsOut: string[]; gasUsed: BigNumber; }> => { - const { sdk, signer } = await setUpForkAndSdk( - network, - blockNumber, - poolAddressesToConsider, - [pool.address], - [pool.slot], - [exitAmount] - ); // Follows similar flow to a front end implementation const { exitOutput, txResult, exitInfo } = await userFlow( pool, @@ -141,7 +132,7 @@ async function userFlow( }; } -async function setUpForkAndSdk( +export async function setUpForkAndSdk( network: Network, blockNumber: number, pools: string[], From 6ba5373c68ea362c1451efbbf9cd0460777b86b4 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Thu, 17 Aug 2023 18:46:03 -0300 Subject: [PATCH 3/5] Move time logs to logger --- balancer-js/src/lib/utils/logger.ts | 12 ++++++++++ balancer-js/src/modules/data/pool/subgraph.ts | 9 ++++++-- .../src/modules/data/pool/subgraphOnChain.ts | 22 ++++++++++++------- .../sor/pool-data/subgraphPoolDataService.ts | 8 +++++-- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/balancer-js/src/lib/utils/logger.ts b/balancer-js/src/lib/utils/logger.ts index 6b322d04b..9712d8602 100644 --- a/balancer-js/src/lib/utils/logger.ts +++ b/balancer-js/src/lib/utils/logger.ts @@ -35,4 +35,16 @@ export class Logger { console.error(`[ERROR] ${message}`); } } + + time(message: string): void { + if (this.enableLogging) { + console.time(`[TIME] ${message}`); + } + } + + timeEnd(message: string): void { + if (this.enableLogging) { + console.timeEnd(`[TIME] ${message}`); + } + } } diff --git a/balancer-js/src/modules/data/pool/subgraph.ts b/balancer-js/src/modules/data/pool/subgraph.ts index 4f5e5c688..cfc963b7a 100644 --- a/balancer-js/src/modules/data/pool/subgraph.ts +++ b/balancer-js/src/modules/data/pool/subgraph.ts @@ -15,6 +15,7 @@ import { GraphQLQuery, Pool } from '@/types'; import { Network } from '@/lib/constants/network'; import { PoolsQueryVariables } from '../../subgraph/subgraph'; import { mapType } from './subgraph-helpers'; +import { Logger } from '@/lib/utils/logger'; interface PoolsSubgraphRepositoryOptions { url: string; @@ -76,7 +77,8 @@ export class PoolsSubgraphRepository * @returns Promise resolving to pools list */ private async fetchAllPools(): Promise { - console.time('fetching pools'); + const logger = Logger.getInstance(); + logger.time('fetching pools'); if (this.blockHeight) { this.query.args.block = { number: await this.blockHeight() }; @@ -88,7 +90,7 @@ export class PoolsSubgraphRepository const { pool0, pool1000, pool2000 } = await this.client.AllPools( formattedQuery ); - console.timeEnd('fetching pools'); + logger.timeEnd('fetching pools'); return [...pool0, ...pool1000, ...pool2000].map((pool) => mapType(pool, this.chainId) @@ -96,6 +98,8 @@ export class PoolsSubgraphRepository } async fetch(options?: PoolsRepositoryFetchOptions): Promise { + const logger = Logger.getInstance(); + logger.time('fetching pools'); if (options?.skip) { this.query.args.skip = options.skip; } @@ -112,6 +116,7 @@ export class PoolsSubgraphRepository const { pools } = await this.client.Pools(formattedQuery); this.skip = (options?.skip || 0) + pools.length; + logger.timeEnd('fetching pools'); return pools.map((pool) => mapType(pool, this.chainId)); } diff --git a/balancer-js/src/modules/data/pool/subgraphOnChain.ts b/balancer-js/src/modules/data/pool/subgraphOnChain.ts index c5b2b1ed6..b74c752dc 100644 --- a/balancer-js/src/modules/data/pool/subgraphOnChain.ts +++ b/balancer-js/src/modules/data/pool/subgraphOnChain.ts @@ -5,6 +5,7 @@ import { Pool } from '@/types'; import { getOnChainBalances } from '../../../modules/sor/pool-data/onChainData'; import { PoolsSubgraphRepository } from './subgraph'; import { isSameAddress } from '@/lib/utils'; +import { Logger } from '@/lib/utils/logger'; interface PoolsSubgraphOnChainRepositoryOptions { provider: Provider; @@ -59,35 +60,40 @@ export class PoolsSubgraphOnChainRepository * @returns Promise resolving to pools list */ private async fetchDefault(): Promise { - console.time('fetching pools SG'); const pools = await this.poolsSubgraph.all(); - console.timeEnd('fetching pools SG'); const filteredPools = this.filterPools(pools); - console.time(`fetching onchain ${filteredPools.length} pools`); + + const logger = Logger.getInstance(); + logger.time(`fetching onchain ${filteredPools.length} pools`); + const onchainPools = await getOnChainBalances( filteredPools, this.multicall, this.vault, this.provider ); - console.timeEnd(`fetching onchain ${filteredPools.length} pools`); + + logger.timeEnd(`fetching onchain ${filteredPools.length} pools`); return onchainPools; } async fetch(options?: PoolsRepositoryFetchOptions): Promise { - console.time('fetching pools SG'); const pools = await this.poolsSubgraph.fetch(options); - console.timeEnd('fetching pools SG'); const filteredPools = this.filterPools(pools); - console.time(`fetching onchain ${filteredPools.length} pools`); + + const logger = Logger.getInstance(); + logger.time(`fetching onchain ${filteredPools.length} pools`); + const onchainPools = await getOnChainBalances( filteredPools, this.multicall, this.vault, this.provider ); - console.timeEnd(`fetching onchain ${filteredPools.length} pools`); + + logger.timeEnd(`fetching onchain ${filteredPools.length} pools`); + return onchainPools; } diff --git a/balancer-js/src/modules/sor/pool-data/subgraphPoolDataService.ts b/balancer-js/src/modules/sor/pool-data/subgraphPoolDataService.ts index b1245c234..86dbcef33 100644 --- a/balancer-js/src/modules/sor/pool-data/subgraphPoolDataService.ts +++ b/balancer-js/src/modules/sor/pool-data/subgraphPoolDataService.ts @@ -20,6 +20,7 @@ import { } from '@/lib/graphql/args-builder'; import { isSameAddress } from '@/lib/utils'; +import { Logger } from '@/lib/utils/logger'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function mapPools(pools: any[]): SubgraphPoolBase[] { @@ -87,14 +88,17 @@ export class SubgraphPoolDataService implements PoolDataService { return mapped; } - console.time(`fetching on-chain balances for ${mapped.length} pools`); + const logger = Logger.getInstance(); + logger.time(`fetching on-chain balances for ${mapped.length} pools`); + const onChainBalances = await getOnChainBalances( mapped, this.network.addresses.contracts.multicall, this.network.addresses.contracts.vault, this.provider ); - console.timeEnd(`fetching on-chain balances for ${mapped.length} pools`); + + logger.timeEnd(`fetching on-chain balances for ${mapped.length} pools`); return onChainBalances; } From 8bf5357b926d0c9d6368d33d8b5a13e7d854775b Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 18 Aug 2023 09:54:17 -0300 Subject: [PATCH 4/5] Revert "Refactor tests so we're able to hold pool state between them when necessary" This reverts commit c00570519e68758caa5309c52a6c4318920e5129. --- .../exits.module.integration-mainnet.spec.ts | 205 ++++++++---------- balancer-js/src/modules/exits/testHelper.ts | 15 +- 2 files changed, 105 insertions(+), 115 deletions(-) diff --git a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts index 687a0d72e..6ec4335db 100644 --- a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts +++ b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts @@ -1,97 +1,48 @@ // yarn test:only ./src/modules/exits/exits.module.integration-mainnet.spec.ts import dotenv from 'dotenv'; import { expect } from 'chai'; -import { BalancerSDK, Network, PoolWithMethods } from '@/.'; +import { Network } from '@/.'; import { BigNumber, parseFixed } from '@ethersproject/bignumber'; import { accuracy } from '@/test/lib/utils'; import { ADDRESSES, TEST_BLOCK } from '@/test/lib/constants'; -import { setUpForkAndSdk, testFlow } from './testHelper'; -import { JsonRpcSigner } from '@ethersproject/providers'; +import { testFlow } from './testHelper'; dotenv.config(); -describe('generalised exit execution', async function () { - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; - let pool: { id: string; address: string; slot: number; decimals: number }; - let unwrapExitAmount: BigNumber; - let mainExitAmount: BigNumber; - let amountRatio: number; - let sdk: BalancerSDK; - let signer: JsonRpcSigner; - - const network = Network.MAINNET; - const blockNo = TEST_BLOCK[Network.MAINNET]; - const poolAddresses = Object.values(ADDRESSES[network]).map( - (address) => address.address - ); - const slippage = '10'; // 10 bps = 0.1% +const TEST_BBAUSD3 = true; - beforeEach(async () => { - const setup = await setUpForkAndSdk( - network, - blockNo, - poolAddresses, - [pool.address], - [pool.slot], - [parseFixed('120000000', 18).toString()] - ); - sdk = setup.sdk; - signer = setup.signer; - }); +const blockNo = TEST_BLOCK[Network.MAINNET]; +describe('generalised exit execution', async function () { this.timeout(120000); // Sets timeout for all tests within this scope to 2 minutes - context.only('aaveLinear V1 - bbausd', async () => { - before(async () => { - pool = ADDRESSES[network].bbausd; - amountRatio = 2; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - unwrapExitAmount = parseFixed('2000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - mainExitAmount = unwrapExitAmount.div(amountRatio); - }); + context('aaveLinear V1 - bbausd', async () => { + const network = Network.MAINNET; + const pool = ADDRESSES[network].bbausd; + const slippage = '10'; // 10 bps = 0.1% + let unwrappingTokensAmountsOut: string[]; + let unwrappingTokensGasUsed: BigNumber; + let mainTokensAmountsOut: string[]; + let mainTokensGasUsed: BigNumber; + const poolAddresses = Object.values(ADDRESSES[network]).map( + (address) => address.address + ); - beforeEach(async () => { - // prepare pool to have more wrapped than main tokens - await testFlow( - pool, - slippage, - parseFixed('1270000', 18).toString(), - [], - sdk, - signer - ); - }); + const amountRatio = 10; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + const unwrapExitAmount = parseFixed('1273000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + const mainExitAmount = unwrapExitAmount.div(amountRatio); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { - const parentPool = (await sdk.pools.find(pool.id)) as PoolWithMethods; - const childPool0 = (await sdk.pools.findBy( - 'address', - parentPool.tokensList[0] - )) as PoolWithMethods; - const childPool1 = (await sdk.pools.findBy( - 'address', - parentPool.tokensList[1] - )) as PoolWithMethods; - const childPool2 = (await sdk.pools.findBy( - 'address', - parentPool.tokensList[2] - )) as PoolWithMethods; - // log pool state to see if it's persisting between tests - console.log('childPool0', childPool0.tokens); - console.log('childPool1', childPool1.tokens); - console.log('childPool2', childPool2.tokens); - const { expectedAmountsOut, gasUsed } = await testFlow( pool, slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - sdk, - signer + network, + blockNo, + poolAddresses ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -105,8 +56,9 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - sdk, - signer + network, + blockNo, + poolAddresses ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -131,14 +83,23 @@ describe('generalised exit execution', async function () { }); context('ERC4626 - bbausd3', async () => { - before(async () => { - pool = ADDRESSES[network].bbausd3; - amountRatio = 10; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - unwrapExitAmount = parseFixed('10000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - mainExitAmount = unwrapExitAmount.div(amountRatio); - }); + if (!TEST_BBAUSD3) return true; + const network = Network.MAINNET; + const pool = ADDRESSES[network].bbausd3; + const slippage = '10'; // 10 bps = 0.1% + let unwrappingTokensAmountsOut: string[]; + let unwrappingTokensGasUsed: BigNumber; + let mainTokensAmountsOut: string[]; + let mainTokensGasUsed: BigNumber; + const poolAddresses = Object.values(ADDRESSES[network]).map( + (address) => address.address + ); + + const amountRatio = 10; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + const unwrapExitAmount = parseFixed('10000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + const mainExitAmount = unwrapExitAmount.div(amountRatio); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -147,8 +108,9 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - sdk, - signer + network, + blockNo, + poolAddresses ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -162,8 +124,9 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - sdk, - signer + network, + blockNo, + poolAddresses ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -188,15 +151,22 @@ describe('generalised exit execution', async function () { }); context('GearboxLinear - bbgusd', async () => { - before(async () => { - pool = ADDRESSES[network].bbgusd; + const network = Network.MAINNET; + const pool = ADDRESSES[network].bbgusd; + const slippage = '10'; // 10 bps = 0.1% + let unwrappingTokensAmountsOut: string[]; + let unwrappingTokensGasUsed: BigNumber; + let mainTokensAmountsOut: string[]; + let mainTokensGasUsed: BigNumber; + const poolAddresses = Object.values(ADDRESSES[network]).map( + (address) => address.address + ); - amountRatio = 100000; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - unwrapExitAmount = parseFixed('1000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - mainExitAmount = unwrapExitAmount.div(amountRatio); - }); + const amountRatio = 100000; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + const unwrapExitAmount = parseFixed('1000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + const mainExitAmount = unwrapExitAmount.div(amountRatio); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -205,8 +175,9 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].USDC.address], - sdk, - signer + network, + blockNo, + poolAddresses ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -220,8 +191,9 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - sdk, - signer + network, + blockNo, + poolAddresses ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; @@ -245,16 +217,23 @@ describe('generalised exit execution', async function () { }); }); - context('AaveLinear - bbausd2', async () => { - before(async () => { - pool = ADDRESSES[network].bbausd2; + context('AaveLinear - bbausd', async () => { + const network = Network.MAINNET; + const pool = ADDRESSES[network].bbausd2; + const slippage = '10'; // 10 bps = 0.1% + let unwrappingTokensAmountsOut: string[]; + let unwrappingTokensGasUsed: BigNumber; + let mainTokensAmountsOut: string[]; + let mainTokensGasUsed: BigNumber; + const poolAddresses = Object.values(ADDRESSES[network]).map( + (address) => address.address + ); - amountRatio = 1000; - // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped - unwrapExitAmount = parseFixed('3000000', pool.decimals); - // Amount smaller than the underlying main token balance, which will cause the exit to be done directly - mainExitAmount = unwrapExitAmount.div(amountRatio); - }); + const amountRatio = 1000; + // Amount greater than the underlying main token balance, which will cause the exit to be unwrapped + const unwrapExitAmount = parseFixed('3000000', pool.decimals); + // Amount smaller than the underlying main token balance, which will cause the exit to be done directly + const mainExitAmount = unwrapExitAmount.div(amountRatio); context('exit by unwrapping tokens', async () => { it('should exit via unwrapping', async () => { @@ -263,8 +242,9 @@ describe('generalised exit execution', async function () { slippage, unwrapExitAmount.toString(), [ADDRESSES[network].DAI.address], - sdk, - signer + network, + blockNo, + poolAddresses ); unwrappingTokensAmountsOut = expectedAmountsOut; unwrappingTokensGasUsed = gasUsed; @@ -278,8 +258,9 @@ describe('generalised exit execution', async function () { slippage, mainExitAmount.toString(), [], - sdk, - signer + network, + blockNo, + poolAddresses ); mainTokensAmountsOut = expectedAmountsOut; mainTokensGasUsed = gasUsed; diff --git a/balancer-js/src/modules/exits/testHelper.ts b/balancer-js/src/modules/exits/testHelper.ts index e7f7b77dc..bb073fb73 100644 --- a/balancer-js/src/modules/exits/testHelper.ts +++ b/balancer-js/src/modules/exits/testHelper.ts @@ -32,12 +32,21 @@ export const testFlow = async ( slippage: string, exitAmount: string, expectToUnwrap: string[], - sdk: BalancerSDK, - signer: JsonRpcSigner + network: Network, + blockNumber: number, + poolAddressesToConsider: string[] ): Promise<{ expectedAmountsOut: string[]; gasUsed: BigNumber; }> => { + const { sdk, signer } = await setUpForkAndSdk( + network, + blockNumber, + poolAddressesToConsider, + [pool.address], + [pool.slot], + [exitAmount] + ); // Follows similar flow to a front end implementation const { exitOutput, txResult, exitInfo } = await userFlow( pool, @@ -132,7 +141,7 @@ async function userFlow( }; } -export async function setUpForkAndSdk( +async function setUpForkAndSdk( network: Network, blockNumber: number, pools: string[], From aadc3923540883d0a54bf98ef22a1aa4b2b0b270 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 18 Aug 2023 10:11:30 -0300 Subject: [PATCH 5/5] Remove exit by unwrapping test scenarios --- .../exits.module.integration-mainnet.spec.ts | 40 +------------------ 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts index 6ec4335db..c1c2899a7 100644 --- a/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts +++ b/balancer-js/src/modules/exits/exits.module.integration-mainnet.spec.ts @@ -19,10 +19,6 @@ describe('generalised exit execution', async function () { const network = Network.MAINNET; const pool = ADDRESSES[network].bbausd; const slippage = '10'; // 10 bps = 0.1% - let unwrappingTokensAmountsOut: string[]; - let unwrappingTokensGasUsed: BigNumber; - let mainTokensAmountsOut: string[]; - let mainTokensGasUsed: BigNumber; const poolAddresses = Object.values(ADDRESSES[network]).map( (address) => address.address ); @@ -33,25 +29,9 @@ describe('generalised exit execution', async function () { // Amount smaller than the underlying main token balance, which will cause the exit to be done directly const mainExitAmount = unwrapExitAmount.div(amountRatio); - context('exit by unwrapping tokens', async () => { - it('should exit via unwrapping', async () => { - const { expectedAmountsOut, gasUsed } = await testFlow( - pool, - slippage, - unwrapExitAmount.toString(), - [ADDRESSES[network].DAI.address], - network, - blockNo, - poolAddresses - ); - unwrappingTokensAmountsOut = expectedAmountsOut; - unwrappingTokensGasUsed = gasUsed; - }); - }); - context('exit to main tokens directly', async () => { it('should exit to main tokens directly', async () => { - const { expectedAmountsOut, gasUsed } = await testFlow( + await testFlow( pool, slippage, mainExitAmount.toString(), @@ -60,24 +40,6 @@ describe('generalised exit execution', async function () { blockNo, poolAddresses ); - mainTokensAmountsOut = expectedAmountsOut; - mainTokensGasUsed = gasUsed; - }); - }); - - context('exit by unwrapping vs exit to main tokens', async () => { - it('should return similar amounts (proportional to the input)', async () => { - mainTokensAmountsOut.forEach((amount, i) => { - const unwrappedAmount = BigNumber.from( - unwrappingTokensAmountsOut[i] - ).div(amountRatio); - expect( - accuracy(unwrappedAmount, BigNumber.from(amount)) - ).to.be.closeTo(1, 1e-4); // inaccuracy should not be over 1 bps - }); - }); - it('should spend more gas when unwrapping tokens', async () => { - expect(unwrappingTokensGasUsed.gt(mainTokensGasUsed)).to.be.true; }); }); });