Algo Ssstablecoinsss

AI First Flight #2
Beginner FriendlyDeFi
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

`burn_dsc` Unnecessarily Asserts MIN_HEALTH_FACTOR, Trapping Undercollateralized Users and Forcing Liquidation

Summary

  • burn_dsc() allows borrowers to repay DSC debt and reduce liability.

  • After burning tokens, the function executes self._revert_if_health_factor_is_broken(msg.sender).

  • If a position is already undercollateralized (health factor < 1.0), partial repayments that do not immediately restore the health factor above 1.0 revert, blocking borrowers from reducing risk.

Vulnerability Details

Description

In dsc_engine.vy, burn_dsc() includes a health factor assertion after reducing the borrower's debt:

@external
def burn_dsc(amount_dsc_to_burn: uint256):
self._burn_dsc(amount_dsc_to_burn, msg.sender, msg.sender)
@> self._revert_if_health_factor_is_broken(msg.sender)

In _calculate_health_factor():
$$

Because total_dsc_minted is the denominator, reducing debt strictly improves the borrower's health factor.

However, if an account's health factor drops below MIN_HEALTH_FACTOR (1.0) due to price depreciation, and the user attempts a partial repayment, the resulting health factor may still be below 1.0 (e.g., rising from 0.70 to 0.95). Because 0.95 is still < MIN_HEALTH_FACTOR, the function reverts.

Risk

Likelihood: High

  • Occurs whenever an undercollateralized borrower attempts partial debt repayment to de-risk their position.

Impact: High

  • Borrowers unable to repay 100% of their shortfall in a single transaction are trapped and forced into liquidation, creating unnecessary liquidation penalties and increasing protocol bad debt.

Severity: High

Proof of Concept

def test_poc_burn_dsc_reverts_when_health_factor_broken(
dsce_minted, eth_usd, dsc, some_user
):
# User deposited 10 ETH ($20,000) and minted 100 DSC.
# ETH price drops to $18 ($180 collateral, $90 threshold value, 100 DSC debt).
# Health factor = 90 / 100 = 0.9 (< 1.0 MIN_HEALTH_FACTOR).
eth_usd.updateAnswer(18 * 10**8)
assert dsce_minted.health_factor(some_user) < MIN_HEALTH_FACTOR
# User attempts to repay 5 DSC to improve health factor to 90 / 95 = 0.947
partial_repay = to_wei(5, "ether")
with boa.env.prank(some_user):
dsc.approve(dsce_minted, partial_repay)
# Reverts with DSCEngine__BreaksHealthFactor
with boa.reverts("DSCEngine__BreaksHealthFactor"):
dsce_minted.burn_dsc(partial_repay)

Explanation: The user attempt to de-risk by repaying 5 DSC reverts because the health check enforces user_health_factor >= MIN_HEALTH_FACTOR, trapping the borrower.

Recommended Mitigation

Remove the health factor check from burn_dsc(). Burning debt can only increase or maintain solvency:

@external
def burn_dsc(amount_dsc_to_burn: uint256):
self._burn_dsc(amount_dsc_to_burn, msg.sender, msg.sender)
- self._revert_if_health_factor_is_broken(msg.sender)

Explanation: Burning debt monotonically improves health factor; removing this check allows borrowers to repay debt incrementally during market distress.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 20 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!