QuantAMM

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

Risk of Division by Zero

Summary

The risk of division by zero arises when the contract attempts to perform division operations where the divisor may be zero. In the context of the _getData() function, this issue can occur when the oracle data returns zero, which could happen if:

  • The oracle is malfunctioning.

  • The data from the oracle is intentionally manipulated or corrupted.

  • A calculation results in zero due to certain price feeds or market conditions.

Vulnerability Details

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;
}
}
}
}

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/MultiHopOracle.sol#L31-L55

Impact

  • Any attempt to retrieve data will fail if any of the oracles return zero, causing the entire function execution to fail.

  • Users may be unable to retrieve data, leading to a poor user experience.

  • If this behavior isn't handled properly, users could be impacted by failed transactions, leading to losses in transaction fees and unavailable data.

Tools Used

  • Manual Code Review

Recommendations

  • In case the oracle data is zero, you may want to provide a fallback value or revert with a meaningful error message, like "Oracle returned zero price".

  • It's essential to ensure that any invalid or zero data returned from an oracle is caught early in the process, preventing the contract from executing further with unreliable data.

if (firstOracle.invert) {
require(data != 0, "Oracle returned zero price"); // Prevent division by zero
data = 10 ** 36 / data; // Inversion
}
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
}
require(oracleRes != 0, "Oracle returned zero price"); // Prevent division by zero
// depends which way the oracle conversion is happening
if (oracleConfig.invert) {
data = (data * 10 ** 18) / oracleRes;
} else {
data = (data * oracleRes) / 10 ** 18;
}
unchecked {
++i;
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

invalid_getData_negative_or_zero_price

Multihop will call ChainlinkOracle and the check is in it: `require(data > 0, "INVLDDATA");` MultiHop is just here to combine Chainlinks feed when there is no direct USD price feed for a token.

Support

FAQs

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

Give us feedback!