chris@schmid:~$
← ./blog

article

An On-Chain Factory for One-Transaction NFT Collections

SolidityOpenZeppelinERC-721wagmi

Deploying your own ERC-721 collection normally means writing a contract, deploying it, minting into it, and wiring up whatever’s supposed to own it — several transactions, several places to get it wrong. This factory collapses all of that into one call.

Two contracts, one job

CustomNFT is a small ERC721URIStorage + Ownable contract — nothing unusual, metadata resolved against a base URI, minting gated to the owner. The interesting part is NFTFactory, which deploys CustomNFT on demand:

function createNFT(string memory name, string memory symbol, string memory baseURI)
    external returns (address)
{
    CustomNFT nft = new CustomNFT(name, symbol, address(this));
    nft.safeMint(msg.sender, baseURI);
    nft.transferOwnership(msg.sender);

    userNFTs[msg.sender].push(address(nft));
    allNFTs.push(address(nft));

    emit NFTCreated(address(nft), msg.sender, name, symbol);
    return address(nft);
}

In one transaction, the factory deploys a brand-new CustomNFT with itself as a temporary owner, mints token #0 straight to the caller, then transfers ownership of the whole collection over — so the caller ends up as the sole owner of a live, mintable ERC-721 contract without ever having deployed anything themselves. userNFTs[msg.sender] and allNFTs keep every collection the factory has ever spun up discoverable on-chain, via getUserNFTs, getAllNFTs, and getTotalNFTs — no indexer required to answer “what has this factory created.”

Wiring it into a frontend

The contract ships with a typed wagmi/viem integration: a useDeployNFT() hook submits createNFT, waits for the transaction receipt, and decodes the NFTCreated event log to recover the freshly deployed collection’s address — the one piece of information a createNFT call doesn’t return directly to a frontend, since the return value only surfaces to other contracts, not to the calling UI.

Where it’s deployed

Built on OpenZeppelin Contracts 5.x, compiled with Solidity 0.8.31, and deployed to Sepolia at 0xC010f83b8a127D48a489e07c6DD804bCE98Bb455, verified via Sourcify. It backs the contract-builder dashboard on this site, where the whole flow — connect a wallet, name a collection, deploy it — happens without leaving the page.

Source: github.com/chris017/nft-factory-contract