Dria

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

Variance calculation causes reverts due to arithmetic underflow

Summary

Subtracting mean from an element of the dataset will likely result in arithmetic underflow in unsigned arithmetic in most cases.

Vulnerability Details

In the Statistics library, the variance method is used to calculate the variance of an array of unsigned integers, data. Variance measures how far each element in the dataset is from the mean. For each element data[i], the method calculates the difference between that element and the mean:

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

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; // <-- calculating difference from the mean
sum += diff * diff;
}
ans = sum / data.length;
}

However, since unsigned integers are used, this can result in arithmetic underflow when the data array contains more than one distinct value.

PoC

describe("with validation", function () {
const [numGenerations, numValidations] = [2, 2];
const dummyScore = parseEther("0.9");
--- const scores = Array.from({ length: numGenerations }, () => dummyScore);
+++ const scores = [parseEther("0.9"), parseEther("0.8")];
let generatorAllowancesBefore: bigint[];
let validatorAllowancesBefore: bigint[];
....
  • Run test:

yarn test ./test/LLMOracleCoordinator.test.ts
  • Test output:

1) LLMOracleCoordinator
with validation
should validate (2/2):
Error: VM Exception while processing transaction: reverted with panic code 0x11 (Arithmetic operation overflowed outside of an unchecked block)
at LLMOracleCoordinator.variance (contracts/libraries/Statistics.sol:22)
at LLMOracleCoordinator.stddev (contracts/libraries/Statistics.sol:32)
at LLMOracleCoordinator.finalizeValidation (contracts/llm/LLMOracleCoordinator.sol:365)
at LLMOracleCoordinator.validate (contracts/llm/LLMOracleCoordinator.sol:304)

Impact

There is a high probability of reverts during task finalization, which will block purchases.

Tools Used

Manual review, Hardhat tests

Recommendations

Modify the difference calculation to account for which value is less than the other, preventing arithmetic underflow:

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;
+++ 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 9 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.