Dria

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

Underflow Vulnerability in `variance` Function Causes Denial of Service (DoS) in `finalizeValidation` of `LLMOracleCoordinator`

Github

Summary

The variance function in the Statistics library calculates the variance of a dataset but is vulnerable to an underflow issue. This underflow can occur when an element in the dataset is smaller than the calculated mean, causing the function to revert. This issue extends to the LLMOracleCoordinator contract’s finalizeValidation function, which relies on the stddev function (a wrapper around variance). When finalizeValidation attempts to process data where elements are below the mean, it triggers a revert due to the underflow in variance. This revert halts the task validation process and could lead to a Denial of Service (DoS) condition, preventing task completion and disrupting user interactions with the platform.

Vulnerability Details

The core issue lies within the variance function in the Statistics library. Here’s a closer look at how this underflow vulnerability arises:

/// @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; // Potential underflow
sum += diff * diff;
}
ans = sum / data.length;
}

The variance function calculates the variance by first computing the mean of the dataset. Then, for each element in the dataset, it calculates diff = data[i] - mean and squares this difference to accumulate the sum of squared deviations. However, if data[i] is less than mean, this subtraction results in a negative value, which underflows in Solidity, causing the function to revert.

Example of Underflow in variance

Consider the following dataset:

uint256[] memory data = [10, 20, 30, 40];

The function first calculates the mean as:

mean = (10 + 20 + 30 + 40) / 4 = 25;

The function then iterates over data, calculating diff = data[i] - mean:

For data[0] = 10, the calculation diff = 10 - 25 results in a negative value, which causes an underflow in Solidity’s uint256 arithmetic, triggering a revert.

This vulnerability limits the usability of the variance function, as it reverts whenever any value in the dataset is below the mean. Consequently, any functions or contracts relying on variance to process data with values below the mean will fail, potentially leading to broader system issues.

The underflow vulnerability in variance directly impacts the LLMOracleCoordinator contract, specifically in the finalizeValidation function, which uses stddev (and therefore variance) to compute the standard deviation of validation scores. Here’s how this issue propagates to finalizeValidation:

Code Context in finalizeValidation:

// Compute the mean and standard deviation
(uint256 _stddev, uint256 _mean) = Statistics.stddev(scores);

The finalizeValidation function calls stddev to compute the standard deviation of validation scores for each generation. The stddev function internally calls variance, and any underflow in variance due to scores being below the mean will cause stddev to revert. This revert in turn halts the finalizeValidation function, preventing the task’s validation from completing.

Suppose finalizeValidation is processing a task with a set of scores [10, 20, 30, 40]. When stddev is called with these scores, the following steps occur:

  • stddev calls variance to compute the variance of the scores.

  • In variance, the mean is calculated as 25.

  • As variance iterates over the scores, it encounters the first score, 10, which is less than the mean (25). The calculation 10 - 25 causes an underflow, reverting the variance function and, consequently, stddev and finalizeValidation.

Impact

Since finalizeValidation reverts when an underflow occurs, it prevents task validation from completing and causes DOS. The finalizeValidation function cannot complete the validation for the task, which means that the task cannot proceed to completion, nor can rewards or other outcomes be distributed. Validators and participants may waste gas fees on transactions that revert due to this underflow, increasing costs and discouraging participation. In a high-stakes or economically incentivized platform, this DoS issue could have significant financial repercussions.

Tools Used

Manual Review

Recommendations

To address this issue, modify the variance function to prevent underflow by using the absolute difference between each value and the mean, ensuring that diff is always non-negative. Here’s the modified variance function:

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]; // Use absolute difference
sum += diff * diff;
}
ans = sum / data.length;
}
Updates

Lead Judging Commences

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