From 1a12a4bd894c03d6f4dbe8d0f88087e223dec926 Mon Sep 17 00:00:00 2001 From: mihaisc Date: Tue, 22 Feb 2022 18:37:41 +0200 Subject: [PATCH] Calculating max swap/liquidity (#1306) * calc max * more max checks * fix description --- src/pools/balancer/Pool.ts | 53 +++++++++++++++++++++++++++++++++----- src/utils/PoolHelpers.ts | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 src/utils/PoolHelpers.ts diff --git a/src/pools/balancer/Pool.ts b/src/pools/balancer/Pool.ts index 4c90af18..b8161d54 100644 --- a/src/pools/balancer/Pool.ts +++ b/src/pools/balancer/Pool.ts @@ -21,6 +21,13 @@ import { PoolPriceAndFees } from '../../@types' import { Config } from '../../models' +import { + getMaxAddLiquidity, + getMaxRemoveLiquidity, + getMaxSwapExactIn, + getMaxSwapExactOut +} from '../../utils/PoolHelpers' +import Decimal from 'decimal.js' const MaxUint256 = '115792089237316195423570985008687907853269984665640564039457584007913129639934' @@ -847,6 +854,11 @@ export class Pool { this.config ) + const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenInOutMarket.tokenIn) + if (new Decimal(amountsInOutMaxFee.tokenAmountIn).greaterThan(maxSwap)) { + throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`) + } + amountsInOutMaxFee.tokenAmountIn = await amountToUnits( this.web3, tokenInOutMarket.tokenIn, @@ -971,6 +983,11 @@ export class Pool { ) let result = null + const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenInOutMarket.tokenIn) + if (new Decimal(amountsInOutMaxFee.tokenAmountOut).greaterThan(maxSwap)) { + throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) + } + amountsInOutMaxFee.maxAmountIn = await amountToUnits( this.web3, tokenInOutMarket.tokenIn, @@ -1233,7 +1250,6 @@ export class Pool { * Pay tokenAmountIn of baseToken to join the pool, getting poolAmountOut of the pool shares. * @param {String} account * @param {String} poolAddress - * @param {String} tokenIn * @param {String} tokenAmountIn exact number of base tokens to spend * @param {String} minPoolAmountOut minimum of pool shares expectex * @return {TransactionReceipt} @@ -1249,12 +1265,13 @@ export class Pool { this.config ) let result = null + const tokenIn = await this.getBaseToken(poolAddress) + const maxSwap = await getMaxAddLiquidity(this, poolAddress, tokenIn) + if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) { + throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) + } - const amountInFormatted = await amountToUnits( - this.web3, - await this.getBaseToken(poolAddress), - tokenAmountIn - ) + const amountInFormatted = await amountToUnits(this.web3, tokenIn, tokenAmountIn) const estGas = await this.estJoinswapExternAmountIn( account, poolAddress, @@ -1321,7 +1338,6 @@ export class Pool { * Pay poolAmountIn pool shares into the pool, getting minTokenAmountOut of the baseToken * @param {String} account * @param {String} poolAddress - * @param {String} tokenOut * @param {String} poolAmountIn exact number of pool shares to spend * @param {String} minTokenAmountOut minimum amount of basetokens expected * @return {TransactionReceipt} @@ -1337,6 +1353,18 @@ export class Pool { this.config ) let result = null + const tokenOut = await this.getBaseToken(poolAddress) + + const tokenAmountOut = await this.calcSingleOutGivenPoolIn( + poolAddress, + tokenOut, + poolAmountIn + ) + + const maxSwap = await getMaxRemoveLiquidity(this, poolAddress, tokenOut) + if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) { + throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) + } const minTokenOutFormatted = await amountToUnits( this.web3, @@ -1451,6 +1479,12 @@ export class Pool { this.config ) + const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenIn) + + if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) { + throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) + } + const amountOutFormatted = await amountToUnits(this.web3, tokenOut, tokenAmountOut) let amount = null @@ -1509,6 +1543,11 @@ export class Pool { this.config ) + const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenIn) + if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) { + throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`) + } + const amountInFormatted = await amountToUnits(this.web3, tokenIn, tokenAmountIn) let amount = null diff --git a/src/utils/PoolHelpers.ts b/src/utils/PoolHelpers.ts new file mode 100644 index 00000000..c817d64d --- /dev/null +++ b/src/utils/PoolHelpers.ts @@ -0,0 +1,47 @@ +import Decimal from 'decimal.js' +import { Pool } from '..' + +export function calcMaxExactOut(balance: string): Decimal { + return new Decimal(balance).div(3.01) +} + +export function calcMaxExactIn(balance: string): Decimal { + return new Decimal(balance).div(2.01) +} +export async function getMaxSwapExactOut( + poolInstance: Pool, + poolAddress: string, + tokenAddress: string +): Promise { + const reserve = await poolInstance.getReserve(poolAddress, tokenAddress) + return calcMaxExactOut(reserve) +} + +export async function getMaxSwapExactIn( + poolInstance: Pool, + poolAddress: string, + tokenAddress: string +): Promise { + const reserve = await poolInstance.getReserve(poolAddress, tokenAddress) + return calcMaxExactIn(reserve) +} + +export async function getMaxAddLiquidity( + poolInstance: Pool, + poolAddress: string, + tokenAddress: string +): Promise { + const reserve = await poolInstance.getReserve(poolAddress, tokenAddress) + + return calcMaxExactIn(reserve) +} + +export async function getMaxRemoveLiquidity( + poolInstance: Pool, + poolAddress: string, + tokenAddress: string +): Promise { + const reserve = await poolInstance.getReserve(poolAddress, tokenAddress) + + return calcMaxExactIn(reserve) +}