Dria

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

Swan dria doesn't enforce that validator scores are between 0 and 1 ether

Summary

Missing validation of score ranges in validate() function can cause underflows in the Statistics library calculations, leading to failed validations and disrupted protocol operations. The protocol assumes but doesn't enforce that validator scores are between 0 and 1 ether.

Vulnerability Details

When validators submit scores in the validate() function (in LLMOracleCoordinator), there's no enforcement of score ranges:

function validate(uint256 taskId, uint256 nonce, uint256[] calldata scores, bytes calldata metadata)
public
onlyRegistered(LLMOracleKind.Validator)
{
// Only checks:
// - Validator is registered
// - Proof of work valid
// - Number of scores matches generations
// Missing: Score range validation (0-1 ether)
validations[taskId].push(TaskValidation({
scores: scores, // Scores can be any uint256 value - @audit
...
}));
}

These scores are then used in Statistics library calculations:

function variance(uint256[] memory data) internal pure {
mean = avg(data);
for (uint256 i = 0; i < data.length; i++) {
uint256 diff = data[i] - mean; // Underflows with large scores - @audit
sum += diff * diff;
}
}

Impact

HIGH

  1. Protocol Disruption:

    • Validation transactions revert due to underflow

    • Tasks stuck in PendingValidation state

    • Generator rewards can't be distributed

    • Buyer agent operations blocked

  2. Economic Impact:

    • Validators waste gas on failed validations

    • Generators don't receive timely payments

    • Protocol's reward distribution mechanism breaks

Likelihood

LOW

  • Requires malicious or faulty validator

  • Current staking + PoW provides some economic deterrent

  • But a single bad validator can disrupt entire tasks

Proof of Concept

// 1. Validator submits extreme scores
scores = [100 ether, 0.1 ether] // Should be 0-1 ether
// 2. In Statistics.variance():
mean = avg(data) = 50.05 ether
diff = 0.1 ether - 50.05 ether // Underflows
// 3. Transaction reverts, validation fails

Recommendation

  1. Add score range validation in validate():

function validate(uint256 taskId, uint256 nonce, uint256[] calldata scores) public {
// Add range check
for (uint256 i = 0; i < scores.length; i++) {
if (scores[i] > 1 ether) {
revert InvalidScore(scores[i]);
}
}
// Rest of function...
}
  1. Long-term solution:

    • Implement validator whitelist

    • Only allow highly trusted validators

    • Stronger trust model than stake + PoW alone

This ensures statistical calculations can't underflow and protocol operations remain stable.

Updates

Lead Judging Commences

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

Unbounded score values in `validate` function

Support

FAQs

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