Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Valid

Underflow in the `variance()` function in Statistics.sol

Summary

Underflow while calculating diffvariable in Statistics.sol::variance()

Vulnerability Details

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/libraries/Statistics.sol#L18

When the variance function is called, it receives an array of uint that is very likely to be different. The average of these numbers is calculated first, and then the difference between the number and the average of all the numbers is calculated for each number.

function variance(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
mean = avg(data);
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
uint256 diff = data[i] - mean;
sum += diff * diff;
}
ans = sum / data.length;
}

The problem is that there will almost inevitably be numbers below the average.
This will result in uint256 diff = number < 0, causing an underflow and a revert.

Let's take an example with data = [1;3;5;4].

We have mean = avg(data) = (1 + 3 + 5 + 4) /4 = 13/4 = 3,25 -> 3 (in solidity)

On the first iteration of the loop, data[0] = 1

We then have the following calculation: uint256 diff = 1 - 3 < 0

This calculation will cause the function to revert.

Note that the function will not revert if all the scores are the same or if the truncation to the lower number caused by the division into solidity corresponds to the smallest number present in the array data (low likelyhood).

Impact

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/llm/LLMOracleCoordinator.sol#L335

The function finalizeValidation() in LLMOracleCoordinator.sol cannot be used, as it will revert on almost each call.
Indeed, finalizeValidation() calls the stddev() function which uses the variance() function to make its calculations.

Tools Used

Manual verification

Recommendations

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/libraries/Statistics.sol#L22

Calculate absolute difference to avoid underflow.

Change :

uint256 diff = data[i] - mean;

by :

uint256 diff = data[i] >= mean ? data[i] - mean : mean - data[i];
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Underflow in computing variance

Support

FAQs

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