15,000 USDC
View results
Submission Details
Severity: medium
Valid

Different price returned by the oracle in case of market crash

Summary

Different price is returned by the oracle in case of a market crash. PriceOracle will return the wrong price for asset if underlying aggregator hits the minPrice.

Vulnerability Details

Chainlink aggregators have a built in circuit breaker, if the price of an asset goes outside of a predetermined price band or range. Therefore, if the price of a particular asset faces a massive drop in its value, the price of the oracle continues to return the minPrice and the maxPrice instead of the actual price of that asset This would allow users to continue to deposit collateral but at the wrong price.

Example:
Let's consider an example of TokenX, which has a designated minPrice of $1. However, due to market conditions, the price of TokenX plummets to $0.1. Despite of this significant drop, the aggregator continues to provide a price feed of $1 for TokenX. This results in enabling the users to borrow against TokenX based on its artificially inflated value of $1.

Instance:

https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/main/src/libraries/OracleLib.sol#L21

    function staleCheckLatestRoundData(AggregatorV3Interface priceFeed)
    public
    view
    returns (uint80, int256, uint256, uint256, uint80)
{
    (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
        priceFeed.latestRoundData();

    uint256 secondsSince = block.timestamp - updatedAt;
    if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();

    return (roundId, answer, startedAt, updatedAt, answeredInRound);
}

Impact

If there is a market crash, wrong price will be returned and users may continue to deposit collateral at a different price than the actual price.

Tools Used

Manual review and VS Code

Recommendations

There should be proper check for each asset and it should revert in case the price is outside the range. The following check can be included in the staleCheckLatestRoundData function.

require(price >= minPrice && price <= maxPrice, "invalid price");

Support

FAQs

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