Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Snowman.tokenURI contains a dead-code zero-address check that is unreachable because OZ ERC721 ownerOf reverts first

Description

Snowman.tokenURI attempts to handle queries for nonexistent token IDs by checking if (ownerOf(tokenId) == address(0)). However, OpenZeppelin's ERC721.ownerOf already reverts internally before the comparison is reached — in OZ v4.x with "ERC721: invalid token ID" and in OZ v5.x with ERC721NonexistentToken. The custom error ERC721Metadata__URI_QueryFor_NonExistentToken declared in this contract can therefore never be emitted.

// src/Snowman.sol
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (ownerOf(tokenId) == address(0)) { // @> OZ ownerOf reverts before this is reached
revert ERC721Metadata__URI_QueryFor_NonExistentToken(); // @> unreachable
}
...
}

Callers receive OpenZeppelin's standard revert instead of the contract's documented custom error, breaking any external integration that catches ERC721Metadata__URI_QueryFor_NonExistentToken to detect nonexistent-token queries.

Risk

Code-quality issue. External integrations or frontends that specifically catch ERC721Metadata__URI_QueryFor_NonExistentToken will not receive it — they will get an unexpected OZ revert instead. This breaks error handling for any caller relying on the documented error selector.

Proof of Concept

function test_TokenURI_DeadCheck() public {
// OZ reverts first — custom error is never thrown
vm.expectRevert(); // receives OZ revert, NOT ERC721Metadata__URI_QueryFor_NonExistentToken
nft.tokenURI(999);
}

Result: [PASS] — OZ reverts before the custom error check is reached.

Recommended Mitigation

Replace the public ownerOf call with the internal _ownerOf, which returns address(0) for nonexistent tokens instead of reverting:

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
- if (ownerOf(tokenId) == address(0)) {
+ if (_ownerOf(tokenId) == address(0)) {
revert ERC721Metadata__URI_QueryFor_NonExistentToken();
}
...
}

_ownerOf is the internal getter that returns address(0) for nonexistent tokens without reverting, allowing the custom error to actually be thrown.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 2 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!