Algo Ssstablecoinsss

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

Zero oracle answers are not rejected and can DoS core protocol flows

Root + Impact

Description

  • invalid oracle prices should be rejected before they are used in collateral calculations.

  • the stale check validates freshness but does not validate that price > 0.

    A fresh zero price passes validation.

    _get_token_amount_from_usd() can then divide by zero and revert.

(
round_id, price, started_at, updated_at, answered_in_round
) = staticcall price_price.latestRoundData()
assert updated_at != 0, "DSCEngine_StalePrice"
assert answered_in_round >= round_id, "DSCEngine_StalePrice"
...
<assert seconds_since <= TIMEOUT, "DSCEngine_StalePrice">

Risk

Likelihood:

  • This occurs whenever an oracle reports 0 with a fresh timestamp.

  • The current oracle guard does not reject zero values.

Impact:

  • Liquidations and any path needing token/USD conversion can revert.

  • Protocol functionality can be partially or fully denied until the oracle recovers.

Proof of Concept

/*
The oracle safety check only verifies that the round data is fresh.
It does not verify that the returned price is greater than zero.
So the following sequence is possible:
1. latestRoundData() returns:
- updated_at = recent timestamp
- answered_in_round >= round_id
- price = 0
2. oracle_lib._stale_check_latest_round_data() accepts this result because:
- updated_at != 0
- answered_in_round >= round_id
- seconds_since <= TIMEOUT
3. The engine then uses this zero price in downstream calculations.
In _get_token_amount_from_usd():
(usd_amount_in_wei * PRECISION) // (convert(price, uint256) * ADDITIONAL_FEED_PRECISION)
If price == 0, this becomes:
(usd_amount_in_wei * PRECISION) // (0 * ADDITIONAL_FEED_PRECISION)
Which simplifies to division by zero and reverts.
Example:
- user or liquidator calls a function that needs token/USD conversion
- the oracle answer is fresh but zero
- the conversion path reverts
- the whole operation fails
This can break any path that depends on price-based conversion, including:
- liquidation flows
- collateral redemption calculations
- view/helper functions that determine token amount from USD
- any operational logic that depends on these conversions
So even though the data is "fresh", it is still invalid and can deny protocol functionality.
*/

Recommended Mitigation

- accept any fresh price
+ reject non-positive prices before returning oracle data
+ add an explicit check such as: assert price > 0, "DSCEngine_InvalidPrice"
+ use a dedicated invalid-price error instead of reusing the stale-price error
+ add unit tests for:
+ - price == 0
+ - price < 0
+ - fresh but invalid rounds
+ ensure all downstream pricing logic can only operate on validated oracle answers
Updates

Lead Judging Commences

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