The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: low
Invalid

Protocol unable to handle tokens with decimals() > 18

Summary

  • distributeAssets() assumes that all tokens in the protocol will have at most 18 decimals and uses _portion * 10 ** (18 - asset.token.dec) in its calculations. This is not necessarily true and will fail due to underflow whenever token decimals() > 18.

  • Similar logic error effects the swap() functionality.

LiquidationPool.sol#L220

function distributeAssets(ILiquidationPoolManager.Asset[] memory _assets, uint256 _collateralRate, uint256 _hundredPC) external payable {
consolidatePendingStakes();
(,int256 priceEurUsd,,,) = Chainlink.AggregatorV3Interface(eurUsd).latestRoundData();
uint256 stakeTotal = getStakeTotal();
uint256 burnEuros;
uint256 nativePurchased;
for (uint256 j = 0; j < holders.length; j++) {
Position memory _position = positions[holders[j]];
uint256 _positionStake = stake(_position);
if (_positionStake > 0) {
for (uint256 i = 0; i < _assets.length; i++) {
ILiquidationPoolManager.Asset memory asset = _assets[i];
if (asset.amount > 0) {
(,int256 assetPriceUsd,,,) = Chainlink.AggregatorV3Interface(asset.token.clAddr).latestRoundData();
uint256 _portion = asset.amount * _positionStake / stakeTotal;
@------------------> uint256 costInEuros = _portion * 10 ** (18 - asset.token.dec) * uint256(assetPriceUsd) / uint256(priceEurUsd)
* _hundredPC / _collateralRate;
...
...
}

SmartVaultV3.sol#L217

function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external onlyOwner {
uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
address inToken = getSwapAddressFor(_inToken);
@-----> uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: inToken,
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount - swapFee,
amountOutMinimum: minimumAmountOut,
sqrtPriceLimitX96: 0
});
inToken == ISmartVaultManagerV3(manager).weth() ?
executeNativeSwapAndFee(params, swapFee) :
executeERC20SwapAndFee(params, swapFee);
}

Vulnerability Details

The above mentioned code will revert for such tokens which have decimals() greater than 18. This issue is also visible in contracts/utils/PriceCalculator.sol#L40 inside the function getTokenScaleDiff() which is in turn called by functions

  • tokenToEurAvg() #L45

  • tokenToEur() #L53

  • eurToToken() #L64
    used by in-scope file SmartVaultV3.sol to calculate calculateMinimumAmountOut(), which is integral to swap().

    These functions will revert if a token with decimals > 18 is encountered.

Impact

Critical functions of the protocol like swap(), distributeAssets() do not function for tokens with decimals > 18.

Tools Used

Manual inspection.

Recommendations

This would require changes in multiple places. Consider operating with a higher precision like 36 decimals instead of the current 18, wherein every token is converted to 36 places of decimal precision and then converted back to original scale when required.

Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Out of scope
Assigned finding tags:

informational/invalid

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.