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

10 stars 9 forks source link

Upgraded Q -> 2 from #252 [1719594295360] #307

Closed c4-judge closed 4 months ago

c4-judge commented 4 months ago

Judge has assessed an item in Issue #252 as 2 risk. The relevant finding follows:

6. No check for stale prices upon querying chainlink tokens

Links to affected code *

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

Impact

The getSqrtPrice function queries chainlink's latestRoundData but doesn't check if the price returned is stale. Using a stale price can cause the calculations depending on the getSqrtPrice function to be inaccurate, which, for example, can mistakenly consider a user to be ripe for liquidation when in reality they're not and unexpectedly allow the user to be liquidated.

    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);

Recommended Mitigation Steps

Consider checking for stale prices.

(uint80 roundID, int256 feedPrice, , uint256 timestamp, uint80 answeredInRound) = feed.latestRoundData();
require(feedPrice > 0, "Chainlink price <= 0"); 
require(answeredInRound >= roundID, "Stale price");
require(timestamp != 0, "Round not complete");
require(timeStamp < block.timestamp - staleTime, "Stale price")
c4-judge commented 4 months ago

alex-ppg marked the issue as duplicate of #69

c4-judge commented 4 months ago

alex-ppg marked the issue as partial-50