Dria

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

Validate requests in the LLMOracleCoordinator contract consistently revert due to an overflow issue in the Statistics library

Summary

The variance function in Statistics library, utilized in the LLMOracleCoordinator contract to compute data standard deviation, has an overflow issue that causes the validate function in the LLMOracleCoordinator contract to always revert.

Vulnerability Details

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

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 diff can be negative?
sum += diff * diff;
}
ans = sum / data.length;
}

The finalizeValidation function in the LLMOracleCoordinator contract calls stddev to calculate the standard deviation of the scores.
When scores are not same, the variance function encounters an overflow, leading it to consistently revert.

describe("with validation", function () {
const [numGenerations, numValidations] = [2, 2];
const scores = [parseEther("0.9"), parseEther("0.94")]; // @audit scores are not same
this.beforeAll(async () => {
taskId++;
});
it("should make a request", async function () {
await safeRequest(coordinator, token, requester, taskId, input, models, {
difficulty,
numGenerations,
numValidations,
});
});
it("should respond (1/2 & 2/2)", async function () {
for (let i = 0; i < numGenerations; i++) {
await safeRespond(coordinator, generators[i], output, metadata, taskId, BigInt(i));
}
});
it("should validate (1/2) a generation only once", async function () {
const validator = validators[0];
await safeValidate(coordinator, validator, scores, metadata, taskId, 0n);
// should NOT respond again
await expect(safeValidate(coordinator, validator, scores, metadata, taskId, 0n))
.to.be.revertedWithCustomError(coordinator, "AlreadyResponded")
.withArgs(taskId, validator.address);
});
it("should validate (2/2)", async function () {
const validator = validators[1];
await safeValidate(coordinator, validator, scores, metadata, taskId, 1n);
const request = await coordinator.requests(taskId);
expect(request.status).to.equal(TaskStatus.Completed);
});
});

Impact

Due to this overflow issue in the Statistics library, the validate function in LLMOracleCoordinator always fails, preventing validation for any task with more than two scores.

Tools Used

Manual review

Recommendations

Modify the variance function in the Statistics library to prevent overflow and enable successful validation.

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.