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)
onlyAtStatus(taskId, TaskStatus.PendingGeneration)
{
TaskRequest storage task = requests[taskId];
for (uint256 i = 0; i < responses[taskId].length; i++) {
if (responses[taskId][i].responder == msg.sender) {
revert AlreadyResponded(taskId, msg.sender);
}
}
assertValidNonce(taskId, task, nonce);
TaskResponse memory response =
TaskResponse({responder: msg.sender, nonce: nonce, output: output, metadata: metadata, score: 0});
responses[taskId].push(response);
emit Response(taskId, msg.sender);
if (task.parameters.numValidations == 0) {
_increaseAllowance(msg.sender, task.generatorFee);
}
bool isCompleted = responses[taskId].length == uint256(task.parameters.numGenerations);
if (isCompleted) {
if (task.parameters.numValidations == 0) {
task.status = TaskStatus.Completed;
emit StatusUpdate(taskId, task.protocol, TaskStatus.PendingGeneration, TaskStatus.Completed);
} else {
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];
if (requests[taskId].status != LLMOracleTask.TaskStatus.Completed) {
revert InvalidTaskStatus(taskId, requests[taskId].status, LLMOracleTask.TaskStatus.Completed);
}
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.