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

A user can be unfairly liquidated right after depositing wBTC to the system

Summary

When a user deposits wBTC into the system, their collateralValue in terms of USD is inaccurately calculated, resulting in a health factor below the threshold of 1e18, even if the price of BTC remains unchanged. This miscalculation exposes the user to the risk of immediate liquidation, potentially leading to the loss of their wBTC holdings.

Vulnerability Details

wBTC is a token with 8 decimals, so when a user deposits wBTC into the system, the amount parameter will also have 8 decimals. For example, if a user deposits 1 BTC, they will send 1 * 1e8 as the amount parameter, and the s_collateralDeposited state will be updated as follows:
s_collateralDeposited[user][wBTC] = 1 * 1e8;

As a result, the getAccountCollateralValue() function will return a significantly lower amount of USD value (in 8 decimals instead of 18) that it should in case the user deposits wBTC to the system, and the healthFactor of the user will be with 8 decimals which will be significantly lower than the minimum health factor (18 decimals).

This means that right after depositing wBTC to the system, and without minting DSC tokens the user's wBTC is in a risk of liquidation since his startingUserHealthFactory is lower than the MIN_HEALTH_FACTOR.

Any other malicious user can mint DSC tokens using wETH collateral and steal the wBTC collateral deposited by the vulnerable user.

Impact

Users will loose the wBTC right after depositing it to the system.

Tools Used

VSCode

Recommendations

The problem relies of a wrong USD value calculation of wBTC collateral (in 8 decimals instead of 18).
In order to fix the issue, modify the getUsdValue(address token, uint256 amount) function so it will take into consideration the token's decimals.

Change this:
uint256 usdValue = ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;

To that:
uint256 usdValue = ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / token.decimals();

Support

FAQs

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