Normal behavior: The BidBeastsNFTMarket::listNFT function is intended to allow the current human NFT owner to list their token on the marketplace. After a successful listing, the NFT is transferred into escrow (address(market)) and the seller is recorded in the listings mapping so that only they can unlist and receive proceeds.
Issue: After the first listing, BidBeasts::ownerOf(tokenId) becomes the marketplace contract. Since the code checks only require(BBERC721.ownerOf(tokenId) == msg.sender), if msg.sender is also the marketplace, the contract can call its own BidBeastsNFTMarket::listNFT function. This overwrites the seller field in the listing with address(this). As a result, the real seller loses the ability to unlist, and any sales will send funds to the contract itself with no withdrawal path.
Likelihood:
Once a token is listed, its BidBeasts::ownerOf changes to the marketplace contract, so any internal context where msg.sender == address(market) can re-trigger BidBeastsNFTMarket::listNFT.
No additional check (!listed) prevents overwriting, making this scenario consistently reproducible.
Impact:
Loss of funds: On sale, the seller is the marketplace itself. Proceeds are sent to the contract, not the real seller, and remain locked.
Permanent lock: The original seller cannot call BidBeastsNFTMarket::unlistNFT anymore because BidBeastsNFTMarket::isSeller check fails. This prevents reclaiming their NFT.
Result:
Explanation:
This test shows that after the NFT is escrowed, the marketplace can re-list it as if it were the seller. The overwrite breaks accounting and leaves both the funds and NFT effectively stuck.
Explanation:
Add a guard to prevent re-listing (!listings[tokenId].listed).
Explicitly forbid the marketplace itself from being recorded as the seller (msg.sender != address(this)).
Consider storing the original seller in an immutable field for the listing lifetime and never overwriting it.
Optionally, implement a withdrawal fallback only for user funds — but ideally this should be unnecessary if the invariant is preserved.
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.