15,000 USDC
View results
Submission Details
Severity: high
Valid

Protocol will completely break if working with token that have non 18 decimals

Summary

Protocol operation and collateral value calculation assume that the tokens have 18 decimals, this can cause issue when the collateral is token that have lower or higher decimals.

Vulnerability Details

When calculating health factor, protocol call getAccountInformation, protocol eventually loop over collaterals and used getUsdValue for every collateral to get the usd value :

https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/main/src/DSCEngine.sol#L349-L359

function getAccountCollateralValue(address user) public view returns (uint256 totalCollateralValueInUsd) {
// loop through each collateral token, get the amount they have deposited, and map it to
// the price, to get the USD value
for (uint256 i = 0; i < s_collateralTokens.length; i++) {
address token = s_collateralTokens[i];
uint256 amount = s_collateralDeposited[user][token];
totalCollateralValueInUsd += getUsdValue(token, amount);
}
return totalCollateralValueInUsd;
}

https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/main/src/DSCEngine.sol#L361-L367

function getUsdValue(address token, uint256 amount) public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
(, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
// 1 ETH = $1000
// The returned value from CL will be 1000 * 1e8
return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;
}

However, the PRECISION used is 10e18, this can cause issue if the collateral used is not 18 decimals token.

getTokenAmountFromUsd also calculate the token amount that will be seized in liquidation and use the same assumption:

https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/main/src/DSCEngine.sol#L339-L348

function getTokenAmountFromUsd(address token, uint256 usdAmountInWei) public view returns (uint256) {
// price of ETH (token)
// $/ETH ETH ??
// $2000 / ETH. $1000 = 0.5 ETH
AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
(, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
// ($10e18 * 1e18) / ($2000e8 * 1e10)
return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
}

Impact

This will cause protocol completely broken when working with non 18 decimals token.

Tools Used

Manual review

Recommendations

Consider to add mechanism to scale the getTokenAmountFromUsd and getUsdValue based on collateral token decimals.

Support

FAQs

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