15,000 USDC
View results
Submission Details
Severity: medium

Incorrect collateral value calculation for users, if any of the collateral's chainlink feed aggregator hits minAnswer

Summary

Chainlink aggregators have a built in circuit breaker if the price of an asset goes outside of a predetermined price band. The result is that if an asset experiences a huge drop in value (i.e. LUNA crash) the price of the oracle will continue to return the minPrice instead of the actual price of the asset. This would allow user to continue integrating with protocol with wrong price.
NB: This is exactly what happened to Venus on BSC when LUNA imploded.

Vulnerability Detail

Take a look at DSCEngine.sol#L350-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;
}

This function is used to iterate through all the collateral tokens a user has and provide the summation of all their values in usd, now the function calls the getUsdValue() function:

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

This function just queries the price from chainlink and retrieves the latest round data from the aggregator, but there is no check for the minAnswer circuit breaker. This circuit breaker is a built-in mechanism in Chainlink aggregators that prevents the price from going outside a predefined range.

Example:

Consider fetching the price of any erc20 token in USD, say ABC.
Let's assume that ABC has a minAnswer value set at $0.1. Now, imagine a situation where the actual price of ABC plummets to $0.01 due to market conditions.

Despite the significant drop in value, the aggregator continues to report the price of ABC as $0.1. Consequently, the DSCEngine.sol contract would be misled into thinking ABC is collateral value would be somewhat inflated, in the case where user only has the ABC token as a collateral then the DSCEngine.sol contract would assume thier collateral value to be times 10 the value it really is

Impact

In short wrong collateral value assumption for users

Tool used

Manual Audit

Recommendation

Implement a check for the minAnswer circuit breaker. If the returned price falls below the minAnswer threshold, DSC should handle it appropriately.

Support

FAQs

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