QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Missing Stale Price Check in ChainlinkOracle

Summary

The _getData() function in ChainlinkOracle.sol lacks validation for stale price data from Chainlink oracle feeds, which could lead to using outdated price information in critical pool operations.

Vulnerability Details

In _getData(), the contract retrieves price data using priceFeed.latestRoundData() but only validates that the price is positive (data > 0). It does not implement checks for:

  1. Stale prices using timestamp

  2. Round completeness using answeredInRound

  3. Round ID sequence using roundID

function _getData() internal view override returns (int216, uint40) {
(, /*uint80 roundID*/ int data, , /*uint startedAt*/ uint timestamp, ) = /*uint80 answeredInRound*/
priceFeed.latestRoundData();
require(data > 0, "INVLDDATA");
data = data * int(10 ** normalizationFactor);
return (int216(data), uint40(timestamp));
}

Affected Code

contract ChainlinkOracle is OracleWrapper {
AggregatorV3Interface internal immutable priceFeed;
uint internal immutable normalizationFactor;
function _getData() internal view override returns (int216, uint40) {
(, /*uint80 roundID*/ int data, , /*uint startedAt*/ uint timestamp, ) = /*uint80 answeredInRound*/
priceFeed.latestRoundData();
require(data > 0, "INVLDDATA");
data = data * int(10 ** normalizationFactor);
return (int216(data), uint40(timestamp));
}
}

Impact

  • Pool operations could use stale or outdated price data

  • Weight updates and rebalancing could occur based on incorrect price information

  • Potential manipulation of pool dynamics if oracle data is not fresh

  • Trading functions could execute at incorrect prices

Recommendations

Add comprehensive oracle data validation:

function _getData() internal view override returns (int216, uint40) {
(uint80 roundID, int data, , uint timestamp, uint80 answeredInRound) = priceFeed.latestRoundData();
require(data > 0, "INVLDDATA");
require(answeredInRound >= roundID, "Stale price");
require(block.timestamp - timestamp < MAXIMUM_STALENESS_PERIOD, "Price too old");
data = data * int(10 ** normalizationFactor);
return (int216(data), uint40(timestamp));
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

invalid_chainlink_staled_data_updateAt_roundId_known_issue

LightChaser: ## [Medium-4] Insufficient oracle validation

Support

FAQs

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