Root Cause: The unlistNFT function uses BBERC721.transferFrom to return an NFT to the seller (msg.sender), but it lacks a mechanism to handle cases where msg.sender is a malicious smart contract that reverts in its onERC721Received implementation. This revert causes the entire transaction to fail, preventing the NFT from being unlisted.
Impact: Sellers cannot unlist their NFTs if the recipient is a malicious contract, potentially locking NFTs in the marketplace indefinitely. This creates a denial-of-service (DoS) risk, disrupting seller operations and risking financial loss due to inaccessible assets, while undermining trust in the platform.
The BidBeastsNFTMarket::unlistNFT function transfers an NFT back to the seller using:
If msg.sender is a malicious smart contract, it can revert the transfer (e.g., via a malicious onERC721Received implementation). This will cause the entire unlistNFT transaction to revert, effectively blocking the seller from unlisting their NFT.
Likelihood: Medium. The vulnerability depends on a seller interacting with the function via a malicious contract, which requires deliberate action (e.g., a compromised wallet or targeted attack). The likelihood increases in environments with untrusted or automated contract interactions.
Impact: Medium. While not causing immediate asset theft, the inability to unlist locks NFTs, leading to potential financial loss and operational disruption. The impact is significant for affected sellers and could damage platform reputation if exploited widely.
Deploy a malicious contract that reverts in onERC721Received.
List an NFT and attempt to unlist it with the malicious contract as msg.sender.
Observe that unlistNFT reverts every time, preventing the NFT from being returned.
Use a pull pattern: record unlisted NFTs in a mapping and allow sellers to withdraw them manually.
Optionally, restrict recipients to EOAs or trusted contracts.
Consider using try/catch around transferFrom for safety when interacting with untrusted contracts.
Example Fix:
OpenZeppelin ERC721 Safe Transfers
Explains the behavior of safeTransferFrom and potential reverts when interacting with contracts.
https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#ERC721-safeTransferFrom-address-address-uint256-
Solidity Design Pattern: Pull Over Push
Discusses why the pull-over-push pattern is safer for sending tokens or ETH to potentially untrusted contracts.
https://solidity-by-example.org/pull-over-push/
ERC721 Receiver Interface (IERC721Receiver)
Details how contracts can implement onERC721Received and how a revert can block transfers.
https://eips.ethereum.org/EIPS/eip-721#erc-721-token-receiver
Non-safe transferFrom calls can send NFTs to non-compliant contracts, potentially locking them permanently.
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.