DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: medium
Invalid

Price Verification Issue with Chainlink Oracle Integration

Summary

The price returned by the oracle is not adequately verified, leading to incorrect pricing being accepted.

Vulnerability Details

The ChainlinkUtil.sol contract is using Chainlink’s latestRoundData function in getPrice(), but is not fully validating the returned data.

The value returned from the pricefeed.latestRoundData function (answer) should be verified to ensure that the price returned by the oracle is not zero. However, this was not implemented.

....snip....
try priceFeed.latestRoundData() returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80) {
if (block.timestamp - updatedAt > priceFeedHeartbeatSeconds) {
revert Errors.OraclePriceFeedHeartbeat(address(priceFeed));
}
IOffchainAggregator aggregator = IOffchainAggregator(priceFeed.aggregator());
int192 minAnswer = aggregator.minAnswer();
int192 maxAnswer = aggregator.maxAnswer();
if (answer <= minAnswer || answer >= maxAnswer) {
revert Errors.OraclePriceFeedOutOfRange(address(priceFeed));
}
price = ud60x18(answer.toUint256() * 10 ** (Constants.SYSTEM_DECIMALS - priceDecimals));

For Zaros and many other protocols involving financial transactions, it is critical that the price of assets cannot be zero due to errors from Oracle. Thus, a zero-values check is consistently implemented on such kind of protocols.

One can argue that the returned value checked for minAnswer and maxAnswer bounds. But according to chainlink docs, minAnswer and maxAnswer values are no longer used on most data feeds.

The data feed aggregator includes both minAnswer and maxAnswer values. On most data feeds, these values are no longer used and they do not stop your application from reading the most recent answer. For monitoring purposes, you must decide what limits are acceptable for your application.

Impact

The protocol relies heavily on accurate pricing from the Chainlink oracle for critical operations like collateral valuation and liquidation calculations. An erroneous zero value returned by the oracle could lead to affected assets within the protocol to be considered worthless.

Tools Used

Manual Review

Recommendations

try priceFeed.latestRoundData() returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80) {
if (block.timestamp - updatedAt > priceFeedHeartbeatSeconds) {
revert Errors.OraclePriceFeedHeartbeat(address(priceFeed));
}
+ if (answer <= 0){
+ revert Errors.InvalidOracleReturn();
+ }
IOffchainAggregator aggregator = IOffchainAggregator(priceFeed.aggregator());
int192 minAnswer = aggregator.minAnswer();
int192 maxAnswer = aggregator.maxAnswer();
if (answer <= minAnswer || answer >= maxAnswer) {
revert Errors.OraclePriceFeedOutOfRange(address(priceFeed));
}
price = ud60x18(answer.toUint256() * 10 ** (Constants.SYSTEM_DECIMALS - priceDecimals));
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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