NFT Dealers

First Flight #58
Beginner FriendlyFoundry
100 EXP
Submission Details
Impact: high
Likelihood: low

Missing Zero Address Validation in Constructor Permanently Bricks Protocol

Author Revealed upon completion

Missing Zero Address Validation in Constructor Permanently Bricks Protocol

Description

  • The constructor accepts an _owner and _usdc address to set critical
    protocol parameters. These values are immutable after deployment — owner
    controls all privileged functions and usdc is the sole payment token.

  • Neither _owner nor _usdc are validated against address(0). A
    deployment with either set to the zero address permanently disables all
    owner-gated functionality and breaks all payment flows with no recovery path.

constructor(
address _owner,
address _usdc,
...
) ERC721(_collectionName, _symbol) {
//@> no zero address check
owner = _owner;
//@> no zero address check
usdc = IERC20(_usdc);
collectionName = _collectionName;
tokenSymbol = _symbol;
collectionImage = _collectionImage;
lockAmount = _lockAmount;
}

Risk

Likelihood: Low

  • A deployer passes address(0) as _owner or _usdc due to a
    deployment script error or misconfiguration

  • No on-chain validation exists to catch this at deployment time —
    the constructor succeeds silently with zero addresses

Impact: High

  • owner = address(0)revealCollection, whitelistWallet,
    withdrawFees all permanently uncallable, protocol never starts

  • usdc = address(0) — all transferFrom and safeTransfer calls
    revert, minting and buying permanently broken

Proof of Concept

We can set owner as zero address in the contract which is not intended

function test_ZeroAddressOwnerBricksProtocol() public {
// deploy with address(0) as owner
NFTDealers brokenDealers = new NFTDealers(
address(0), // ← zero address owner
address(usdc),
"Test",
"TST",
"ipfs://image",
20e6
);
// protocol is permanently bricked
assertEq(brokenDealers.owner(), address(0));
vm.prank(address(this));
vm.expectRevert("Only owner can call this function");
brokenDealers.revealCollection();
assertEq(brokenDealers.isCollectionRevealed(), false);
console.log("owner set to :", brokenDealers.owner());
console.log("collection revealed:", brokenDealers.isCollectionRevealed());
}

Recommended Mitigation

Add following checks below to revert the contract while setting zero address

constructor(
address _owner,
address _usdc,
...
) ERC721(_collectionName, _symbol) {
+ if (_owner == address(0)) revert InvalidAddress();
+ if (_usdc == address(0)) revert InvalidAddress();
owner = _owner;
usdc = IERC20(_usdc);
collectionName = _collectionName;
tokenSymbol = _symbol;
collectionImage = _collectionImage;
lockAmount = _lockAmount;
}

Support

FAQs

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

Give us feedback!