MIN_HEALTH_FACTOR = 10**18 is sized for WETH's 18-decimal precision. WBTC uses 8 decimals (the Satoshi factor = 108), so any WBTC-collateralized position produces a health factor 1010 times larger than the equivalent WETH position. The _revert_if_health_factor_is_broken check compares this inflated value against the WETH-calibrated constant, meaning WBTC users can never break the health factor threshold — even when genuinely undercollateralized.
_revert_if_health_factor_is_broken calls _health_factor(user) and asserts the result is at or above MIN_HEALTH_FACTOR:
_health_factor computes collateral value and debt using token-native decimals. For WETH (18 decimals), the resulting ratio is in the 1e18 range — matching MIN_HEALTH_FACTOR. For WBTC (8 decimals, Satoshi factor = 1e8), the same ratio is scaled 1e10 times larger, making it appear the position is 10,000,000,000× healthier than it actually is.
A WBTC borrower who is severely undercollateralized will still produce a health factor well above MIN_HEALTH_FACTOR, so _revert_if_health_factor_is_broken never triggers — the protocol accepts positions it should reject.
Likelihood:
Any user depositing WBTC as collateral is affected. The decimal mismatch is structural and present in every WBTC interaction from the first deposit.
Impact:
The core solvency invariant of the stablecoin engine is broken for WBTC. Undercollateralized WBTC positions are never liquidated, leaving the protocol holding bad debt. DSC backed by WBTC collateral becomes unbacked.
A WBTC depositor mints DSC up to what should be their borrow limit and then withdraws collateral below the safe threshold. The health factor check should revert but does not — the inflated WBTC value (1e10× larger) satisfies the WETH-calibrated minimum.
The assertion never fails for WBTC, proving the health check provides no protection.
Normalize collateral values to a common decimal precision before computing the health factor, or apply a per-token decimal adjustment:
The correct fix normalizes _health_factor output to 1e18 precision regardless of the collateral token's decimals, so a single MIN_HEALTH_FACTOR constant applies correctly to all supported tokens.
## 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.