Dria

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

Swan NFT Marketplace Unauthorized Transfer Vulnerability: Swan.sol

Summary

The Swan NFT marketplace contains a critical vulnerability in its listing and purchase functions where token transfers can occur without proper ownership validation. This could allow an attacker to transfer any NFT that has previously approved the marketplace contract, regardless of ownership. The vulnerability stems from using ownerOf() instead of msg.sender for token transfers.

Vulnerability Details

The vulnerability exists in the listing and purchase functions of the Swan contract:

In the purchase() function:

// First transfer: Asset NFT from seller to contract
SwanAsset(_asset).transferFrom(listing.seller, address(this), 1);
SwanAsset(_asset).transferFrom(address(this), listing.buyer, 1);
token.transferFrom(listing.buyer, address(this), listing.price);

In the transferRoyalties() function:

token.transferFrom(asset.seller, address(this), buyerFee);

The key issue is that these functions do not validate that msg.sender owns the tokens being transferred. Instead, they assume the tokens can be transferred as long as the contract has approval. This violates a core assumption of ERC20/ERC721 token safety:

The contract should only transfer tokens on behalf of the actual current owner

Token approvals should only allow designated operators to initiate transfers

Token transfers should validate ownership at time of transfer

Impact

The vulnerability is considered HIGH severity for the following reasons:

Unauthorized Token Transfers

  • Any user could transfer NFTs that have approved the marketplace contract

  • No ownership verification is performed at time of transfer

  • Users who previously approved the contract are at risk of NFT theft

Loss of User Assets

  • NFTs approved to the contract could be stolen by an attacker

  • The vulnerability exposes approved NFTs from any collection

  • Attacker could drain NFTs from multiple victims in a single transaction

Protocol Trust

  • The vulnerability fundamentally breaks the trust model of the marketplace

  • Users expect the marketplace to only transfer tokens they explicitly list

  • Undermines the core security assumptions of the NFT trading protocol

Tools Used

Manual code review

slitherin .

Swan transferRoyalties parameter from is not related to msg.sender token.transferFrom(asset.seller,address(this),buyerFee) (contracts/swan/Swan.sol#265)
Swan purchase parameter from is not related to msg.sender SwanAsset(_asset).transferFrom(listing.seller,address(this),1) (contracts/swan/Swan.sol#294)
Swan purchase parameter from is not related to msg.sender SwanAsset(_asset).transferFrom(address(this),listing.buyer,1) (contracts/swan/Swan.sol#295)
Swan purchase parameter from is not related to msg.sender token.transferFrom(listing.buyer,address(this),listing.price) (contracts/swan/Swan.sol#298)
Reference: https://ventral.digital/posts/2022/8/18/sznsdaos-bountyboard-unauthorized-transferfrom-vulnerability

Recommendations

The following changes are required to fix the vulnerability:

Add approval checks before transfers:

function transferRoyalties(AssetListing storage asset) internal {
// Check approval first
require(token.allowance(msg.sender, address(this)) >= buyerFee,
"Insufficient allowance");
// Transfer after validation
token.transferFrom(msg.sender, address(this), buyerFee);
...
}

Add ownership validation by requiring msg.sender to be the token owner:

function transferRoyalties(AssetListing storage asset) internal {
// Check approval first
require(token.allowance(msg.sender, address(this)) >= buyerFee,
"Insufficient allowance");
// Transfer after validation
token.transferFrom(msg.sender, address(this), buyerFee);
...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
8 months ago
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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