Summary
LLMOracleCoordinator::getBestResponse
using storage access instead memory
Vulnerability Details
LLMOracleCoordinator.sol#L404-L420
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;
}
this function are intended to be called as part of the core function of Swan Dria protocol.
using storage would impact the gas usage (because of frequent SLOAD and SSTORE) and the gas cost is increased with taskResponses.length
which should be correspond to number of generated response by generator.
Impact
The cost of core functions like BuyerAgent::updateState
and BuyerAgent::purchase
would be high because of BuyerAgent::oracleResult
is called which then call the LLMOracleCoordinator::getBestResponse
.
This might discourage users from using them as it could offset the profits made from using the protocol.
This also would impact the user experience, because of the unnecessary increase in operational cost.
If the issue is not corrected, beside the user experience, there would be a cap of how many max generator it can have before the gas is incredibly high.
Tools Used
foundry
Recommendations
Change the storage
to memory
function getBestResponse(uint256 taskId) external view returns (TaskResponse memory) {
- TaskResponse[] storage taskResponses = responses[taskId];
+ TaskResponse[] memory 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];
+ TaskResponse memory 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;
}