Dria

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

H-03 Buyer DoS Through Zero-Price Relisting Manipulation

Summary

A vulnerability has been identified in the Swan smart contract where attackers can deny service to buyers by repeatedly relisting assets at zero price, avoiding paying fees while filling up the buyer's asset quota for a given round.

Vulnerability Details

In Swan.sol, the contract's relisting mechanism contains a significant vulnerability in how it handles zero-price relistings and royalty calculations. The relevant code section shows:

// buyer must not have more than `maxAssetCount` many assets
uint256 count = assetsPerBuyerRound[_buyer][round].length;
if (count >= getCurrentMarketParameters().maxAssetCount) {
revert AssetLimitExceeded(count);
}
// create listing
listings[_asset] = AssetListing({
createdAt: block.timestamp,
royaltyFee: buyer.royaltyFee(),
price: _price,
seller: msg.sender,
status: AssetStatus.Listed,
buyer: _buyer,
round: round
});
// add this to list of listings for the buyer for this round
assetsPerBuyerRound[_buyer][round].push(_asset);
// ...

The vulnerability exists because:

  1. Assets can be relisted at a price of 0

  2. Royalty fees are calculated as a percentage of the price, so zero-price listings result in zero royalties

  3. Each relisting adds another entry to assetsPerBuyerRound regardless of price

  4. No cost is incurred by the attacker when relisting at zero price

  5. Previous listings remain in the array, contributing to the maxAssetCount limit

An attacker can exploit this by:

  1. Accumulating multiple unsold assets

  2. Repeatedly relisting these assets at zero price

  3. Avoiding any royalty payments due to the zero price

  4. Filling up the buyer's asset quota for the round with zero-price listings

Impact

  • Buyers can be denied service for entire rounds

  • Legitimate sellers are blocked from listing assets

  • Platform royalty mechanism is circumvented

  • Zero cost to execute the attack (besides the transaction cost)

Tools Used

Manual Review

Recommendations

To address this vulnerability, consider implementing the following measures:

  1. Minimum Price and Royalty Requirements

    function relist(address _asset, address _buyer, uint256 _price) external {
    require(_price >= minimumListingPrice, "Price too low");
    uint256 minRoyalty = calculateMinimumRoyalty();
    require((_price * buyer.royaltyFee()) / 10000 >= minRoyalty,
    "Royalty too low");
    // ... rest of the relisting logic
    }
  2. Fixed Relisting Fee

    uint256 constant RELIST_FEE = 0.01 ether; // Example fee
    function relist(address _asset, address _buyer, uint256 _price) external {
    // Charge a fixed fee regardless of price
    token.transferFrom(msg.sender, address(this), RELIST_FEE);
    // ... rest of the relisting logic
    }
Updates

Lead Judging Commences

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

DOS the buyer / Lack of minimal amount of listing price

Support

FAQs

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