DittoETH

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

Lack of validation to check whether or not the retrieved-price would be a stale price in the LibOracle#`oracleCircuitBreaker()`

Summary

Within the LibOracle#oracleCircuitBreaker(), there is no validation to check whether or not the retrieved-price would be a stale price (timeStamp > block.timestamp + 2 hours).

This lead to retrieving a stale price when the LibOracle#oracleCircuitBreaker() would be called.

Vulnerability Details

Within the LibOracle#oracleCircuitBreaker(), a fetched-data via Oracle would be checked and the result would be stored into the invalidFetchData.
And then, if the invalidFetchData would be True, it would be reverted like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/libraries/LibOracle.sol#L120-L125

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;
if (invalidFetchData) revert Errors.InvalidPrice(); ///<--------------- @audit
}

According to the "Invalid Fetch Data" in the documentation, it is supposed to be checked whether or not the timeStamp would be greater than block.timestamp + 2 hours in order to confirm that the timeStamp would not be a stale Data like this:

Invalid Fetch Data
The following are checked regarding incoming Chainlink data:

  1. roundId == 0

  2. timeStamp == 0

  3. price <= 0

  4. timeStamp > block.timestamp (Implies Chainlink data is coming from the future)

  5. timeStamp > block.timestamp + 2 hours (stale Data: Chainlink has not updated a round in over 2 hours)

However, within the LibOracle#oracleCircuitBreaker(), there is no validation to check whether or not the retrieved-price would be a stale price (timeStamp > block.timestamp + 2 hours).

This lead to retrieving a stale price when the LibOracle#oracleCircuitBreaker() would be called.

Impact

This lead to retrieving a stale price when the LibOracle#oracleCircuitBreaker() would be called.

Tools Used

  • Foundry

Recommendations

Within the LibOracle#oracleCircuitBreaker(), consider adding the validation to check whether or not the retrieved-price would be a stale price (timeStamp > block.timestamp + 2 hours) like this:

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
+ || block.timestamp > 2 hours + timeStamp;
|| baseChainlinkPrice <= 0;
if (invalidFetchData) revert Errors.InvalidPrice();
}
Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other
0xnevi Lead Judge almost 2 years 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.