context: DSCEngine.sol
The DSC protocol is facing a serious issue with its liquidation process, particularly for positions backed by wBTC. When
the health factor of a depositor's position drops below 1, it becomes eligible for liquidation according to the
protocol's documentation.
However, due to a vulnerability in the function DSCEngine.getTokenAmountFromUsd(), the protocol mistakenly calculates a
large 18-decimal token value for an 8-decimal token address (wBTC).
The problem arises from DSCEngine.getTokenAmountFromUsd(), which returns an 18-decimal token value for wBTC, even though
it should be 8-decimal. Consequently, when attempting to perform liquidations, the protocol subtracts the incorrect 18-
decimal value from the actual 8-decimal wBTC token value, causing an overflow error.
Example:
Let's consider a scenario where the wBTC price is 30,000 USD.
1 wBTC = 30,000 USD
A user mints 15,000 DSC stable coins with a health factor of 1 (1e18).
Later, the wBTC value drops to 27,000 USD, resulting in a health factor of 0.9.
DSCEngine.getTokenAmountFromUsd()
uint256 tokenAmountFromDebtCovered = getTokenAmountFromUsd(
collateral,
debtToCover
);
_redeemCollateral(
user,
msg.sender,
collateral,
totalCollateralToRedeem
);
s_collateralDeposited[from][tokenCollateralAddress] -= amountCollateral;
When a liquidator tries to liquidate this position by providing 15,000 USD worth of tokens, the flawed calculation leads
to a value of 555,555,555,555,555,555 (17 decimal places), which exceeds the capacity of the 8-decimal wBTC.
This implementation of the code itself leads to the protocol becoming insolvent, with almost no way to recover.
Actually, this kind of situation happens when token prices fall drastically, but here, the implemented code is making
the protocol insolvent.
Now, depositors take advantage only deposits wBTC to mint DSC stable coins because these positions cannot be liquidated
by anyone. In the end, only depositors can redeem their collateral by providing DSC stable coins to the protocol.
After some time, the value of DSC stable coins increases, and the collateral tokens decreases. Finally, the protocol
enters into an undercollateralized situation. Consequently, users lose trust in the protocol.
Manual
To rectify the issue and ensure accurate calculations, it is crucial to calculate the token value based on the token's
actual decimals. Specifically:
For wBTC ( 8 decimals ): ( usdAmountInWei * 1e8 ) / ( uint256(price ) * 1e10 )
For other tokens like wETH ( 18 decimals ): ( usdAmountInWei * 1e18 ) / ( uint256(price ) * 1e10 )
uint256 decimals = IERC20(token_address).decimals();
price in 8 decimals
// ($10e18 * 1e18) / ($2000e8 * 1e10)
if (decimals == 8) {
return ( usdAmountInWei * 1e8 ) / ( uint256(price ) * 1e10 );
} else {
return ( usdAmountInWei * 1e18 ) / ( uint256(price ) * 1e10 )
}
By implementing this fix, the protocol can avoid potential insolvency and ensure a more secure and reliable liquidation
process.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.