Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Invalid

Unauthorized BuyerAgent Deployment Vulnerability

Description

An attacker can deploy a malicious BuyerAgent to interfere with multiple aspects of the protocol. The protocol assumes BuyerAgent contracts are deployed exclusively through the BuyerAgentFactory using Swan::createBuyer(). However, an attacker can deploy a modified BuyerAgent to bypass certain security features, which are only enforced by the trusted Swan operator.

Impact

  • Phase Manipulation: Allows buying and withdrawing assets outside the intended phase.

  • Fee Evasion: Enables avoidance of protocol fees on purchase requests.

Proof of Concept

  • Phase manipulation explanation : while the normal workflow to make a purchase is to call BuyerAgent::purchase(), a malicious agent can call directly Swan::purchase()which doesn't check if it's a buy phase. The malicious agent can also customize functions like BuyerAgent::_checkRoundPhase() in order to return the wrong phase and make a withdraw during the buying phase.

  • Fee Evasion : A malicious agent can set BuyerAgent::roaltyFeeat 0, which will occure to uint256 buyerFee = (asset.price * asset.royaltyFee) / 100; equal to 0 and uint256 driaFee = (buyerFee * getCurrentMarketParameters().platformFee) / 100;. So the protocol will receive no fee.

The proof of concept for this vulnerability can be accessed at Gist by Valin Security Group, containing:

  • MaliciousBuyerAgent.sol – A modified BuyerAgent contract.

  • PoC.t.sol – A setup script compatible with Forge Foundry.

The setups are adapted from Swan Dria’s test environment. Modifications in the malicious agent are annotated with @audit to explain the exploit behavior.

Recommendation

To address this issue, enforce a whitelist of deployed BuyerAgent addresses. Modify BuyerAgentFactory as follows:

mapping(address => bool) public isDeployed;

Then, add a modifier to Swan contract functions interacting with BuyerAgent instances:

modifier onlyWhitelistedBuyer(address _buyer) {
if (!buyerAgentFactory.isDeployed(_buyer)) {
revert UnauthorizedBuyer(_buyer);
}
_;
}

Applying this modifier ensures that only authorized BuyerAgent instances interact with the protocol.

Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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