Title: MIN_HEALTH_FACTOR constant only calibrated for WETH, breaks WBTC health checks
Severity: High
Impact: WBTC depositors cannot mint any meaningful DSC — one of two collateral tokens is completely unusable.
Likelihood: High — deterministic arithmetic mismatch affects every WBTC-backed position.
Reference Files: src/dsc_engine.vy:300-329, src/dsc_engine.vy:269-273
The _calculate_health_factor function returns results with 8 decimals of precision for WBTC collateral because the upstream _get_usd_value fails to normalize WBTC's 8 decimals to the protocol's 18-decimal precision standard. MIN_HEALTH_FACTOR is set to 10**18 — appropriate for WETH's 18 decimals but 10^10 times larger than any health factor a WBTC position can achieve. The vulnerable check:
Since _get_usd_value undervalues WBTC collateral by 10^10, the health factor for a WBTC position minting even 0.001 DSC falls to ~3 * 10^8 — six orders of magnitude below MIN_HEALTH_FACTOR (10^18) — causing every WBTC-backed mint to revert.
Impact: High. WBTC, one of only two collateral tokens in the protocol, is rendered completely unusable for minting DSC. Users depositing WBTC cannot open positions of any practical size, breaking the protocol's multi-collateral design.
Likelihood: High. The bug is deterministic — no market conditions, manipulation, or special triggers required. Any WBTC deposit followed by a mint attempt always fails.
A user depositing 1 BTC ($60,000) can mint at most ~0.000003 DSC instead of the expected ~30,000 DSC, a 10^10 reduction in borrowing power.
This Python simulation reproduces the exact arithmetic path through _get_usd_value → _calculate_health_factor → _revert_if_health_factor_is_broken, demonstrating that any WBTC position with >0.000003 DSC minted fails the health factor assertion.
Normalizing amount to 18 decimals before the price multiplication fixes the upstream valuation error. This ensures _calculate_health_factor receives correctly-scaled collateral values for WBTC, making the result directly comparable to MIN_HEALTH_FACTOR (10^18) without any magnitude mismatch. The fix applies to all functions that depend on _get_usd_value including _get_token_amount_from_usd and _get_account_collateral_value.
## 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.