QuantAMM

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

single failing oracle can render the entire MultiHopOracle contract unusable

Summary

The MultiHopOracle contract relies on an immutable configuration of oracles, which cannot be updated after deployment.
If any oracle in the sequence returns a value of zero, the entire transaction will fail due this in require(data > 0, "INVLDDATA") in ChainlinkOracle.sol
This immutability creates a critical limitation, as a single failing oracle can render the entire MultiHopOracle contract unusable

Vulnerability Details

The oracles array is initialized during deployment and is immutable thereafter. If any of the oracles in the array return a zero value,
the _getData function will revert due to this check require(data > 0, "INVLDDATA") in ChainlinkOracle.sol. This would make the entire MultiHopOracle contract unusable.

Unlike in UpdateWeightRunner.sol it implement function to remove Oracle for security and integrity.

POC:

function _getData() internal view override returns (int216 data, uint40 timestamp) {
HopConfig memory firstOracle = oracles[0];
(data, timestamp) = firstOracle.oracle.getData();
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();
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;
}
}
}

Oracle Batch Tx will fail if oracle retunes 0:

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

Impact

If any oracle in the sequence fails, the MultiHopOracle batch will fail, and any contract rely on MultiHopOracle getData will fail.

Recommendations

Implement a Mechanism to remove oracles from the array.

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_no_try_catch_for_Chainlink_oracle

Likelihood: Low, price feed should revert. Impact: High, DoS of the protocol

Appeal created

pontifex Auditor
10 months ago
0xwsecteam Submitter
10 months ago
n0kto Lead Judge
9 months ago
n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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