Algo Ssstablecoinsss

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

No Minimum Deposit Threshold Enables Dust Attacks and Unliquidatable Positions

Root + Impact

Root Cause: The _deposit_collateral() function only checks that amount_collateral > 0, allowing deposits of any non-zero amount including dust amounts worth fractions of a cent.

Impact: Attackers can create thousands of micro-positions that cost more gas to liquidate than they're worth. These positions accumulate as unliquidatable bad debt when they become underwater, gradually making the protocol insolvent.

Description

Normal Behavior: Users should deposit meaningful amounts of collateral that can be economically liquidated if needed.

Issue: The _deposit_collateral() function only checks that amount_collateral > 0, allowing dust deposits. Micro-positions may cost more gas to liquidate than they're worth.
# dsc_engine.vy
@internal
def _deposit_collateral(token_collateral_address: address, amount_collateral: uint256):
assert amount_collateral > 0, "DSCEngine_NeedsMoreThanZero" # @> Only checks > 0
# @> No minimum value threshold
# ...

Risk

Likelihood:MEDIUM

  • Reason 1 : Attackers can create thousands of micro-positions cheaply

  • Reason 2 : Normal users may accidentally create tiny positions

Impact:

  • Impact 1 : Dust positions accumulate as bad debt when liquidation is uneconomical

  • Impact 2 : Protocol becomes cluttered with unliquidatable position

Proof of Concept

An attacker creates 1000 positions, each depositing 1 wei of ETH and minting 1 wei of DSC. Each position has collateral worth less than $0.000001. When these positions become liquidatable, the gas cost to liquidate (approximately $10 at normal gas prices) far exceeds the value recovered. These positions remain as permanent bad debt in the system.

def test_dust_attack():
# Attacker creates 1000 micro-positions
for i in range(1000):
# Deposit 1 wei of ETH (~$0.0000000001)
engine.deposit_collateral(WETH, 1, sender=attacker_wallets[i])
# Mint 1 wei of DSC
engine.mint_dsc(1, sender=attacker_wallets[i])
# Each position:
# - Collateral: 1 wei ETH
# - Debt: 1 wei DSC
# - Gas to liquidate: ~200,000 gas = $10 at 50 gwei
# - Value recovered: < $0.01
# Result: 1000 positions that will never be liquidated
# Bad debt accumulates as these positions become underwater

Recommended Mitigation

Implement a minimum collateral value threshold in USD terms. Check that either the deposit itself or the user's total position after deposit meets this minimum. This ensures all positions can be economically liquidated.

# dsc_engine.vy
+ MIN_COLLATERAL_VALUE_USD: constant(uint256) = 100 * 10**18 # $100 minimum
@internal
def _deposit_collateral(token_collateral_address: address, amount_collateral: uint256):
assert amount_collateral > 0, "DSCEngine_NeedsMoreThanZero"
assert self.token_address_to_price_feed[token_collateral_address] != empty(address), "DSCEngine__TokenNotAllowed"
+ # Check minimum collateral value
+ collateral_value_usd: uint256 = self._get_usd_value(token_collateral_address, amount_collateral)
+ total_user_collateral: uint256 = self._get_account_collateral_value(msg.sender) + collateral_value_usd
+ assert total_user_collateral >= MIN_COLLATERAL_VALUE_USD, "DSCEngine__BelowMinimumCollateral"
self.user_to_token_address_to_amount_deposited[msg.sender][token_collateral_address] += amount_collateral
# ...
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 3 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!