Dria

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

Underflow in stddev calculation breaks core protocol functionality

Summary

The standard deviation calculation in the Statistics library causes an underflow for normal input values, causing validation to revert and breaking core protocol functionality.

Vulnerability Details

function finalizeValidation(uint256 taskId) private {
TaskRequest storage task = requests[taskId];
// compute score for each generation
for (uint256 g_i = 0; g_i < task.parameters.numGenerations; g_i++) {
// get the scores for this generation, i.e. the g_i-th element of each validation
uint256[] memory scores = new uint256[]();
for (uint256 v_i = 0; v_i < task.parameters.numValidations; v_i++) {
scores[v_i] = validations[taskId][v_i].scores[g_i];
}
// compute the mean and standard deviation
>> (uint256 _stddev, uint256 _mean) = Statistics.stddev(scores);
...
}

The finalizeValidation function calculates the standard deviation of validation scores.

function avg(uint256[] memory data) internal pure returns (uint256 ans) {
uint256 sum = 0;
for (uint256 i = 0; i < data.length; i++) {
sum += data[i];
}
ans = sum / data.length;
}
/// @notice Compute the variance of the data.
/// @param data The data to compute the variance for.
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; // @audit underflow
sum += diff * diff;
}
ans = sum / data.length;
}
/// @notice Compute the standard deviation of the data.
/// @dev Computes variance, and takes the square root.
/// @param data The data to compute the standard deviation for.
function stddev(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
>> (uint256 _variance, uint256 _mean) = variance(data);
mean = _mean;
ans = sqrt(_variance);
}

When calculating variance, the function subtracts the mean from each data. An underflow occurs when data[i] is less than the mean.

Impact

Validation will always revert unless all scores are identical so LLMOracleCoordinator and BuyerAgent cannot function properly.

And users pay fees for requests but never receive results due to validation failures because request function is working.

Tools Used

None

Recommendations

Modify the difference calculation logic in the variance function to handle values below mean:

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 ? data[i] - mean : mean - data[i];
sum += diff * diff;
}
ans = sum / data.length;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 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.