From 8fa8512549ee01e2e33515970f5b273b0870738c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 08:38:16 +0000 Subject: [PATCH 1/7] Bump path-parse from 1.0.6 to 1.0.7 Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d910a209..8c1d028d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4156,9 +4156,9 @@ path-key@^3.0.0, path-key@^3.1.0: integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" From 3d220912ac4ff90c6fba84cb2c32e9317bffbe1e Mon Sep 17 00:00:00 2001 From: Steffen Schuldenzucker Date: Thu, 16 Nov 2023 01:55:40 +0100 Subject: [PATCH 2/7] Add Gyro2V2 pool = Gyro 2CLP supporting rate scaling --- src/index.ts | 2 + .../gyro2V2Pool/GyroscopeBalancerLicense.pdf | Bin 0 -> 184467 bytes src/pools/gyro2V2Pool/LICENSE | 5 + src/pools/gyro2V2Pool/gyro2V2Abi.json | 1371 +++++++++++++++++ .../gyro2V2Math/gyro2V2MathHelpers.ts | 17 + src/pools/gyro2V2Pool/gyro2V2Pool.ts | 513 ++++++ src/pools/index.ts | 13 +- src/types.ts | 2 +- test/lib/onchainData.ts | 25 + tsconfig.json | 3 +- 10 files changed, 1947 insertions(+), 4 deletions(-) create mode 100644 src/pools/gyro2V2Pool/GyroscopeBalancerLicense.pdf create mode 100644 src/pools/gyro2V2Pool/LICENSE create mode 100644 src/pools/gyro2V2Pool/gyro2V2Abi.json create mode 100644 src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts create mode 100644 src/pools/gyro2V2Pool/gyro2V2Pool.ts diff --git a/src/index.ts b/src/index.ts index c6e50400..391ce431 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,9 @@ export { MetaStablePool } from './pools/metaStablePool/metaStablePool'; export { PhantomStablePool } from './pools/phantomStablePool/phantomStablePool'; export { ComposableStablePool } from './pools/composableStable/composableStablePool'; export { LinearPool } from './pools/linearPool/linearPool'; +// TODO should we still export the (deprecated) Gyro2Pool or scrap that & only export Gyro2V2Pool? export { Gyro2Pool } from './pools/gyro2Pool/gyro2Pool'; +export { Gyro2V2Pool } from './pools/gyro2V2Pool/gyro2V2Pool'; export { Gyro3Pool } from './pools/gyro3Pool/gyro3Pool'; export { GyroEV2Pool } from './pools/gyroEV2Pool/gyroEV2Pool'; export { FxPool } from './pools/xaveFxPool/fxPool'; diff --git a/src/pools/gyro2V2Pool/GyroscopeBalancerLicense.pdf b/src/pools/gyro2V2Pool/GyroscopeBalancerLicense.pdf new file mode 100644 index 0000000000000000000000000000000000000000..531fd47e92bd6d9a92e0b12ce115f326daf32f6a GIT binary patch literal 184467 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

Zq;X2GWn?73IbM%)O^eRj;`1y@ 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 z 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 ME7t**SfynL3tto*Gp6GFPmzlv>rz%G2K_OP@M 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

KA(?m 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 parseFixed('1', d)); + + return balances.map((bal, index) => + mulDown(bal.mul(ONE).div(scalingFactors[index]), tokenRates[index]) + ); +} diff --git a/src/pools/gyro2V2Pool/gyro2V2Pool.ts b/src/pools/gyro2V2Pool/gyro2V2Pool.ts new file mode 100644 index 00000000..8761bfee --- /dev/null +++ b/src/pools/gyro2V2Pool/gyro2V2Pool.ts @@ -0,0 +1,513 @@ +import { getAddress } from '@ethersproject/address'; +import { WeiPerEther as ONE, Zero } from '@ethersproject/constants'; +import { formatFixed, BigNumber } from '@ethersproject/bignumber'; +import { BigNumber as OldBigNumber, bnum, ZERO } from '../../utils/bignumber'; + +import { + PoolBase, + PoolPairBase, + PoolTypes, + SubgraphToken, + SwapTypes, + SubgraphPoolBase, +} from '../../types'; +import { isSameAddress, safeParseFixed } from '../../utils'; +import { mulDown, divDown } from '../gyroHelpers/gyroSignedFixedPoint'; +import { + _calculateInvariant, + _calcOutGivenIn, + _calcInGivenOut, + _findVirtualParams, + _calculateNewSpotPrice, + _derivativeSpotPriceAfterSwapExactTokenInForTokenOut, + _derivativeSpotPriceAfterSwapTokenInForExactTokenOut, +} from '../gyro2Pool/gyro2Math'; +import { + _reduceFee, + _addFee, +} from '../gyroHelpers/helpers'; +import { SWAP_LIMIT_FACTOR } from '../gyroHelpers/constants'; +import { universalNormalizedLiquidity } from '../liquidity'; + +import { normalizeBalances } from './gyro2V2Math/gyro2V2MathHelpers'; + +type Gyro2V2PoolPairData = PoolPairBase & { + // NB we follow a different approach than for the gyroE[V2]Pool here, where the pool pair data contains everything we need to know and we can forget about whether token-in is token 0 or 1. + sqrtAlpha: BigNumber; + sqrtBeta: BigNumber; + tokenRates: BigNumber[]; +}; + +export type Gyro2PoolToken = Pick< + SubgraphToken, + 'address' | 'balance' | 'decimals' +>; + +export class Gyro2V2Pool implements PoolBase { + poolType: PoolTypes = PoolTypes.Gyro2; + id: string; + address: string; + tokensList: string[]; + tokens: Gyro2PoolToken[]; + swapFee: BigNumber; + totalShares: BigNumber; + sqrtAlpha: BigNumber; + sqrtBeta: BigNumber; + tokenRates: BigNumber[]; + + static fromPool(pool: SubgraphPoolBase): Gyro2V2Pool { + if (!pool.sqrtAlpha || !pool.sqrtBeta) + throw new Error( + 'Pool missing Gyro2 sqrtAlpha and/or sqrtBeta params' + ); + + if (!pool.tokenRates) throw new Error('GyroEV2 Pool missing tokenRates'); + + return new Gyro2V2Pool( + pool.id, + pool.address, + pool.swapFee, + pool.totalShares, + pool.tokens as Gyro2PoolToken[], + pool.tokensList, + pool.sqrtAlpha, + pool.sqrtBeta, + pool.tokenRates + ); + } + + constructor( + id: string, + address: string, + swapFee: string, + totalShares: string, + tokens: Gyro2PoolToken[], + tokensList: string[], + sqrtAlpha: string, + sqrtBeta: string, + tokenRates: string[] + ) { + this.id = id; + this.address = address; + this.swapFee = safeParseFixed(swapFee, 18); + this.totalShares = safeParseFixed(totalShares, 18); + this.tokens = tokens; + this.tokensList = tokensList; + this.sqrtAlpha = safeParseFixed(sqrtAlpha, 18); + this.sqrtBeta = safeParseFixed(sqrtBeta, 18); + this.tokenRates = [ + safeParseFixed(tokenRates[0], 18), + safeParseFixed(tokenRates[1], 18), + ]; + } + + parsePoolPairData(tokenIn: string, tokenOut: string): Gyro2V2PoolPairData { + const tokenInIndex = this.tokens.findIndex( + (t) => getAddress(t.address) === getAddress(tokenIn) + ); + if (tokenInIndex < 0) throw 'Pool does not contain tokenIn'; + const tI = this.tokens[tokenInIndex]; + const balanceIn = tI.balance; + const decimalsIn = tI.decimals; + + const tokenOutIndex = this.tokens.findIndex( + (t) => getAddress(t.address) === getAddress(tokenOut) + ); + if (tokenOutIndex < 0) throw 'Pool does not contain tokenOut'; + const tO = this.tokens[tokenOutIndex]; + const balanceOut = tO.balance; + const decimalsOut = tO.decimals; + + const tokenInIsToken0 = tokenInIndex === 0; + + const poolPairData: Gyro2V2PoolPairData = { + id: this.id, + address: this.address, + poolType: this.poolType, + tokenIn: tokenIn, + tokenOut: tokenOut, + decimalsIn: Number(decimalsIn), + decimalsOut: Number(decimalsOut), + balanceIn: safeParseFixed(balanceIn, decimalsIn), + balanceOut: safeParseFixed(balanceOut, decimalsOut), + swapFee: this.swapFee, + sqrtAlpha: tokenInIsToken0 + ? this.sqrtAlpha + : divDown(ONE, this.sqrtBeta), + sqrtBeta: tokenInIsToken0 + ? this.sqrtBeta + : divDown(ONE, this.sqrtAlpha), + tokenRates: tokenInIsToken0 + ? this.tokenRates + : [this.tokenRates[1], this.tokenRates[0]] + }; + + return poolPairData; + } + + getNormalizedLiquidity(poolPairData: Gyro2V2PoolPairData): OldBigNumber { + return universalNormalizedLiquidity( + this._derivativeSpotPriceAfterSwapExactTokenInForTokenOut( + poolPairData, + ZERO + ) + ); + } + + getLimitAmountSwap( + poolPairData: Gyro2V2PoolPairData, + swapType: SwapTypes + ): OldBigNumber { + if (swapType === SwapTypes.SwapExactIn) { + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const maxAmountInAssetInPool = mulDown( + invariant, + divDown(ONE, poolPairData.sqrtAlpha).sub( + divDown(ONE, poolPairData.sqrtBeta) + ) + ); // x+ = L * (1/sqrtAlpha - 1/sqrtBeta) + const limitAmountIn = divDown( + maxAmountInAssetInPool.sub(normalizedBalances[0]), + poolPairData.tokenRates[0] + ); + const limitAmountInPlusSwapFee = divDown( + limitAmountIn, + ONE.sub(poolPairData.swapFee) + ); + return bnum( + formatFixed( + mulDown(limitAmountInPlusSwapFee, SWAP_LIMIT_FACTOR), + 18 + ) + ); + } else { + return bnum( + formatFixed( + mulDown(poolPairData.balanceOut, SWAP_LIMIT_FACTOR), + poolPairData.decimalsOut + ) + ); + } + } + + // Updates the balance of a given token for the pool + updateTokenBalanceForPool(token: string, newBalance: BigNumber): void { + // token is BPT + if (isSameAddress(this.address, token)) { + this.updateTotalShares(newBalance); + } else { + // token is underlying in the pool + const T = this.tokens.find((t) => isSameAddress(t.address, token)); + if (!T) throw Error('Pool does not contain this token'); + T.balance = formatFixed(newBalance, T.decimals); + } + } + + updateTotalShares(newTotalShares: BigNumber): void { + this.totalShares = newTotalShares; + } + + _exactTokenInForTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const inAmount = safeParseFixed(amount.toString(), 18); + const inAmountLessFee = _reduceFee(inAmount, poolPairData.swapFee); + const inAmountLessFeeScaled = mulDown( + inAmountLessFee, + poolPairData.tokenRates[0] + ); + + const outAmountScaled = _calcOutGivenIn( + normalizedBalances[0], + normalizedBalances[1], + inAmountLessFeeScaled, + virtualParamIn, + virtualParamOut + ); + const outAmount = divDown(outAmountScaled, poolPairData.tokenRates[1]); + return bnum(formatFixed(outAmount, 18)); + } catch (error) { + return bnum(0); + } + } + + _tokenInForExactTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const outAmount = safeParseFixed(amount.toString(), 18); + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const inAmountScaledLessFee = _calcInGivenOut( + normalizedBalances[0], + normalizedBalances[1], + outAmountScaled, + virtualParamIn, + virtualParamOut + ); + const inAmountLessFee = divDown( + inAmountScaledLessFee, + poolPairData.tokenRates[0] + ); + const inAmount = _addFee(inAmountLessFee, poolPairData.swapFee); + + return bnum(formatFixed(inAmount, 18)); + } catch (error) { + return bnum(0); + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _calcTokensOutGivenExactBptIn(bptAmountIn: BigNumber): BigNumber[] { + // Missing maths for this + return new Array(this.tokens.length).fill(Zero); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _calcBptOutGivenExactTokensIn(amountsIn: BigNumber[]): BigNumber { + // Missing maths for this + return Zero; + } + + _spotPriceAfterSwapExactTokenInForTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const inAmount = safeParseFixed(amount.toString(), 18); + const inAmountScaled = mulDown( + inAmount, + poolPairData.tokenRates[0] + ); + const inAmountLessFee = _reduceFee(inAmount, poolPairData.swapFee); + const inAmountLessFeeScaled = mulDown( + inAmountLessFee, + poolPairData.tokenRates[0] + ); + const outAmountScaled = _calcOutGivenIn( + normalizedBalances[0], + normalizedBalances[1], + inAmountLessFeeScaled, + virtualParamIn, + virtualParamOut + ); + const newSpotPriceScaled = _calculateNewSpotPrice( + normalizedBalances, + inAmountScaled, + outAmountScaled, + virtualParamIn, + virtualParamOut, + poolPairData.swapFee + ); + const newSpotPrice = divDown( + mulDown(newSpotPriceScaled, poolPairData.tokenRates[1]), + poolPairData.tokenRates[0] + ); + return bnum(formatFixed(newSpotPrice, 18)); + } catch (error) { + return bnum(0); + } + } + + _spotPriceAfterSwapTokenInForExactTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const outAmount = safeParseFixed(amount.toString(), 18); + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); + const inAmountLessFeeScaled = _calcInGivenOut( + normalizedBalances[0], + normalizedBalances[1], + outAmountScaled, + virtualParamIn, + virtualParamOut + ); + const inAmountScaled = _addFee(inAmountLessFeeScaled, poolPairData.swapFee); + const newSpotPriceScaled = _calculateNewSpotPrice( + normalizedBalances, + inAmountScaled, + outAmountScaled, + virtualParamIn, + virtualParamOut, + poolPairData.swapFee + ); + const newSpotPrice = divDown( + mulDown(newSpotPriceScaled, poolPairData.tokenRates[1]), + poolPairData.tokenRates[0] + ); + + return bnum(formatFixed(newSpotPrice, 18)); + } catch (error) { + return bnum(0); + } + } + + _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const inAmount = safeParseFixed(amount.toString(), 18); + const inAmountLessFee = _reduceFee(inAmount, poolPairData.swapFee); + const inAmountLessFeeScaled = mulDown( + inAmountLessFee, + poolPairData.tokenRates[0] + ); + const outAmountScaled = _calcOutGivenIn( + normalizedBalances[0], + normalizedBalances[1], + inAmountLessFeeScaled, + virtualParamIn, + virtualParamOut + ); + const derivativeScaled = + _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( + normalizedBalances, + outAmountScaled, + virtualParamOut + ); + const derivative = mulDown(derivativeScaled, poolPairData.tokenRates[1]); + return bnum(formatFixed(derivative, 18)); + } catch (error) { + return bnum(0); + } + } + + _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( + poolPairData: Gyro2V2PoolPairData, + amount: OldBigNumber + ): OldBigNumber { + try { + const outAmount = safeParseFixed(amount.toString(), 18); + const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; + const normalizedBalances = normalizeBalances(balances, + [poolPairData.decimalsIn, poolPairData.decimalsOut], + poolPairData.tokenRates + ); + const invariant = _calculateInvariant( + normalizedBalances, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const [virtualParamIn, virtualParamOut] = _findVirtualParams( + invariant, + poolPairData.sqrtAlpha, + poolPairData.sqrtBeta + ); + const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); + const inAmountLessFeeScaled = _calcInGivenOut( + normalizedBalances[0], + normalizedBalances[1], + outAmountScaled, + virtualParamIn, + virtualParamOut + ); + const inAmountScaled = _addFee(inAmountLessFeeScaled, poolPairData.swapFee); + + const derivativeScaled = + _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( + normalizedBalances, + inAmountScaled, + outAmountScaled, + virtualParamIn, + virtualParamOut, + poolPairData.swapFee + ); + const rateAdjFactor = divDown( + mulDown(poolPairData.tokenRates[1], poolPairData.tokenRates[1]), + poolPairData.tokenRates[0] + ); + const derivative = mulDown(derivativeScaled, rateAdjFactor); + return bnum(formatFixed(derivative, 18)); + } catch (error) { + return bnum(0); + } + } +} diff --git a/src/pools/index.ts b/src/pools/index.ts index 45db5f49..891dc2dc 100644 --- a/src/pools/index.ts +++ b/src/pools/index.ts @@ -6,6 +6,7 @@ import { ElementPool } from './elementPool/elementPool'; import { PhantomStablePool } from './phantomStablePool/phantomStablePool'; import { ComposableStablePool } from './composableStable/composableStablePool'; import { Gyro2Pool } from './gyro2Pool/gyro2Pool'; +import { Gyro2V2Pool } from './gyro2V2Pool/gyro2V2Pool'; import { Gyro3Pool } from './gyro3Pool/gyro3Pool'; import { GyroEPool } from './gyroEPool/gyroEPool'; import { GyroEV2Pool } from './gyroEV2Pool/gyroEV2Pool'; @@ -37,6 +38,7 @@ export function parseNewPool( | PhantomStablePool | ComposableStablePool | Gyro2Pool + | Gyro2V2Pool | Gyro3Pool | GyroEPool | GyroEV2Pool @@ -54,6 +56,7 @@ export function parseNewPool( | PhantomStablePool | ComposableStablePool | Gyro2Pool + | Gyro2V2Pool | Gyro3Pool | GyroEPool | GyroEV2Pool @@ -81,8 +84,14 @@ export function parseNewPool( newPool = PhantomStablePool.fromPool(pool); else if (pool.poolType === 'ComposableStable') newPool = ComposableStablePool.fromPool(pool); - else if (pool.poolType === 'Gyro2') newPool = Gyro2Pool.fromPool(pool); - else if (pool.poolType === 'Gyro3') newPool = Gyro3Pool.fromPool(pool); + else if (pool.poolType === 'Gyro2') { + if (pool.poolTypeVersion === 2) { + newPool = Gyro2V2Pool.fromPool(pool); + } else { + newPool = Gyro2Pool.fromPool(pool); + } + } else if (pool.poolType === 'Gyro3') + newPool = Gyro3Pool.fromPool(pool); else if (pool.poolType === 'GyroE') { if (pool.poolTypeVersion === 2) { newPool = GyroEV2Pool.fromPool(pool); diff --git a/src/types.ts b/src/types.ts index daced257..3ce14f9a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -120,7 +120,7 @@ export interface SubgraphPoolBase { z?: string; dSq?: string; - // GyroEV2 specific fields + // GyroEV2 and Gyro2V2 specific fields tokenRates?: string[]; // FxPool diff --git a/test/lib/onchainData.ts b/test/lib/onchainData.ts index bf4a60bd..1e59b023 100644 --- a/test/lib/onchainData.ts +++ b/test/lib/onchainData.ts @@ -13,6 +13,7 @@ import elementPoolAbi from '../../src/pools/elementPool/ConvergentCurvePool.json import linearPoolAbi from '../../src/pools/linearPool/linearPoolAbi.json'; import fxPoolAbi from '../../src/pools/xaveFxPool/fxPoolAbi.json'; import gyroEV2Abi from '../../src/pools/gyroEV2Pool/gyroEV2Abi.json'; +import gyro2V2Abi from '../../src/pools/gyro2V2Pool/gyro2V2Abi.json'; import { PoolFilter, SubgraphPoolBase, PoolDataService } from '../../src'; import { Multicaller } from './multicaller'; import { Fragment, JsonFragment } from '@ethersproject/abi/lib/fragments'; @@ -39,6 +40,7 @@ export async function getOnChainBalances( ...composableStablePoolAbi, ...fxPoolAbi, ...gyroEV2Abi, + ...gyro2V2Abi, ].map((row) => [row.name, row]) ) ); @@ -158,6 +160,15 @@ export async function getOnChainBalances( pool.address, 'getTokenRates' ); + } else if ( + pool.poolType.toString() === 'Gyro2' && + pool.poolTypeVersion === 2 + ) { + multiPool.call( + `${pool.id}.tokenRates`, + pool.address, + 'getTokenRates' + ); } } }); @@ -328,6 +339,20 @@ export async function getOnChainBalances( ); } + if ( + subgraphPools[index].poolType === 'Gyro2' && + subgraphPools[index].poolTypeVersion == 2 + ) { + if (!Array.isArray(tokenRates) || tokenRates.length !== 2) { + console.error( + `Gyro2V2 pool with missing or invalid tokenRates: ${poolId}` + ); + return; + } + subgraphPools[index].tokenRates = tokenRates.map((rate) => + formatFixed(rate, 18) + ); + } onChainPools.push(subgraphPools[index]); } catch (err) { throw `Issue with pool onchain data: ${err}`; diff --git a/tsconfig.json b/tsconfig.json index 42f46e40..b0009957 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,8 @@ "src/pools/linearPool/linearPoolAbi.json", "src/pools/composableStable/ComposableStable.json", "src/pools/xaveFxPool/fxPoolAbi.json", - "src/pools/gyroEV2Pool/gyroEV2Abi.json" + "src/pools/gyroEV2Pool/gyroEV2Abi.json", + "src/pools/gyro2V2Pool/gyro2V2Abi.json" ], "files": ["hardhat.config.ts"] } From cd2ac26bcc29a07a8506724963195f20d487b653 Mon Sep 17 00:00:00 2001 From: Steffen Schuldenzucker Date: Sat, 18 Nov 2023 13:28:12 +0100 Subject: [PATCH 3/7] reformat gyro2V2Pool --- src/pools/gyro2V2Pool/gyro2V2Pool.ts | 66 +++++++++++++++++++--------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/src/pools/gyro2V2Pool/gyro2V2Pool.ts b/src/pools/gyro2V2Pool/gyro2V2Pool.ts index 8761bfee..60ebc1ca 100644 --- a/src/pools/gyro2V2Pool/gyro2V2Pool.ts +++ b/src/pools/gyro2V2Pool/gyro2V2Pool.ts @@ -22,10 +22,7 @@ import { _derivativeSpotPriceAfterSwapExactTokenInForTokenOut, _derivativeSpotPriceAfterSwapTokenInForExactTokenOut, } from '../gyro2Pool/gyro2Math'; -import { - _reduceFee, - _addFee, -} from '../gyroHelpers/helpers'; +import { _reduceFee, _addFee } from '../gyroHelpers/helpers'; import { SWAP_LIMIT_FACTOR } from '../gyroHelpers/constants'; import { universalNormalizedLiquidity } from '../liquidity'; @@ -61,7 +58,8 @@ export class Gyro2V2Pool implements PoolBase { 'Pool missing Gyro2 sqrtAlpha and/or sqrtBeta params' ); - if (!pool.tokenRates) throw new Error('GyroEV2 Pool missing tokenRates'); + if (!pool.tokenRates) + throw new Error('GyroEV2 Pool missing tokenRates'); return new Gyro2V2Pool( pool.id, @@ -139,7 +137,7 @@ export class Gyro2V2Pool implements PoolBase { : divDown(ONE, this.sqrtAlpha), tokenRates: tokenInIsToken0 ? this.tokenRates - : [this.tokenRates[1], this.tokenRates[0]] + : [this.tokenRates[1], this.tokenRates[0]], }; return poolPairData; @@ -160,7 +158,8 @@ export class Gyro2V2Pool implements PoolBase { ): OldBigNumber { if (swapType === SwapTypes.SwapExactIn) { const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -222,7 +221,8 @@ export class Gyro2V2Pool implements PoolBase { ): OldBigNumber { try { const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -250,7 +250,10 @@ export class Gyro2V2Pool implements PoolBase { virtualParamIn, virtualParamOut ); - const outAmount = divDown(outAmountScaled, poolPairData.tokenRates[1]); + const outAmount = divDown( + outAmountScaled, + poolPairData.tokenRates[1] + ); return bnum(formatFixed(outAmount, 18)); } catch (error) { return bnum(0); @@ -264,8 +267,12 @@ export class Gyro2V2Pool implements PoolBase { try { const outAmount = safeParseFixed(amount.toString(), 18); const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); - const normalizedBalances = normalizeBalances(balances, + const outAmountScaled = mulDown( + outAmount, + poolPairData.tokenRates[1] + ); + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -316,7 +323,8 @@ export class Gyro2V2Pool implements PoolBase { ): OldBigNumber { try { const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -372,7 +380,8 @@ export class Gyro2V2Pool implements PoolBase { try { const outAmount = safeParseFixed(amount.toString(), 18); const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -386,7 +395,10 @@ export class Gyro2V2Pool implements PoolBase { poolPairData.sqrtAlpha, poolPairData.sqrtBeta ); - const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); + const outAmountScaled = mulDown( + outAmount, + poolPairData.tokenRates[1] + ); const inAmountLessFeeScaled = _calcInGivenOut( normalizedBalances[0], normalizedBalances[1], @@ -394,7 +406,10 @@ export class Gyro2V2Pool implements PoolBase { virtualParamIn, virtualParamOut ); - const inAmountScaled = _addFee(inAmountLessFeeScaled, poolPairData.swapFee); + const inAmountScaled = _addFee( + inAmountLessFeeScaled, + poolPairData.swapFee + ); const newSpotPriceScaled = _calculateNewSpotPrice( normalizedBalances, inAmountScaled, @@ -420,7 +435,8 @@ export class Gyro2V2Pool implements PoolBase { ): OldBigNumber { try { const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -453,7 +469,10 @@ export class Gyro2V2Pool implements PoolBase { outAmountScaled, virtualParamOut ); - const derivative = mulDown(derivativeScaled, poolPairData.tokenRates[1]); + const derivative = mulDown( + derivativeScaled, + poolPairData.tokenRates[1] + ); return bnum(formatFixed(derivative, 18)); } catch (error) { return bnum(0); @@ -467,7 +486,8 @@ export class Gyro2V2Pool implements PoolBase { try { const outAmount = safeParseFixed(amount.toString(), 18); const balances = [poolPairData.balanceIn, poolPairData.balanceOut]; - const normalizedBalances = normalizeBalances(balances, + const normalizedBalances = normalizeBalances( + balances, [poolPairData.decimalsIn, poolPairData.decimalsOut], poolPairData.tokenRates ); @@ -481,7 +501,10 @@ export class Gyro2V2Pool implements PoolBase { poolPairData.sqrtAlpha, poolPairData.sqrtBeta ); - const outAmountScaled = mulDown(outAmount, poolPairData.tokenRates[1]); + const outAmountScaled = mulDown( + outAmount, + poolPairData.tokenRates[1] + ); const inAmountLessFeeScaled = _calcInGivenOut( normalizedBalances[0], normalizedBalances[1], @@ -489,7 +512,10 @@ export class Gyro2V2Pool implements PoolBase { virtualParamIn, virtualParamOut ); - const inAmountScaled = _addFee(inAmountLessFeeScaled, poolPairData.swapFee); + const inAmountScaled = _addFee( + inAmountLessFeeScaled, + poolPairData.swapFee + ); const derivativeScaled = _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( From 68a0966034eaa66ea789524ae417fe9c0bc453af Mon Sep 17 00:00:00 2001 From: Steffen Schuldenzucker Date: Sat, 18 Nov 2023 13:28:43 +0100 Subject: [PATCH 4/7] Add gyro2V2Pool unit tests --- test/gyro2V2Pool.spec.ts | 217 ++++++++++++++++++ test/testData/gyro2Pools/gyro2V2TestPool.json | 49 ++++ 2 files changed, 266 insertions(+) create mode 100644 test/gyro2V2Pool.spec.ts create mode 100644 test/testData/gyro2Pools/gyro2V2TestPool.json diff --git a/test/gyro2V2Pool.spec.ts b/test/gyro2V2Pool.spec.ts new file mode 100644 index 00000000..d7bb3dac --- /dev/null +++ b/test/gyro2V2Pool.spec.ts @@ -0,0 +1,217 @@ +// TS_NODE_PROJECT='tsconfig.testing.json' npx mocha -r ts-node/register test/gyro2V2Pool.spec.ts + +import 'dotenv/config'; +import { expect } from 'chai'; +import cloneDeep from 'lodash.clonedeep'; +import { formatFixed, parseFixed } from '@ethersproject/bignumber'; +import { JsonRpcProvider } from '@ethersproject/providers'; +import { bnum } from '../src/utils/bignumber'; +import { USDC, DAI, sorConfigEth } from './lib/constants'; +import { SwapTypes, SOR, SwapInfo, SubgraphPoolBase } from '../src'; +// Add new PoolType +import { Gyro2V2Pool } from '../src/pools/gyro2V2Pool/gyro2V2Pool'; +// Add new pool test data in Subgraph Schema format +import testPools from './testData/gyro2Pools/gyro2V2TestPool.json'; +import { MockPoolDataService } from './lib/mockPoolDataService'; +import { mockTokenPriceService } from './lib/mockTokenPriceService'; + +describe('Gyro2V2Pool tests USDC > DAI', () => { + const testPool = cloneDeep(testPools).pools[0]; + const pool = Gyro2V2Pool.fromPool(testPool); + + const poolPairData = pool.parsePoolPairData(USDC.address, DAI.address); + + const poolPairData2 = pool.parsePoolPairData(DAI.address, USDC.address); + + context('parsePoolPairData', () => { + it(`should correctly parse USDC > DAI`, async () => { + // Tests that compare poolPairData to known results with correct number scaling, etc, i.e.: + expect(poolPairData.swapFee.toString()).to.eq( + parseFixed(testPool.swapFee, 18).toString() + ); + expect(poolPairData.id).to.eq(testPool.id); + expect(poolPairData.tokenRates[0].toString()).to.eq( + parseFixed(testPool.tokenRates[1], 18).toString() + ); + expect(poolPairData.tokenRates[1].toString()).to.eq( + parseFixed(testPool.tokenRates[0], 18).toString() + ); + }); + + // NB these price bounds are not affected by rate scaling, so they're the same as for gyro2Pool. + it(`should correctly calculate price bounds USDC > DAI`, async () => { + expect( + Number(formatFixed(poolPairData.sqrtAlpha, 18)) + ).to.be.approximately(0.9995003747, 0.00000001); + + expect( + Number(formatFixed(poolPairData.sqrtBeta, 18)) + ).to.be.approximately(1.000500375, 0.00000001); + }); + + it(`should correctly calculate price bounds DAI > USDC`, async () => { + expect( + Number(formatFixed(poolPairData2.sqrtAlpha, 18)) + ).to.be.approximately(0.9994998749, 0.00000001); + + expect( + Number(formatFixed(poolPairData2.sqrtBeta, 18)) + ).to.be.approximately(1.000499875, 0.00000001); + }); + }); + + context('limit amounts', () => { + it(`should correctly calculate limit amounts, USDC > DAI`, async () => { + let amount = pool.getLimitAmountSwap( + poolPairData, + SwapTypes.SwapExactIn + ); + + expect(amount.toString()).to.eq('1865.435197059850834134'); + + amount = pool.getLimitAmountSwap( + poolPairData, + SwapTypes.SwapExactOut + ); + + expect(amount.toString()).to.eq('1231.998768'); + }); + }); + + context('normalized liquidity', () => { + it(`should correctly calculate normalized liquidity, USDC > DAI`, async () => { + const normalizedLiquidity = + pool.getNormalizedLiquidity(poolPairData); + + expect(Number(normalizedLiquidity.toString())).to.be.approximately( + 949690.862560122978692435, + 0.00001 + ); + }); + + it(`should correctly calculate normalized liquidity, DAI > USDC`, async () => { + const normalizedLiquidity = + pool.getNormalizedLiquidity(poolPairData2); + + expect(Number(normalizedLiquidity.toString())).to.be.approximately( + 1424111.581891956376601924, + 0.00001 + ); + }); + }); + + context('Test Swaps', () => { + context('SwapExactIn', () => { + const amountIn = bnum('13.5'); + + it('should correctly calculate amountOut given amountIn', async () => { + const amountOut = pool._exactTokenInForTokenOut( + poolPairData, + amountIn + ); + expect(Number(amountOut.toString())).to.be.approximately( + 8.921618001976369271, + 0.000000000000000001 + ); + // expect(amountOut.toString()).to.eq('8.921618001976369271'); + }); + it('should correctly calculate newSpotPrice', async () => { + const newSpotPrice = + pool._spotPriceAfterSwapExactTokenInForTokenOut( + poolPairData, + amountIn + ); + expect(newSpotPrice.toString()).to.eq('1.513185546431756763'); + }); + it('should correctly calculate derivative of spot price function at newSpotPrice', async () => { + const derivative = + pool._derivativeSpotPriceAfterSwapExactTokenInForTokenOut( + poolPairData, + amountIn + ); + expect(derivative.toString()).to.eq('0.000001052979170973'); + }); + }); + + context('SwapExactOut', () => { + const amountOut = bnum('45.568'); + + it('should correctly calculate amountIn given amountOut', async () => { + const amountIn = pool._tokenInForExactTokenOut( + poolPairData, + amountOut + ); + expect(amountIn.toString()).to.eq('68.953845491508993928'); + }); + it('should correctly calculate newSpotPrice', async () => { + const newSpotPrice = + pool._spotPriceAfterSwapTokenInForExactTokenOut( + poolPairData, + amountOut + ); + expect(Number(newSpotPrice.toString())).to.be.approximately( + 1.513243938739323921, + 0.000000000000000001 + ); + }); + it('should correctly calculate derivative of spot price function at newSpotPrice', async () => { + const derivative = + pool._derivativeSpotPriceAfterSwapTokenInForExactTokenOut( + poolPairData, + amountOut + ); + expect(Number(derivative.toString())).to.be.approximately( + 0.000001593445091924, + 0.000000000000000005 + ); + }); + }); + + context('FullSwap', () => { + it(`Full Swap - swapExactIn, Token>Token`, async () => { + const pools: SubgraphPoolBase[] = cloneDeep(testPools.pools); + const tokenIn = USDC.address; + const tokenOut = DAI.address; + const swapType = SwapTypes.SwapExactIn; + const swapAmt = parseFixed('13.5', 6); + + const gasPrice = parseFixed('30', 9); + const maxPools = 4; + const provider = new JsonRpcProvider(``); + + const sor = new SOR( + provider, + sorConfigEth, + new MockPoolDataService(pools), + mockTokenPriceService + ); + const fetchSuccess = await sor.fetchPools(); + expect(fetchSuccess).to.be.true; + + const swapInfo: SwapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmt, + { gasPrice, maxPools } + ); + + console.log(`Return amt:`); + console.log(swapInfo.returnAmount.toString()); + // This value is hard coded as sanity check if things unexpectedly change. Taken from V2 test run (with extra fee logic added). + // TO DO - expect(swapInfo.returnAmount.toString()).eq('999603'); + expect(swapInfo.swaps.length).eq(1); + expect(swapInfo.swaps[0].amount.toString()).eq( + swapAmt.toString() + ); + expect(swapInfo.swaps[0].poolId).eq(testPools.pools[0].id); + expect( + swapInfo.tokenAddresses[swapInfo.swaps[0].assetInIndex] + ).eq(tokenIn); + expect( + swapInfo.tokenAddresses[swapInfo.swaps[0].assetOutIndex] + ).eq(tokenOut); + }); + }); + }); +}); diff --git a/test/testData/gyro2Pools/gyro2V2TestPool.json b/test/testData/gyro2Pools/gyro2V2TestPool.json new file mode 100644 index 00000000..3b37dec8 --- /dev/null +++ b/test/testData/gyro2Pools/gyro2V2TestPool.json @@ -0,0 +1,49 @@ +{ + "tradeInfo": { + "SwapType": "n/a", + "TokenIn": "n/a", + "TokenOut": "n/a", + "NoPools": 1, + "SwapAmount": "n/a", + "GasPrice": "n/a", + "SwapAmountDecimals": "n/a", + "ReturnAmountDecimals": "n/a" + }, + "pools": [ + { + "id": "0xebfed10e11dc08fcda1af1fda146945e8710f22e0000000000000000000000ff", + "address": "0xebfed10e11dc08fcda1af1fda146945e8710f22e", + "swapFee": "0.009", + "tokens": [ + { + "address": "0x6b175474e89094c44da98b954eedeac495271d0f", + "balance": "1232", + "decimals": 18, + "symbol": "DAI", + "weight": null, + "priceRate": "1" + }, + { + "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "balance": "1000", + "decimals": 6, + "weight": null, + "priceRate": "1", + "symbol": "USDC" + } + ], + "tokensList": [ + "0x6b175474e89094c44da98b954eedeac495271d0f", + "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + ], + "totalWeight": "15", + "totalShares": "100", + "poolType": "Gyro2", + "poolTypeVersion": 2, + "swapEnabled": true, + "sqrtAlpha": "0.9994998749", + "sqrtBeta": "1.000499875", + "tokenRates": ["1.5", "1"] + } + ] +} From e8c2ff13ea98731b5a5758a0018b0ebb0715e651 Mon Sep 17 00:00:00 2001 From: Steffen Schuldenzucker Date: Sat, 18 Nov 2023 13:28:58 +0100 Subject: [PATCH 5/7] update Gyro license files in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2766c945..27059b70 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,4 @@ INFINITESIMAL=0.000001 Except where indicated otherwise, the code in this repository is licensed GPLv3. -Superluminal Labs Ltd. is the owner of the directories `balancer-sor/src/pools/gyro2Pool/`, `balancer-sor/src/pools/gyro3Pool/` and `balancer-sor/src/pools/gyroEPool/` and any accompanying files contained herein (collectively, these “Software”). Use of these Software is exclusively subject to the [Gyroscope Pool License](./src/pools/gyroEPool/LICENSE), which is available at the provided link (the “Gyroscope Pool License”). These Software are not covered by the General Public License and do not confer any rights to the user other than the limited rights specified in the Gyroscope Pool License. A special hybrid license between Superluminal Labs Ltd and Balancer Labs OÜ governs Superluminal Labs Ltd's use of the Balancer Labs OÜ code [Special License](./src/pools/gyroEPool/GyroscopeBalancerLicense.pdf), which is available at the provided link. By using these Software, you agree to be bound by the terms and conditions of the Gyroscope Pool License. If you do not agree to all terms and conditions of the Gyroscope Pool License, do not use any of these Software. +Superluminal Labs Ltd. is the owner of the directories `balancer-sor/src/pools/gyro2Pool/`, `balancer-sor/src/pools/gyro3Pool/`, `balancer-sor/src/pools/gyroEPool/`, `balancer-sor/src/pools/gyro2V2Pool/`, and `balancer-sor/src/pools/gyroEV2Pool/` and any accompanying files contained herein (collectively, these “Software”). Use of these Software is exclusively subject to the [Gyroscope Pool License](./src/pools/gyroEPool/LICENSE), which is available at the provided link (the “Gyroscope Pool License”). These Software are not covered by the General Public License and do not confer any rights to the user other than the limited rights specified in the Gyroscope Pool License. A special hybrid license between Superluminal Labs Ltd and Balancer Labs OÜ governs Superluminal Labs Ltd's use of the Balancer Labs OÜ code [Special License](./src/pools/gyroEPool/GyroscopeBalancerLicense.pdf), which is available at the provided link. By using these Software, you agree to be bound by the terms and conditions of the Gyroscope Pool License. If you do not agree to all terms and conditions of the Gyroscope Pool License, do not use any of these Software. From 280eb93d5cfbcce58dad25ee5a05df0c73d6f870 Mon Sep 17 00:00:00 2001 From: Josh Guha Date: Wed, 22 Nov 2023 10:31:18 +0000 Subject: [PATCH 6/7] minor updates to Gyro2V2 --- src/index.ts | 1 - src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts | 2 -- src/pools/gyro2V2Pool/gyro2V2Pool.ts | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 391ce431..da0829ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,6 @@ export { MetaStablePool } from './pools/metaStablePool/metaStablePool'; export { PhantomStablePool } from './pools/phantomStablePool/phantomStablePool'; export { ComposableStablePool } from './pools/composableStable/composableStablePool'; export { LinearPool } from './pools/linearPool/linearPool'; -// TODO should we still export the (deprecated) Gyro2Pool or scrap that & only export Gyro2V2Pool? export { Gyro2Pool } from './pools/gyro2Pool/gyro2Pool'; export { Gyro2V2Pool } from './pools/gyro2V2Pool/gyro2V2Pool'; export { Gyro3Pool } from './pools/gyro3Pool/gyro3Pool'; diff --git a/src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts b/src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts index bf2a00fe..441351f0 100644 --- a/src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts +++ b/src/pools/gyro2V2Pool/gyro2V2Math/gyro2V2MathHelpers.ts @@ -1,5 +1,3 @@ -// Same file as for gyroEV2Pool. (could just refer to that but I think this way it's cleaner) - import { BigNumber, parseFixed } from '@ethersproject/bignumber'; import { WeiPerEther as ONE } from '@ethersproject/constants'; import { mulDown } from '../../gyroHelpers/gyroSignedFixedPoint'; diff --git a/src/pools/gyro2V2Pool/gyro2V2Pool.ts b/src/pools/gyro2V2Pool/gyro2V2Pool.ts index 60ebc1ca..b8d77a76 100644 --- a/src/pools/gyro2V2Pool/gyro2V2Pool.ts +++ b/src/pools/gyro2V2Pool/gyro2V2Pool.ts @@ -59,7 +59,7 @@ export class Gyro2V2Pool implements PoolBase { ); if (!pool.tokenRates) - throw new Error('GyroEV2 Pool missing tokenRates'); + throw new Error('Gyro2V2 Pool missing tokenRates'); return new Gyro2V2Pool( pool.id, From dc2171199a8b74e4e65eeef434fc742501ea9eba Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Tue, 20 Feb 2024 12:07:27 -0300 Subject: [PATCH 7/7] Add integration tests for Gyro2V2 --- test/gyro2V2.integration.spec.ts | 224 +++++++++++++++++++++++++++++++ test/testScripts/utils.ts | 10 +- 2 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 test/gyro2V2.integration.spec.ts diff --git a/test/gyro2V2.integration.spec.ts b/test/gyro2V2.integration.spec.ts new file mode 100644 index 00000000..d4976225 --- /dev/null +++ b/test/gyro2V2.integration.spec.ts @@ -0,0 +1,224 @@ +// yarn test:only test/gyro2V2.integration.spec.ts +import dotenv from 'dotenv'; +dotenv.config(); + +import { expect } from 'chai'; +import { JsonRpcProvider } from '@ethersproject/providers'; +import { parseFixed } from '@ethersproject/bignumber'; +import { AddressZero } from '@ethersproject/constants'; +import { Vault__factory } from '@balancer-labs/typechain'; + +import { SOR, SubgraphPoolBase, SwapTypes } from '../src'; +import { ADDRESSES, Network, vaultAddr } from './testScripts/constants'; +import { setUp } from './testScripts/utils'; + +const networkId = Network.MAINNET; +const jsonRpcUrl = process.env.RPC_URL_MAINNET ?? ''; +const rpcUrl = 'http://127.0.0.1:8545'; +const provider = new JsonRpcProvider(rpcUrl, networkId); +const blocknumber = 19269440; + +const vault = Vault__factory.connect(vaultAddr, provider); + +const WETH = ADDRESSES[networkId].WETH; +const wSTETH = ADDRESSES[networkId].wSTETH; + +const gyro2V2_WSTETH_WETH: SubgraphPoolBase = { + id: '0xc6853f0539f7d4926c719326d60bd84a752bbb8f00020000000000000000065e', + address: '0xc6853f0539f7d4926c719326d60bd84a752bbb8f', + poolType: 'Gyro2', + poolTypeVersion: 2, + swapFee: '0.0001', + swapEnabled: true, + totalWeight: '0', + totalShares: '0.000026367631539116', + tokensList: [ + '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0', + '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + ], + tokens: [ + { + address: '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0', + balance: '0.000005508044603265', + decimals: 18, + priceRate: '1', + weight: null, + }, + { + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + balance: '0.000019999999999999', + decimals: 18, + priceRate: '1', + weight: null, + }, + ], + sqrtAlpha: '0.998348636499294268', + sqrtBeta: '1.001249219725039286', +}; + +const ROUNDING_ERROR_TOLERANCE = 2; // in wei + +describe('gyro2V2: WETH-wSTETH integration tests', () => { + let sor: SOR; + const funds = { + sender: AddressZero, + recipient: AddressZero, + fromInternalBalance: false, + toInternalBalance: false, + }; + + // Setup chain + before(async function () { + sor = await setUp( + networkId, + provider, + [gyro2V2_WSTETH_WETH], + jsonRpcUrl as string, + blocknumber + ); + + await sor.fetchPools(); + }); + context('ExactIn', async () => { + const swapType = SwapTypes.SwapExactIn; + + it('should return no swaps when above limit', async () => { + const tokenIn = WETH.address; + const tokenOut = wSTETH.address; + const swapAmount = parseFixed('1', WETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + expect(swapInfo.swaps.length).to.eq(0); + expect(swapInfo.returnAmount.toString()).to.eq('0'); + }); + it('token > LSD, getSwaps result should match queryBatchSwap', async () => { + const tokenIn = WETH.address; + const tokenOut = wSTETH.address; + const swapAmount = parseFixed('0.000000001', WETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + + const queryResult = await vault.callStatic.queryBatchSwap( + swapType, + swapInfo.swaps, + swapInfo.tokenAddresses, + funds + ); + + expect(queryResult[0].toNumber()).to.be.closeTo( + swapInfo.swapAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + expect(queryResult[1].toNumber() * -1).to.be.closeTo( + swapInfo.returnAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + }); + it('LSD > token, getSwaps result should match queryBatchSwap', async () => { + const tokenIn = wSTETH.address; + const tokenOut = WETH.address; + const swapAmount = parseFixed('0.000000001', wSTETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + + const queryResult = await vault.callStatic.queryBatchSwap( + swapType, + swapInfo.swaps, + swapInfo.tokenAddresses, + funds + ); + + expect(queryResult[0].toNumber()).to.be.closeTo( + swapInfo.swapAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + expect(queryResult[1].toNumber() * -1).to.be.closeTo( + swapInfo.returnAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + }); + }); + + context('ExactOut', async () => { + const swapType = SwapTypes.SwapExactOut; + + it('should return no swaps when above limit', async () => { + const tokenIn = WETH.address; + const tokenOut = wSTETH.address; + const swapAmount = parseFixed('1', wSTETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + + expect(swapInfo.swaps.length).to.eq(0); + expect(swapInfo.returnAmount.toString()).to.eq('0'); + }); + it('token > LSD, getSwaps result should match queryBatchSwap', async () => { + const tokenIn = WETH.address; + const tokenOut = wSTETH.address; + const swapAmount = parseFixed('0.000000001', wSTETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + + const queryResult = await vault.callStatic.queryBatchSwap( + swapType, + swapInfo.swaps, + swapInfo.tokenAddresses, + funds + ); + expect(queryResult[0].toNumber()).to.be.closeTo( + swapInfo.returnAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + expect(queryResult[1].toNumber() * -1).to.be.closeTo( + swapInfo.swapAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + }); + it('LSD > token, getSwaps result should match queryBatchSwap', async () => { + const tokenIn = wSTETH.address; + const tokenOut = WETH.address; + const swapAmount = parseFixed('0.000000001', WETH.decimals); + const swapInfo = await sor.getSwaps( + tokenIn, + tokenOut, + swapType, + swapAmount + ); + + const queryResult = await vault.callStatic.queryBatchSwap( + swapType, + swapInfo.swaps, + swapInfo.tokenAddresses, + funds + ); + expect(queryResult[0].toNumber()).to.be.closeTo( + swapInfo.returnAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + expect(queryResult[1].toNumber() * -1).to.be.closeTo( + swapInfo.swapAmount.toNumber(), + ROUNDING_ERROR_TOLERANCE + ); + }); + }); +}); diff --git a/test/testScripts/utils.ts b/test/testScripts/utils.ts index b9cae3aa..d5ddb0be 100644 --- a/test/testScripts/utils.ts +++ b/test/testScripts/utils.ts @@ -239,7 +239,7 @@ export const setUp = async ( provider, pools, }); - class CoingeckoTokenPriceService implements TokenPriceService { + class MockTokenPriceService implements TokenPriceService { constructor(private readonly chainId: number) {} async getNativeAssetPriceInToken( // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -249,16 +249,14 @@ export const setUp = async ( } } - // Use coingecko to fetch token price information. Used to calculate cost of additonal swaps/hops. - const coingeckoTokenPriceService = new CoingeckoTokenPriceService( - networkId - ); + // Mock token price information. Used to calculate cost of additonal swaps/hops. + const mockTokenPriceService = new MockTokenPriceService(networkId); return new SOR( provider, SOR_CONFIG[networkId], onChainPoolDataService, - coingeckoTokenPriceService + mockTokenPriceService ); };