sherlock-audit / 2024-03-arrakis-judging

0 stars 0 forks source link

cergyk - HOTOracle::getSqrtOraclePriceX96 Missing checks on values returned by Chainlink aggregators #72

Closed sherlock-admin3 closed 1 month ago

sherlock-admin3 commented 1 month ago

cergyk

medium

HOTOracle::getSqrtOraclePriceX96 Missing checks on values returned by Chainlink aggregators

Summary

HOTOracle::getSqrtOraclePriceX96 is relying on latestRoundData() but the returned data isn’t properly checked potentially returning stale or incorrect result.

Vulnerability Detail

HOTOracle::getSqrtOraclePriceX96 is relying on Chainlink latestRoundData() function to get the price in USD: HOTOracle.sol#L142.

However, according to Chainlink documentation, the returned data should be checked to ensure no stale or incorrect result:

function latestRoundData() external view
    returns (
        uint80 roundId,
        int256 answer,
        uint256 startedAt,
        uint256 updatedAt,
        uint80 answeredInRound
    )

In the current implementation, only updatedAt is checked, which could lead to stale or incorrect result: HOTOracle.sol#L144-L146.

Here’s an example of a previous report related to this issue: https://github.com/sherlock-audit/2023-02-blueberry-judging/issues/94.

Impact

HOTOracle::_getOraclePriceUSD could return stale or incorrect data, thus wrongly calculating sqrt oracle price.

Code Snippet

Tool used

Manual Review, Solodit

Recommendation

Add the below checks for returned data: HOTOracle.sol#L138-L149

    function _getOraclePriceUSD(
        AggregatorV3Interface feed,
        uint32 maxOracleUpdateDuration
    ) internal view returns (uint256 oraclePriceUSD) {
-       (, int256 oraclePriceUSDInt, , uint256 updatedAt, ) = feed.latestRoundData();
+       (uint80 roundID, int256 answer, uint256 timestamp, uint256 updatedAt, ) = feed.latestRoundData();

+           require(updatedAt >= roundID, "Stale price");
+           require(timestamp != 0, "Round not complete");
+           require(answer > 0, "Chainlink answer reporting 0");

        if (block.timestamp - updatedAt > maxOracleUpdateDuration) {
            revert HOTOracle___getOraclePriceUSD_stalePrice();
        }

        oraclePriceUSD = oraclePriceUSDInt.toUint256();
    }