Dria

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

Broken Market Model

Summary

The Swan marketplace incorrectly charges royalty fees at the time of listing/relisting instead of at purchase time. This leads to sellers losing funds when their assets don't sell and potentially paying multiple rounds of royalties through relisting, even without any sales occurring.

Vulnerability Details

The vulnerability exists in the listing and relisting process where royalties are charged immediately instead of at the time of sale. The root cause is in the transferRoyalties function being called during list and relist operations:

function list(...) external {
// ... listing logic ...
// transfer royalties immediately
transferRoyalties(listings[asset]);
}
function relist(...) external {
// ... relisting logic ...
// transfer royalties again
transferRoyalties(listings[_asset]);
}

The transferRoyalties function immediately charges the seller:

function transferRoyalties(AssetListing storage asset) internal {
uint256 buyerFee = (asset.price * asset.royaltyFee) / 100;
uint256 driaFee = (buyerFee * getCurrentMarketParameters().platformFee) / 100;
// Seller pays immediately
token.transferFrom(asset.seller, address(this), buyerFee);
token.transfer(asset.buyer, buyerFee - driaFee);
token.transfer(owner(), driaFee);
}

Proof of Concept

Scenario: Alice's Multiple Royalty Payments

  1. Initial Setup:

    • Alice wants to sell her NFT for 1000 USDC

    • Royalty fee is 10%

    • Platform fee is 20% of royalties

    • Bob is the designated buyer agent

  2. First Listing (Day 1):

    • Alice lists her NFT for 1000 USDC

    • Immediately pays 100 USDC in royalties (10% of 1000)

    • 80 USDC goes to Bob (buyer agent)

    • 20 USDC goes to platform

    • No one purchases the NFT during this round

  3. First Relisting (Day 30 - Next Round):

    • Alice's NFT didn't sell in the first round

    • She relists it for the same price

    • Pays another 100 USDC in royalties

    • Another 80 USDC goes to Bob

    • Another 20 USDC goes to platform

    • Still no purchase

  4. Second Relisting (Day 60):

    • Alice tries one more time

    • Pays yet another 100 USDC in royalties

    • Total paid in royalties: 300 USDC

    • Total value received: 0 USDC

    • NFT remains unsold

Final Result: Alice has lost 300 USDC in royalty payments without ever making a sale, effectively paying royalties on revenue she never received.

Impact

  • Sellers lose royalty fees even if their assets never sell

  • Multiple relisting operations compound the loss

  • Economic model is broken as royalties are traditionally a portion of actual sales

  • May discourage platform usage due to upfront costs

Quantifiable impact example:

  • Asset price: 1000 tokens

  • Royalty fee: 10% (100 tokens)

  • Platform fee: 20% of royalty (20 tokens)

  • After 3 relists without sales: Seller loses 300 tokens without any sale

Tools Used

Manual Review

Recommendations

  1. Remove royalty transfer from list and relist functions:

  2. Implement royalty handling in the purchase function:

These changes ensure that:

  • Royalties are only paid when a sale occurs

  • Sellers don't lose funds on unsold assets

  • The economic model aligns with marketplace standards

Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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