From 4e68c90a96010957efc94f8b7aed9087576e7429 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 9 Jan 2025 17:03:23 +0530 Subject: [PATCH 01/28] addres center price in poolReserves datatype --- src/abi/fluid-dex/resolver.abi.json | 30 ++++ src/dex/fluid-dex/config.ts | 4 +- src/dex/fluid-dex/constants.ts | 2 +- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 7 + .../fluid-dex/fluid-dex-liquidity-proxy.ts | 3 + src/dex/fluid-dex/fluid-dex.ts | 143 +++++++++--------- src/dex/fluid-dex/types.ts | 3 + 7 files changed, 121 insertions(+), 71 deletions(-) diff --git a/src/abi/fluid-dex/resolver.abi.json b/src/abi/fluid-dex/resolver.abi.json index 1664bce5a..3eb753451 100644 --- a/src/abi/fluid-dex/resolver.abi.json +++ b/src/abi/fluid-dex/resolver.abi.json @@ -201,6 +201,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { @@ -395,6 +400,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { @@ -1192,6 +1202,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { @@ -1392,6 +1407,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { @@ -1616,6 +1636,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { @@ -1816,6 +1841,11 @@ "name": "fee", "type": "uint256" }, + { + "internalType": "uint256", + "name": "centerPrice", + "type": "uint256" + }, { "components": [ { diff --git a/src/dex/fluid-dex/config.ts b/src/dex/fluid-dex/config.ts index 980c07325..4d5e29bbc 100644 --- a/src/dex/fluid-dex/config.ts +++ b/src/dex/fluid-dex/config.ts @@ -7,14 +7,14 @@ export const FluidDexConfig: DexConfigMap = { [Network.MAINNET]: { commonAddresses: { liquidityProxy: '0x52aa899454998be5b000ad077a46bbe360f4e497', - resolver: '0x45f4ad57e300da55c33dea579a40fcee000d7b94', + resolver: '0xF38082d58bF0f1e07C04684FF718d69a70f21e62', dexFactory: '0x91716C4EDA1Fb55e84Bf8b4c7085f84285c19085', }, }, [Network.ARBITRUM]: { commonAddresses: { liquidityProxy: '0x52Aa899454998Be5b000Ad077a46Bbe360F4e497', - resolver: '0xb8f526718FF58758E256D9aD86bC194a9ff5986D', + resolver: '0xCe6F4E40152a1DF97ae95a7e4F60D944871A4060', dexFactory: '0x91716C4EDA1Fb55e84Bf8b4c7085f84285c19085', }, }, diff --git a/src/dex/fluid-dex/constants.ts b/src/dex/fluid-dex/constants.ts index da6d99534..e5060df3f 100644 --- a/src/dex/fluid-dex/constants.ts +++ b/src/dex/fluid-dex/constants.ts @@ -1 +1 @@ -export const MIN_SWAP_LIQUIDITY = 10n ** 4n; +export const MIN_SWAP_LIQUIDITY = 20n ** 4n; diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index b10f72c5d..33bb6c82d 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -247,6 +247,9 @@ function NewDebtReservesOne(): DebtReserves { }; } +const centerPriceTight: bigint = 3401944443797854601871360n; +const centerPriceWide: bigint = 1190081051944310368000000000n; + const limitsTight: DexLimits = { withdrawableToken0: { available: 456740438880263n, @@ -314,6 +317,7 @@ describe('TestPoolSimulator_SwapInLimits', () => { 100n, 18, limitsTight, + BigInt(centerPriceTight), Math.floor(Date.now() / 1000) - 10, ); expect(outAmt).toEqual(0n); @@ -331,6 +335,7 @@ describe('TestPoolSimulator_SwapInLimits', () => { 100n, 18, limitsTight, + BigInt(centerPriceTight), Math.floor(Date.now() / 1000) - 6000, ); console.log('outAmt: ', outAmt); @@ -348,6 +353,7 @@ describe('TestPoolSimulator_SwapInLimits', () => { 100n, 18, limitsWide, + BigInt(centerPriceWide), Math.floor(Date.now() / 1000) - 10, ); expect(outAmt).toEqual(0n); @@ -367,6 +373,7 @@ describe('TestPoolSimulator_SwapInLimits', () => { 100n, 18, limitsWide, + BigInt(centerPriceWide), Math.floor(Date.now() / 1000) - 10, ); expect(outAmt).toEqual(0n); diff --git a/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts b/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts index f6f7b890b..66691b0cc 100644 --- a/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts +++ b/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts @@ -137,12 +137,14 @@ export class FluidDexLiquidityProxy extends StatefulEventSubscriber { logger: Logger; pools: FluidDexPool[] = []; - // temporarily limit FLUID-ETH Dex Pool. restrictedIds: string[] = [ 'FluidDex_0xc800b0e15c40a1ff0539218100c86f4c1bac8d9c', @@ -260,6 +259,7 @@ export class FluidDex extends SimpleExchange implements IDex { destToken.decimals, BigInt(currentPoolReserves.fee), currentPoolReserves.dexLimits, + BigInt(currentPoolReserves.centerPrice), Math.floor(Date.now() / 1000), ); } else { @@ -272,6 +272,7 @@ export class FluidDex extends SimpleExchange implements IDex { destToken.decimals, BigInt(currentPoolReserves.fee), currentPoolReserves.dexLimits, + BigInt(currentPoolReserves.centerPrice), Math.floor(Date.now() / 1000), ); } @@ -415,6 +416,7 @@ export class FluidDex extends SimpleExchange implements IDex { outDecimals: number, fee: bigint, currentLimits: DexLimits, + centerPrice: bigint, syncTime: number, ): bigint { if (amountIn === 0n) { @@ -438,6 +440,7 @@ export class FluidDex extends SimpleExchange implements IDex { fee, outDecimals, currentLimits, + centerPrice, syncTime, ); return (amountOut * BigInt(10 ** outDecimals)) / BigInt(10 ** 12); @@ -459,6 +462,7 @@ export class FluidDex extends SimpleExchange implements IDex { fee: bigint, outDecimals: number, currentLimits: DexLimits, + centerPrice: bigint, syncTime: number, ): bigint { const { @@ -603,6 +607,40 @@ export class FluidDex extends SimpleExchange implements IDex { return 0n; } + if (amountInCollateral > 0) { + let reservesRatioValid = swap0To1 + ? this.verifyToken1Reserves( + colReserveIn + amountInCollateral, + colReserveOut - amountOutCollateral, + centerPrice, + ) + : this.verifyToken0Reserves( + colReserveOut - amountOutCollateral, + colReserveIn + amountInCollateral, + centerPrice, + ); + if (!reservesRatioValid) { + return BigInt(Number.MAX_VALUE); + } + } + + if (amountInDebt > 0) { + let reservesRatioValid = swap0To1 + ? this.verifyToken1Reserves( + debtReserveIn + amountInDebt, + debtReserveOut - amountOutDebt, + centerPrice, + ) + : this.verifyToken0Reserves( + debtReserveOut - amountOutDebt, + debtReserveIn + amountInDebt, + centerPrice, + ); + if (!reservesRatioValid) { + return BigInt(Number.MAX_VALUE); + } + } + // For price calculations, we'll use a precision factor for bigint division const PRECISION = 1000000000000000000000000000n; // 1e27 @@ -642,40 +680,6 @@ export class FluidDex extends SimpleExchange implements IDex { return 0n; } - if (amountInCollateral > 0) { - let reservesRatioValid = swap0To1 - ? this.verifyToken1Reserves( - colReserveIn + amountInCollateral, - colReserveOut - amountOutCollateral, - oldPrice, - ) - : this.verifyToken0Reserves( - colReserveOut - amountOutCollateral, - colReserveIn + amountInCollateral, - oldPrice, - ); - if (!reservesRatioValid) { - return 0n; - } - } - - if (amountInDebt > 0) { - let reservesRatioValid = swap0To1 - ? this.verifyToken1Reserves( - debtReserveIn + amountInDebt, - debtReserveOut - amountOutDebt, - oldPrice, - ) - : this.verifyToken0Reserves( - debtReserveOut - amountOutDebt, - debtReserveIn + amountInDebt, - oldPrice, - ); - if (!reservesRatioValid) { - return 0n; - } - } - const totalAmountOut = amountOutCollateral + amountOutDebt; return totalAmountOut; @@ -879,6 +883,7 @@ export class FluidDex extends SimpleExchange implements IDex { outDecimals: number, fee: bigint, currentLimits: DexLimits, + centerPrice: bigint, syncTime: number, ): bigint { const amountOutAdjusted = @@ -892,6 +897,7 @@ export class FluidDex extends SimpleExchange implements IDex { fee, outDecimals, currentLimits, + centerPrice, syncTime, ); @@ -919,6 +925,7 @@ export class FluidDex extends SimpleExchange implements IDex { fee: bigint, outDecimals: number, currentLimits: DexLimits, + centerPrice: bigint, syncTime: number, ): bigint { if (amountOut === 0n) { @@ -1079,6 +1086,39 @@ export class FluidDex extends SimpleExchange implements IDex { } } + if (amountInCollateral > 0) { + let reservesRatioValid = swap0to1 + ? this.verifyToken1Reserves( + colReserveIn + amountInCollateral, + colReserveOut - amountOutCollateral, + centerPrice, + ) + : this.verifyToken0Reserves( + colReserveOut - amountOutCollateral, + colReserveIn + amountInCollateral, + centerPrice, + ); + if (!reservesRatioValid) { + return BigInt(Number.MAX_VALUE); + } + } + if (amountInDebt > 0) { + let reservesRatioValid = swap0to1 + ? this.verifyToken1Reserves( + debtReserveIn + amountInDebt, + debtReserveOut - amountOutDebt, + centerPrice, + ) + : this.verifyToken0Reserves( + debtReserveOut - amountOutDebt, + debtReserveIn + amountInDebt, + centerPrice, + ); + if (!reservesRatioValid) { + return BigInt(Number.MAX_VALUE); + } + } + let oldPrice: bigint; let newPrice: bigint; const SCALE = BigInt(1e27); @@ -1115,39 +1155,6 @@ export class FluidDex extends SimpleExchange implements IDex { return 2n ** 256n - 1n; } - if (amountInCollateral > 0) { - let reservesRatioValid = swap0to1 - ? this.verifyToken1Reserves( - colReserveIn + amountInCollateral, - colReserveOut - amountOutCollateral, - oldPrice, - ) - : this.verifyToken0Reserves( - colReserveOut - amountOutCollateral, - colReserveIn + amountInCollateral, - oldPrice, - ); - if (!reservesRatioValid) { - return 0n; - } - } - if (amountInDebt > 0) { - let reservesRatioValid = swap0to1 - ? this.verifyToken1Reserves( - debtReserveIn + amountInDebt, - debtReserveOut - amountOutDebt, - oldPrice, - ) - : this.verifyToken0Reserves( - debtReserveOut - amountOutDebt, - debtReserveIn + amountInDebt, - oldPrice, - ); - if (!reservesRatioValid) { - return 0n; - } - } - const totalAmountIn = amountInCollateral + amountInDebt; return totalAmountIn; diff --git a/src/dex/fluid-dex/types.ts b/src/dex/fluid-dex/types.ts index 0fb982e07..f572e5a04 100644 --- a/src/dex/fluid-dex/types.ts +++ b/src/dex/fluid-dex/types.ts @@ -6,6 +6,7 @@ export type PoolReserve = { token0: string; token1: string; fee: number; + centerPrice: number; collateralReserves: CollateralReserves; debtReserves: DebtReserves; dexLimits: DexLimits; @@ -16,6 +17,7 @@ export type PoolReserveResponse = [ string, string, BigNumber, + BigNumber, BigNumber[], BigNumber[], DexLimitResponse, @@ -68,6 +70,7 @@ export interface PoolWithReserves { token0: string; token1: string; fee: number; + centerPrice: number; collateralReserves: CollateralReserves; debtReserves: DebtReserves; } From 1b8768f8133a2a257df8df68da353cef8c65e112 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 9 Jan 2025 21:45:34 +0530 Subject: [PATCH 02/28] changed e2e test file --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 33bb6c82d..d976ed46b 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -119,13 +119,14 @@ describe('FluidDex E2E', () => { const network = Network.MAINNET; // TODO: Uncomment & test when the issue is resolved. Currently no price as expected. + // isSwapAndArbitragePaused is set to true, so will not work // describe.only('FLUID -> ETH', () => { // const tokenASymbol: string = 'FLUID'; // const tokenBSymbol: string = 'ETH'; - // + // const tokenAAmount: string = '160097047322810379'; // const tokenBAmount: string = '79923068733005505624'; - // + // testForNetwork( // network, // dexKey, @@ -136,7 +137,7 @@ describe('FluidDex E2E', () => { // ); // }); - describe('ETH -> INST', () => { + describe.only('ETH -> INST', () => { const tokenASymbol: string = 'ETH'; const tokenBSymbol: string = 'INST'; @@ -339,7 +340,7 @@ describe('TestPoolSimulator_SwapInLimits', () => { Math.floor(Date.now() / 1000) - 6000, ); console.log('outAmt: ', outAmt); - expect(outAmt?.toString()).toEqual('998262697204710'); + expect(outAmt?.toString()).toEqual('998163044346107'); }); it('when price diff hit', () => { From 7316f716aebea646ef07e41535f418f147d2786c Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 9 Jan 2025 23:32:15 +0530 Subject: [PATCH 03/28] . --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 47 +++++++++++++------------ src/dex/fluid-dex/fluid-dex.ts | 17 ++++----- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index d976ed46b..1d69c8190 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -119,30 +119,14 @@ describe('FluidDex E2E', () => { const network = Network.MAINNET; // TODO: Uncomment & test when the issue is resolved. Currently no price as expected. - // isSwapAndArbitragePaused is set to true, so will not work - // describe.only('FLUID -> ETH', () => { - // const tokenASymbol: string = 'FLUID'; - // const tokenBSymbol: string = 'ETH'; - - // const tokenAAmount: string = '160097047322810379'; - // const tokenBAmount: string = '79923068733005505624'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // ); - // }); + describe('FLUID -> ETH', () => { + const tokenASymbol: string = 'FLUID'; + const tokenBSymbol: string = 'ETH'; - describe.only('ETH -> INST', () => { - const tokenASymbol: string = 'ETH'; - const tokenBSymbol: string = 'INST'; - - const tokenAAmount: string = '100000000000000'; - const tokenBAmount: string = '100000000000000'; + const tokenAAmount: string = '16009704732281'; + const tokenBAmount: string = '7992306873000001'; + // const tokenAAmount: string = '160097047322810379'; + // const tokenBAmount: string = '79923068733005505624'; testForNetwork( network, @@ -154,6 +138,23 @@ describe('FluidDex E2E', () => { ); }); + // describe.only('ETH -> INST', () => { + // const tokenASymbol: string = 'ETH'; + // const tokenBSymbol: string = 'INST'; + + // const tokenAAmount: string = '100000000000000'; + // const tokenBAmount: string = '100000000000000'; + + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // ); + // }); + describe('ETH -> wstETH', () => { const tokenASymbol: string = 'wstETH'; const tokenBSymbol: string = 'ETH'; diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 6fd9274c6..53c3aecee 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -48,9 +48,7 @@ export class FluidDex extends SimpleExchange implements IDex { pools: FluidDexPool[] = []; // temporarily limit FLUID-ETH Dex Pool. - restrictedIds: string[] = [ - 'FluidDex_0xc800b0e15c40a1ff0539218100c86f4c1bac8d9c', - ]; + restrictedIds: string[] = []; eventPools: FluidDexEventPool[] = []; @@ -620,7 +618,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return BigInt(Number.MAX_VALUE); + return 2n ** 256n - 1n; } } @@ -637,7 +635,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return BigInt(Number.MAX_VALUE); + return 2n ** 256n - 1n; } } @@ -904,7 +902,10 @@ export class FluidDex extends SimpleExchange implements IDex { if (amountIn === 2n ** 256n - 1n) { return amountIn; } - const ans = (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12); + const ans = + amountIn !== 2n ** 256n - 1n + ? (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12) + : amountIn; return ans; } @@ -1099,7 +1100,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return BigInt(Number.MAX_VALUE); + return 2n ** 256n - 1n; } } if (amountInDebt > 0) { @@ -1115,7 +1116,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return BigInt(Number.MAX_VALUE); + return 2n ** 256n - 1n; } } From 0f54120974eb4c5da8fea7aa34ddf97f69f39d52 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Fri, 10 Jan 2025 02:45:08 +0530 Subject: [PATCH 04/28] cleaned up --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 19 ------------------- src/dex/fluid-dex/fluid-dex.ts | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 1d69c8190..ec10815b7 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -125,8 +125,6 @@ describe('FluidDex E2E', () => { const tokenAAmount: string = '16009704732281'; const tokenBAmount: string = '7992306873000001'; - // const tokenAAmount: string = '160097047322810379'; - // const tokenBAmount: string = '79923068733005505624'; testForNetwork( network, @@ -138,23 +136,6 @@ describe('FluidDex E2E', () => { ); }); - // describe.only('ETH -> INST', () => { - // const tokenASymbol: string = 'ETH'; - // const tokenBSymbol: string = 'INST'; - - // const tokenAAmount: string = '100000000000000'; - // const tokenBAmount: string = '100000000000000'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // ); - // }); - describe('ETH -> wstETH', () => { const tokenASymbol: string = 'wstETH'; const tokenBSymbol: string = 'ETH'; diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 53c3aecee..c5f5992b7 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -47,7 +47,7 @@ export class FluidDex extends SimpleExchange implements IDex { logger: Logger; pools: FluidDexPool[] = []; - // temporarily limit FLUID-ETH Dex Pool. + restrictedIds: string[] = []; eventPools: FluidDexEventPool[] = []; From 42b68932c1132fdaf38947eba45cf5ee99f06899 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Fri, 10 Jan 2025 14:16:55 +0530 Subject: [PATCH 05/28] . --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 1 - src/dex/fluid-dex/fluid-dex.ts | 18 +++--------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index ec10815b7..b9805e344 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -118,7 +118,6 @@ describe('FluidDex E2E', () => { describe('Mainnet', () => { const network = Network.MAINNET; - // TODO: Uncomment & test when the issue is resolved. Currently no price as expected. describe('FLUID -> ETH', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index c5f5992b7..ce729d654 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -48,8 +48,6 @@ export class FluidDex extends SimpleExchange implements IDex { pools: FluidDexPool[] = []; - restrictedIds: string[] = []; - eventPools: FluidDexEventPool[] = []; readonly factory: FluidDexFactory; @@ -112,9 +110,7 @@ export class FluidDex extends SimpleExchange implements IDex { // implement this function async initializePricing(blockNumber: number) { await this.factory.initialize(blockNumber); - this.pools = (await this.fetchFluidDexPools(blockNumber)).filter( - pool => !this.restrictedIds.includes(pool.id), - ); + this.pools = await this.fetchFluidDexPools(blockNumber); this.eventPools = await Promise.all( this.pools.map(async pool => { const eventPool = new FluidDexEventPool( @@ -137,9 +133,7 @@ export class FluidDex extends SimpleExchange implements IDex { } protected onPoolCreatedUpdatePools(poolsFromFactory: readonly Pool[]) { - this.pools = this.generateFluidDexPoolsFromPoolsFactory( - poolsFromFactory, - ).filter(pool => !this.restrictedIds.includes(pool.id)); + this.pools = this.generateFluidDexPoolsFromPoolsFactory(poolsFromFactory); this.logger.info(`${this.dexKey}: pools list was updated ...`); } @@ -179,9 +173,6 @@ export class FluidDex extends SimpleExchange implements IDex { // A pair must have 2 different tokens. if (srcAddress === destAddress) return []; - this.pools = this.pools.filter( - pool => !this.restrictedIds.includes(pool.id), - ); const pools = this.pools.filter( pool => (srcAddress === pool.token0 && destAddress === pool.token1) || @@ -902,10 +893,7 @@ export class FluidDex extends SimpleExchange implements IDex { if (amountIn === 2n ** 256n - 1n) { return amountIn; } - const ans = - amountIn !== 2n ** 256n - 1n - ? (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12) - : amountIn; + const ans = (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12); return ans; } From 530658cb6249b9bb59d72261dce835382bd4ccc1 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Sat, 11 Jan 2025 15:15:38 +0530 Subject: [PATCH 06/28] updated resolver address --- src/dex/fluid-dex/config.ts | 2 +- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/fluid-dex/config.ts b/src/dex/fluid-dex/config.ts index 4d5e29bbc..b7ab3abfe 100644 --- a/src/dex/fluid-dex/config.ts +++ b/src/dex/fluid-dex/config.ts @@ -7,7 +7,7 @@ export const FluidDexConfig: DexConfigMap = { [Network.MAINNET]: { commonAddresses: { liquidityProxy: '0x52aa899454998be5b000ad077a46bbe360f4e497', - resolver: '0xF38082d58bF0f1e07C04684FF718d69a70f21e62', + resolver: '0xb387f9C2092cF7c4943F97842887eBff7AE96EB3', dexFactory: '0x91716C4EDA1Fb55e84Bf8b4c7085f84285c19085', }, }, diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index b9805e344..f455b06bb 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -122,8 +122,8 @@ describe('FluidDex E2E', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; - const tokenAAmount: string = '16009704732281'; - const tokenBAmount: string = '7992306873000001'; + const tokenAAmount: string = '16009704732'; + const tokenBAmount: string = '7992306000001'; testForNetwork( network, From 917f21999ea44b57ef7d1dd004ecec8f4b994356 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 16 Jan 2025 12:40:10 +0530 Subject: [PATCH 07/28] added errors --- src/dex/fluid-dex/constants.ts | 2 +- src/dex/fluid-dex/fluid-dex.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dex/fluid-dex/constants.ts b/src/dex/fluid-dex/constants.ts index e5060df3f..da6d99534 100644 --- a/src/dex/fluid-dex/constants.ts +++ b/src/dex/fluid-dex/constants.ts @@ -1 +1 @@ -export const MIN_SWAP_LIQUIDITY = 20n ** 4n; +export const MIN_SWAP_LIQUIDITY = 10n ** 4n; diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index ce729d654..56294d41f 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -609,7 +609,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); } } @@ -626,7 +626,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); } } @@ -1088,7 +1088,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); } } if (amountInDebt > 0) { @@ -1104,7 +1104,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); } } From 7349bb08ac05edc8f9358415546864580e483148 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 16 Jan 2025 14:38:31 +0530 Subject: [PATCH 08/28] updated min_swap_liquidity --- src/dex/fluid-dex/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/fluid-dex/constants.ts b/src/dex/fluid-dex/constants.ts index da6d99534..91a261b71 100644 --- a/src/dex/fluid-dex/constants.ts +++ b/src/dex/fluid-dex/constants.ts @@ -1 +1 @@ -export const MIN_SWAP_LIQUIDITY = 10n ** 4n; +export const MIN_SWAP_LIQUIDITY = 2n * 10n ** 4n; From 0d67f08629401db08efd83e45d7e4e51105f2da0 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Fri, 17 Jan 2025 13:52:44 +0530 Subject: [PATCH 09/28] updated min_swap_liquidity --- src/dex/fluid-dex/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/fluid-dex/constants.ts b/src/dex/fluid-dex/constants.ts index 91a261b71..937bdfb73 100644 --- a/src/dex/fluid-dex/constants.ts +++ b/src/dex/fluid-dex/constants.ts @@ -1 +1,2 @@ -export const MIN_SWAP_LIQUIDITY = 2n * 10n ** 4n; +// on-chain we use 1e4 but use extra buffer to avoid reverts +export const MIN_SWAP_LIQUIDITY = 5n * 10n ** 3n; From ca07db914cd85e6c04b6a82c99ac9f619d8d7cb7 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 23 Jan 2025 13:43:02 +0530 Subject: [PATCH 10/28] handled price calculation errors --- src/dex/fluid-dex/constants.ts | 2 +- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 73 ++++++++++++++++++++----- src/dex/fluid-dex/fluid-dex.ts | 3 +- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/dex/fluid-dex/constants.ts b/src/dex/fluid-dex/constants.ts index 937bdfb73..3db958610 100644 --- a/src/dex/fluid-dex/constants.ts +++ b/src/dex/fluid-dex/constants.ts @@ -1,2 +1,2 @@ // on-chain we use 1e4 but use extra buffer to avoid reverts -export const MIN_SWAP_LIQUIDITY = 5n * 10n ** 3n; +export const MIN_SWAP_LIQUIDITY = 8500n; diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index f455b06bb..6378e9109 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -4,11 +4,7 @@ dotenv.config(); import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { generateConfig } from '../../config'; import { CollateralReserves, DebtReserves, DexLimits } from './types'; @@ -66,9 +62,14 @@ function testForNetwork( generateConfig(network).privateHttpProvider, network, ); + const tokens = Tokens[network]; const holders = Holders[network]; + // Create FluidDex instance to check reserves + const dexHelper = new DummyDexHelper(network); + const fluidDex = new FluidDex(network, dexKey, dexHelper); + const sideToContractMethods = new Map([ [SwapSide.SELL, [ContractMethod.swapExactAmountIn]], [SwapSide.BUY, [ContractMethod.swapExactAmountOut]], @@ -79,11 +80,32 @@ function testForNetwork( describe(`${side}`, () => { contractMethods.forEach((contractMethod: string) => { describe(`${contractMethod}`, () => { - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { + await fluidDex.initializePricing(await provider.getBlockNumber()); + + try { + const pricesB2A = await fluidDex.getPricesVolume( + tokens[tokenBSymbol], + tokens[tokenASymbol], + [BigInt(tokenBAmount)], + side, + await provider.getBlockNumber(), + ); + console.log( + `price check ${tokenBSymbol} -> ${tokenASymbol}`, + pricesB2A, + ); + } catch (e: any) { + console.log(`Skipping ${tokenBSymbol} -> ${tokenASymbol}`); + if (e.message.includes('TokenReservesTooLow')) { + return; + } + } + await testE2E( - tokens[tokenASymbol], tokens[tokenBSymbol], - holders[tokenASymbol], + tokens[tokenASymbol], + holders[tokenBSymbol], tokenBAmount, side, dexKey, @@ -92,12 +114,37 @@ function testForNetwork( provider, ); }); - it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { + + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // Check prices before running test + try { + await fluidDex.initializePricing( + await provider.getBlockNumber(), + ); + + const pricesA2B = await fluidDex.getPricesVolume( + tokens[tokenASymbol], + tokens[tokenBSymbol], + [BigInt(tokenAAmount)], + side, + await provider.getBlockNumber(), + ); + console.log( + `price check ${tokenASymbol} -> ${tokenBSymbol}`, + pricesA2B, + ); + } catch (e: any) { + console.log(`Skipping ${tokenASymbol} -> ${tokenBSymbol}`); + if (e.message.includes('TokenReservesTooLow')) { + return; + } + } + await testE2E( - tokens[tokenBSymbol], tokens[tokenASymbol], - holders[tokenBSymbol], - tokenBAmount, + tokens[tokenBSymbol], + holders[tokenASymbol], + tokenAAmount, side, dexKey, contractMethod as ContractMethod, @@ -121,7 +168,6 @@ describe('FluidDex E2E', () => { describe('FLUID -> ETH', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; - const tokenAAmount: string = '16009704732'; const tokenBAmount: string = '7992306000001'; @@ -320,7 +366,6 @@ describe('TestPoolSimulator_SwapInLimits', () => { BigInt(centerPriceTight), Math.floor(Date.now() / 1000) - 6000, ); - console.log('outAmt: ', outAmt); expect(outAmt?.toString()).toEqual('998163044346107'); }); diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 56294d41f..a41386ea5 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -293,6 +293,7 @@ export class FluidDex extends SimpleExchange implements IDex { }, ${side}:`, e, ); + throw e; return null; } } @@ -895,7 +896,7 @@ export class FluidDex extends SimpleExchange implements IDex { } const ans = (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12); - return ans; + return (ans * (100000n - 5n)) / 100000n; } /** From c958d11d3ffebf1a2e88e95c64937706a65433cf Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 23 Jan 2025 18:41:57 +0530 Subject: [PATCH 11/28] . --- src/dex/fluid-dex/fluid-dex.ts | 39 ++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index a41386ea5..21f1f5a8e 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -416,7 +416,8 @@ export class FluidDex extends SimpleExchange implements IDex { colReserves.token0RealReserves + debtReserves.token0RealReserves == 0n && colReserves.token1RealReserves + debtReserves.token1RealReserves == 0n ) { - return 0n; + throw new Error('InvalidCollateralReserves'); + // return 0n; } const amountInAdjusted = @@ -583,18 +584,22 @@ export class FluidDex extends SimpleExchange implements IDex { } if (amountOutDebt > debtReserveOut) { - return 0n; + throw new Error('DebtReservesTooLow'); + // return 0n; } if (amountOutDebt > borrowable) { - return 0n; + throw new Error('DebtLimitReached'); + // return 0n; } if (amountOutCollateral > colReserveOut) { - return 0n; + throw new Error('TokenReservesTooLow'); + // return 0n; } if (amountOutCollateral > withdrawable) { - return 0n; + throw new Error('WithdrawLimitReached'); + // return 0n; } if (amountInCollateral > 0) { @@ -667,7 +672,8 @@ export class FluidDex extends SimpleExchange implements IDex { const maxAllowedDiff = (oldPrice * MAX_PRICE_DIFF) / 100n; if (priceDiff > maxAllowedDiff) { - return 0n; + throw new Error('OracleUpdateHugeSwapDiff'); + // return 0n; } const totalAmountOut = amountOutCollateral + amountOutDebt; @@ -1033,10 +1039,12 @@ export class FluidDex extends SimpleExchange implements IDex { ); amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOut > debtReserveOut) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); + // return 2n ** 256n - 1n; } if (amountOut > borrowable) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); + // return 2n ** 256n - 1n; } } else if (a >= amountOut) { // Entire trade routes through collateral pool @@ -1048,10 +1056,12 @@ export class FluidDex extends SimpleExchange implements IDex { ); amountInCollateral = this.applyFeeForBuy(amountInCollateral, fee); if (amountOut > colReserveOut) { - return 2n ** 256n - 1n; + throw new Error('DebtLimitReached'); + // return 2n ** 256n - 1n; } if (amountOut > withdrawable) { - return 2n ** 256n - 1n; + throw new Error('WithdrawLimitReached'); + // return 2n ** 256n - 1n; } } else { // Trade routes through both pools @@ -1069,10 +1079,12 @@ export class FluidDex extends SimpleExchange implements IDex { amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOutDebt > debtReserveOut || a > colReserveOut) { - return 2n ** 256n - 1n; + throw new Error('TokenReservesTooLow'); + // return 2n ** 256n - 1n; } if (amountOutDebt > borrowable || a > withdrawable) { - return 2n ** 256n - 1n; + throw new Error('SwapOutLimitingAmounts'); + // return 2n ** 256n - 1n; } } @@ -1142,7 +1154,8 @@ export class FluidDex extends SimpleExchange implements IDex { (oldPrice / BigInt(100)) * MAX_PRICE_DIFF ) { // if price diff is > 5% then swap would revert. - return 2n ** 256n - 1n; + throw new Error('OracleUpdateHugeSwapDiff'); + // return 2n ** 256n - 1n; } const totalAmountIn = amountInCollateral + amountInDebt; From d17f4060a30fa35849557adb3da7d641fa6f7755 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Thu, 23 Jan 2025 19:36:59 +0530 Subject: [PATCH 12/28] updated errors --- src/dex/fluid-dex/fluid-dex.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 21f1f5a8e..e5aa02860 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -1043,7 +1043,7 @@ export class FluidDex extends SimpleExchange implements IDex { // return 2n ** 256n - 1n; } if (amountOut > borrowable) { - throw new Error('TokenReservesTooLow'); + throw new Error('DebtLimitReached'); // return 2n ** 256n - 1n; } } else if (a >= amountOut) { @@ -1056,7 +1056,7 @@ export class FluidDex extends SimpleExchange implements IDex { ); amountInCollateral = this.applyFeeForBuy(amountInCollateral, fee); if (amountOut > colReserveOut) { - throw new Error('DebtLimitReached'); + throw new Error('TokenReservesTooLow'); // return 2n ** 256n - 1n; } if (amountOut > withdrawable) { @@ -1083,7 +1083,7 @@ export class FluidDex extends SimpleExchange implements IDex { // return 2n ** 256n - 1n; } if (amountOutDebt > borrowable || a > withdrawable) { - throw new Error('SwapOutLimitingAmounts'); + throw new Error('WithdrawLimitReached or DebtLimitReached'); // return 2n ** 256n - 1n; } } From 0565996caa8b6a8e9b5a7d32195ddde960762a52 Mon Sep 17 00:00:00 2001 From: 0xprinc Date: Fri, 24 Jan 2025 15:19:40 +0530 Subject: [PATCH 13/28] added errors to test also --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 36 +++++++++++++++++++++---- src/dex/fluid-dex/fluid-dex.ts | 13 --------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index e8b835e0b..3bfacc104 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -87,7 +87,20 @@ function testForNetwork( ); } catch (e: any) { console.log(`Skipping ${tokenBSymbol} -> ${tokenASymbol}`); - if (e.message.includes('TokenReservesTooLow')) { + const errorMessages = [ + 'TokenReservesTooLow', + 'InvalidCollateralReserves', + 'No pools are enabled', + 'DebtReservesTooLow', + 'DebtLimitReached', + 'WithdrawLimitReached', + 'OracleUpdateHugeSwapDiff', + ]; + if ( + errorMessages.some(errorMessage => + e.message.includes(errorMessage), + ) + ) { return; } } @@ -125,7 +138,20 @@ function testForNetwork( ); } catch (e: any) { console.log(`Skipping ${tokenASymbol} -> ${tokenBSymbol}`); - if (e.message.includes('TokenReservesTooLow')) { + const errorMessages = [ + 'TokenReservesTooLow', + 'InvalidCollateralReserves', + 'No pools are enabled', + 'DebtReservesTooLow', + 'DebtLimitReached', + 'WithdrawLimitReached', + 'OracleUpdateHugeSwapDiff', + ]; + if ( + errorMessages.some(errorMessage => + e.message.includes(errorMessage), + ) + ) { return; } } @@ -314,9 +340,9 @@ const limitsWide: DexLimits = { }, }; -const ErrInsufficientBorrowable = new Error('insufficient borrowable'); -const ErrInsufficientMaxPrice = new Error('insufficient max price'); -const ErrInsufficientReserve = new Error('insufficient reserve'); +const ErrInsufficientBorrowable = new Error('DebtLimitReached'); +const ErrInsufficientMaxPrice = new Error('OracleUpdateHugeSwapDiff'); +const ErrInsufficientReserve = new Error('DebtReservesTooLow'); describe('TestPoolSimulator_SwapInLimits', () => { const network = Network.MAINNET; diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index e5aa02860..7cfdbf8bf 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -417,7 +417,6 @@ export class FluidDex extends SimpleExchange implements IDex { colReserves.token1RealReserves + debtReserves.token1RealReserves == 0n ) { throw new Error('InvalidCollateralReserves'); - // return 0n; } const amountInAdjusted = @@ -585,21 +584,17 @@ export class FluidDex extends SimpleExchange implements IDex { if (amountOutDebt > debtReserveOut) { throw new Error('DebtReservesTooLow'); - // return 0n; } if (amountOutDebt > borrowable) { throw new Error('DebtLimitReached'); - // return 0n; } if (amountOutCollateral > colReserveOut) { throw new Error('TokenReservesTooLow'); - // return 0n; } if (amountOutCollateral > withdrawable) { throw new Error('WithdrawLimitReached'); - // return 0n; } if (amountInCollateral > 0) { @@ -673,7 +668,6 @@ export class FluidDex extends SimpleExchange implements IDex { if (priceDiff > maxAllowedDiff) { throw new Error('OracleUpdateHugeSwapDiff'); - // return 0n; } const totalAmountOut = amountOutCollateral + amountOutDebt; @@ -1040,11 +1034,9 @@ export class FluidDex extends SimpleExchange implements IDex { amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOut > debtReserveOut) { throw new Error('TokenReservesTooLow'); - // return 2n ** 256n - 1n; } if (amountOut > borrowable) { throw new Error('DebtLimitReached'); - // return 2n ** 256n - 1n; } } else if (a >= amountOut) { // Entire trade routes through collateral pool @@ -1057,11 +1049,9 @@ export class FluidDex extends SimpleExchange implements IDex { amountInCollateral = this.applyFeeForBuy(amountInCollateral, fee); if (amountOut > colReserveOut) { throw new Error('TokenReservesTooLow'); - // return 2n ** 256n - 1n; } if (amountOut > withdrawable) { throw new Error('WithdrawLimitReached'); - // return 2n ** 256n - 1n; } } else { // Trade routes through both pools @@ -1080,11 +1070,9 @@ export class FluidDex extends SimpleExchange implements IDex { amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOutDebt > debtReserveOut || a > colReserveOut) { throw new Error('TokenReservesTooLow'); - // return 2n ** 256n - 1n; } if (amountOutDebt > borrowable || a > withdrawable) { throw new Error('WithdrawLimitReached or DebtLimitReached'); - // return 2n ** 256n - 1n; } } @@ -1155,7 +1143,6 @@ export class FluidDex extends SimpleExchange implements IDex { ) { // if price diff is > 5% then swap would revert. throw new Error('OracleUpdateHugeSwapDiff'); - // return 2n ** 256n - 1n; } const totalAmountIn = amountInCollateral + amountInDebt; From e7e18f7ab7f828000e50fdb566501d6ac9c4b1a7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 28 Jan 2025 21:59:55 +0200 Subject: [PATCH 14/28] fix: add failing test + minor --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 35 +++---------------------- tests/constants-e2e.ts | 2 +- tests/tenderly-simulation.ts | 1 + 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 3bfacc104..4911b5e23 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -11,35 +11,6 @@ import { CollateralReserves, DebtReserves, DexLimits } from './types'; import { DummyDexHelper } from '../../dex-helper/index'; import { FluidDex } from './fluid-dex'; -/* - README - ====== - - The template already enumerates the basic structure which involves - testing simpleSwap, multiSwap, megaSwap contract methods for - ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and - tokenB with any two highly liquid tokens on FluidDex for the tests - to work. If the tokens that you would like to use are not defined in - Tokens or Holders map, you can update the './tests/constants-e2e' - - Other than the standard cases that are already added by the template - it is highly recommended to add test cases which could be specific - to testing FluidDex (Eg. Tests based on poolType, special tokens, - etc). - - You can run this individual test script by running: - `npx jest src/dex//-e2e.test.ts` - - e2e tests use the Tenderly fork api. Please add the following to your - .env file: - TENDERLY_TOKEN=Find this under Account>Settings>Authorization. - TENDERLY_ACCOUNT_ID=Your Tenderly account name. - TENDERLY_PROJECT=Name of a Tenderly project you have created in your - dashboard. - - (This comment should be removed from the final implementation) -*/ - function testForNetwork( network: Network, dexKey: string, @@ -181,11 +152,11 @@ describe('FluidDex E2E', () => { describe('Mainnet', () => { const network = Network.MAINNET; - describe('FLUID -> ETH', () => { + describe('failing:FLUID -> ETH', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; - const tokenAAmount: string = '16009704732'; - const tokenBAmount: string = '7992306000001'; + const tokenAAmount: string = '160097047322810379'; + const tokenBAmount: string = '79923068733005505624'; testForNetwork( network, diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 1f6c30739..ac7e9b6f9 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1737,7 +1737,7 @@ export const Holders: { BB_sUSDe: '0xaFeb95DEF3B2A3D532D74DaBd51E62048d6c07A4', AA_iETHv2: '0xA118aD79E2152b9a3c7Df8B8791887762b0f1D49', BB_iETHv2: '0x15079cBAa74C1df2a602fAc88Bd5b98B08FfE6A4', - ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', + ETH: '0x28C6c06298d514Db089934071355E5743bf21d60', USDC: '0x7713974908be4bed47172370115e8b1219f4a5f0', USDE: '0x8707f238936c12c309bfc2B9959C35828AcFc512', AMPL: '0x223592a191ECfC7FDC38a9256c3BD96E771539A9', diff --git a/tests/tenderly-simulation.ts b/tests/tenderly-simulation.ts index 7cbdd99fb..0709e3ca3 100644 --- a/tests/tenderly-simulation.ts +++ b/tests/tenderly-simulation.ts @@ -246,6 +246,7 @@ export class TenderlySimulation implements TransactionSimulator { }; } } catch (e) { + console.error('TenderlySimulation_simulate_error', e); return { success: false, }; From ac8656256eef9e485f5bc2d0dca64632fa105724 Mon Sep 17 00:00:00 2001 From: Samarendra Gouda Date: Thu, 6 Feb 2025 15:22:52 +0530 Subject: [PATCH 15/28] fix: adjust expected swapOut amount --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 24 ++++++++++++++++++++---- src/dex/fluid-dex/utils.ts | 10 ++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 4911b5e23..026dbae19 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -10,6 +10,7 @@ import { generateConfig } from '../../config'; import { CollateralReserves, DebtReserves, DexLimits } from './types'; import { DummyDexHelper } from '../../dex-helper/index'; import { FluidDex } from './fluid-dex'; +import { adjustTestSwapOutAmount } from './utils'; function testForNetwork( network: Network, @@ -26,6 +27,8 @@ function testForNetwork( const tokens = Tokens[network]; const holders = Holders[network]; + let adjustedTokenAAmount = tokenAAmount; + let adjustedTokenBAmount = tokenBAmount; // Create FluidDex instance to check reserves const dexHelper = new DummyDexHelper(network); @@ -43,12 +46,18 @@ function testForNetwork( describe(`${contractMethod}`, () => { it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { await fluidDex.initializePricing(await provider.getBlockNumber()); + if (contractMethod === ContractMethod.swapExactAmountOut) { + adjustedTokenBAmount = adjustTestSwapOutAmount( + BigInt(tokenBAmount), + tokens[tokenBSymbol].decimals, + ); + } try { const pricesB2A = await fluidDex.getPricesVolume( tokens[tokenBSymbol], tokens[tokenASymbol], - [BigInt(tokenBAmount)], + [BigInt(adjustedTokenBAmount)], side, await provider.getBlockNumber(), ); @@ -80,7 +89,7 @@ function testForNetwork( tokens[tokenBSymbol], tokens[tokenASymbol], holders[tokenBSymbol], - tokenBAmount, + adjustedTokenBAmount, side, dexKey, contractMethod as ContractMethod, @@ -96,10 +105,17 @@ function testForNetwork( await provider.getBlockNumber(), ); + if (contractMethod === ContractMethod.swapExactAmountOut) { + adjustedTokenAAmount = adjustTestSwapOutAmount( + BigInt(tokenAAmount), + tokens[tokenASymbol].decimals, + ); + } + const pricesA2B = await fluidDex.getPricesVolume( tokens[tokenASymbol], tokens[tokenBSymbol], - [BigInt(tokenAAmount)], + [BigInt(adjustedTokenAAmount)], side, await provider.getBlockNumber(), ); @@ -131,7 +147,7 @@ function testForNetwork( tokens[tokenASymbol], tokens[tokenBSymbol], holders[tokenASymbol], - tokenAAmount, + adjustedTokenAAmount, side, dexKey, contractMethod as ContractMethod, diff --git a/src/dex/fluid-dex/utils.ts b/src/dex/fluid-dex/utils.ts index ff9dd3620..2972dda4a 100644 --- a/src/dex/fluid-dex/utils.ts +++ b/src/dex/fluid-dex/utils.ts @@ -13,3 +13,13 @@ export function sqrt(value: BigNumber) { } return y; } + +export function adjustTestSwapOutAmount( + amountOut: bigint, + outDecimals: number, +) { + return ( + ((amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals)) * + BigInt(10 ** (outDecimals - 12)) + ).toString(); +} From ecba870eb8baaf8b20c5ca5c72bcf6917a9c90d4 Mon Sep 17 00:00:00 2001 From: Samarendra Gouda Date: Thu, 6 Feb 2025 15:53:14 +0530 Subject: [PATCH 16/28] fix: normalisation value --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 88 ++++++++++++++----------- src/dex/fluid-dex/utils.ts | 2 +- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 026dbae19..76784e5ea 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -66,7 +66,11 @@ function testForNetwork( pricesB2A, ); } catch (e: any) { - console.log(`Skipping ${tokenBSymbol} -> ${tokenASymbol}`); + console.log( + `Skipping ${contractMethod} - ${tokenBSymbol} -> ${tokenASymbol}`, + ); + console.log(e.message); + const errorMessages = [ 'TokenReservesTooLow', 'InvalidCollateralReserves', @@ -124,7 +128,11 @@ function testForNetwork( pricesA2B, ); } catch (e: any) { - console.log(`Skipping ${tokenASymbol} -> ${tokenBSymbol}`); + console.log( + `Skipping ${contractMethod} - ${tokenBSymbol} -> ${tokenASymbol}`, + ); + console.log(e.message); + const errorMessages = [ 'TokenReservesTooLow', 'InvalidCollateralReserves', @@ -189,7 +197,7 @@ describe('FluidDex E2E', () => { const tokenBSymbol: string = 'ETH'; const tokenAAmount: string = '100000000000000'; - const tokenBAmount: string = '100000000000000'; + const tokenBAmount: string = '2500000000000000000'; testForNetwork( network, @@ -219,43 +227,43 @@ describe('FluidDex E2E', () => { }); }); - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - - describe('ETH -> wstETH', () => { - const tokenASymbol: string = 'wstETH'; - const tokenBSymbol: string = 'ETH'; - - const tokenAAmount: string = '1000000000000000'; - const tokenBAmount: string = '1000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - ); - }); - - describe('ETH -> weETH', () => { - const tokenBSymbol: string = 'ETH'; - const tokenASymbol: string = 'weETH'; - - const tokenAAmount: string = '1000000000000000'; - const tokenBAmount: string = '1000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - ); - }); - }); + // describe('Arbitrum', () => { + // const network = Network.ARBITRUM; + + // describe('ETH -> wstETH', () => { + // const tokenASymbol: string = 'wstETH'; + // const tokenBSymbol: string = 'ETH'; + + // const tokenAAmount: string = '1000000000000000'; + // const tokenBAmount: string = '1000000000000000'; + + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // ); + // }); + + // describe('ETH -> weETH', () => { + // const tokenBSymbol: string = 'ETH'; + // const tokenASymbol: string = 'weETH'; + + // const tokenAAmount: string = '1000000000000000'; + // const tokenBAmount: string = '1000000000000000'; + + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // ); + // }); + // }); }); function NewColReservesOne(): CollateralReserves { diff --git a/src/dex/fluid-dex/utils.ts b/src/dex/fluid-dex/utils.ts index 2972dda4a..5ecbb9194 100644 --- a/src/dex/fluid-dex/utils.ts +++ b/src/dex/fluid-dex/utils.ts @@ -20,6 +20,6 @@ export function adjustTestSwapOutAmount( ) { return ( ((amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals)) * - BigInt(10 ** (outDecimals - 12)) + BigInt(10 ** Math.abs(outDecimals - 12)) ).toString(); } From fa78fdc1300a3fcac12ee1d36896458fbc88c83d Mon Sep 17 00:00:00 2001 From: Samarendra Gouda Date: Thu, 6 Feb 2025 16:08:29 +0530 Subject: [PATCH 17/28] fix: uncommnent arb tests --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 78 ++++++++++++------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 76784e5ea..0c409e44e 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -176,7 +176,7 @@ describe('FluidDex E2E', () => { describe('Mainnet', () => { const network = Network.MAINNET; - describe('failing:FLUID -> ETH', () => { + describe('FLUID -> ETH', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; const tokenAAmount: string = '160097047322810379'; @@ -197,7 +197,7 @@ describe('FluidDex E2E', () => { const tokenBSymbol: string = 'ETH'; const tokenAAmount: string = '100000000000000'; - const tokenBAmount: string = '2500000000000000000'; + const tokenBAmount: string = '3500000000000000000'; testForNetwork( network, @@ -227,43 +227,43 @@ describe('FluidDex E2E', () => { }); }); - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - - // describe('ETH -> wstETH', () => { - // const tokenASymbol: string = 'wstETH'; - // const tokenBSymbol: string = 'ETH'; - - // const tokenAAmount: string = '1000000000000000'; - // const tokenBAmount: string = '1000000000000000'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // ); - // }); - - // describe('ETH -> weETH', () => { - // const tokenBSymbol: string = 'ETH'; - // const tokenASymbol: string = 'weETH'; - - // const tokenAAmount: string = '1000000000000000'; - // const tokenBAmount: string = '1000000000000000'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // ); - // }); - // }); + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + + describe('ETH -> wstETH', () => { + const tokenASymbol: string = 'wstETH'; + const tokenBSymbol: string = 'ETH'; + + const tokenAAmount: string = '1000000000000000'; + const tokenBAmount: string = '1000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + ); + }); + + describe('ETH -> weETH', () => { + const tokenBSymbol: string = 'ETH'; + const tokenASymbol: string = 'weETH'; + + const tokenAAmount: string = '1000000000000000'; + const tokenBAmount: string = '1000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + ); + }); + }); }); function NewColReservesOne(): CollateralReserves { From bc35274982625f4b5e1523ce1ec2b13786e28575 Mon Sep 17 00:00:00 2001 From: Samarendra Gouda Date: Thu, 6 Feb 2025 16:21:07 +0530 Subject: [PATCH 18/28] fix: update normalisation logic --- src/dex/fluid-dex/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/fluid-dex/utils.ts b/src/dex/fluid-dex/utils.ts index 5ecbb9194..eaa91b89a 100644 --- a/src/dex/fluid-dex/utils.ts +++ b/src/dex/fluid-dex/utils.ts @@ -18,8 +18,9 @@ export function adjustTestSwapOutAmount( amountOut: bigint, outDecimals: number, ) { + let normalisationDecimalFactor = outDecimals > 12 ? outDecimals - 12 : 0; return ( ((amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals)) * - BigInt(10 ** Math.abs(outDecimals - 12)) + BigInt(10 ** normalisationDecimalFactor) ).toString(); } From 0592fa465b84c3888a266b2e4496d719c910441b Mon Sep 17 00:00:00 2001 From: Samarendra Gouda Date: Thu, 6 Feb 2025 22:39:59 +0530 Subject: [PATCH 19/28] fix: move test utils --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 16 +++++++++++++++- src/dex/fluid-dex/utils.ts | 11 ----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 0c409e44e..4844d2581 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -10,7 +10,7 @@ import { generateConfig } from '../../config'; import { CollateralReserves, DebtReserves, DexLimits } from './types'; import { DummyDexHelper } from '../../dex-helper/index'; import { FluidDex } from './fluid-dex'; -import { adjustTestSwapOutAmount } from './utils'; +import BigNumber from 'bignumber.js'; function testForNetwork( network: Network, @@ -420,3 +420,17 @@ describe('TestPoolSimulator_SwapInLimits', () => { } }); }); + +export function adjustTestSwapOutAmount( + amountOut: bigint, + outDecimals: number, +) { + const amountOutParsed = new BigNumber(amountOut.toString()); + const normalisationDecimalFactor = outDecimals - 12; + + return amountOutParsed + .times(10 ** 12) + .dividedToIntegerBy(10 ** outDecimals) + .times(10 ** normalisationDecimalFactor) + .toFixed(0); +} diff --git a/src/dex/fluid-dex/utils.ts b/src/dex/fluid-dex/utils.ts index eaa91b89a..ff9dd3620 100644 --- a/src/dex/fluid-dex/utils.ts +++ b/src/dex/fluid-dex/utils.ts @@ -13,14 +13,3 @@ export function sqrt(value: BigNumber) { } return y; } - -export function adjustTestSwapOutAmount( - amountOut: bigint, - outDecimals: number, -) { - let normalisationDecimalFactor = outDecimals > 12 ? outDecimals - 12 : 0; - return ( - ((amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals)) * - BigInt(10 ** normalisationDecimalFactor) - ).toString(); -} From c6497090d86e402b2f39beda6dba764c02140ba8 Mon Sep 17 00:00:00 2001 From: bergben Date: Mon, 10 Feb 2025 15:20:01 +0100 Subject: [PATCH 20/28] Revert "fix: adjust expected swapOut amount" This reverts commit ac8656256eef9e485f5bc2d0dca64632fa105724. --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 4844d2581..98606b889 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -10,7 +10,6 @@ import { generateConfig } from '../../config'; import { CollateralReserves, DebtReserves, DexLimits } from './types'; import { DummyDexHelper } from '../../dex-helper/index'; import { FluidDex } from './fluid-dex'; -import BigNumber from 'bignumber.js'; function testForNetwork( network: Network, @@ -27,8 +26,6 @@ function testForNetwork( const tokens = Tokens[network]; const holders = Holders[network]; - let adjustedTokenAAmount = tokenAAmount; - let adjustedTokenBAmount = tokenBAmount; // Create FluidDex instance to check reserves const dexHelper = new DummyDexHelper(network); @@ -46,18 +43,12 @@ function testForNetwork( describe(`${contractMethod}`, () => { it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { await fluidDex.initializePricing(await provider.getBlockNumber()); - if (contractMethod === ContractMethod.swapExactAmountOut) { - adjustedTokenBAmount = adjustTestSwapOutAmount( - BigInt(tokenBAmount), - tokens[tokenBSymbol].decimals, - ); - } try { const pricesB2A = await fluidDex.getPricesVolume( tokens[tokenBSymbol], tokens[tokenASymbol], - [BigInt(adjustedTokenBAmount)], + [BigInt(tokenBAmount)], side, await provider.getBlockNumber(), ); @@ -93,7 +84,7 @@ function testForNetwork( tokens[tokenBSymbol], tokens[tokenASymbol], holders[tokenBSymbol], - adjustedTokenBAmount, + tokenBAmount, side, dexKey, contractMethod as ContractMethod, @@ -109,17 +100,10 @@ function testForNetwork( await provider.getBlockNumber(), ); - if (contractMethod === ContractMethod.swapExactAmountOut) { - adjustedTokenAAmount = adjustTestSwapOutAmount( - BigInt(tokenAAmount), - tokens[tokenASymbol].decimals, - ); - } - const pricesA2B = await fluidDex.getPricesVolume( tokens[tokenASymbol], tokens[tokenBSymbol], - [BigInt(adjustedTokenAAmount)], + [BigInt(tokenAAmount)], side, await provider.getBlockNumber(), ); @@ -155,7 +139,7 @@ function testForNetwork( tokens[tokenASymbol], tokens[tokenBSymbol], holders[tokenASymbol], - adjustedTokenAAmount, + tokenAAmount, side, dexKey, contractMethod as ContractMethod, From c41721118196ec55c2b714d56aa746881c4bf8fb Mon Sep 17 00:00:00 2001 From: bergben Date: Mon, 10 Feb 2025 16:59:03 +0100 Subject: [PATCH 21/28] fix(fluid): tiny buffer for target out amount when calling Fluid Dex --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 17 +++-------------- src/dex/fluid-dex/fluid-dex.ts | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index 98606b889..b98f385f9 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -131,6 +131,9 @@ function testForNetwork( e.message.includes(errorMessage), ) ) { + console.log( + 'Pool out of range or not sufficient liquidity for swap at the moment, error is expected.', + ); return; } } @@ -404,17 +407,3 @@ describe('TestPoolSimulator_SwapInLimits', () => { } }); }); - -export function adjustTestSwapOutAmount( - amountOut: bigint, - outDecimals: number, -) { - const amountOutParsed = new BigNumber(amountOut.toString()); - const normalisationDecimalFactor = outDecimals - 12; - - return amountOutParsed - .times(10 ** 12) - .dividedToIntegerBy(10 ** outDecimals) - .times(10 ** normalisationDecimalFactor) - .toFixed(0); -} diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 7cfdbf8bf..8baa2b8a1 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -371,9 +371,19 @@ export class FluidDex extends SimpleExchange implements IDex { } } else { if (pool!.token0.toLowerCase() !== srcToken.toLowerCase()) { - args = [false, BigInt(destAmount), BigInt(srcAmount), recipient]; + args = [ + false, + (BigInt(destAmount) * 1000001n) / 1000000n, // 0.0001% increase target out amount when calling Fluid Dex as it is not 100% exact. Guarantees meeting reaching exact out amount condition + BigInt(srcAmount), + recipient, + ]; } else { - args = [true, BigInt(destAmount), BigInt(srcAmount), recipient]; + args = [ + true, + (BigInt(destAmount) * 1000001n) / 1000000n, // 0.0001% increase target out amount when calling Fluid Dex as it is not 100% exact. Guarantees meeting reaching exact out amount condition + BigInt(srcAmount), + recipient, + ]; } } const swapData = this.fluidDexPoolIface.encodeFunctionData(method, args); From de988948296197b90f120e54f60e3b8418c2c95f Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 12 Feb 2025 19:43:18 +0200 Subject: [PATCH 22/28] fix: rewrite errors -> 0n && adjust tests --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 88 +------------------------ src/dex/fluid-dex/fluid-dex.ts | 34 +++++----- 2 files changed, 20 insertions(+), 102 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index b98f385f9..d5cec3767 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -42,44 +42,6 @@ function testForNetwork( contractMethods.forEach((contractMethod: string) => { describe(`${contractMethod}`, () => { it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { - await fluidDex.initializePricing(await provider.getBlockNumber()); - - try { - const pricesB2A = await fluidDex.getPricesVolume( - tokens[tokenBSymbol], - tokens[tokenASymbol], - [BigInt(tokenBAmount)], - side, - await provider.getBlockNumber(), - ); - console.log( - `price check ${tokenBSymbol} -> ${tokenASymbol}`, - pricesB2A, - ); - } catch (e: any) { - console.log( - `Skipping ${contractMethod} - ${tokenBSymbol} -> ${tokenASymbol}`, - ); - console.log(e.message); - - const errorMessages = [ - 'TokenReservesTooLow', - 'InvalidCollateralReserves', - 'No pools are enabled', - 'DebtReservesTooLow', - 'DebtLimitReached', - 'WithdrawLimitReached', - 'OracleUpdateHugeSwapDiff', - ]; - if ( - errorMessages.some(errorMessage => - e.message.includes(errorMessage), - ) - ) { - return; - } - } - await testE2E( tokens[tokenBSymbol], tokens[tokenASymbol], @@ -94,50 +56,6 @@ function testForNetwork( }); it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // Check prices before running test - try { - await fluidDex.initializePricing( - await provider.getBlockNumber(), - ); - - const pricesA2B = await fluidDex.getPricesVolume( - tokens[tokenASymbol], - tokens[tokenBSymbol], - [BigInt(tokenAAmount)], - side, - await provider.getBlockNumber(), - ); - console.log( - `price check ${tokenASymbol} -> ${tokenBSymbol}`, - pricesA2B, - ); - } catch (e: any) { - console.log( - `Skipping ${contractMethod} - ${tokenBSymbol} -> ${tokenASymbol}`, - ); - console.log(e.message); - - const errorMessages = [ - 'TokenReservesTooLow', - 'InvalidCollateralReserves', - 'No pools are enabled', - 'DebtReservesTooLow', - 'DebtLimitReached', - 'WithdrawLimitReached', - 'OracleUpdateHugeSwapDiff', - ]; - if ( - errorMessages.some(errorMessage => - e.message.includes(errorMessage), - ) - ) { - console.log( - 'Pool out of range or not sufficient liquidity for swap at the moment, error is expected.', - ); - return; - } - } - await testE2E( tokens[tokenASymbol], tokens[tokenBSymbol], @@ -163,11 +81,11 @@ describe('FluidDex E2E', () => { describe('Mainnet', () => { const network = Network.MAINNET; - describe('FLUID -> ETH', () => { + describe('limit:FLUID -> ETH', () => { const tokenASymbol: string = 'FLUID'; const tokenBSymbol: string = 'ETH'; - const tokenAAmount: string = '160097047322810379'; - const tokenBAmount: string = '79923068733005505624'; + const tokenAAmount: string = '16009704732281037900'; + const tokenBAmount: string = '7992306873300550562400'; testForNetwork( network, diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 8baa2b8a1..82c146afd 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -426,7 +426,7 @@ export class FluidDex extends SimpleExchange implements IDex { colReserves.token0RealReserves + debtReserves.token0RealReserves == 0n && colReserves.token1RealReserves + debtReserves.token1RealReserves == 0n ) { - throw new Error('InvalidCollateralReserves'); + return 0n; } const amountInAdjusted = @@ -593,18 +593,18 @@ export class FluidDex extends SimpleExchange implements IDex { } if (amountOutDebt > debtReserveOut) { - throw new Error('DebtReservesTooLow'); + return 0n; } if (amountOutDebt > borrowable) { - throw new Error('DebtLimitReached'); + return 0n; } if (amountOutCollateral > colReserveOut) { - throw new Error('TokenReservesTooLow'); + return 0n; } if (amountOutCollateral > withdrawable) { - throw new Error('WithdrawLimitReached'); + return 0n; } if (amountInCollateral > 0) { @@ -620,7 +620,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - throw new Error('TokenReservesTooLow'); + return 0n; } } @@ -637,7 +637,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - throw new Error('TokenReservesTooLow'); + return 0n; } } @@ -677,7 +677,7 @@ export class FluidDex extends SimpleExchange implements IDex { const maxAllowedDiff = (oldPrice * MAX_PRICE_DIFF) / 100n; if (priceDiff > maxAllowedDiff) { - throw new Error('OracleUpdateHugeSwapDiff'); + return 0n; } const totalAmountOut = amountOutCollateral + amountOutDebt; @@ -1043,10 +1043,10 @@ export class FluidDex extends SimpleExchange implements IDex { ); amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOut > debtReserveOut) { - throw new Error('TokenReservesTooLow'); + return 0n; } if (amountOut > borrowable) { - throw new Error('DebtLimitReached'); + return 0n; } } else if (a >= amountOut) { // Entire trade routes through collateral pool @@ -1058,10 +1058,10 @@ export class FluidDex extends SimpleExchange implements IDex { ); amountInCollateral = this.applyFeeForBuy(amountInCollateral, fee); if (amountOut > colReserveOut) { - throw new Error('TokenReservesTooLow'); + return 0n; } if (amountOut > withdrawable) { - throw new Error('WithdrawLimitReached'); + return 0n; } } else { // Trade routes through both pools @@ -1079,10 +1079,10 @@ export class FluidDex extends SimpleExchange implements IDex { amountInDebt = this.applyFeeForBuy(amountInDebt, fee); if (amountOutDebt > debtReserveOut || a > colReserveOut) { - throw new Error('TokenReservesTooLow'); + return 0n; } if (amountOutDebt > borrowable || a > withdrawable) { - throw new Error('WithdrawLimitReached or DebtLimitReached'); + return 0n; } } @@ -1099,7 +1099,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - throw new Error('TokenReservesTooLow'); + return 0n; } } if (amountInDebt > 0) { @@ -1115,7 +1115,7 @@ export class FluidDex extends SimpleExchange implements IDex { centerPrice, ); if (!reservesRatioValid) { - throw new Error('TokenReservesTooLow'); + return 0n; } } @@ -1152,7 +1152,7 @@ export class FluidDex extends SimpleExchange implements IDex { (oldPrice / BigInt(100)) * MAX_PRICE_DIFF ) { // if price diff is > 5% then swap would revert. - throw new Error('OracleUpdateHugeSwapDiff'); + return 0n; } const totalAmountIn = amountInCollateral + amountInDebt; From 2d2d028af934a7a59c786a760b2b8ce895705b5a Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 12 Feb 2025 19:44:28 +0200 Subject: [PATCH 23/28] 4.1.2-fluid --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7e641ac7..952c69414 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "4.1.2", + "version": "4.1.2-fluid", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d3505a9ebb12f464ec40f0c47eefe96d49cbf4a4 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 13 Feb 2025 13:07:10 +0200 Subject: [PATCH 24/28] fix: acc to review --- src/dex/fluid-dex/fluid-dex-e2e.test.ts | 88 ++++++++++--------------- src/dex/fluid-dex/fluid-dex.ts | 1 - 2 files changed, 36 insertions(+), 53 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex-e2e.test.ts b/src/dex/fluid-dex/fluid-dex-e2e.test.ts index d5cec3767..2e1bbc960 100644 --- a/src/dex/fluid-dex/fluid-dex-e2e.test.ts +++ b/src/dex/fluid-dex/fluid-dex-e2e.test.ts @@ -240,10 +240,6 @@ const limitsWide: DexLimits = { }, }; -const ErrInsufficientBorrowable = new Error('DebtLimitReached'); -const ErrInsufficientMaxPrice = new Error('OracleUpdateHugeSwapDiff'); -const ErrInsufficientReserve = new Error('DebtReservesTooLow'); - describe('TestPoolSimulator_SwapInLimits', () => { const network = Network.MAINNET; const dexHelper = new DummyDexHelper(network); @@ -252,22 +248,18 @@ describe('TestPoolSimulator_SwapInLimits', () => { it('when limits hit', () => { let outAmt; - try { - outAmt = fluidDex.swapInAdjusted( - true, - BigInt(1e15), - NewColReservesOne(), - NewDebtReservesOne(), - 100n, - 18, - limitsTight, - BigInt(centerPriceTight), - Math.floor(Date.now() / 1000) - 10, - ); - expect(outAmt).toEqual(0n); - } catch (err: any) { - expect(err.message).toEqual(ErrInsufficientBorrowable.message); - } + outAmt = fluidDex.swapInAdjusted( + true, + BigInt(1e15), + NewColReservesOne(), + NewDebtReservesOne(), + 100n, + 18, + limitsTight, + BigInt(centerPriceTight), + Math.floor(Date.now() / 1000) - 10, + ); + expect(outAmt).toEqual(0n); }); it('when expanded', () => { @@ -287,41 +279,33 @@ describe('TestPoolSimulator_SwapInLimits', () => { it('when price diff hit', () => { let outAmt; - try { - outAmt = fluidDex.swapInAdjusted( - true, - BigInt(3e16), - NewColReservesOne(), - NewDebtReservesOne(), - 100n, - 18, - limitsWide, - BigInt(centerPriceWide), - Math.floor(Date.now() / 1000) - 10, - ); - expect(outAmt).toEqual(0n); - } catch (err: any) { - expect(err.message).toEqual(ErrInsufficientMaxPrice.message); - } + outAmt = fluidDex.swapInAdjusted( + true, + BigInt(3e16), + NewColReservesOne(), + NewDebtReservesOne(), + 100n, + 18, + limitsWide, + BigInt(centerPriceWide), + Math.floor(Date.now() / 1000) - 10, + ); + expect(outAmt).toEqual(0n); }); it('when reserves limit is hit', () => { let outAmt; - try { - outAmt = fluidDex.swapInAdjusted( - true, - BigInt(5e16), - NewColReservesOne(), - NewDebtReservesOne(), - 100n, - 18, - limitsWide, - BigInt(centerPriceWide), - Math.floor(Date.now() / 1000) - 10, - ); - expect(outAmt).toEqual(0n); - } catch (err: any) { - expect(err.message).toEqual(ErrInsufficientReserve.message); - } + outAmt = fluidDex.swapInAdjusted( + true, + BigInt(5e16), + NewColReservesOne(), + NewDebtReservesOne(), + 100n, + 18, + limitsWide, + BigInt(centerPriceWide), + Math.floor(Date.now() / 1000) - 10, + ); + expect(outAmt).toEqual(0n); }); }); diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index 82c146afd..a4af53173 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -293,7 +293,6 @@ export class FluidDex extends SimpleExchange implements IDex { }, ${side}:`, e, ); - throw e; return null; } } From cb799ebb8c96718ac48c57e322f4429698617935 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 13 Feb 2025 17:09:01 +0200 Subject: [PATCH 25/28] fix: swapOut calc --- src/dex/fluid-dex/fluid-dex.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index a4af53173..ae38bbcfe 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -904,8 +904,7 @@ export class FluidDex extends SimpleExchange implements IDex { return amountIn; } const ans = (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12); - - return (ans * (100000n - 5n)) / 100000n; + return ans; } /** From f6d6f54e9d2e727a4739d43dca35ef2e5380ad24 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 13 Feb 2025 17:11:24 +0200 Subject: [PATCH 26/28] 4.1.2-fluid.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 952c69414..ace2e649d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "4.1.2-fluid", + "version": "4.1.2-fluid.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 597e4f9f1c97a9fc6898336704329f823a5f7f21 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 14 Feb 2025 13:11:53 +0200 Subject: [PATCH 27/28] fix: remove max uint check --- src/dex/fluid-dex/fluid-dex.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index ae38bbcfe..a184d1ef6 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -900,9 +900,6 @@ export class FluidDex extends SimpleExchange implements IDex { syncTime, ); - if (amountIn === 2n ** 256n - 1n) { - return amountIn; - } const ans = (amountIn * BigInt(10 ** inDecimals)) / BigInt(10 ** 12); return ans; } From b903f4639702ab08f7be4db26591cd1365f8db16 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 14 Feb 2025 13:15:49 +0200 Subject: [PATCH 28/28] 4.1.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ace2e649d..ee1325fb9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "4.1.2-fluid.2", + "version": "4.1.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib",