DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: low
Invalid

If the Chainlink registry returns a price outside the designated minimum and maximum range, getPrice() will utilize an incorrect price.

Summary

Chainlink aggregators are equipped with a built-in circuit breaker designed to activate if the price of an asset exceeds a predetermined price range. Consequently, in the event of a substantial decrease in the value of an asset, the oracle's price will persistently display the minimum price instead of the actual asset price. This scenario could enable users to continue borrowing against the asset, albeit at an inaccurate price.

Vulnerability detail

Currently the function checkForInvalidTimestampOrAnswer checks only that answer (price) to be non-positive

function checkForInvalidTimestampOrAnswer(
uint256 timestamp,
int256 answer,
uint256 currentTimestamp,
uint256 maxTimeout
) private pure returns (bool) {
// Check for an invalid timeStamp that is 0, or in the future
if (timestamp == 0 || timestamp > currentTimestamp) return true;
// Check if Chainlink's price feed has timed out
if (currentTimestamp.sub(timestamp) > maxTimeout) return true;
// Check for non-positive price
if (answer <= 0) return true;
}

Consider the following scenario:

Token X, with a minimum price set at 10, experiences a drop in value to 1. Despite this, the aggregator continues to report 10, enabling users to borrow against Token X as if it were valued at 10, which is basically 10 times its actual worth.

Impact

In case of a market crash, an incorrect price might be provided, allowing adversaries to borrow against this inaccurate valuation and accumulate detrimental debt within the protocol.

Recommendation

The ChainlinkAdapterOracle needs to verify that the returned answer falls within the specified minPrice and maxPrice ranges. If the answer lies outside of these boundaries, the system should revert.

function checkForInvalidTimestampOrAnswer(
uint256 timestamp,
int256 answer,
uint256 currentTimestamp,
uint256 maxTimeout
) private pure returns (bool) {
// Check for an invalid timeStamp that is 0, or in the future
if (timestamp == 0 || timestamp > currentTimestamp) return true;
// Check if Chainlink's price feed has timed out
if (currentTimestamp.sub(timestamp) > maxTimeout) return true;
// Check for non-positive price
if (answer <= 0) return true;
+ if (answer >= maxPrice or answer <= minPrice) return true;
}
Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Chainlink validation

Support

FAQs

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