getUsdValue
function assumes that amount parameter it is taken have 18 decimals. Because DSCEngine is supposed to be able to work with other tokens which have different decimals (for example WBTC have 8 decimals) user's healthFactor calculation will be wrong and _revertIfHealthFactorIsBroken
will always returns true if user deposits with tokens with less than 18 decimals. Although it is not common in practice, if user deposits with tokens with more than 18 decimals they will be able to mint more DSC than expected.
getUsdValue
function's amount parameter is coming from getAccountCollateralValue
function's amount calculation. This amount calculation is taken from s_collateralDeposited[user][token]
. Lets use WBTC in our example. If user deposits WBTC which have 8 decimals, this value will have 8 decimals. Hence calculation below will be done with 8 decimal amount:
Let's analyze the return value's decimal:
uint256(price)
= 8 decimals
ADDITIONAL_FEED_PRECISION
= 10 decimals
amount
= 8 decimals
PRECISION
= 18 decimals
Hence result will be in 8 (8+10+8/18) decimals. Then this value will be used in _getAccountInformation
as collateralValueInUsd, then will be used in _healthFactor
as collateralValueInUsd. Finally _calculateHealthFactor
function will use this value while calculating HealthFactor as shown:
This function will return at 8 decimals because:
collateralAdjustedForThreshold
is in 8 decimals, and totalDscMinted
is in 18 decimals.
This 8 decimal value will be used in _revertIfHealthFactorIsBroken
as a userHealthFactor
as shown below: (Because _healthFactor
calls _calculateHealthFactor
and returns its return value which is in 8 decimals)
Because MIN_HEALTH_FACTOR
is in 18 decimals:
This function will always revert if only called with WBTC.
Also if user both uses WETH and WBTC, their WBTC collateral won't have any meaningful effect, hence it is again pointless to use WBTC in this case. This of course applies to all other tokens that have different decimal amount than 18.
The protocol user can not use any other tokens that are not 18 decimals properly, for example there is no way to mint DSC using WBTC. Although there is no loss of funds, since WBTC is protocol's one of main collateral and protocol also assumes to be used with any token that have chainlink priceFeed with USD counterparty, this issue creates a medium severity vulnerability.
Manual Review
In getUsdValue
function, first check the decimal of token and then calculate accordingly.
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.