Dria

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

Attacker can steal oracle fees when `numValidations` set to zero.

Summary

The possibility to set validation requirements to zero, together with permissionless and instant oracle registrations, allows malicious users to instantly collect Oracle fees.

Vulnerability Details

In the LLMOracleManager, it is possible to set minimumParameters.numValidations to zero: https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/llm/LLMOracleManager.sol#L130, the same possibility exists in SwanManager: https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/swan/SwanManager.sol#L90. This opens room for an admin error when these parameters are set to zero instructing Swan protocol to create tasks with zero validation requirements via oracleStateRequest and oraclePurchaseRequest:

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/swan/BuyerAgent.sol#L179

function oracleStateRequest(bytes calldata _input, bytes calldata _models) external onlyAuthorized {
// check that we are in the Withdraw phase, and return round
(uint256 round,) = _checkRoundPhase(Phase.Withdraw);
oracleStateRequests[round] =
swan.coordinator().request(SwanBuyerStateOracleProtocol, _input, _models, swan.getOracleParameters());
}

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/swan/BuyerAgent.sol#L194

function oraclePurchaseRequest(bytes calldata _input, bytes calldata _models) external onlyAuthorized {
// check that we are in the Buy phase, and return round
(uint256 round,) = _checkRoundPhase(Phase.Buy);
oraclePurchaseRequests[round] =
swan.coordinator().request(SwanBuyerPurchaseOracleProtocol, _input, _models, swan.getOracleParameters());
}

It’s worth noting that oracle registrations are permissionless and instant, allowing attackers to exploit this by registering oracles solely to collect fees. This is possible because, when numValidations is set to zero, the protocol immediately awards oracle fees:

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/llm/LLMOracleCoordinator.sol#L234

// send rewards to the generator if there is no validation
if (task.parameters.numValidations == 0) {
_increaseAllowance(msg.sender, task.generatorFee);
}

PoC

  • prerequisite: LLMOracleManager.minimumParameters.numValidations set to 0

  • prerequisite: SwanManager.oracleParameters.numValidations set to 0

  1. User submits oracle task.

  2. Attacker registers account #1 as a generator oracle.

  3. Attacker submits the result to respond method.

  4. Since numValidations is zero, the protocol immediately grants a fee to the oracle.

  5. Attacker deregisters account #1, collects fees, and repeats steps 2 - 4 as many times as needed using different accounts.

Impact

Anyone can register an oracle and steal fees. The probability is low since this attack is possible only when numValidations is set to zero.

Tools Used

Manual review

Recommendations

Imlement oracles whitelist, or delays for new oracle activation. Alternatively, disallow the possibility of setting zero validation.

Updates

Lead Judging Commences

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

There is no oracle whitelisting

Support

FAQs

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