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

Incorrect price calculation in `getUsdValue()` due to decimal assumption

Summary

The DSCEngine contract fetches the latest price data from the Chainlink Oracle using the OracleLib library. It assumes a fixed number of decimals (8) for the price feed from the Chainlink Oracle. This can cause incorrect calculations when the number of decimals in the token's USD price feed is not equal to 8. For example, the AMPL/USD price feed uses 18 decimals, as per the Chainlink documentation (https://docs.chain.link/data-feeds/price-feeds/addresses).

Vulnerability Details

The getUsdValue() function of the DSCEngine contract calculates the USD value of a specific amount of a token. It fetches the price of the token in USD from the Chainlink Oracle and performs calculations based on this price. However, the function assumes that the price feed has a fixed number of decimals (8).

The problematic code is shown below:

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;
}

Impact

When the price feed with decimals != 8 is set, the USD value calculated by the getUsdValue() function may be incorrect. This can lead to significant errors, allowing an attacker to deposit a small amount of the asset and drain all the funds from the protocol.

Tools Used

Manual review

Recommendations

The getUsdValue() function should be modified to fetch the number of decimals from the price feed dynamically. The Chainlink AggregatorV3Interface provides a decimals() function that returns the number of decimal places in the price feed. This function can be used to correctly scale the price for calculations.
Alternatively, a check can be added in the constructor to ensure the decimals() of the feed is 8. If the number of decimals is not 8, the function should revert.

Support

FAQs

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