code-423n4 / 2024-05-predy-findings

10 stars 9 forks source link

Lack of Chainlink Price Range Validation in PriceFeed Contract #263

Closed howlbot-integration[bot] closed 2 months ago

howlbot-integration[bot] commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-05-predy/blob/a9246db5f874a91fb71c296aac6a66902289306a/src/PriceFeed.sol#L45

Vulnerability details

Impact

The PriceFeed contract leverages Chainlink and Pyth oracles to determine the price of assets. The getSqrtPrice function fetches data from Chainlink without validating if the price is within a predefined acceptable range. This oversight can lead to using distorted prices in financial calculations, especially during extreme market conditions or oracle malfunctions.

Proof of Concept

The PriceFeed contract employs AggregatorV3Interface for fetching the price of quote tokens. The function does not incorporate checks for these prices against any minPrice or maxPrice limits, unlike the setup in some other oracle integrations which have built-in circuit breakers to handle such scenarios.

function getSqrtPrice() external view returns (uint256 sqrtPrice) {
    (, int256 quoteAnswer,,,) = AggregatorV3Interface(_quotePriceFeed).latestRoundData();
    IPyth.Price memory basePrice = IPyth(_pyth).getPriceNoOlderThan(_priceId, VALID_TIME_PERIOD);

    require(basePrice.expo == -8, "INVALID_EXP");
    require(quoteAnswer > 0 && basePrice.price > 0);

    uint256 price = uint256(int256(basePrice.price)) * Constants.Q96 / uint256(quoteAnswer);
    price = price * Constants.Q96 / _decimalsDiff;

    sqrtPrice = FixedPointMathLib.sqrt(price);
}

Tools Used

Manual

Recommended Mitigation Steps

Implement minPrice/maxPrice validation within the getSqrtPrice function to ensure price integrity. Here is a recommended code snippet to add:

(, int256 price, , , ) = AggregatorV3Interface(_quotePriceFeed).latestRoundData();

if (price < minPrice || price > maxPrice) {
    revert("Price out of bounds");
}

Assessed type

Oracle

c4-judge commented 2 months ago

alex-ppg marked the issue as unsatisfactory: Invalid