From f8a42d95599f16de030f8aa0bf037d018790c5c5 Mon Sep 17 00:00:00 2001 From: "Miquel A. Cabot" Date: Tue, 3 May 2022 18:06:39 +0200 Subject: [PATCH] Issue-#1409: Excessive contract calls (#1424) * add decimals parameter to unitsToAmount() and amountToUnits() * unify use of amountToUnits() and unitsToAmount() * use tokenDecimals in TokenUtils * add tokenDecimals to functions in SideStaking * add parameters to doc comments * calculate amountToUnits and unitsToAmount using decimals in FixedRateExchange * remove unused amountToUnits() function from SideStaking * use decimals in unitsToAmount() function in Pool * add tokenInDecimals and tokenOutDecimals to TokenInOutMarket interface * use decimals in amountToUnits() function in Pool * fix errors related to pool decimals Co-authored-by: mihaisc --- src/@types/Pool.ts | 2 + src/pools/balancer/Pool.ts | 245 +++++++++++++++-------- src/pools/fixedRate/FixedRateExchange.ts | 138 ++++++++----- src/pools/ssContracts/SideStaking.ts | 63 ++---- src/utils/ContractUtils.ts | 10 +- src/utils/TokenUtils.ts | 20 +- 6 files changed, 294 insertions(+), 184 deletions(-) diff --git a/src/@types/Pool.ts b/src/@types/Pool.ts index d93e4a69..b8ee82a8 100644 --- a/src/@types/Pool.ts +++ b/src/@types/Pool.ts @@ -23,6 +23,8 @@ export interface TokenInOutMarket { tokenIn: string tokenOut: string marketFeeAddress: string + tokenInDecimals?: number + tokenOutDecimals?: number } export interface AmountsInMaxFee { diff --git a/src/pools/balancer/Pool.ts b/src/pools/balancer/Pool.ts index 76ff7ed2..ca43bb0b 100644 --- a/src/pools/balancer/Pool.ts +++ b/src/pools/balancer/Pool.ts @@ -52,6 +52,22 @@ export class Pool { this.config = config || new ConfigHelper().getConfig(network || 'unknown') } + async amountToUnits( + token: string, + amount: string, + tokenDecimals?: number + ): Promise { + return amountToUnits(this.web3, token, amount, tokenDecimals) + } + + async unitsToAmount( + token: string, + amount: string, + tokenDecimals?: number + ): Promise { + return unitsToAmount(this.web3, token, amount, tokenDecimals) + } + /** * Get user shares of pool tokens * @param {String} account @@ -367,9 +383,14 @@ export class Pool { * Returns the current token reserve amount * @param {String} poolAddress * @param {String} token Address of the token to be checked + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ - async getReserve(poolAddress: string, token: string): Promise { + async getReserve( + poolAddress: string, + token: string, + tokenDecimals?: number + ): Promise { let amount = null try { const pool = setContractDefaults( @@ -377,7 +398,7 @@ export class Pool { this.config ) const result = await pool.methods.getBalance(token).call() - amount = await unitsToAmount(this.web3, token, result) + amount = await this.unitsToAmount(token, result, tokenDecimals) } catch (e) { LoggerInstance.error(`ERROR: Failed to get how many tokens \ are in the pool: ${e.message}`) @@ -503,9 +524,14 @@ export class Pool { * Get Market Fees available to be collected for a specific token * @param {String} poolAddress * @param {String} token token we want to check fees + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ - async getMarketFees(poolAddress: string, token: string): Promise { + async getMarketFees( + poolAddress: string, + token: string, + tokenDecimals?: number + ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), this.config @@ -513,7 +539,7 @@ export class Pool { let weight = null try { const result = await pool.methods.publishMarketFees(token).call() - weight = await unitsToAmount(this.web3, token, result) + weight = await this.unitsToAmount(token, result, tokenDecimals) } catch (e) { LoggerInstance.error(`ERROR: Failed to get market fees for a token: ${e.message}`) } @@ -562,9 +588,14 @@ export class Pool { * Get Community Fees available to be collected for a specific token * @param {String} poolAddress * @param {String} token token we want to check fees + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ - async getCommunityFees(poolAddress: string, token: string): Promise { + async getCommunityFees( + poolAddress: string, + token: string, + tokenDecimals?: number + ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), this.config @@ -572,7 +603,7 @@ export class Pool { let weight = null try { const result = await pool.methods.communityFees(token).call() - weight = await unitsToAmount(this.web3, token, result) + weight = await this.unitsToAmount(token, result, tokenDecimals) } catch (e) { LoggerInstance.error( `ERROR: Failed to get community fees for a token: ${e.message}` @@ -807,21 +838,20 @@ export class Pool { this.config ) - const tokenAmountIn = await amountToUnits( - this.web3, + const tokenAmountIn = await this.amountToUnits( tokenInOutMarket.tokenIn, - amountsInOutMaxFee.tokenAmountIn + amountsInOutMaxFee.tokenAmountIn, + tokenInOutMarket.tokenInDecimals ) - const minAmountOut = await amountToUnits( - this.web3, + const minAmountOut = await this.amountToUnits( tokenInOutMarket.tokenOut, - amountsInOutMaxFee.minAmountOut + amountsInOutMaxFee.minAmountOut, + tokenInOutMarket.tokenOutDecimals ) const maxPrice = amountsInOutMaxFee.maxPrice - ? amountToUnits( - this.web3, + ? this.amountToUnits( await this.getBaseToken(poolAddress), amountsInOutMaxFee.maxPrice ) @@ -887,23 +917,22 @@ export class Pool { amountsInOutMaxFee ) - const tokenAmountIn = await amountToUnits( - this.web3, + const tokenAmountIn = await this.amountToUnits( tokenInOutMarket.tokenIn, - amountsInOutMaxFee.tokenAmountIn + amountsInOutMaxFee.tokenAmountIn, + tokenInOutMarket.tokenInDecimals ) - const minAmountOut = await amountToUnits( - this.web3, + const minAmountOut = await this.amountToUnits( tokenInOutMarket.tokenOut, - amountsInOutMaxFee.minAmountOut + amountsInOutMaxFee.minAmountOut, + tokenInOutMarket.tokenOutDecimals ) let result = null const maxPrice = amountsInOutMaxFee.maxPrice - ? await amountToUnits( - this.web3, + ? await this.amountToUnits( await this.getBaseToken(poolAddress), amountsInOutMaxFee.maxPrice ) @@ -961,21 +990,20 @@ export class Pool { const gasLimitDefault = this.GASLIMIT_DEFAULT - const maxAmountIn = await amountToUnits( - this.web3, + const maxAmountIn = await this.amountToUnits( tokenInOutMarket.tokenIn, - amountsInOutMaxFee.maxAmountIn + amountsInOutMaxFee.maxAmountIn, + tokenInOutMarket.tokenInDecimals ) - const tokenAmountOut = await amountToUnits( - this.web3, + const tokenAmountOut = await this.amountToUnits( tokenInOutMarket.tokenOut, - amountsInOutMaxFee.tokenAmountOut + amountsInOutMaxFee.tokenAmountOut, + tokenInOutMarket.tokenOutDecimals ) const maxPrice = amountsInOutMaxFee.maxPrice - ? await amountToUnits( - this.web3, + ? await this.amountToUnits( await this.getBaseToken(poolAddress), amountsInOutMaxFee.maxPrice ) @@ -1036,21 +1064,20 @@ export class Pool { amountsInOutMaxFee ) - const maxAmountIn = await amountToUnits( - this.web3, + const maxAmountIn = await this.amountToUnits( tokenInOutMarket.tokenIn, - amountsInOutMaxFee.maxAmountIn + amountsInOutMaxFee.maxAmountIn, + tokenInOutMarket.tokenInDecimals ) - const tokenAmountOut = await amountToUnits( - this.web3, + const tokenAmountOut = await this.amountToUnits( tokenInOutMarket.tokenOut, - amountsInOutMaxFee.tokenAmountOut + amountsInOutMaxFee.tokenAmountOut, + tokenInOutMarket.tokenOutDecimals ) const maxPrice = amountsInOutMaxFee.maxPrice - ? amountToUnits( - this.web3, + ? this.amountToUnits( await this.getBaseToken(poolAddress), amountsInOutMaxFee.maxPrice ) @@ -1145,7 +1172,7 @@ export class Pool { throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) } - const amountInFormatted = await amountToUnits(this.web3, tokenIn, tokenAmountIn) + const amountInFormatted = await this.amountToUnits(tokenIn, tokenAmountIn) const estGas = await this.estJoinswapExternAmountIn( account, poolAddress, @@ -1240,8 +1267,7 @@ export class Pool { throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) } - const minTokenOutFormatted = await amountToUnits( - this.web3, + const minTokenOutFormatted = await this.amountToUnits( await this.getBaseToken(poolAddress), minTokenAmountOut ) @@ -1340,13 +1366,17 @@ export class Pool { * @param tokenOut token to get * @param tokenAmountOut exact amount of tokenOut * @param swapMarketFee consume market swap fee + * @param {number} tokenInDecimals optional number of decimals of the token to be swaped + * @param {number} tokenOutDecimals optional number of decimals of the token to get */ public async getAmountInExactOut( poolAddress: string, tokenIn: string, tokenOut: string, tokenAmountOut: string, - swapMarketFee: string + swapMarketFee: string, + tokenInDecimals?: number, + tokenOutDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1359,7 +1389,11 @@ export class Pool { throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) } - const amountOutFormatted = await amountToUnits(this.web3, tokenOut, tokenAmountOut) + const amountOutFormatted = await this.amountToUnits( + tokenOut, + tokenAmountOut, + tokenOutDecimals + ) let amount = null @@ -1373,22 +1407,30 @@ export class Pool { ) .call() amount = { - tokenAmount: await unitsToAmount(this.web3, tokenOut, result.tokenAmountIn), - liquidityProviderSwapFeeAmount: await unitsToAmount( - this.web3, - tokenIn, - result.lpFeeAmount + tokenAmount: await this.unitsToAmount( + tokenOut, + result.tokenAmountIn, + tokenOutDecimals ), - oceanFeeAmount: await unitsToAmount(this.web3, tokenIn, result.oceanFeeAmount), - publishMarketSwapFeeAmount: await unitsToAmount( - this.web3, + liquidityProviderSwapFeeAmount: await this.unitsToAmount( tokenIn, - result.publishMarketSwapFeeAmount + result.lpFeeAmount, + tokenInDecimals ), - consumeMarketSwapFeeAmount: await unitsToAmount( - this.web3, + oceanFeeAmount: await this.unitsToAmount( tokenIn, - result.consumeMarketSwapFeeAmount + result.oceanFeeAmount, + tokenInDecimals + ), + publishMarketSwapFeeAmount: await this.unitsToAmount( + tokenIn, + result.publishMarketSwapFeeAmount, + tokenInDecimals + ), + consumeMarketSwapFeeAmount: await this.unitsToAmount( + tokenIn, + result.consumeMarketSwapFeeAmount, + tokenInDecimals ) } } catch (e) { @@ -1402,15 +1444,19 @@ export class Pool { * Returns: tokenAmountOut, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee * @param tokenIn token to be swaped * @param tokenOut token to get - * @param tokenAmountOut exact amount of tokenOut - * @param _consumeMarketSwapFee consume market swap fee + * @param tokenAmountIn exact amount of tokenIn + * @param swapMarketFee + * @param {number} tokenInDecimals optional number of decimals of the token to be swaped + * @param {number} tokenOutDecimals optional number of decimals of the token to get */ public async getAmountOutExactIn( poolAddress: string, tokenIn: string, tokenOut: string, tokenAmountIn: string, - swapMarketFee: string + swapMarketFee: string, + tokenInDecimals?: number, + tokenOutDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1422,7 +1468,11 @@ export class Pool { throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`) } - const amountInFormatted = await amountToUnits(this.web3, tokenIn, tokenAmountIn) + const amountInFormatted = await this.amountToUnits( + tokenIn, + tokenAmountIn, + tokenInDecimals + ) let amount = null @@ -1437,22 +1487,30 @@ export class Pool { .call() amount = { - tokenAmount: await unitsToAmount(this.web3, tokenOut, result.tokenAmountOut), - liquidityProviderSwapFeeAmount: await unitsToAmount( - this.web3, - tokenIn, - result.lpFeeAmount + tokenAmount: await this.unitsToAmount( + tokenOut, + result.tokenAmountOut, + tokenOutDecimals ), - oceanFeeAmount: await unitsToAmount(this.web3, tokenIn, result.oceanFeeAmount), - publishMarketSwapFeeAmount: await unitsToAmount( - this.web3, + liquidityProviderSwapFeeAmount: await this.unitsToAmount( tokenIn, - result.publishMarketSwapFeeAmount + result.lpFeeAmount, + tokenInDecimals ), - consumeMarketSwapFeeAmount: await unitsToAmount( - this.web3, + oceanFeeAmount: await this.unitsToAmount( tokenIn, - result.consumeMarketSwapFeeAmount + result.oceanFeeAmount, + tokenInDecimals + ), + publishMarketSwapFeeAmount: await this.unitsToAmount( + tokenIn, + result.publishMarketSwapFeeAmount, + tokenInDecimals + ), + consumeMarketSwapFeeAmount: await this.unitsToAmount( + tokenIn, + result.consumeMarketSwapFeeAmount, + tokenInDecimals ) } } catch (e) { @@ -1465,11 +1523,15 @@ export class Pool { * Returns number of poolshares obtain by staking exact tokenAmountIn tokens * @param tokenIn tokenIn * @param tokenAmountIn exact number of tokens staked + * @param {number} poolDecimals optional number of decimals of the poool + * @param {number} tokenInDecimals optional number of decimals of the token */ public async calcPoolOutGivenSingleIn( poolAddress: string, tokenIn: string, - tokenAmountIn: string + tokenAmountIn: string, + poolDecimals?: number, + tokenInDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1481,11 +1543,11 @@ export class Pool { const result = await pool.methods .calcPoolOutSingleIn( tokenIn, - await amountToUnits(this.web3, tokenIn, tokenAmountIn) + await this.amountToUnits(tokenIn, tokenAmountIn, tokenInDecimals) ) .call() - amount = await unitsToAmount(this.web3, poolAddress, result) + amount = await this.unitsToAmount(poolAddress, result, poolDecimals) } catch (e) { LoggerInstance.error( `ERROR: Failed to calculate PoolOutGivenSingleIn : ${e.message}` @@ -1498,25 +1560,32 @@ export class Pool { * Returns number of tokens to be staked to the pool in order to get an exact number of poolshares * @param tokenIn tokenIn * @param poolAmountOut expected amount of pool shares + * @param {number} poolDecimals optional number of decimals of the pool + * @param {number} tokenInDecimals optional number of decimals of the token */ public async calcSingleInGivenPoolOut( poolAddress: string, tokenIn: string, - poolAmountOut: string + poolAmountOut: string, + poolDecimals?: number, + tokenInDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), this.config ) let amount = null - const amountFormatted = await amountToUnits(this.web3, poolAddress, poolAmountOut) + const amountFormatted = await this.amountToUnits( + poolAddress, + poolAmountOut, + poolDecimals + ) try { const result = await pool.methods .calcSingleInPoolOut(tokenIn, amountFormatted) - .call() - amount = await unitsToAmount(this.web3, tokenIn, result) + amount = await this.unitsToAmount(tokenIn, result, tokenInDecimals) } catch (e) { LoggerInstance.error( `ERROR: Failed to calculate SingleInGivenPoolOut : ${e.message}` @@ -1529,11 +1598,15 @@ export class Pool { * Returns expected amount of tokenOut for removing exact poolAmountIn pool shares from the pool * @param tokenOut tokenOut * @param poolAmountIn amount of shares spent + * @param {number} poolDecimals optional number of decimals of the pool + * @param {number} tokenOutDecimals optional number of decimals of the token */ public async calcSingleOutGivenPoolIn( poolAddress: string, tokenOut: string, - poolAmountIn: string + poolAmountIn: string, + poolDecimals?: number, + tokenOutDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1545,10 +1618,10 @@ export class Pool { const result = await pool.methods .calcSingleOutPoolIn( tokenOut, - await amountToUnits(this.web3, poolAddress, poolAmountIn) + await this.amountToUnits(poolAddress, poolAmountIn, poolDecimals) ) .call() - amount = await unitsToAmount(this.web3, tokenOut, result) + amount = await this.unitsToAmount(tokenOut, result, tokenOutDecimals) } catch (e) { LoggerInstance.error(`ERROR: Failed to calculate SingleOutGivenPoolIn : ${e}`) } @@ -1559,11 +1632,15 @@ export class Pool { * Returns number of poolshares needed to withdraw exact tokenAmountOut tokens * @param tokenOut tokenOut * @param tokenAmountOut expected amount of tokensOut + * @param {number} poolDecimals optional number of decimals of the pool + * @param {number} tokenOutDecimals optional number of decimals of the token */ public async calcPoolInGivenSingleOut( poolAddress: string, tokenOut: string, - tokenAmountOut: string + tokenAmountOut: string, + poolDecimals?: number, + tokenOutDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1575,11 +1652,11 @@ export class Pool { const result = await pool.methods .calcPoolInSingleOut( tokenOut, - await amountToUnits(this.web3, tokenOut, tokenAmountOut) + await this.amountToUnits(tokenOut, tokenAmountOut, tokenOutDecimals) ) .call() - amount = await unitsToAmount(this.web3, poolAddress, result) + amount = await this.unitsToAmount(poolAddress, result, poolDecimals) } catch (e) { LoggerInstance.error( `ERROR: Failed to calculate PoolInGivenSingleOut : ${e.message}` diff --git a/src/pools/fixedRate/FixedRateExchange.ts b/src/pools/fixedRate/FixedRateExchange.ts index 2b8a8929..e1bdcf56 100644 --- a/src/pools/fixedRate/FixedRateExchange.ts +++ b/src/pools/fixedRate/FixedRateExchange.ts @@ -92,12 +92,20 @@ export class FixedRateExchange { ) } - async amountToUnits(token: string, amount: string): Promise { - return amountToUnits(this.web3, token, amount) + async amountToUnits( + token: string, + amount: string, + tokenDecimals: number + ): Promise { + return amountToUnits(this.web3, token, amount, tokenDecimals) } - async unitsToAmount(token: string, amount: string): Promise { - return unitsToAmount(this.web3, token, amount) + async unitsToAmount( + token: string, + amount: string, + tokenDecimals: number + ): Promise { + return unitsToAmount(this.web3, token, amount, tokenDecimals) } /** @@ -173,11 +181,13 @@ export class FixedRateExchange { const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee) const dtAmountFormatted = await this.amountToUnits( exchange.datatoken, - datatokenAmount + datatokenAmount, + +exchange.dtDecimals ) const maxBtFormatted = await this.amountToUnits( exchange.baseToken, - maxBaseTokenAmount + maxBaseTokenAmount, + +exchange.btDecimals ) const estGas = await this.estBuyDT( @@ -269,11 +279,13 @@ export class FixedRateExchange { const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee) const dtAmountFormatted = await this.amountToUnits( exchange.datatoken, - datatokenAmount + datatokenAmount, + +exchange.dtDecimals ) const minBtFormatted = await this.amountToUnits( exchange.baseToken, - minBaseTokenAmount + minBaseTokenAmount, + +exchange.btDecimals ) const estGas = await this.estBuyDT( address, @@ -531,12 +543,8 @@ export class FixedRateExchange { */ public async getDTSupply(exchangeId: string): Promise { const dtSupply = await this.contract.methods.getDTSupply(exchangeId).call() - return await this.unitsToAmount( - ( - await this.getExchange(exchangeId) - ).datatoken, - dtSupply - ) + const exchange = await this.getExchange(exchangeId) + return await this.unitsToAmount(exchange.datatoken, dtSupply, +exchange.dtDecimals) } /** @@ -546,12 +554,8 @@ export class FixedRateExchange { */ public async getBTSupply(exchangeId: string): Promise { const btSupply = await this.contract.methods.getBTSupply(exchangeId).call() - return await this.unitsToAmount( - ( - await this.getExchange(exchangeId) - ).baseToken, - btSupply - ) + const exchange = await this.getExchange(exchangeId) + return await this.unitsToAmount(exchange.baseToken, btSupply, +exchange.btDecimals) } /** @@ -579,7 +583,11 @@ export class FixedRateExchange { const result = await this.contract.methods .calcBaseInGivenOutDT( exchangeId, - await this.amountToUnits(fixedRateExchange.datatoken, datatokenAmount), + await this.amountToUnits( + fixedRateExchange.datatoken, + datatokenAmount, + +fixedRateExchange.dtDecimals + ), this.web3.utils.toWei(consumeMarketFee) ) .call() @@ -587,19 +595,23 @@ export class FixedRateExchange { const priceAndFees = { baseTokenAmount: await this.unitsToAmount( fixedRateExchange.baseToken, - result.baseTokenAmount + result.baseTokenAmount, + +fixedRateExchange.btDecimals ), marketFeeAmount: await this.unitsToAmount( fixedRateExchange.baseToken, - result.marketFeeAmount + result.marketFeeAmount, + +fixedRateExchange.btDecimals ), oceanFeeAmount: await this.unitsToAmount( fixedRateExchange.baseToken, - result.oceanFeeAmount + result.oceanFeeAmount, + +fixedRateExchange.btDecimals ), consumeMarketFeeAmount: await this.unitsToAmount( fixedRateExchange.baseToken, - result.consumeMarketFeeAmount + result.consumeMarketFeeAmount, + +fixedRateExchange.btDecimals ) } as PriceAndFees return priceAndFees @@ -621,17 +633,16 @@ export class FixedRateExchange { const result = await this.contract.methods .calcBaseOutGivenInDT( exchangeId, - await this.amountToUnits(exchange.datatoken, datatokenAmount), + await this.amountToUnits( + exchange.datatoken, + datatokenAmount, + +exchange.dtDecimals + ), this.web3.utils.toWei(consumeMarketFee) ) .call() - return await this.unitsToAmount( - ( - await this.getExchange(exchangeId) - ).baseToken, - result[0] - ) + return await this.unitsToAmount(exchange.baseToken, result[0], +exchange.btDecimals) } /** @@ -645,10 +656,26 @@ export class FixedRateExchange { .call() result.dtDecimals = result.dtDecimals.toString() result.btDecimals = result.btDecimals.toString() - result.dtBalance = await this.unitsToAmount(result.datatoken, result.dtBalance) - result.btBalance = await this.unitsToAmount(result.baseToken, result.btBalance) - result.dtSupply = await this.unitsToAmount(result.datatoken, result.dtSupply) - result.btSupply = await this.unitsToAmount(result.baseToken, result.btSupply) + result.dtBalance = await this.unitsToAmount( + result.datatoken, + result.dtBalance, + +result.dtDecimals + ) + result.btBalance = await this.unitsToAmount( + result.baseToken, + result.btBalance, + +result.btDecimals + ) + result.dtSupply = await this.unitsToAmount( + result.datatoken, + result.dtSupply, + +result.dtDecimals + ) + result.btSupply = await this.unitsToAmount( + result.baseToken, + result.btSupply, + +result.btDecimals + ) result.fixedRate = this.web3.utils.fromWei(result.fixedRate) result.exchangeId = exchangeId return result @@ -664,17 +691,16 @@ export class FixedRateExchange { result.opcFee = this.web3.utils.fromWei(result.opcFee.toString()) result.marketFee = this.web3.utils.fromWei(result.marketFee.toString()) + const exchange = await this.getExchange(exchangeId) result.marketFeeAvailable = await this.unitsToAmount( - ( - await this.getExchange(exchangeId) - ).baseToken, - result.marketFeeAvailable + exchange.baseToken, + result.marketFeeAvailable, + +exchange.btDecimals ) result.oceanFeeAvailable = await this.unitsToAmount( - ( - await this.getExchange(exchangeId) - ).baseToken, - result.oceanFeeAvailable + exchange.baseToken, + result.oceanFeeAvailable, + +exchange.btDecimals ) result.exchangeId = exchangeId @@ -822,7 +848,11 @@ export class FixedRateExchange { const fixedrate: FixedPriceExchange = await this.contract.methods .getExchange(exchangeId) .call() - const amountWei = await this.amountToUnits(fixedrate.baseToken, amount) + const amountWei = await this.amountToUnits( + fixedrate.baseToken, + amount, + +fixedrate.btDecimals + ) try { estGas = await fixedRate.methods .collectBT(exchangeId, amountWei) @@ -852,7 +882,11 @@ export class FixedRateExchange { const fixedrate: FixedPriceExchange = await this.contract.methods .getExchange(exchangeId) .call() - const amountWei = await this.amountToUnits(fixedrate.baseToken, amount) + const amountWei = await this.amountToUnits( + fixedrate.baseToken, + amount, + +fixedrate.btDecimals + ) const trxReceipt = await this.contract.methods.collectBT(exchangeId, amountWei).send({ from: address, gas: estGas + 1, @@ -881,7 +915,11 @@ export class FixedRateExchange { const fixedrate: FixedPriceExchange = await this.contract.methods .getExchange(exchangeId) .call() - const amountWei = await this.amountToUnits(fixedrate.datatoken, amount) + const amountWei = await this.amountToUnits( + fixedrate.datatoken, + amount, + +fixedrate.dtDecimals + ) try { estGas = await fixedRate.methods .collectDT(exchangeId, amountWei) @@ -911,7 +949,11 @@ export class FixedRateExchange { const fixedrate: FixedPriceExchange = await this.contract.methods .getExchange(exchangeId) .call() - const amountWei = await this.amountToUnits(fixedrate.datatoken, amount) + const amountWei = await this.amountToUnits( + fixedrate.datatoken, + amount, + +fixedrate.dtDecimals + ) const trxReceipt = await this.contract.methods.collectDT(exchangeId, amountWei).send({ from: address, gas: estGas + 1, diff --git a/src/pools/ssContracts/SideStaking.ts b/src/pools/ssContracts/SideStaking.ts index 1ec9c5f4..957514bf 100644 --- a/src/pools/ssContracts/SideStaking.ts +++ b/src/pools/ssContracts/SideStaking.ts @@ -2,10 +2,8 @@ import Web3 from 'web3' import { AbiItem } from 'web3-utils/types' import { TransactionReceipt } from 'web3-core' import { Contract } from 'web3-eth-contract' -import { LoggerInstance, getFairGasPrice, ConfigHelper } from '../../utils' -import BigNumber from 'bignumber.js' +import { LoggerInstance, getFairGasPrice, ConfigHelper, unitsToAmount } from '../../utils' import SideStakingTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json' -import defaultErc20Abi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json' import { Config } from '../../models' export class SideStaking { @@ -26,38 +24,12 @@ export class SideStaking { this.config = config || new ConfigHelper().getConfig(network || 'unknown') } - async amountToUnits(token: string, amount: string): Promise { - let decimals = 18 - const tokenContract = new this.web3.eth.Contract( - defaultErc20Abi.abi as AbiItem[], - token - ) - try { - decimals = await tokenContract.methods.decimals().call() - } catch (e) { - LoggerInstance.error('ERROR: FAILED TO CALL DECIMALS(), USING 18') - } - - const amountFormatted = new BigNumber(parseInt(amount) * 10 ** decimals) - - return amountFormatted.toString() - } - - async unitsToAmount(token: string, amount: string): Promise { - let decimals = 18 - const tokenContract = new this.web3.eth.Contract( - defaultErc20Abi.abi as AbiItem[], - token - ) - try { - decimals = await tokenContract.methods.decimals().call() - } catch (e) { - LoggerInstance.error('ERROR: FAILED TO CALL DECIMALS(), USING 18') - } - - const amountFormatted = new BigNumber(parseInt(amount) / 10 ** decimals) - - return amountFormatted.toString() + async unitsToAmount( + token: string, + amount: string, + tokenDecimals?: number + ): Promise { + return unitsToAmount(this.web3, token, amount, tokenDecimals) } /** @@ -183,11 +155,13 @@ export class SideStaking { * Get dt balance in the staking contract available for being added as liquidity * @param {String} ssAddress side staking contract address * @param {String} datatokenAddress datatokenAddress + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ async getDatatokenBalance( ssAddress: string, - datatokenAddress: string + datatokenAddress: string, + tokenDecimals?: number ): Promise { const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress) let result = null @@ -196,7 +170,7 @@ export class SideStaking { } catch (e) { LoggerInstance.error(`ERROR: Failed to get: ${e.message}`) } - result = await this.unitsToAmount(datatokenAddress, result) + result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals) return result } @@ -221,9 +195,14 @@ export class SideStaking { * Get total amount vesting * @param {String} ssAddress side staking contract address * @param {String} datatokenAddress datatokenAddress + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ - async getvestingAmount(ssAddress: string, datatokenAddress: string): Promise { + async getvestingAmount( + ssAddress: string, + datatokenAddress: string, + tokenDecimals?: number + ): Promise { const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress) let result = null try { @@ -231,7 +210,7 @@ export class SideStaking { } catch (e) { LoggerInstance.error(`ERROR: Failed to get: ${e.message}`) } - result = await this.unitsToAmount(datatokenAddress, result) + result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals) return result } @@ -259,11 +238,13 @@ export class SideStaking { * Get how much has been taken from the vesting amount * @param {String} ssAddress side staking contract address * @param {String} datatokenAddress datatokenAddress + * @param {number} tokenDecimals optional number of decimals of the token * @return {String} */ async getvestingAmountSoFar( ssAddress: string, - datatokenAddress: string + datatokenAddress: string, + tokenDecimals?: number ): Promise { const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress) let result = null @@ -272,7 +253,7 @@ export class SideStaking { } catch (e) { LoggerInstance.error(`ERROR: Failed to get: ${e.message}`) } - result = await this.unitsToAmount(datatokenAddress, result) + result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals) return result } diff --git a/src/utils/ContractUtils.ts b/src/utils/ContractUtils.ts index 827cd13d..d7502b9f 100644 --- a/src/utils/ContractUtils.ts +++ b/src/utils/ContractUtils.ts @@ -120,11 +120,12 @@ export async function getPoolCreationParams( export async function unitsToAmount( web3: Web3, token: string, - amount: string + amount: string, + tokenDecimals?: number ): Promise { try { const tokenContract = new web3.eth.Contract(minAbi, token) - let decimals = await tokenContract.methods.decimals().call() + let decimals = tokenDecimals || (await tokenContract.methods.decimals().call()) if (decimals === '0') { decimals = 18 } @@ -143,11 +144,12 @@ export async function unitsToAmount( export async function amountToUnits( web3: Web3, token: string, - amount: string + amount: string, + tokenDecimals?: number ): Promise { try { const tokenContract = new web3.eth.Contract(minAbi, token) - let decimals = await tokenContract.methods.decimals().call() + let decimals = tokenDecimals || (await tokenContract.methods.decimals().call()) if (decimals === '0') { decimals = 18 } diff --git a/src/utils/TokenUtils.ts b/src/utils/TokenUtils.ts index f3f409d7..64e9f83f 100644 --- a/src/utils/TokenUtils.ts +++ b/src/utils/TokenUtils.ts @@ -46,7 +46,8 @@ export async function estApprove( * @param {String} tokenAddress * @param {String} spender * @param {String} amount (always expressed as wei) - * @param {String} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed + * @param {boolean} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed + * @param {number} tokenDecimals optional number of decimals of the token */ export async function approve( web3: Web3, @@ -54,7 +55,8 @@ export async function approve( tokenAddress: string, spender: string, amount: string, - force = false + force = false, + tokenDecimals?: number ): Promise { const tokenContract = new web3.eth.Contract(minAbi, tokenAddress) if (!force) { @@ -64,7 +66,7 @@ export async function approve( } } let result = null - const amountFormatted = await amountToUnits(web3, tokenAddress, amount) + const amountFormatted = await amountToUnits(web3, tokenAddress, amount, tokenDecimals) const estGas = await estApprove( web3, account, @@ -94,17 +96,19 @@ export async function approve( * @param {String } tokenAdress * @param {String} account * @param {String} spender + * @param {number} tokenDecimals optional number of decimals of the token */ export async function allowance( web3: Web3, tokenAddress: string, account: string, - spender: string + spender: string, + tokenDecimals?: number ): Promise { const tokenContract = new web3.eth.Contract(minAbi, tokenAddress) const trxReceipt = await tokenContract.methods.allowance(account, spender).call() - return await unitsToAmount(web3, tokenAddress, trxReceipt) + return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals) } /** @@ -113,14 +117,16 @@ export async function allowance( * @param {String} tokenAdress * @param {String} owner * @param {String} spender + * @param {number} tokenDecimals optional number of decimals of the token */ export async function balance( web3: Web3, tokenAddress: string, - account: string + account: string, + tokenDecimals?: number ): Promise { const tokenContract = new web3.eth.Contract(minAbi, tokenAddress) const trxReceipt = await tokenContract.methods.balanceOf(account).call() - return await unitsToAmount(web3, tokenAddress, trxReceipt) + return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals) }