Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: low
Invalid

Precision loss in variance and standard deviation calculations will lead to inaccurate variance and standard deviation values in `Statistics.sol`

Summary

This report highlights a precision loss vulnerability in the variance and stddev functions of the Statistics library. The issue arises from using integer arithmetic to perform calculations, resulting in loss of accuracy, especially when dealing with large numbers or datasets with minimal variation. This lack of precision could lead to inaccurate variance and standard deviation values, affecting downstream calculations that rely on these functions.

Vulnerability Details

The precision loss in the variance and stddev functions results from integer division in Solidity. When calculating variance, the squared difference of each element from the mean is divided by the dataset size, which can result in truncation. Similarly, the sqrt function in stddev applies integer-based square root calculation, which further reduces precision.

In the variance function, the calculation divides the sum of squared differences by data.length, which truncates any fractional component. Additionally, the stddev function's use of sqrt introduces additional rounding.

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; // Precision loss occurs here due to integer division
}
function stddev(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
(uint256 _variance, uint256 _mean) = variance(data);
mean = _mean;
ans = sqrt(_variance); // Precision loss due to integer-based square root
}

Impact

The precision loss could lead to inaccurate results for variance and standard deviation calculations, potentially impacting any contract logic that relies on these statistical calculations. This issue is particularly relevant for financial or data-analysis contracts that require accurate calculations to ensure fair outcomes or proper decision-making.

Tools Used

Manual review.

Recommendations

Use a fixed-point arithmetic library to maintain fractional precision in calculations. This involves scaling values by a large factor (e.g., 1e18) to allow fractional parts during division and square root operations, then dividing by the scale factor afterward.

function variance(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
require(data.length > 0, "Statistics: empty array");
mean = avg(data);
uint256 sum = 0;
uint256 scale = 1e18; // Fixed-point scaling factor
for (uint256 i = 0; i < data.length; i++) {
uint256 diff = data[i] * scale - mean * scale;
sum += (diff * diff) / scale; // Square differences in fixed-point
}
ans = (sum / data.length) / scale; // Adjust result back to regular precision
}
function stddev(uint256[] memory data) internal pure returns (uint256 ans, uint256 mean) {
(uint256 _variance, uint256 _mean) = variance(data);
mean = _mean;
ans = sqrt(_variance * 1e18) / 1e9; // Additional scaling in sqrt for precision
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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