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

Liquidations will fail or overpay collateral for collateral which does not have 18 decimals of precision

Summary

When a liquidator attempts to liquidate another user, they specify an amount of debtToCover to pay to liquidate a specified collateral for a user. As part of this function, to determine how much collateral to return to the liquidator, it calls tokenAmountFromDebtCovered, which should return the amount of collateral equal to the USD value of the DSC token they are using to pay down the debt. However, this function always returns an amount of collateral assuming the collateral has 18 decimals of precision. This means that if the collateral has < 18 decimals of precision, this will severely overpay the liquidator for the amount of debt they are paying down. This can even cause the liquidation to revert, if the tokenAmountFromDebtCovered function returns a value larger than the amount of collateral deposited by that user.

Vulnerability Details

In the liquidate function, the following call is made:

uint256 tokenAmountFromDebtCovered = getTokenAmountFromUsd(collateral, debtToCover);

The getTokenAmountFromUsd function is defined as follows:

function getTokenAmountFromUsd(address token, uint256 usdAmountInWei) public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
(, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
}

Let's consider the case where we are using a collateral with 6 decimals of precision and 1e6 of this collateral is worth 1000 USD. Here the liquidator is intending to pay off 10 USD in debt, so debtToCover is 10e18. The output from getTokenAmountFromUsd will be the following: 10e18 * 1e18 / (1000e8 * 1e10) = 10e18 / 1000 = 1e16 of collateral. However, considering the collateral has 6 decimals of precision, this returns an amount of collateral worth significantly more than 10 USD, and so the liquidator is getting overpaid.

Impact

The logic of the getTokenAmountFromUsd function called during liquidations will revert or overpay collateral to the liquidator for the amount of debt they are paying down. This breaks the entire protocol design.

Tools Used

Manual review

Recommendations

The getTokenAmountFromUsd function needs to be updated to convert the returned amount to use the native precision of the collateral token.

Support

FAQs

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