Lack of essential stale check in oracleCircuitBreaker()
The `LibOracle::oracleCircuitBreaker()` lacks checking the condition: "block.timestamp > 2 hours + baseTimeStamp". Hence, the function will not be able to verify whether or not the `baseChainlinkPrice` is stale (2-hour stale heartbeat).\\nThis report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the `oracleCircuitBreaker()` only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues.\\nThe `oracleCircuitBreaker()` lacks checking the condition: "block.timestamp > 2 hours + baseTimeStamp" when compared to the `baseOracleCircuitBreaker()`.\\nWithout the check of the condition: "block.timestamp > 2 hours + baseTimeStamp", the `oracleCircuitBreaker()` will not be able to verify whether or not the `baseChainlinkPrice` is stale (2-hour stale heartbeat).\\nFor this reason, the `oracleCircuitBreaker()` will not revert the transaction as expected if the `baseChainlinkPrice` is stale.\\n```\\n    //@audit -- this report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the oracleCircuitBreaker() only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues\\n    function oracleCircuitBreaker(\\n        uint80 roundId,\\n        uint80 baseRoundId,\\n        int256 chainlinkPrice,\\n        int256 baseChainlinkPrice,\\n        uint256 timeStamp,\\n        uint256 baseTimeStamp\\n    ) private view { //@audit -- this report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the oracleCircuitBreaker() only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues\\n      bool invalidFetchData = roundId == 0 || timeStamp == 0\\n          || timeStamp > block.timestamp || chainlinkPrice <= 0 || baseRoundId == 0\\n          || baseTimeStamp == 0 || baseTimeStamp > block.timestamp\\n          || baseChainlinkPrice <= 0; //@audit -- lack the condition: "block.timestamp > 2 hours + baseTimeStamp"\\n\\n        if (invalidFetchData) revert Errors.InvalidPrice();\\n    }\\n\\n    function baseOracleCircuitBreaker(\\n        uint256 protocolPrice,\\n        uint80 roundId,\\n        int256 chainlinkPrice,\\n        uint256 timeStamp,\\n        uint256 chainlinkPriceInEth\\n    ) private view returns (uint256 _protocolPrice) {\\n        bool invalidFetchData = roundId == 0 || timeStamp == 0\\n            || timeStamp > block.timestamp || chainlinkPrice <= 0\\n          || block.timestamp > 2 hours + timeStamp; //@audit -- the baseOracleCircuitBreaker() checks this condition, but the oracleCircuitBreaker() does not check it (for the base oracle (ETH/USD price) only)\\n        uint256 chainlinkDiff = chainlinkPriceInEth > protocolPrice\\n            ? chainlinkPriceInEth - protocolPrice\\n            : protocolPrice - chainlinkPriceInEth;\\n        bool priceDeviation =\\n            protocolPrice > 0 && chainlinkDiff.div(protocolPrice) > 0.5 ether;\\n\\n        // rest of code\\n    }\\n```\\n\\nThe oracleCircuitBreaker() lacks checking the condition: "block.timestamp > 2 hours + baseTimeStamp": https://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/libraries/LibOracle.sol#L120-L123\\nWhereas the baseOracleCircuitBreaker() checks that condition: https://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/libraries/LibOracle.sol#L73
Add the condition: "block.timestamp > 2 hours + baseTimeStamp" in the `oracleCircuitBreaker()` to provide the stale check.\\n```\\n    function oracleCircuitBreaker(\\n        uint80 roundId,\\n        uint80 baseRoundId,\\n        int256 chainlinkPrice,\\n        int256 baseChainlinkPrice,\\n        uint256 timeStamp,\\n        uint256 baseTimeStamp\\n    ) private view {\\n        bool invalidFetchData = roundId == 0 || timeStamp == 0\\n            || timeStamp > block.timestamp || chainlinkPrice <= 0 || baseRoundId == 0\\n            || baseTimeStamp == 0 || baseTimeStamp > block.timestamp\\n// Remove the line below\\n           || baseChainlinkPrice <= 0;\\n// Add the line below\\n           || baseChainlinkPrice <= 0 || block.timestamp > 2 hours // Add the line below\\n baseTimeStamp;\\n\\n        if (invalidFetchData) revert Errors.InvalidPrice();\\n    }\\n```\\n
This report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the `oracleCircuitBreaker()` only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues.\\nThe `oracleCircuitBreaker()` lacks checking the condition: "block.timestamp > 2 hours + baseTimeStamp". Hence, the function will not be able to verify whether or not the `baseChainlinkPrice` is stale (2-hour stale heartbeat).\\nConsequently, the `oracleCircuitBreaker()` will not revert the transaction as expected if the `baseChainlinkPrice` is stale. The stale price will be consumed by core functions of the protocol, leading to harming the funds of the protocol and its users.
```\\n    //@audit -- this report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the oracleCircuitBreaker() only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues\\n    function oracleCircuitBreaker(\\n        uint80 roundId,\\n        uint80 baseRoundId,\\n        int256 chainlinkPrice,\\n        int256 baseChainlinkPrice,\\n        uint256 timeStamp,\\n        uint256 baseTimeStamp\\n    ) private view { //@audit -- this report raises an issue regarding the lack of stale price check for the base oracle (ETH/USD price) in the oracleCircuitBreaker() only, as the 2-hour stale check and the lack of stale price check for the non-USD asset oracle were flagged as known issues\\n      bool invalidFetchData = roundId == 0 || timeStamp == 0\\n          || timeStamp > block.timestamp || chainlinkPrice <= 0 || baseRoundId == 0\\n          || baseTimeStamp == 0 || baseTimeStamp > block.timestamp\\n          || baseChainlinkPrice <= 0; //@audit -- lack the condition: "block.timestamp > 2 hours + baseTimeStamp"\\n\\n        if (invalidFetchData) revert Errors.InvalidPrice();\\n    }\\n\\n    function baseOracleCircuitBreaker(\\n        uint256 protocolPrice,\\n        uint80 roundId,\\n        int256 chainlinkPrice,\\n        uint256 timeStamp,\\n        uint256 chainlinkPriceInEth\\n    ) private view returns (uint256 _protocolPrice) {\\n        bool invalidFetchData = roundId == 0 || timeStamp == 0\\n            || timeStamp > block.timestamp || chainlinkPrice <= 0\\n          || block.timestamp > 2 hours + timeStamp; //@audit -- the baseOracleCircuitBreaker() checks this condition, but the oracleCircuitBreaker() does not check it (for the base oracle (ETH/USD price) only)\\n        uint256 chainlinkDiff = chainlinkPriceInEth > protocolPrice\\n            ? chainlinkPriceInEth - protocolPrice\\n            : protocolPrice - chainlinkPriceInEth;\\n        bool priceDeviation =\\n            protocolPrice > 0 && chainlinkDiff.div(protocolPrice) > 0.5 ether;\\n\\n        // rest of code\\n    }\\n```\\n