A vulnerability in the NFT purchase mechanism allows malicious sellers to list tokens for sale, then transfer ownership, which causes subsequent purchase attempts to revert. This is because the purchase() function expects the listing.seller to hold the token.
If the seller transfers the NFT to another address, the purchase operation will fail, potentially blocking the purchase of other listed assets in the same transaction.
The list() function allows a seller to list an NFT without enforcing ownership restrictions, leaving the asset transferable post-listing:
In the BuyerAgent contract, the purchase() function begins by checking the current round, phase and retrieves a list of assets eligible for purchase from the oracle. It then iterates through each asset, attempting to buy it by calling the purchase() function in Swan.
In Swan, the purchase() function tries to transfer the NFT from listing.seller:
Issue Scenario:
A user lists their NFT through the list() function with a specified buyer.
Since no price validation is enforced at the time of listing, they could set a zero price for the asset.
This means they’re not financially invested in the listing (they won’t lose anything if the asset fails to be sold).
After listing the asset, the user transfers the NFT to another address, possibly even to a different wallet they control.
This action breaks the ownership link between the seller (as stored in listing.seller) and the NFT itself, as the NFT is no longer in the possession of the listed seller.
The purchase() function assumes that the listed token remains with the original listing.seller. If a seller transfers the NFT after listing, the purchase will revert because the transferFrom() call in purchase() will fail when trying to pull the NFT from listing.seller.
---> By listing at a zero price, malicious sellers can intentionally transfer ownership of the NFT, leading to a denial of service without incurring any financial loss.
Manual Review
Enforce a transfer lock on NFTs when they are listed, preventing the seller from transferring them while listed. This approach ensures that the listing.seller will always be the token holder during a purchase.
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.