Dria

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

The registration of generators and validators is permissionless, allow malicious actors to exploit buyer agents in different ways.

Summary

The registration of generators and validators in the Swan protocol via the register() function is permissionless. Only staking tokens is required, however there are no slashing mechanisms implemented, and registered entities can withdraw their stake at any time. Given that the main purpose of the Swan protocol is to allow buyer agents to buy Swan NFTs so that with each new asset bought, the agent's state changes and the simulation evolves. The assets that the buyer agent will try and buy are determined by the output parameter in the respond() function called by registered generators. If there are multiple generators required for a request, then validators have to provide a score for each generator via the validate() function. There are different ways how malicious generators can be detrimental for the buyer agent. For example generators may provide completely random assets addresses in the output parameter they provide in the respond() function, so that when the buyer agent tries to call the purchase() function, it will always revert. They can also always provide only the most expensive Swan asset that the buyer agent can buy. It is hard to consider all the ways malicious validators and generators can hurt the buyer agents, given that the goal of the protocol is not very clear, however whatever it is it can be manipulated by malicious generators and validators. Malicious validators can also vote in a such a way that certain generators don't get paid for the work they did. In the finalizeValidation() function, as can be seen from the below code snippet if the score for a generator is less than a certain threshold the generator won't get paid:

function finalizeValidation(uint256 taskId) private {
...
(uint256 stddev, uint256 mean) = Statistics.stddev(generationScores);
for (uint256 g_i = 0; g_i < task.parameters.numGenerations; g_i++) {
// ignore lower outliers
if (generationScores[g_i] >= mean - generationDeviationFactor * stddev) {
_increaseAllowance(responses[taskId][g_i].responder, task.generatorFee);
}
}
}

Vulnerability Details

There are no deployment scripts, but from the test files we can assume that the protocol intends to deploy with 1 required generator and 1 validator. This just makes the attack much more simpler. However even if there are 10s of generators and validators required, a malicious actor just needs different addresses in order to register and control the required number of generators and validators, in order to guarantee he is going to control the output provided to the buyer agent purchase() function.

Impact

Malicious generators and validators can hurt the buyer agent in different ways. DOSing the purchase() function, and thus not allowing the buyer agent to continue his simulation. Making the buyer agent buy only the most expensive Swan NFT, never providing an output argument with asset addresses that were created by a certain creator, and so on. When a buyer agent calls the request() function he pays the required fees. If generators and validators provide a bogus output the buyer agent will loose his fees, and the oracles will still get paid.

Tools Used

Manual review

Recommendations

Consider creating a whitelisting process for generators and validators, and implement a slashing mechanism if they misbehave.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year 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.