Algo Ssstablecoinsss

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

Missing Collateral Token Validation in `liquidate` Function

Summary

The liquidate function in dsc_engine.vy does not validate that the collateral parameter is one of the accepted collateral tokens. An attacker can pass an arbitrary address as the collateral parameter, which could lead to unexpected behavior or manipulation of the liquidation process.

Description

In the liquidate function, the collateral parameter is used directly without validation:

@external
def liquidate(collateral: address, user: address, debt_to_cover: uint256):
assert debt_to_cover > 0, "DSCEngine__NeedsMoreThanZero"
starting_user_health_factor: uint256 = self._health_factor(user)
assert (
starting_user_health_factor < MIN_HEALTH_FACTOR
), "DSCEngine__HealthFactorOk"
token_amount_from_debt_covered: uint256 = self._get_token_amount_from_usd(
collateral, debt_to_cover # ← No validation that collateral is accepted!
)
bonus_collateral: uint256 = (
token_amount_from_debt_covered * LIQUIDATION_BONUS
) // LIQUIDATION_PRECISION
self._redeem_collateral(
collateral,
token_amount_from_debt_covered + bonus_collateral,
user,
msg.sender,
)
# ... rest of function

The _get_token_amount_from_usd function uses self.token_address_to_price_feed[collateral] to get the price feed. If collateral is not in the mapping, it returns the zero address (default value for HashMap), which could cause issues in the oracle call.

Unlike _deposit_collateral which validates the token:

assert self.token_address_to_price_feed[token_collateral_address] != empty(
address
), "DSCEngine__TokenNotAllowed"

The liquidate function lacks this validation.

Risk

Severity: Medium
Likelihood: Medium
Impact: Medium

An attacker can:

  1. Call liquidate with an arbitrary collateral address

  2. If the address is not in token_address_to_price_feed, the oracle call may fail or return unexpected results

  3. This could cause the liquidation to fail unexpectedly or behave in unintended ways

  4. Could be used to grief legitimate liquidations or manipulate the protocol

Proof of Concept

import boa
from eth_utils import to_wei
def test_liquidate_with_invalid_collateral(dsce, weth, dsc, some_user, liquidator, eth_usd):
# 1. Setup: User deposits and mints
with boa.env.prank(some_user):
weth.approve(dsce.address, to_wei(10, "ether"))
dsce.deposit_collateral_and_mint_dsc(weth.address, to_wei(10, "ether"), to_wei(100, "ether"))
# 2. Drop price to make user unhealthy
eth_usd.updateAnswer(18 * 10**8)
# 3. Liquidator tries to liquidate with invalid collateral address
invalid_collateral = boa.env.generate_address()
with boa.env.prank(liquidator):
weth.approve(dsce.address, to_wei(1, "ether"))
dsce.deposit_collateral(weth.address, to_wei(1, "ether"))
dsc.approve(dsce.address, to_wei(100, "ether"))
# This should revert but doesn't have proper validation
try:
dsce.liquidate(invalid_collateral, some_user, to_wei(100, "ether"))
print("️ Liquidate accepted invalid collateral address!")
except Exception as e:
print(f"✅ Liquidate rejected invalid collateral: {e}")

Run: mox test -k test_liquidate_with_invalid_collateral

Recommended Mitigation

Add validation that the collateral parameter is one of the accepted collateral tokens:

@external
def liquidate(collateral: address, user: address, debt_to_cover: uint256):
assert debt_to_cover > 0, "DSCEngine__NeedsMoreThanZero"
# Add validation that collateral is accepted
assert self.token_address_to_price_feed[collateral] != empty(
address
), "DSCEngine__TokenNotAllowed"
starting_user_health_factor: uint256 = self._health_factor(user)
assert (
starting_user_health_factor < MIN_HEALTH_FACTOR
), "DSCEngine__HealthFactorOk"
# ... rest of function

Why This Works:
This ensures that only accepted collateral tokens can be used in liquidations, preventing unexpected behavior and maintaining protocol integrity.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 4 hours 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!