NFT Dealers

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

Missing Zero Address Checks for `_owner` and `_usdc` in Constructor

Author Revealed upon completion

Root + Impact

If _owner or _usdc is set to address(0) at deployment, all owner-gated functions become permanently inaccessible and every USDC operation reverts, bricking the contract entirely with no recovery path.

Description

  • The constructor assigns _owner and _usdc directly without validating that they are non-zero addresses

  • There is no way to update these values post-deployment since owner has no setter and usdc is immutable, making a bad deployment unrecoverable

constructor(
address _owner,
address _usdc,
...
) ERC721(_collectionName, _symbol) {
// @audit no zero address check before assignment
owner = _owner;
usdc = IERC20(_usdc);
}

Risk

Likelihood:

  • Occurs at deployment time — a single misconfigured deploy script or copy-paste error is enough to trigger this

  • No on-chain safeguard exists to catch the mistake after the fact

Impact:

  • If _owner == address(0): revealCollection, whitelistWallet, removeWhitelistedWallet, and withdrawFees are permanently locked

  • If _usdc == address(0): every call to mintNft, buy, cancelListing, collectUsdcFromSelling, and withdrawFees reverts, making the contract completely non-functional

Proof of Concept

The following demonstrates deploying with a zero owner address. Because owner is set to address(0) and never updatable, the onlyOwner modifier will revert on every privileged call for the entire lifetime of the contract.

NFTDealers dealers = new NFTDealers(
address(0), // _owner set to zero by mistake
address(usdc),
"MyNFT",
"NFT",
"ipfs://image",
20e6
);
// All onlyOwner functions permanently revert
dealers.revealCollection(); // reverts: "Only owner can call this function"
dealers.whitelistWallet(alice); // reverts
dealers.withdrawFees(); // reverts

Recommended Mitigation

Add a guard at the very top of the constructor body using the existing InvalidAddress custom error. This ensures any misconfigured deployment reverts immediately at deploy time rather than silently producing a broken contract. Both addresses must be checked independently since either being zero causes a distinct failure mode.

constructor(
address _owner,
address _usdc,
...
) ERC721(_collectionName, _symbol) {
+ if (_owner == address(0) || _usdc == address(0)) revert InvalidAddress();
owner = _owner;
usdc = IERC20(_usdc);
...
}

Support

FAQs

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

Give us feedback!