Summary
variance function is used to compute the variance by using the given set of values. It deduct the mean from the input values.
when the mean is greater than the input value, the function will revert.
Vulnerability Details
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;
}
the variance
function is used in the stddev
function.
In the LLM oracle implementation, it is used in the validate
function to validate the requests for a given task ID.
bool isCompleted = validations[taskId].length == task.parameters.numValidations;
if (isCompleted) {
task.status = TaskStatus.Completed;
emit StatusUpdate(taskId, task.protocol, TaskStatus.PendingValidation, TaskStatus.Completed);
finalizeValidation(taskId); ---->>>
}
for (uint256 g_i = 0; g_i < task.parameters.numGenerations; g_i++) {
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];
}
(uint256 _stddev, uint256 _mean) = Statistics.stddev(scores);
The task which has highest score would be used in the purchase process.
function oracleResult(uint256 taskId) public view returns (bytes memory) {
if (taskId == 0) {
revert TaskNotRequested();
}
return swan.coordinator().getBestResponse(taskId).output;
}
Impact
since the purchase()
and updateState()
are two important operation in the buyer flow. Reverting the function call in stddev
would cause hindrance in the purchase operation.
since the finalizeValidation revert below, the score update would fail for some tasks.
for (uint256 g_i = 0; g_i < task.parameters.numGenerations; g_i++) {
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];
}
(uint256 _stddev, uint256 _mean) = Statistics.stddev(scores); ---->>>> revert here for some score
uint256 innerSum = 0;
uint256 innerCount = 0;
for (uint256 v_i = 0; v_i < task.parameters.numValidations; ++v_i) {
uint256 score = scores[v_i];
if ((score >= _mean - _stddev) && (score <= _mean + _stddev)) {
innerSum += score;
innerCount++;
_increaseAllowance(validations[taskId][v_i].validator, task.validatorFee);
}
}
Tools Used
Manual review.
Recommendations
We would suggest to modify the variance computation such that always deduct from largest of the two ( input and mean)