Dria

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

When there is no validator, first respond is always the best answer

Vulnerability Details

When generator submit respond, its score is always 0, and when there is no validation and enough generattion, task will be marked as completed:

function respond(uint256 taskId, uint256 nonce, bytes calldata output, bytes calldata metadata)
public
onlyRegistered(LLMOracleKind.Generator) //@idea register-unregister liên tục ? (mất gì đâu)
onlyAtStatus(taskId, TaskStatus.PendingGeneration)
{
TaskRequest storage task = requests[taskId];
// ensure responder to be unique for this task
for (uint256 i = 0; i < responses[taskId].length; i++) {
if (responses[taskId][i].responder == msg.sender) {
revert AlreadyResponded(taskId, msg.sender);
}
}
// check nonce (proof-of-work)
assertValidNonce(taskId, task, nonce);
// push response
TaskResponse memory response =
TaskResponse({responder: msg.sender, nonce: nonce, output: output, metadata: metadata, score: 0}); // <--
responses[taskId].push(response);
// emit response events
emit Response(taskId, msg.sender);
// send rewards to the generator if there is no validation
if (task.parameters.numValidations == 0) {
_increaseAllowance(msg.sender, task.generatorFee);
}
// check if we have received enough responses & update task status
bool isCompleted = responses[taskId].length == uint256(task.parameters.numGenerations);
if (isCompleted) {
if (task.parameters.numValidations == 0) {
// no validations required, task is completed
task.status = TaskStatus.Completed;
emit StatusUpdate(taskId, task.protocol, TaskStatus.PendingGeneration, TaskStatus.Completed); // <--
} else {
// now we are waiting for validations
task.status = TaskStatus.PendingValidation;
emit StatusUpdate(taskId, task.protocol, TaskStatus.PendingGeneration, TaskStatus.PendingValidation);
}
}
}

Function getBestResponse()will always return first response as best due to the checking condition (0 > 0 is always false):

function getBestResponse(uint256 taskId) external view returns (TaskResponse memory) {
TaskResponse[] storage taskResponses = responses[taskId];
// ensure that task is completed
if (requests[taskId].status != LLMOracleTask.TaskStatus.Completed) {
revert InvalidTaskStatus(taskId, requests[taskId].status, LLMOracleTask.TaskStatus.Completed);
}
// pick the result with the highest validation score
TaskResponse storage result = taskResponses[0];
uint256 highestScore = result.score;
for (uint256 i = 1; i < taskResponses.length; i++) {
if (taskResponses[i].score > highestScore) { // <--
highestScore = taskResponses[i].score;
result = taskResponses[i];
}
}
return result;
}

Which lead to malicious generator submit malicious response, lead to unexpected result for user.

Impact

Malicious generator can submit malicious response, and it will be best response for user

Tools Used

Manual review

Recommendations

In case of there is no validator, random one task response and choose it as best.

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Return value of `getBestResponse` when no validators

Support

FAQs

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