DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Valid

Lack of essential stale check in oracleCircuitBreaker()

Summary

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

Vulnerability Details

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.

The oracleCircuitBreaker() lacks checking the condition: "block.timestamp > 2 hours + baseTimeStamp" when compared to the baseOracleCircuitBreaker().

Without 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).

For this reason, the oracleCircuitBreaker() will not revert the transaction as expected if the baseChainlinkPrice is stale.

//@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
function oracleCircuitBreaker(
uint80 roundId,
uint80 baseRoundId,
int256 chainlinkPrice,
int256 baseChainlinkPrice,
uint256 timeStamp,
uint256 baseTimeStamp
) 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
@> bool invalidFetchData = roundId == 0 || timeStamp == 0
@> || timeStamp > block.timestamp || chainlinkPrice <= 0 || baseRoundId == 0
@> || baseTimeStamp == 0 || baseTimeStamp > block.timestamp
@> || baseChainlinkPrice <= 0; //@audit -- lack the condition: "block.timestamp > 2 hours + baseTimeStamp"
if (invalidFetchData) revert Errors.InvalidPrice();
}
function baseOracleCircuitBreaker(
uint256 protocolPrice,
uint80 roundId,
int256 chainlinkPrice,
uint256 timeStamp,
uint256 chainlinkPriceInEth
) private view returns (uint256 _protocolPrice) {
bool invalidFetchData = roundId == 0 || timeStamp == 0
|| timeStamp > block.timestamp || chainlinkPrice <= 0
@> || 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)
uint256 chainlinkDiff = chainlinkPriceInEth > protocolPrice
? chainlinkPriceInEth - protocolPrice
: protocolPrice - chainlinkPriceInEth;
bool priceDeviation =
protocolPrice > 0 && chainlinkDiff.div(protocolPrice) > 0.5 ether;
...
}

Impact

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.

The 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).

Consequently, 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.

Tools Used

Manual Review

Recommendations

Add the condition: "block.timestamp > 2 hours + baseTimeStamp" in the oracleCircuitBreaker() to provide the stale check.

function oracleCircuitBreaker(
uint80 roundId,
uint80 baseRoundId,
int256 chainlinkPrice,
int256 baseChainlinkPrice,
uint256 timeStamp,
uint256 baseTimeStamp
) private view {
bool invalidFetchData = roundId == 0 || timeStamp == 0
|| timeStamp > block.timestamp || chainlinkPrice <= 0 || baseRoundId == 0
|| baseTimeStamp == 0 || baseTimeStamp > block.timestamp
- || baseChainlinkPrice <= 0;
+ || baseChainlinkPrice <= 0 || block.timestamp > 2 hours + baseTimeStamp;
if (invalidFetchData) revert Errors.InvalidPrice();
}
Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issues
serialcoder Submitter
over 1 year ago
0xnevi Lead Judge
over 1 year ago
serialcoder Submitter
over 1 year ago
0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-644

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.