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.
Phase Manipulation: Allows buying and withdrawing assets outside the intended phase.
Fee Evasion: Enables avoidance of protocol fees on purchase requests.
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.
To address this issue, enforce a whitelist of deployed BuyerAgent addresses. Modify BuyerAgentFactory as follows:
Then, add a modifier to Swan contract functions interacting with BuyerAgent instances:
Applying this modifier ensures that only authorized BuyerAgent instances interact with the protocol.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.