Possible rounding error during 1 / oraclePrice calculation in TradingUtils._getLimitAmount().
Summary
Possible rounding error during 1 / oraclePrice calculation in TradingUtils._getLimitAmount().
Vulnerability Detail
Possible rounding error during 1 / oraclePrice calculation in TradingUtils._getLimitAmount().
Currently, it uses the oracleDecimals to increase the precision here.
// For exact out trades, we need to invert the oracle price (1 / oraclePrice)
// We increase the precision before we divide because oraclePrice is in
// oracle decimals
oraclePrice = (oracleDecimals * oracleDecimals) / oraclePrice;
// For exact out trades, limitAmount is the max amount of sellToken the DEX can
// pull from the contract
limitAmount =
((oraclePrice +
((oraclePrice * uint256(slippageLimit)) /
Constants.SLIPPAGE_LIMIT_PRECISION)) * amount) /
oracleDecimals;
But as we can see here, some tokens have low decimals and there would be a rounding error during calculation.
Let's assume the ERC20 token A has 4 decimals and oraclePrice = 1e5here.
Then the calculation result will be 1e4 * 1e4 / (1e5 * 1e4) = 0.
So limitAmount = 0.
Impact
The limitAmount might be calculated wrongly due to the rounding error.
I think we should use 1e18 instead of oracleDecimals like below.
// For exact out trades, we need to invert the oracle price (1 / oraclePrice)
// We increase the precision before we divide because oraclePrice is in
// oracle decimals
oraclePrice = (oracleDecimals * 1e18) / oraclePrice; //++++++++++++++++++++++++++++++++++++++++++
// For exact out trades, limitAmount is the max amount of sellToken the DEX can
// pull from the contract
limitAmount =
((oraclePrice +
((oraclePrice * uint256(slippageLimit)) /
Constants.SLIPPAGE_LIMIT_PRECISION)) * amount) /
1e18; //++++++++++++++++++++++++++++++++++++++++++
hansfriese
medium
Possible rounding error during
1 / oraclePrice
calculation inTradingUtils._getLimitAmount()
.Summary
Possible rounding error during
1 / oraclePrice
calculation inTradingUtils._getLimitAmount()
.Vulnerability Detail
Possible rounding error during
1 / oraclePrice
calculation inTradingUtils._getLimitAmount()
.Currently, it uses the
oracleDecimals
to increase the precision here.But as we can see here, some tokens have low decimals and there would be a rounding error during calculation.
A
has 4 decimals andoraclePrice = 1e5
here.1e4 * 1e4 / (1e5 * 1e4)
= 0.limitAmount = 0
.Impact
The
limitAmount
might be calculated wrongly due to the rounding error.Code Snippet
https://github.com/sherlock-audit/2022-09-notional/blob/main/leveraged-vaults/contracts/trading/TradingUtils.sol#L192
Tool used
Manual Review
Recommendation
I think we should use
1e18
instead oforacleDecimals
like below.