sherlock-audit / 2023-04-blueberry-judging

8 stars 5 forks source link

Bauchibred - The Oracle data feed still lacks sufficient validation. #82

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

Bauchibred

medium

The Oracle data feed still lacks sufficient validation.

Summary

Though similar case has been reported in former contest, the Oracle data feed is still insufficiently validated as not all advised checks have been added to protocol

Vulnerability Detail

Insufficient validation of oracle's data feed is present. There is no complete check for stale prices and rounding. Price can be stale, leading to incorrect return amounts.

  /**
     * @notice Returns the USD price of given token, price value has 18 decimals
     * @param token_ Token address to get price of
     * @return price USD price of token in 18 decimal
     */
    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

It is possible for price to be stale, resulting in the return value provided being wrong.

Code Snippet

https://github.com/sherlock-audit/2023-04-blueberry/blob/96eb1829571dc46e1a387985bd56989702c5e1dc/blueberry-core/contracts/oracle/ChainlinkAdapterOracle.sol#L72-L97

Tool used

Manual Review

Recommendation

Make a complete validation of the data feed

(uint80 roundID, int256 answer, , uint256 updatedAt, uint80 answeredInRound) = registry.latestRoundData(
            token,
            USD
        );
    require(answer > 0, "invalid_oracle_answer");
    require(answeredInRound >= roundID, "ChainLink: Stale price");
    require(updatedAt > 0, "ChainLink: Round not complete");
    require(answeredInRound >= roundID, "round not complete");

Duplicate of #118