QuantAMM

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

Wrong decimals calculation in MultiHopOracle contract

Summary

The value data returned by the Oracle in the function _getData::MultiHopOracle.sol is wrong in certain conditions due to lack of normalizing factor. The data returned by the multiple oracles could have decimals greater, lesser or equal to 18 decimals. Knowing that the data is supposed to be 18 decimals, and getting it in another number of decimals would be a disaster for the protocol.

Vulnerability Details

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

the returned values of dataand oracleReswere not checked if they were in 18 decimals. In the case they were not, it would lead to incorrect calculations.

Impact

Incorrect calculation of the number of decimals could lead to significant malfunctioning of the protocol where the value of data (price) is been utilized. Could even lead to loss of funds

Tools Used

Manual review

Recommendations

a new variable normalizedFactor should be introduced

and be calculated as normalizedFactor = 18 - priceFeedDecimal

where priceFeedDecimal is the token decimal returned by the oracle being used. Then the normalizedFactor should be multiplied to the data

function _getData() internal view override returns (int216 data, uint40 timestamp) {
...
if (firstOracle.invert) {
+ normalizeData = data * int(10 ** normalizationFactor);
+ data = 10 ** 36 / normalizedData;
- data = 10 ** 36 / normalizedData; // 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
}
...
}

this same approach could be applied to oracleRes

Updates

Lead Judging Commences

n0kto 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.

Give us feedback!