Impact: High
Affected File(s): src/dsc_engine.vy:L24, src/dsc_engine.vy:L302-L317, src/dsc_engine.vy:L319-L330
DSCEngine verifies account solvency by checking an account's health factor against a constant MIN_HEALTH_FACTOR of 1e18.
When calculating health factors for WBTC (8 decimals), _get_usd_value() outputs values with 8 decimals of precision instead of 18-decimal USD wei.
The resulting health factor is 10 orders of magnitude too small ($10^8$ vs $10^{18}$ scale), permanently breaking health factor assertions and rendering WBTC unusable as collateral.
In dsc_engine.vy, MIN_HEALTH_FACTOR is hardcoded to 18 decimals:
In _calculate_health_factor(), the engine computes the health factor by multiplying threshold-adjusted collateral by 1e18 and dividing by total minted DSC:
In _get_usd_value(), token amounts are multiplied by price and divided by PRECISION (10^18):
Because WBTC has only 8 decimals, amount is in $10^8$ units. The calculation evaluates to:
The resulting collateral value has 8 decimals instead of 18 decimals. When plugged into _calculate_health_factor, the calculated health factor evaluates to instead of $10^{18}$, which is $10^{10}$ times below MIN_HEALTH_FACTOR.
Likelihood: High
Occurs on every deposit or borrow transaction involving WBTC.
Impact: High
Users depositing WBTC cannot mint any DSC because _revert_if_health_factor_is_broken() reverts immediately.
Any active WBTC position is treated by the contract as deeply underwater and eligible for liquidation despite being completely solvent.
Severity: High
Explanation: Even with $100,000 in WBTC collateral backing only $1 of DSC debt, the health check fails and reverts because the calculated health factor is .
Normalize collateral token amounts to 18 decimals based on token decimals() when computing collateral value:
Explanation: Normalizing amounts to 18 decimals ensures collateral_value_in_usd is in 18-decimal wei, aligning the calculated health factor with MIN_HEALTH_FACTOR = 1e18.
## Description The `_revert_if_health_factor_is_broken` function is responsible for ensuring that a user's health factor meets the minimum required standard. There is only implementation for WETH. ## Vulnerability Details In the function, there is only implementation for WETH. ```Solidity @internal def _revert_if_health_factor_is_broken(user: address): user_health_factor: uint256 = self._health_factor(user) assert ( user_health_factor >= MIN_HEALTH_FACTOR ), "DSCEngine__BreaksHealthFactor" ``` Value of the `MIN_HEALTH_FACTOR=10^18`is higher than the Satoshi factor which is 10^8. As a result, for WBTC, the `user_health_factor` can be inflated to more than 101010^{10} times its normal value. ## Impact Bigger value of MIN_HEALTH_FACTOR for WBTC allows on bigger value of `user_health_factor`and wrong value when function should revert. ## Recommendations Add MIN_HEALTH_FACTOR also for WBTC. ```Solidity @internal def _revert_if_health_factor_is_broken(user: address): user_health_factor: uint256 = self._health_factor(user) # Check if the user's token is WBTC and adjust health factor accordingly if user_health_factor >= (MIN_HEALTH_FACTOR * 10**10): # If user health factor is higher due to WBTC precision, still ensure it meets the minimum assert user_health_factor >= MIN_HEALTH_FACTOR, "DSCEngine__BreaksHealthFactor" else: assert user_health_factor >= MIN_HEALTH_FACTOR, "DSCEngine__BreaksHealthFactor" ```
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.