From 04dddaf1cf9d572ba97ff65c2531ab8079bb13f5 Mon Sep 17 00:00:00 2001 From: johngrantuk Date: Wed, 30 Mar 2022 14:53:51 +0100 Subject: [PATCH 1/5] Added support for erc4626 new pool type. --- src/pools/index.ts | 5 ++++- src/types.ts | 1 + test/lib/onchainData.ts | 10 ++++++++-- test/lib/subgraphPoolDataService.ts | 2 +- test/testScripts/swapExample.ts | 25 ++++++++++++++++++++----- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/pools/index.ts b/src/pools/index.ts index 10e7cb51..95bbe26d 100644 --- a/src/pools/index.ts +++ b/src/pools/index.ts @@ -52,7 +52,10 @@ export function parseNewPool( } else if (pool.poolType === 'Element') { newPool = ElementPool.fromPool(pool); newPool.setCurrentBlockTimestamp(currentBlockTimestamp); - } else if (pool.poolType.toString().includes('Linear')) + } else if ( + pool.poolType.toString().includes('Linear') || + pool.poolType === 'ERC4626Linear' + ) newPool = LinearPool.fromPool(pool); else if (pool.poolType === 'StablePhantom') newPool = PhantomStablePool.fromPool(pool); diff --git a/src/types.ts b/src/types.ts index 176cbf42..caa4ee9b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -161,6 +161,7 @@ export enum PoolFilter { Element = 'Element', AaveLinear = 'AaveLinear', StablePhantom = 'StablePhantom', + ERC4626Linear = 'ERC4626Linear', } export interface PoolBase { diff --git a/test/lib/onchainData.ts b/test/lib/onchainData.ts index b6398fc2..617a5984 100644 --- a/test/lib/onchainData.ts +++ b/test/lib/onchainData.ts @@ -85,7 +85,10 @@ export async function getOnChainBalances( ); } else if (pool.poolType === 'Element') { multiPool.call(`${pool.id}.swapFee`, pool.address, 'percentFee'); - } else if (pool.poolType === 'AaveLinear') { + } else if ( + pool.poolType === 'AaveLinear' || + pool.poolType === 'ERC4626Linear' + ) { multiPool.call( `${pool.id}.swapFee`, pool.address, @@ -158,7 +161,10 @@ export async function getOnChainBalances( } } - if (subgraphPools[index].poolType === 'AaveLinear') { + if ( + subgraphPools[index].poolType === 'AaveLinear' || + subgraphPools[index].poolType === 'ERC4626Linear' + ) { if (!onchainData.targets) { console.error(`Linear Pool Missing Targets: ${poolId}`); return; diff --git a/test/lib/subgraphPoolDataService.ts b/test/lib/subgraphPoolDataService.ts index 0f429346..1e6dc1ec 100644 --- a/test/lib/subgraphPoolDataService.ts +++ b/test/lib/subgraphPoolDataService.ts @@ -77,7 +77,7 @@ export const Query: { [chainId: number]: string } = { 4: queryWithLinear, 5: queryWithLinear, 42: queryWithLinear, - 137: queryWithOutLinear, + 137: queryWithLinear, 42161: queryWithLinear, }; diff --git a/test/testScripts/swapExample.ts b/test/testScripts/swapExample.ts index 68e3b3fe..169a5b7a 100644 --- a/test/testScripts/swapExample.ts +++ b/test/testScripts/swapExample.ts @@ -288,6 +288,21 @@ export const ADDRESSES = { decimals: 18, symbol: 'DAI', }, + STETH: { + address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84', + decimals: 18, + symbol: 'STETH', + }, + stUSD_PLUS: { + address: '0x5a5c6aa6164750b530b8f7658b827163b3549a4d', + decimals: 6, + symbol: 'stUSD+', + }, + bstUSD_PLUS: { + address: '0x1aafc31091d93c3ff003cff5d2d8f7ba2e728425', + decimals: 18, + symbol: 'bstUSD+', + }, }, [Network.ARBITRUM]: { WETH: { @@ -674,13 +689,13 @@ async function makeRelayerTrade( } export async function simpleSwap() { - const networkId = Network.MAINNET; + const networkId = Network.POLYGON; // Pools source can be Subgraph URL or pools data set passed directly // Update pools list with most recent onchain balances - const tokenIn = ADDRESSES[networkId].bbausdc; - const tokenOut = ADDRESSES[networkId].waUSDC; - const swapType = SwapTypes.SwapExactOut; - const swapAmount = parseFixed('10', 6); + const tokenIn = ADDRESSES[networkId].bstUSD_PLUS; + const tokenOut = ADDRESSES[networkId].BAL; + const swapType = SwapTypes.SwapExactIn; + const swapAmount = parseFixed('0.1', 18); const executeTrade = true; const provider = new JsonRpcProvider(PROVIDER_URLS[networkId]); From 91fbd898a9f2a5479ab8f6d6e0b4d35e4facec74 Mon Sep 17 00:00:00 2001 From: johngrantuk Date: Wed, 30 Mar 2022 15:01:11 +0100 Subject: [PATCH 2/5] Changed onChain to use same `.includes(Linear)` syntax as parseNewPool --- src/pools/index.ts | 5 +---- test/lib/onchainData.ts | 10 ++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/pools/index.ts b/src/pools/index.ts index 95bbe26d..10e7cb51 100644 --- a/src/pools/index.ts +++ b/src/pools/index.ts @@ -52,10 +52,7 @@ export function parseNewPool( } else if (pool.poolType === 'Element') { newPool = ElementPool.fromPool(pool); newPool.setCurrentBlockTimestamp(currentBlockTimestamp); - } else if ( - pool.poolType.toString().includes('Linear') || - pool.poolType === 'ERC4626Linear' - ) + } else if (pool.poolType.toString().includes('Linear')) newPool = LinearPool.fromPool(pool); else if (pool.poolType === 'StablePhantom') newPool = PhantomStablePool.fromPool(pool); diff --git a/test/lib/onchainData.ts b/test/lib/onchainData.ts index 617a5984..1071c2c3 100644 --- a/test/lib/onchainData.ts +++ b/test/lib/onchainData.ts @@ -85,10 +85,7 @@ export async function getOnChainBalances( ); } else if (pool.poolType === 'Element') { multiPool.call(`${pool.id}.swapFee`, pool.address, 'percentFee'); - } else if ( - pool.poolType === 'AaveLinear' || - pool.poolType === 'ERC4626Linear' - ) { + } else if (pool.poolType.toString().includes('Linear')) { multiPool.call( `${pool.id}.swapFee`, pool.address, @@ -161,10 +158,7 @@ export async function getOnChainBalances( } } - if ( - subgraphPools[index].poolType === 'AaveLinear' || - subgraphPools[index].poolType === 'ERC4626Linear' - ) { + if (subgraphPools[index].poolType.includes('Linear')) { if (!onchainData.targets) { console.error(`Linear Pool Missing Targets: ${poolId}`); return; From e62cb9eda3616a1f25194ea692410faec10eca30 Mon Sep 17 00:00:00 2001 From: sergioyuhjtman Date: Tue, 5 Apr 2022 20:28:27 -0300 Subject: [PATCH 3/5] complete linearMath --- src/pools/linearPool/linearMath.ts | 502 +++++++++-------------------- src/pools/linearPool/linearPool.ts | 288 +++++++++-------- test/poolsMathLinear.spec.ts | 126 +++++++- 3 files changed, 405 insertions(+), 511 deletions(-) diff --git a/src/pools/linearPool/linearMath.ts b/src/pools/linearPool/linearMath.ts index f9938849..6c46e341 100644 --- a/src/pools/linearPool/linearMath.ts +++ b/src/pools/linearPool/linearMath.ts @@ -1,10 +1,6 @@ -import { BigNumber as OldBigNumber } from '../../utils/bignumber'; import { bnum } from '../../utils/bignumber'; -import { formatFixed } from '@ethersproject/bignumber'; import { MathSol } from '../../utils/basicOperations'; -import { LinearPoolPairData } from './linearPool'; - type Params = { fee: bigint; rate: bigint; @@ -85,6 +81,8 @@ export function _calcBptInPerWrappedOut( export function _calcWrappedOutPerMainIn( mainIn: bigint, mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, params: Params ): bigint { // Amount out, so we round down overall. @@ -97,6 +95,8 @@ export function _calcWrappedOutPerMainIn( export function _calcWrappedInPerMainOut( mainOut: bigint, mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, params: Params ): bigint { // Amount in, so we round up overall. @@ -158,6 +158,8 @@ export function _calcMainOutPerBptIn( export function _calcMainOutPerWrappedIn( wrappedIn: bigint, mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, params: Params ): bigint { // Amount out, so we round down overall. @@ -171,6 +173,8 @@ export function _calcMainOutPerWrappedIn( export function _calcMainInPerWrappedOut( wrappedOut: bigint, mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, params: Params ): bigint { // Amount in, so we round up overall. @@ -325,7 +329,7 @@ function _fromNominal(nominal: bigint, params: Params): bigint { } } -function leftDerivativeToNominalBigInt(amount: bigint, params: Params): bigint { +function leftDerivativeToNominal(amount: bigint, params: Params): bigint { const oneMinusFee = MathSol.complementFixed(params.fee); const onePlusFee = MathSol.ONE + params.fee; if (amount <= params.lowerTarget) { @@ -337,10 +341,7 @@ function leftDerivativeToNominalBigInt(amount: bigint, params: Params): bigint { } } -function rightDerivativeToNominalBigInt( - amount: bigint, - params: Params -): bigint { +function rightDerivativeToNominal(amount: bigint, params: Params): bigint { const oneMinusFee = MathSol.complementFixed(params.fee); const onePlusFee = MathSol.ONE + params.fee; if (amount < params.lowerTarget) { @@ -352,10 +353,7 @@ function rightDerivativeToNominalBigInt( } } -function leftDerivativeFromNominalBigInt( - amount: bigint, - params: Params -): bigint { +function leftDerivativeFromNominal(amount: bigint, params: Params): bigint { const oneMinusFee = MathSol.complementFixed(params.fee); const onePlusFee = MathSol.ONE + params.fee; if (amount <= params.lowerTarget) { @@ -367,10 +365,7 @@ function leftDerivativeFromNominalBigInt( } } -function rightDerivativeFromNominalBigInt( - amount: bigint, - params: Params -): bigint { +function rightDerivativeFromNominal(amount: bigint, params: Params): bigint { const oneMinusFee = MathSol.complementFixed(params.fee); const onePlusFee = MathSol.ONE + params.fee; if (amount < params.lowerTarget) { @@ -415,7 +410,7 @@ export function _calcTokensOutGivenExactBptIn( /// SpotPriceAfterSwap ///////// -// PairType = 'token->BPT' +// PairType = 'main->BPT' // SwapType = 'swapExactIn' export function _spotPriceAfterSwapBptOutPerMainIn( mainIn: bigint, @@ -437,11 +432,11 @@ export function _spotPriceAfterSwapBptOutPerMainIn( } return MathSol.divUpFixed( poolFactor, - rightDerivativeToNominalBigInt(finalMainBalance, params) + rightDerivativeToNominal(finalMainBalance, params) ); } -// PairType = 'token->BPT' +// PairType = 'main->BPT' // SwapType = 'swapExactOut' export function _spotPriceAfterSwapMainInPerBptOut( bptOut: bigint, @@ -464,11 +459,11 @@ export function _spotPriceAfterSwapMainInPerBptOut( const afterNominalMain = previousNominalMain + deltaNominalMain; return MathSol.mulUpFixed( poolFactor, - rightDerivativeFromNominalBigInt(afterNominalMain, params) + rightDerivativeFromNominal(afterNominalMain, params) ); } -// PairType = 'BPT->token' +// PairType = 'BPT->main' // SwapType = 'swapExactIn' export function _spotPriceAfterSwapMainOutPerBptIn( bptIn: bigint, @@ -490,12 +485,12 @@ export function _spotPriceAfterSwapMainOutPerBptIn( MathSol.ONE, MathSol.mulUpFixed( poolFactor, - leftDerivativeFromNominalBigInt(afterNominalMain, params) + leftDerivativeFromNominal(afterNominalMain, params) ) ); } -// PairType = 'BPT->token' +// PairType = 'BPT->main' // SwapType = 'swapExactOut' export function _spotPriceAfterSwapBptInPerMainOut( mainOut: bigint, @@ -513,197 +508,168 @@ export function _spotPriceAfterSwapBptInPerMainOut( ); const poolFactor = MathSol.divUpFixed(invariant, bptSupply); return MathSol.divUpFixed( - leftDerivativeToNominalBigInt(finalMainBalance, params), + leftDerivativeToNominal(finalMainBalance, params), poolFactor ); } -////////////////// - -///////// -/// SpotPriceAfterSwap -///////// - -// PairType = 'token->token' -// SwapType = 'swapExactIn' -export function _spotPriceAfterSwapExactTokenInForTokenOut( - amount, - poolPairData -): OldBigNumber { - // This is not expected to be used by SOR - // but could still be implemented - throw new Error('Function not implemented.'); +// PairType = 'main->wrapped' +// SwapType = 'swapExactOut' +export function _spotPriceAfterSwapMainInPerWrappedOut( + wrappedOut: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + const previousNominalMain = _toNominal(mainBalance, params); + const deltaNominalMain = MathSol.mulUpFixed(wrappedOut, params.rate); + const afterNominalMain = previousNominalMain + deltaNominalMain; + return MathSol.mulUpFixed( + rightDerivativeFromNominal(afterNominalMain, params), + params.rate + ); } -// PairType = 'token->token' +// PairType = 'wrapped->main' // SwapType = 'swapExactOut' -export function _spotPriceAfterSwapTokenInForExactTokenOut( - amount, - poolPairData -): OldBigNumber { - // This is not expected to be used by SOR - // but could still be implemented - throw new Error('Function not implemented.'); +export function _spotPriceAfterSwapWrappedInPerMainOut( + mainOut: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + const afterMain = mainBalance - mainOut; + return MathSol.divUpFixed( + leftDerivativeToNominal(afterMain, params), + params.rate + ); } -// PairType = 'token->BPT' +// PairType = 'main->wrapped' // SwapType = 'swapExactIn' -export function _spotPriceAfterSwapExactTokenInForBPTOut( - amount: OldBigNumber, - poolPairData: LinearPoolPairData -): OldBigNumber { - const mainIn = bnum(amount.toString()); - const mainBalance = bnum( - formatFixed(poolPairData.balanceIn, poolPairData.decimalsIn) - ); - const finalMainBalance = mainIn.plus(mainBalance); - const wrappedBalance = bnum( - formatFixed( - poolPairData.wrappedBalance.toString(), - poolPairData.wrappedDecimals - ) - ); - const virtualBptSupply = bnum( - formatFixed(poolPairData.virtualBptSupply, 18) - ); - const params: OldBigNumber[] = [ - bnum(formatFixed(poolPairData.swapFee, 18)), - bnum(formatFixed(poolPairData.rate.toString(), 18)), - bnum(formatFixed(poolPairData.lowerTarget.toString(), 18)), - bnum(formatFixed(poolPairData.upperTarget.toString(), 18)), - ]; - - const previousNominalMain = toNominal(mainBalance, params); - const invariant = calcInvariant( - previousNominalMain, - wrappedBalance, - params +export function _spotPriceAfterSwapWrappedOutPerMainIn( + mainIn: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + return MathSol.divDownFixed( + params.rate, + rightDerivativeToNominal(mainBalance + mainIn, params) ); - let poolFactor = bnum(1); - if (!virtualBptSupply.eq(0)) { - poolFactor = invariant.div(virtualBptSupply); - } - return poolFactor.div(rightDerivativeToNominal(finalMainBalance, params)); } -// PairType = 'token->BPT' -// SwapType = 'swapExactOut' -export function _spotPriceAfterSwapTokenInForExactBPTOut( - amount: OldBigNumber, - poolPairData: LinearPoolPairData -): OldBigNumber { - const bptOut = bnum(amount.toString()); - const virtualBptSupply = bnum( - formatFixed(poolPairData.virtualBptSupply, 18) - ); - const mainBalance = bnum( - formatFixed(poolPairData.balanceIn, poolPairData.decimalsIn) - ); - const wrappedBalance = bnum( - formatFixed( - poolPairData.wrappedBalance.toString(), - poolPairData.wrappedDecimals - ) +// PairType = 'wrapped->main' +// SwapType = 'swapExactIn' +export function _spotPriceAfterSwapMainOutPerWrappedIn( + wrappedIn: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + const previousNominalMain = _toNominal(mainBalance, params); + const deltaNominalMain = MathSol.mulDownFixed(wrappedIn, params.rate); + const afterNominalMain = previousNominalMain - deltaNominalMain; + const inversePrice = MathSol.mulUpFixed( + leftDerivativeFromNominal(afterNominalMain, params), + params.rate ); - const params: OldBigNumber[] = [ - bnum(formatFixed(poolPairData.swapFee, 18)), - bnum(formatFixed(poolPairData.rate.toString(), 18)), - bnum(formatFixed(poolPairData.lowerTarget.toString(), 18)), - bnum(formatFixed(poolPairData.upperTarget.toString(), 18)), - ]; + return MathSol.divUpFixed(MathSol.ONE, inversePrice); +} - const previousNominalMain = toNominal(mainBalance, params); - const invariant = calcInvariant( - previousNominalMain, +// PairType = 'wrapped->BPT' +// SwapType = 'swapExactIn' +export function _spotPriceAfterSwapBptOutPerWrappedIn( + wrappedIn: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + if (bptSupply == BigInt(0)) { + return params.rate; + } + const nominalMain = _toNominal(mainBalance, params); + const previousInvariant = _calcInvariantUp( + nominalMain, wrappedBalance, params ); - let poolFactor = bnum(1); - if (!virtualBptSupply.eq(0)) { - poolFactor = invariant.div(virtualBptSupply); - } - const deltaNominalMain = bptOut.times(poolFactor); - const afterNominalMain = previousNominalMain.plus(deltaNominalMain); - return poolFactor.times( - rightDerivativeFromNominal(afterNominalMain, params) + return MathSol.divUpFixed( + previousInvariant, + MathSol.mulUpFixed(bptSupply, params.rate) ); } -// PairType = 'BPT->token' +// PairType = 'BPT->wrapped' // SwapType = 'swapExactIn' -export function _spotPriceAfterSwapExactBPTInForTokenOut( - amount: OldBigNumber, - poolPairData: LinearPoolPairData -): OldBigNumber { - const bptIn = bnum(amount.toString()); - const mainBalance = bnum( - formatFixed(poolPairData.balanceOut, poolPairData.decimalsOut) - ); - const wrappedBalance = bnum( - formatFixed( - poolPairData.wrappedBalance.toString(), - poolPairData.wrappedDecimals - ) - ); - const virtualBptSupply = bnum( - formatFixed(poolPairData.virtualBptSupply, 18) - ); - const params: OldBigNumber[] = [ - bnum(formatFixed(poolPairData.swapFee, 18)), - bnum(formatFixed(poolPairData.rate.toString(), 18)), - bnum(formatFixed(poolPairData.lowerTarget.toString(), 18)), - bnum(formatFixed(poolPairData.upperTarget.toString(), 18)), - ]; - - const previousNominalMain = toNominal(mainBalance, params); - const invariant = calcInvariant( - previousNominalMain, +export function _spotPriceAfterSwapWrappedOutPerBptIn( + bptIn: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + const nominalMain = _toNominal(mainBalance, params); + const previousInvariant = _calcInvariantUp( + nominalMain, wrappedBalance, params ); - const poolFactor = invariant.div(virtualBptSupply); - const deltaNominalMain = bptIn.times(poolFactor); - const afterNominalMain = previousNominalMain.minus(deltaNominalMain); - return bnum(1).div( - poolFactor.times(leftDerivativeFromNominal(afterNominalMain, params)) + return MathSol.divUp( + MathSol.mul(bptSupply, params.rate), + previousInvariant ); } -// PairType = 'BPT->token' +// PairType = 'wrapped->BPT' // SwapType = 'swapExactOut' -export function _spotPriceAfterSwapBPTInForExactTokenOut( - amount: OldBigNumber, - poolPairData: LinearPoolPairData -): OldBigNumber { - const mainOut = bnum(amount.toString()); - const mainBalance = bnum( - formatFixed(poolPairData.balanceOut, poolPairData.decimalsOut) - ); - const wrappedBalance = bnum( - formatFixed( - poolPairData.wrappedBalance.toString(), - poolPairData.wrappedDecimals - ) +export function _spotPriceAfterSwapWrappedInPerBptOut( + bptOut: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + if (bptSupply == BigInt(0)) { + return MathSol.divUpFixed(MathSol.ONE, params.rate); + } + + const nominalMain = _toNominal(mainBalance, params); + const previousInvariant = _calcInvariantUp( + nominalMain, + wrappedBalance, + params ); - const virtualBptSupply = bnum( - formatFixed(poolPairData.virtualBptSupply, 18) + return MathSol.divUpFixed( + previousInvariant, + MathSol.mul(bptSupply, params.rate) ); - const finalMainBalance = mainBalance.minus(mainOut); - const params: OldBigNumber[] = [ - bnum(formatFixed(poolPairData.swapFee, 18)), - bnum(formatFixed(poolPairData.rate.toString(), 18)), - bnum(formatFixed(poolPairData.lowerTarget.toString(), 18)), - bnum(formatFixed(poolPairData.upperTarget.toString(), 18)), - ]; +} - const previousNominalMain = toNominal(mainBalance, params); - const invariant = calcInvariant( - previousNominalMain, +// PairType = 'BPT->wrapped' +// SwapType = 'swapExactOut' +export function _spotPriceAfterSwapBptInPerWrappedOut( + wrappedOut: bigint, + mainBalance: bigint, + wrappedBalance: bigint, + bptSupply: bigint, + params: Params +): bigint { + const nominalMain = _toNominal(mainBalance, params); + const previousInvariant = _calcInvariantUp( + nominalMain, wrappedBalance, params ); - const poolFactor = invariant.div(virtualBptSupply); - return leftDerivativeToNominal(finalMainBalance, params).div(poolFactor); + return MathSol.divDown( + MathSol.mul(bptSupply, params.rate), + previousInvariant + ); } ///////// @@ -713,179 +679,3 @@ export function _spotPriceAfterSwapBPTInForExactTokenOut( // Derivative of spot price is always zero, except at the target break points, // where it is infinity in some sense. But we ignore this pathology, return zero // and expect good behaviour at the optimization of amounts algorithm. - -// PairType = 'token->token' -// SwapType = 'swapExactIn' -export function _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( - amount, - poolPairData -): OldBigNumber { - // This is not expected to be used by SOR - // but could still be implemented - throw new Error('Function not implemented.'); -} - -// PairType = 'token->token' -// SwapType = 'swapExactOut' -export function _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( - amount, - poolPairData -): OldBigNumber { - // This is not expected to be used by SOR - // but could still be implemented - throw new Error('Function not implemented.'); -} - -// PairType = 'token->BPT' -// SwapType = 'swapExactIn' -export function _derivativeSpotPriceAfterSwapExactTokenInForBPTOut( - amount, - poolPairData -): OldBigNumber { - return bnum(0); -} - -// PairType = 'token->BPT' -// SwapType = 'swapExactOut' -export function _derivativeSpotPriceAfterSwapTokenInForExactBPTOut( - amount, - poolPairData -): OldBigNumber { - return bnum(0); -} - -// PairType = 'BPT->token' -// SwapType = 'swapExactIn' -export function _derivativeSpotPriceAfterSwapExactBPTInForTokenOut( - amount, - poolPairData -): OldBigNumber { - return bnum(0); -} - -// PairType = 'BPT->token' -// SwapType = 'swapExactOut' -export function _derivativeSpotPriceAfterSwapBPTInForExactTokenOut( - amount, - poolPairData -): OldBigNumber { - return bnum(0); -} - -function calcInvariant( - nominalMainBalance: OldBigNumber, - wrappedBalance: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const rate = params[1]; - return nominalMainBalance.plus(wrappedBalance.times(rate)); -} - -function toNominal(amount: OldBigNumber, params: OldBigNumber[]): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - if (amount.lt(lowerTarget)) { - const fees = lowerTarget.minus(amount).times(fee); - const result = amount.minus(fees); - if (result.lt(0)) { - console.log('negative nominal balance'); - return bnum(0).minus(result); - } - return result; - } else if (amount.lt(upperTarget)) { - return amount; - } else { - const fees = amount.minus(upperTarget).times(fee); - return amount.minus(fees); - } -} - -function leftDerivativeToNominal( - amount: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - const oneMinusFee = bnum(1).minus(fee); - const onePlusFee = bnum(1).plus(fee); - if (amount.lte(lowerTarget)) { - return onePlusFee; - } else if (amount.lte(upperTarget)) { - return bnum(1); - } else { - return oneMinusFee; - } -} - -function rightDerivativeToNominal( - amount: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - const oneMinusFee = bnum(1).minus(fee); - const onePlusFee = bnum(1).plus(fee); - if (amount.lt(lowerTarget)) { - return onePlusFee; - } else if (amount.lt(upperTarget)) { - return bnum(1); - } else { - return oneMinusFee; - } -} - -function fromNominal( - nominal: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - const oneMinusFee = bnum(1).minus(fee); - const onePlusFee = bnum(1).plus(fee); - if (nominal.lt(lowerTarget)) { - return nominal.plus(lowerTarget.times(fee)).div(onePlusFee); - } else if (nominal.lt(upperTarget)) { - return nominal; - } else { - return nominal.minus(upperTarget.times(fee)).div(oneMinusFee); - } -} -function leftDerivativeFromNominal( - amount: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - const oneMinusFee = bnum(1).minus(fee); - const onePlusFee = bnum(1).plus(fee); - if (amount.lte(lowerTarget)) { - return bnum(1).div(onePlusFee); - } else if (amount.lte(upperTarget)) { - return bnum(1); - } else { - return bnum(1).div(oneMinusFee); - } -} - -function rightDerivativeFromNominal( - amount: OldBigNumber, - params: OldBigNumber[] -): OldBigNumber { - const fee = params[0]; - const lowerTarget = params[2]; - const upperTarget = params[3]; - const oneMinusFee = bnum(1).minus(fee); - const onePlusFee = bnum(1).plus(fee); - if (amount.lt(lowerTarget)) { - return bnum(1).div(onePlusFee); - } else if (amount.lt(upperTarget)) { - return bnum(1); - } else { - return bnum(1).div(oneMinusFee); - } -} diff --git a/src/pools/linearPool/linearPool.ts b/src/pools/linearPool/linearPool.ts index ee3bd568..5dbec0eb 100644 --- a/src/pools/linearPool/linearPool.ts +++ b/src/pools/linearPool/linearPool.ts @@ -24,18 +24,18 @@ import { _calcBptOutPerWrappedIn, _calcWrappedInPerBptOut, _calcWrappedOutPerBptIn, - _spotPriceAfterSwapExactTokenInForTokenOut, - _spotPriceAfterSwapExactTokenInForBPTOut, - _spotPriceAfterSwapExactBPTInForTokenOut, - _spotPriceAfterSwapTokenInForExactTokenOut, - _spotPriceAfterSwapTokenInForExactBPTOut, - _spotPriceAfterSwapBPTInForExactTokenOut, - _derivativeSpotPriceAfterSwapExactTokenInForTokenOut, - _derivativeSpotPriceAfterSwapExactTokenInForBPTOut, - _derivativeSpotPriceAfterSwapExactBPTInForTokenOut, - _derivativeSpotPriceAfterSwapTokenInForExactTokenOut, - _derivativeSpotPriceAfterSwapTokenInForExactBPTOut, - _derivativeSpotPriceAfterSwapBPTInForExactTokenOut, + _spotPriceAfterSwapBptOutPerMainIn, + _spotPriceAfterSwapMainOutPerBptIn, + _spotPriceAfterSwapBptOutPerWrappedIn, + _spotPriceAfterSwapWrappedOutPerBptIn, + _spotPriceAfterSwapWrappedOutPerMainIn, + _spotPriceAfterSwapMainOutPerWrappedIn, + _spotPriceAfterSwapMainInPerBptOut, + _spotPriceAfterSwapBptInPerMainOut, + _spotPriceAfterSwapWrappedInPerBptOut, + _spotPriceAfterSwapBptInPerWrappedOut, + _spotPriceAfterSwapMainInPerWrappedOut, + _spotPriceAfterSwapWrappedInPerMainOut, } from './linearMath'; export enum PairTypes { @@ -339,6 +339,8 @@ export class LinearPool implements PoolBase { const amt = _calcMainOutPerWrappedIn( amtScaled.toBigInt(), poolPairData.mainBalanceScaled.toBigInt(), + poolPairData.wrappedBalanceScaled.toBigInt(), + poolPairData.virtualBptSupply.toBigInt(), { fee: poolPairData.swapFee.toBigInt(), lowerTarget: poolPairData.lowerTarget.toBigInt(), @@ -371,6 +373,8 @@ export class LinearPool implements PoolBase { const amt = _calcWrappedOutPerMainIn( amtScaled.toBigInt(), poolPairData.mainBalanceScaled.toBigInt(), + poolPairData.wrappedBalanceScaled.toBigInt(), + poolPairData.virtualBptSupply.toBigInt(), { fee: poolPairData.swapFee.toBigInt(), lowerTarget: poolPairData.lowerTarget.toBigInt(), @@ -559,6 +563,8 @@ export class LinearPool implements PoolBase { const amt = _calcWrappedInPerMainOut( amtScaled.toBigInt(), poolPairData.mainBalanceScaled.toBigInt(), + poolPairData.wrappedBalanceScaled.toBigInt(), + poolPairData.virtualBptSupply.toBigInt(), { fee: poolPairData.swapFee.toBigInt(), lowerTarget: poolPairData.lowerTarget.toBigInt(), @@ -591,6 +597,8 @@ export class LinearPool implements PoolBase { const amt = _calcMainInPerWrappedOut( amtScaled.toBigInt(), poolPairData.mainBalanceScaled.toBigInt(), + poolPairData.wrappedBalanceScaled.toBigInt(), + poolPairData.virtualBptSupply.toBigInt(), { fee: poolPairData.swapFee.toBigInt(), lowerTarget: poolPairData.lowerTarget.toBigInt(), @@ -747,169 +755,167 @@ export class LinearPool implements PoolBase { } } + // SPOT PRICES AFTER SWAP + _spotPriceAfterSwapExactTokenInForTokenOut( poolPairData: LinearPoolPairData, amount: OldBigNumber ): OldBigNumber { - // For now we used the main token eqn for wrapped token as that maths isn't written and estimate should be ok for limited available paths - if ( - poolPairData.pairType === PairTypes.MainTokenToBpt || - poolPairData.pairType === PairTypes.WrappedTokenToBpt - ) { - return this._spotPriceAfterSwapExactTokenInForBPTOut( - poolPairData, - amount + const bigintAmount = parseFixed(amount.toString(), 18).toBigInt(); + const mainBalance = poolPairData.mainBalanceScaled.toBigInt(); + const wrappedBalance = poolPairData.wrappedBalanceScaled.toBigInt(); + const bptSupply = poolPairData.virtualBptSupply.toBigInt(); + const params = { + fee: poolPairData.swapFee.toBigInt(), + lowerTarget: poolPairData.lowerTarget.toBigInt(), + upperTarget: poolPairData.upperTarget.toBigInt(), + rate: poolPairData.rate.toBigInt(), + }; + let result: bigint; + if (poolPairData.pairType === PairTypes.MainTokenToBpt) { + result = _spotPriceAfterSwapBptOutPerMainIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else if ( - poolPairData.pairType === PairTypes.BptToMainToken || - poolPairData.pairType === PairTypes.BptToWrappedToken - ) { - return this._spotPriceAfterSwapExactBPTInForTokenOut( - poolPairData, - amount + } else if (poolPairData.pairType === PairTypes.BptToMainToken) { + result = _spotPriceAfterSwapMainOutPerBptIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else - return _spotPriceAfterSwapExactTokenInForTokenOut( - amount, - poolPairData + } else if (poolPairData.pairType === PairTypes.WrappedTokenToBpt) { + result = _spotPriceAfterSwapBptOutPerWrappedIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } - - _spotPriceAfterSwapExactTokenInForBPTOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _spotPriceAfterSwapExactTokenInForBPTOut(amount, poolPairData); - } - - _spotPriceAfterSwapExactBPTInForTokenOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _spotPriceAfterSwapExactBPTInForTokenOut(amount, poolPairData); - } - - _spotPriceAfterSwapTokenInForExactTokenOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - // For now we used the main token eqn for wrapped token as that maths isn't written and estimate should be ok for limited available paths - if ( - poolPairData.pairType === PairTypes.MainTokenToBpt || - poolPairData.pairType === PairTypes.WrappedTokenToBpt - ) { - return this._spotPriceAfterSwapTokenInForExactBPTOut( - poolPairData, - amount + } else if (poolPairData.pairType === PairTypes.BptToWrappedToken) { + result = _spotPriceAfterSwapWrappedOutPerBptIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); } else if ( - poolPairData.pairType === PairTypes.BptToMainToken || - poolPairData.pairType === PairTypes.BptToWrappedToken + poolPairData.pairType === PairTypes.MainTokenToWrappedToken ) { - return this._spotPriceAfterSwapBPTInForExactTokenOut( - poolPairData, - amount + result = _spotPriceAfterSwapWrappedOutPerMainIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else - return _spotPriceAfterSwapTokenInForExactTokenOut( - amount, - poolPairData + } else if ( + poolPairData.pairType === PairTypes.WrappedTokenToMainToken + ) { + result = _spotPriceAfterSwapMainOutPerWrappedIn( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); + } else return bnum(0); + return scale(bnum(result.toString()), -18).dp( + poolPairData.decimalsOut, + 0 + ); } - _spotPriceAfterSwapTokenInForExactBPTOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _spotPriceAfterSwapTokenInForExactBPTOut(amount, poolPairData); - } - - _spotPriceAfterSwapBPTInForExactTokenOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _spotPriceAfterSwapBPTInForExactTokenOut(amount, poolPairData); - } - - _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( + _spotPriceAfterSwapTokenInForExactTokenOut( poolPairData: LinearPoolPairData, amount: OldBigNumber ): OldBigNumber { + const bigintAmount = parseFixed(amount.toString(), 18).toBigInt(); + const mainBalance = poolPairData.mainBalanceScaled.toBigInt(); + const wrappedBalance = poolPairData.wrappedBalanceScaled.toBigInt(); + const bptSupply = poolPairData.virtualBptSupply.toBigInt(); + const params = { + fee: poolPairData.swapFee.toBigInt(), + lowerTarget: poolPairData.lowerTarget.toBigInt(), + upperTarget: poolPairData.upperTarget.toBigInt(), + rate: poolPairData.rate.toBigInt(), + }; + let result: bigint; if (poolPairData.pairType === PairTypes.MainTokenToBpt) { - return this._derivativeSpotPriceAfterSwapExactTokenInForBPTOut( - poolPairData, - amount + result = _spotPriceAfterSwapMainInPerBptOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); } else if (poolPairData.pairType === PairTypes.BptToMainToken) { - return this._derivativeSpotPriceAfterSwapExactBPTInForTokenOut( - poolPairData, - amount + result = _spotPriceAfterSwapBptInPerMainOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else - return _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( - amount, - poolPairData + } else if (poolPairData.pairType === PairTypes.WrappedTokenToBpt) { + result = _spotPriceAfterSwapWrappedInPerBptOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } - - _derivativeSpotPriceAfterSwapExactTokenInForBPTOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _derivativeSpotPriceAfterSwapExactTokenInForBPTOut( - amount, - poolPairData - ); - } - - _derivativeSpotPriceAfterSwapExactBPTInForTokenOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - return _derivativeSpotPriceAfterSwapExactBPTInForTokenOut( - amount, - poolPairData - ); - } - - _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( - poolPairData: LinearPoolPairData, - amount: OldBigNumber - ): OldBigNumber { - if (poolPairData.pairType === PairTypes.MainTokenToBpt) { - return this._derivativeSpotPriceAfterSwapTokenInForExactBPTOut( - poolPairData, - amount + } else if (poolPairData.pairType === PairTypes.BptToWrappedToken) { + result = _spotPriceAfterSwapBptInPerWrappedOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else if (poolPairData.pairType === PairTypes.BptToMainToken) { - return this._derivativeSpotPriceAfterSwapBPTInForExactTokenOut( - poolPairData, - amount + } else if ( + poolPairData.pairType === PairTypes.MainTokenToWrappedToken + ) { + result = _spotPriceAfterSwapMainInPerWrappedOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); - } else - return _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( - amount, - poolPairData + } else if ( + poolPairData.pairType === PairTypes.WrappedTokenToMainToken + ) { + result = _spotPriceAfterSwapWrappedInPerMainOut( + bigintAmount, + mainBalance, + wrappedBalance, + bptSupply, + params ); + } else return bnum(0); + return scale(bnum(result.toString()), -18).dp( + poolPairData.decimalsOut, + 0 + ); } - _derivativeSpotPriceAfterSwapTokenInForExactBPTOut( + _derivativeSpotPriceAfterSwapExactTokenInForTokenOut( poolPairData: LinearPoolPairData, amount: OldBigNumber ): OldBigNumber { - return _derivativeSpotPriceAfterSwapTokenInForExactBPTOut( - amount, - poolPairData - ); + return bnum(0); } - _derivativeSpotPriceAfterSwapBPTInForExactTokenOut( + _derivativeSpotPriceAfterSwapTokenInForExactTokenOut( poolPairData: LinearPoolPairData, amount: OldBigNumber ): OldBigNumber { - return _derivativeSpotPriceAfterSwapBPTInForExactTokenOut( - amount, - poolPairData - ); + return bnum(0); } } diff --git a/test/poolsMathLinear.spec.ts b/test/poolsMathLinear.spec.ts index 43ae2065..c7be75ee 100644 --- a/test/poolsMathLinear.spec.ts +++ b/test/poolsMathLinear.spec.ts @@ -1,6 +1,7 @@ import * as linear from '../src/pools/linearPool/linearMath'; import { MathSol } from '../src/utils/basicOperations'; import { assert } from 'chai'; +import { wrap } from 'module'; describe('poolsMathLinear', function () { // For swap outcome functions: @@ -117,6 +118,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedOutPerMainIn( mainIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(10.1), 0); @@ -127,6 +130,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainInPerWrappedOut( wrappedOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(10), 0); @@ -139,6 +144,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedInPerMainOut( mainOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(10.1), 0); @@ -149,6 +156,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainOutPerWrappedIn( wrappedIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(10), 0); @@ -273,6 +282,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedOutPerMainIn( mainIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(20), 0); @@ -283,6 +294,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainInPerWrappedOut( wrappedOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(20), 0); @@ -295,6 +308,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedInPerMainOut( mainOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(20), 0); @@ -305,6 +320,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainOutPerWrappedIn( wrappedIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(20), 0); @@ -429,6 +446,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedOutPerMainIn( mainIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(49.5), 0); @@ -439,6 +458,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainInPerWrappedOut( wrappedOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(50), 0); @@ -451,6 +472,8 @@ describe('poolsMathLinear', function () { const result = linear._calcWrappedInPerMainOut( mainOut, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(54.6), 0); @@ -461,6 +484,8 @@ describe('poolsMathLinear', function () { const result = linear._calcMainOutPerWrappedIn( wrappedIn, mainBalance, + wrappedBalance, + bptSupply, params ); verify(result, s(55), 0); @@ -530,8 +555,8 @@ describe('poolsMathLinear', function () { }; const mainBalanceTest = [500, 1400, 8000]; it('BptOutPerMainIn', () => { - for (let mainBalance of mainBalanceTest) { - for (let amount of [70, 700]) { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 700]) { checkDerivative( linear._calcBptOutPerMainIn, linear._spotPriceAfterSwapBptOutPerMainIn, @@ -547,9 +572,27 @@ describe('poolsMathLinear', function () { } } }); + it('MainOutPerBptIn', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 150]) { + checkDerivative( + linear._calcMainOutPerBptIn, + linear._spotPriceAfterSwapMainOutPerBptIn, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + true + ); + } + } + }); it('MainInPerBptOut', () => { - for (let mainBalance of mainBalanceTest) { - for (let amount of [70, 7000]) { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 700]) { checkDerivative( linear._calcMainInPerBptOut, linear._spotPriceAfterSwapMainInPerBptOut, @@ -565,12 +608,30 @@ describe('poolsMathLinear', function () { } } }); - it('MainOutPerBptIn', () => { - for (let mainBalance of mainBalanceTest) { - for (let amount of [70, 150]) { + it('BptInPerMainOut', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 420]) { checkDerivative( - linear._calcMainOutPerBptIn, - linear._spotPriceAfterSwapMainOutPerBptIn, + linear._calcBptInPerMainOut, + linear._spotPriceAfterSwapBptInPerMainOut, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + false + ); + } + } + }); + it('WrappedOutPerMainIn', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 420]) { + checkDerivative( + linear._calcWrappedOutPerMainIn, + linear._spotPriceAfterSwapWrappedOutPerMainIn, amount, mainBalance, 8000, // wrappedBalance @@ -583,12 +644,48 @@ describe('poolsMathLinear', function () { } } }); - it('BptInPerMainOut', () => { - for (let mainBalance of mainBalanceTest) { - for (let amount of [70, 420]) { + it('MainOutPerWrappedIn', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 420]) { checkDerivative( - linear._calcBptInPerMainOut, - linear._spotPriceAfterSwapBptInPerMainOut, + linear._calcMainOutPerWrappedIn, + linear._spotPriceAfterSwapMainOutPerWrappedIn, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + true + ); + } + } + }); + it('WrappedInPerMainOut', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 420]) { + checkDerivative( + linear._calcWrappedInPerMainOut, + linear._spotPriceAfterSwapWrappedInPerMainOut, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + false + ); + } + } + }); + it('MainInPerWrappedOut', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [70, 420]) { + checkDerivative( + linear._calcMainInPerWrappedOut, + linear._spotPriceAfterSwapMainInPerWrappedOut, amount, mainBalance, 8000, // wrappedBalance @@ -601,6 +698,7 @@ describe('poolsMathLinear', function () { } } }); + // TO DO: add wrapped<>Bpt items }); }); From c2cc1ffc13957a5b2b525a9eadadaa5a14742ed1 Mon Sep 17 00:00:00 2001 From: sergioyuhjtman Date: Wed, 6 Apr 2022 20:00:49 -0300 Subject: [PATCH 4/5] debug and complete test cases --- src/pools/linearPool/linearMath.ts | 4 +- test/poolsMathLinear.spec.ts | 128 +++++++++++++++++++++++------ 2 files changed, 106 insertions(+), 26 deletions(-) diff --git a/src/pools/linearPool/linearMath.ts b/src/pools/linearPool/linearMath.ts index 6c46e341..7b351d4d 100644 --- a/src/pools/linearPool/linearMath.ts +++ b/src/pools/linearPool/linearMath.ts @@ -647,7 +647,7 @@ export function _spotPriceAfterSwapWrappedInPerBptOut( ); return MathSol.divUpFixed( previousInvariant, - MathSol.mul(bptSupply, params.rate) + MathSol.mulUpFixed(bptSupply, params.rate) ); } @@ -678,4 +678,4 @@ export function _spotPriceAfterSwapBptInPerWrappedOut( // Derivative of spot price is always zero, except at the target break points, // where it is infinity in some sense. But we ignore this pathology, return zero -// and expect good behaviour at the optimization of amounts algorithm. +// and expect good behaviour at the optimization algorithm. diff --git a/test/poolsMathLinear.spec.ts b/test/poolsMathLinear.spec.ts index c7be75ee..b39821b2 100644 --- a/test/poolsMathLinear.spec.ts +++ b/test/poolsMathLinear.spec.ts @@ -1,7 +1,6 @@ import * as linear from '../src/pools/linearPool/linearMath'; import { MathSol } from '../src/utils/basicOperations'; import { assert } from 'chai'; -import { wrap } from 'module'; describe('poolsMathLinear', function () { // For swap outcome functions: @@ -553,10 +552,11 @@ describe('poolsMathLinear', function () { lowerTarget: s(1000), upperTarget: s(2000), }; - const mainBalanceTest = [500, 1400, 8000]; + const mainBalanceTest = [500, 950, 1050, 1400, 1950, 2050, 8000]; + // main<>bpt it('BptOutPerMainIn', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 700]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { checkDerivative( linear._calcBptOutPerMainIn, linear._spotPriceAfterSwapBptOutPerMainIn, @@ -574,13 +574,13 @@ describe('poolsMathLinear', function () { }); it('MainOutPerBptIn', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 150]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { checkDerivative( linear._calcMainOutPerBptIn, linear._spotPriceAfterSwapMainOutPerBptIn, amount, mainBalance, - 8000, // wrappedBalance + 100, // wrappedBalance 3500, // bptSupply params, delta, @@ -591,26 +591,30 @@ describe('poolsMathLinear', function () { } }); it('MainInPerBptOut', () => { + // missing test case: bptSupply = 0 for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 700]) { - checkDerivative( - linear._calcMainInPerBptOut, - linear._spotPriceAfterSwapMainInPerBptOut, - amount, - mainBalance, - 8000, // wrappedBalance - 3500, // bptSupply - params, - delta, - error, - false - ); + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + for (const bptSupply of [3500]) { + checkDerivative( + linear._calcMainInPerBptOut, + linear._spotPriceAfterSwapMainInPerBptOut, + amount, + mainBalance, + 8000, // wrappedBalance + bptSupply, + params, + delta, + error, + false + ); + } } } }); it('BptInPerMainOut', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 420]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + if (amount > mainBalance) continue; checkDerivative( linear._calcBptInPerMainOut, linear._spotPriceAfterSwapBptInPerMainOut, @@ -626,9 +630,10 @@ describe('poolsMathLinear', function () { } } }); + // main<>wrapped it('WrappedOutPerMainIn', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 420]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { checkDerivative( linear._calcWrappedOutPerMainIn, linear._spotPriceAfterSwapWrappedOutPerMainIn, @@ -646,7 +651,7 @@ describe('poolsMathLinear', function () { }); it('MainOutPerWrappedIn', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 420]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { checkDerivative( linear._calcMainOutPerWrappedIn, linear._spotPriceAfterSwapMainOutPerWrappedIn, @@ -664,7 +669,8 @@ describe('poolsMathLinear', function () { }); it('WrappedInPerMainOut', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 420]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + if (amount > mainBalance) continue; checkDerivative( linear._calcWrappedInPerMainOut, linear._spotPriceAfterSwapWrappedInPerMainOut, @@ -682,7 +688,7 @@ describe('poolsMathLinear', function () { }); it('MainInPerWrappedOut', () => { for (const mainBalance of mainBalanceTest) { - for (const amount of [70, 420]) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { checkDerivative( linear._calcMainInPerWrappedOut, linear._spotPriceAfterSwapMainInPerWrappedOut, @@ -698,7 +704,81 @@ describe('poolsMathLinear', function () { } } }); - // TO DO: add wrapped<>Bpt items + // bpt<>wrapped + it('WrappedOutPerBptIn', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + checkDerivative( + linear._calcWrappedOutPerBptIn, + linear._spotPriceAfterSwapWrappedOutPerBptIn, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + true + ); + } + } + }); + it('BptOutPerWrappedIn', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + checkDerivative( + linear._calcBptOutPerWrappedIn, + linear._spotPriceAfterSwapBptOutPerWrappedIn, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + true + ); + } + } + }); + it('WrappedInPerBptOut', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + for (const bptSupply of [0, 3500]) { + checkDerivative( + linear._calcWrappedInPerBptOut, + linear._spotPriceAfterSwapWrappedInPerBptOut, + amount, + mainBalance, + 8000, // wrappedBalance + bptSupply, + params, + delta, + error, + false + ); + } + } + } + }); + it('BptInPerWrappedOut', () => { + for (const mainBalance of mainBalanceTest) { + for (const amount of [50, 70, 150, 300, 700, 1000, 2000]) { + checkDerivative( + linear._calcBptInPerWrappedOut, + linear._spotPriceAfterSwapBptInPerWrappedOut, + amount, + mainBalance, + 8000, // wrappedBalance + 3500, // bptSupply + params, + delta, + error, + false + ); + } + } + }); }); }); From 0860d9a11e3319e3629db02b8e0db58516d638e7 Mon Sep 17 00:00:00 2001 From: johngrantuk Date: Thu, 7 Apr 2022 09:54:30 +0100 Subject: [PATCH 5/5] Update version: 4.0.0-beta.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ea4efe2..13f1b602 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@balancer-labs/sor", - "version": "4.0.0-beta.1", + "version": "4.0.0-beta.2", "license": "GPL-3.0-only", "main": "dist/index.js", "module": "dist/index.esm.js",