QuantAMM

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

`MultiHopOracle` and `ChainlinkOracle` doesn't validate for minAnswer/maxAnswer affecting weights

Summary

The oracle does not validate for minAnswer/maxAnswer which can lead to incorrect weight updates.

Vulnerability Details

The ChainlinkOracle::_getData and MultiHopOracle::_getData fail to check for the minAnswer/maxAnswer range.

// File: MultiHopOracle.sol
function _getData() internal view override returns (int216 data, uint40 timestamp) {
HopConfig memory firstOracle = oracles[0];
(data, timestamp) = firstOracle.oracle.getData(); <@ - // No minAnswer/maxAnswer range check
if (firstOracle.invert) {
data = 10 ** 36 / data; // 10^36 (i.e., 1 with 18 decimals * 10^18) to get the inverse with 18 decimals.
// 10**36 is automatically precomputed by the compiler, no explicit caching needed
}
uint256 oracleLength = oracles.length;
for (uint i = 1; i < oracleLength; ) {
HopConfig memory oracleConfig = oracles[i];
(int216 oracleRes, uint40 oracleTimestamp) = oracleConfig.oracle.getData(); <@ - // No minAnswer/maxAnswer range check
if (oracleTimestamp < timestamp) {
timestamp = oracleTimestamp; // Return minimum timestamp
}
// depends which way the oracle conversion is happening
if (oracleConfig.invert) {
data = (data * 10 ** 18) / oracleRes;
} else {
data = (data * oracleRes) / 10 ** 18;
}
unchecked {
++i;
}
}
}
// File: ChainlinkOracle.sol
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); <@ - // No minAnswer/maxAnswer range check
return (int216(data), uint40(timestamp)); // Overflow of data is extremely improbable and uint40 is large enough for timestamps for a very long time
}

The Chainlink documentation notes that "On most data feeds, these values are no longer used and they do not prevent your application from reading the most recent answer.". However, this is not the case on Arbitrum, as for most data feeds (including ETH and most stablecoins), these values are indeed used, for example, the ETH/USD aggregator: link

Hence in case of a price crash / fluctuations, incorrect price will be used to calculate the weights for the pool.

Impact

In case of sharp fluctuations, this can affect the weight calculation which is updated at intervals using these oracle prices, hence can even lead to loss of funds as rule uses incorrect values.

Tools Used

Manual Review

Recommendations

If the price is outside the minPrice/maxPrice range of the oracle, activate a breaker in order to mitigate out of bound prices.

Updates

Lead Judging Commences

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

invalid_chainlink_min_max_no_check

LightChaser: ## [Low-25] Chainlink answer is not compared against min/max values

Support

FAQs

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

Give us feedback!