Algo Ssstablecoinsss

AI First Flight #2
Beginner FriendlyDeFi
EXP
View results
Submission Details
Severity: high
Valid

WBTC Decimal Mismatch Causes Incorrect Health Factor Validation

Root + Impact

Impact

High

  • WBTC-backed positions can pass health factor validation when they should revert

  • Users may mint more DSC than intended

  • Liquidations may occur too late or fail to trigger

  • Protocol can become undercollateralized


Likelihood

High

  • WBTC is already a supported collateral asset

  • The issue occurs during normal protocol operation

  • No special permissions or attacker setup required

Description

The protocol validates solvency using _revert_if_health_factor_is_broken():

_revert_if_health_factor_is_broken()

This function enforces:

user_health_factor >= MIN_HEALTH_FACTOR

where:

MIN_HEALTH_FACTOR = 1e18

The issue is that the protocol uses a fixed health factor threshold despite supporting collateral assets with different decimal systems.

WETH uses 18 decimals, while WBTC uses 8 decimals.

However, health factor calculations and validation assume a uniform precision model:

PRECISION = 1e18

without token-specific normalization.

As a result, WBTC-backed positions are evaluated using an incorrect scale, causing health factor calculations to be distorted.

This can cause _revert_if_health_factor_is_broken() to incorrectly pass validation for WBTC users.


Vulnerability Details

The vulnerable logic:

assert (
user_health_factor >= MIN_HEALTH_FACTOR
)

assumes all collateral calculations resolve into the same precision domain.

However:

WETH → 18 decimals
WBTC → 8 decimals

Because WBTC collateral values originate from an 8-decimal token model, the resulting health factor becomes incorrectly scaled.

The protocol therefore compares:

WBTC-derived health factor

against:

1e18 fixed threshold

even though the collateral representation is inconsistent.

Risk

Likelihood

  • WBTC is included as native collateral

  • Users naturally mint against WBTC positions

  • Precision mismatch occurs automatically

Impact

  • Health factor validation becomes inaccurate

  • Users may avoid intended reverts

  • Excess DSC may be minted

  • Liquidation thresholds become unreliable

  • Protocol solvency assumptions degrade

Proof of Concept

Assume a user deposits WBTC as collateral and mints DSC near the maximum allowed borrowing threshold.

Because WBTC uses 8 decimals while protocol precision assumes 18-decimal normalization, the calculated health factor is incorrectly scaled.

The protocol evaluates:

user_health_factor >= MIN_HEALTH_FACTOR

using a threshold designed around 18-decimal precision.

As market prices fluctuate and the user approaches liquidation, the account may still pass _revert_if_health_factor_is_broken() despite being undercollateralized according to intended protocol risk parameters.

This allows a WBTC-backed position to remain open longer than intended and mint more debt than protocol safety assumptions allow.

In practice:

  1. User deposits WBTC

  2. User mints maximum DSC

  3. BTC price decreases

  4. Position should revert or liquidate

  5. Health factor remains artificially inflated due to precision mismatch

  6. Position survives below intended collateralization ratio

Recommended Mitigation

Normalize all collateral values into a shared precision model before computing health factor.

Store token decimals explicitly:

token_decimals[token]

and convert collateral amounts to 18-decimal precision prior to:

  • _get_usd_value()

  • _calculate_health_factor()

  • _revert_if_health_factor_is_broken()

Additionally, add dedicated tests for:

  • WBTC-only collateral

  • mixed WBTC/WETH collateral

  • liquidation edge cases near threshold boundaries

This ensures MIN_HEALTH_FACTOR is evaluated consistently across all supported collateral assets.

This version is much stronger and aligns far better with what the judges appear to have wanted.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 2 days ago
Submission Judgement Published
Validated
Assigned finding tags:

[H-01] In the function \_revert_if_health_factor_is_broken constatnt variable MIN_HEALTH_FACTOR is only for WETH.

## 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" ```

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!