The Swan protocol allows listing assets with zero price, enabling malicious users to spam BuyerAgent with worthless listings without paying fees. This can effectively block legitimate users from listing assets due to the maxAssetCount limitation per round.
function list(string calldata _name, string calldata _symbol, bytes calldata _desc, uint256 _price, address _buyer)
external
{
BuyerAgent buyer = BuyerAgent(_buyer);
(uint256 round, BuyerAgent.Phase phase,) = buyer.getRoundPhase();
if (phase != BuyerAgent.Phase.Sell) {
revert BuyerAgent.InvalidPhase(phase, BuyerAgent.Phase.Sell);
}
>> if (getCurrentMarketParameters().maxAssetCount == assetsPerBuyerRound[_buyer][round].length) {
revert AssetLimitExceeded(getCurrentMarketParameters().maxAssetCount);
}
address asset = address(swanAssetFactory.deploy(_name, _symbol, _desc, msg.sender));
listings[asset] = AssetListing({
createdAt: block.timestamp,
royaltyFee: buyer.royaltyFee(),
price: _price,
seller: msg.sender,
status: AssetStatus.Listed,
buyer: _buyer,
round: round
});
assetsPerBuyerRound[_buyer][round].push(asset);
transferRoyalties(listings[asset]);
emit AssetListed(msg.sender, asset, _price);
}
function transferRoyalties(AssetListing storage asset) internal {
>> uint256 buyerFee = (asset.price * asset.royaltyFee) / 100;
uint256 driaFee = (buyerFee * getCurrentMarketParameters().platformFee) / 100;
token.transferFrom(asset.seller, address(this), buyerFee);
token.transfer(asset.buyer, buyerFee - driaFee);
token.transfer(owner(), driaFee);
}
To prevent spamming the list, a fee is paid via transferRoyalties at the time of listing. However, if user set the asset's Price to 0, user will not pay the fee.
Since each Agent can only receive maxAssetCount in each round, Attacker can fill it with meaningless lists, which can prevent users from using the Agent.
Spamming with a Price of 0 can be used to fill the assetsPerBuyerRound for that round, which not only blocks users who want to use the Agent, but also prevents the Agent from working properly.
It is recommended to set a minimum price or modify it to take a default fee in addition to the price-dependent fee.