When a user deposits wBTC into the system, the _calculateHealthFactor
function responsible for calculating their health factor, which relies on the _getAccountInformation
and the getAccountCollateralValue
function determining their total collateral and total debt.
The getAccountCollateralValue()
function will return a significantly lower amount of USD value that it should in case the user deposits wBTC to the system. As a result, the user will be treated unfairly, appearing undercollateralized, and they will be unable to mint DSC tokens under this circumstance.
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;
The calculateHealthFactor
function relies on getAccountCollateralValue
to determine the total USD value of an account's deposits in the system. This value is then used to assess the health factor, influencing whether a transaction should be reverted or not.
For accurate calculation of the health factor, getAccountCollateralValue
must provide the result in 18 decimal places. The issue arises from how getAccountCollateralValue
calculates the USD value of the wBTC collateral. It uses getUsdValue(wBTC, s_collateralDeposited[user][token])
to determine the USD value of the deposited wBTC. However, as the amount is in 8 decimal places (wBTC amount), the getUsdValue(token, amount)
function returns a USD value with 8 decimal places instead of 18.
Consequently, the calculated value will be much lower than the actual USD value of the deposited wBTC tokens, resulting in a health factor 8 decimals which is significantly lower than the minimum health factory (18 decimals).
This impacts the user in two ways:
The user can't mint DSC tokens.
The user's position becomes vulnerable to immediate liquidation right after the deposit.
Add the following function to the DSCEngineTest.t.sol
file to regenerate the bug:
Users can't mint DSC tokens for their wBTC deposited collateral.
VSCode
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();
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.