sherlock-audit / 2023-04-blueberry-judging

8 stars 5 forks source link

kaysoft - latestRoundData has no check for Round completeness. #134

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

kaysoft

medium

latestRoundData has no check for Round completeness.

Summary

Not validating round completeness from chainlink price feed could lead to using stale or wrong or outdated price and this could lead to fund loss. Please read: https://docs.chain.link/data-feeds/historical-data

Vulnerability Detail

The getPrice() function in the ChainlinkAdapterOracle.sol file calls the latestRoundData function but do not validate that the answerInRound return value is greater or equals to the roundID return value.

File: https://github.com/sherlock-audit/2023-04-blueberry/blob/main/blueberry-core/contracts/oracle/ChainlinkAdapterOracle.sol#L87-L96

function getPrice(address token_) external view override returns (uint256) {
        // remap token if possible
        address token = remappedTokens[token_];
        if (token == address(0)) token = token_;

        uint256 maxDelayTime = timeGaps[token];
        if (maxDelayTime == 0) revert Errors.NO_MAX_DELAY(token_);

        // Get token-USD price
        uint256 decimals = registry.decimals(token, USD);
        (, int256 answer, , uint256 updatedAt, ) = registry.latestRoundData(
            token,
            USD
        );
        if (updatedAt < block.timestamp - maxDelayTime)
            revert Errors.PRICE_OUTDATED(token_);
        if (answer <= 0) revert Errors.PRICE_NEGATIVE(token_);

        return
            (answer.toUint256() * Constants.PRICE_PRECISION) / 10 ** decimals;
    }

Impact

Not validating round completeness could lead to contract using stale data which could lead to loss of funds.

Code Snippet

https://github.com/sherlock-audit/2023-04-blueberry/blob/main/blueberry-core/contracts/oracle/ChainlinkAdapterOracle.sol#L87-L96

Tool used

Manual Review

Recommendation

Ensure round completeness is also validated with the code below

(
        uint80 roundID,
        int signedPrice,
        /*uint startedAt*/,
        uint timeStamp,
        uint80 answeredInRound
    ) = registry.latestRoundData();

 //Validate round completeness with this   
require(answeredInRound >= roundID, "round not complete");

Duplicate of #118