# We do a little minting - ERC721C

By [Chuba](https://paragraph.com/@itsover) · 2022-04-22

---

NFT minting is expensive as shit. Let’s mint an ERC721-compatible NFT, that will work across the various marketplaces (Universe, OpenSea, Rarible, etc) without breaking the bank. The rules are simple: we can break ERC721-compliance, but we can not break compatibility. While following the standards we know and love is generally preferred, a little bit of non-compliance may be interesting at the very least, and actually productive at best.

Let’s start with Solmate’s ERC721 `_mint()` implementation, which is included in their gold standard, highly optimized boilerplate. Minting one NFT costs ~52,009 gas. Pretty damn good. As you can see, we first verify that we’re sending to a valid (non-zero) address, and then ensure that the token has not yet been minted. Afterwards we increment the users balance and assign them as the owner of the tokenID.

        mapping(address => uint256) public balanceOf;
       
        function _mint(address to, uint256 id) internal virtual {
            require(to != address(0), "INVALID_RECIPIENT");
    
            require(ownerOf[id] == address(0), "ALREADY_MINTED");
    
            // Counter overflow is incredibly unrealistic.
            unchecked {
                balanceOf[to]++;
            }
    
            ownerOf[id] = to;
    
            emit Transfer(address(0), to, id);
        }
    

As we can see, there’s not much room to improve upon this boilerplate, so we’re gonna have to get a little bit creative. We got two options. Mess with `balanceOf` or mess with `ownerOf`. I argue that `ownerOf` is a necessary part of the ERC721 standard, as it is the only on-chain storage tying a tokenID to it’s owner’s address. However, `balanceOf` is a different story. When implementing `ERC721Enumerable`, the `balanceOf` call becomes incredibly useful, allowing a frontend to fetch a user’s inventory for example. The problem is, `balanceOf` alone cannot be used to derive any further information, not without the implementation of enumerability at least. Therefore, I propose that `balanceOf` should only be required in an ERC721 that implements `ERC721Enumerable.`

The tradeoff being made is that other contracts will not be able to retrieve a user’s NFT balance from the contract, but these contracts can still verify token ownership of a user if the contract is made aware of the users tokenID(s). One can argue a limitation would be an inability to write a contract that transfers the users first NFT on a given contract, although without implementing enumerability, this is not possible anyway.

Ultimately, this optimization doesn’t break compatibility, as tokens transferred will still emit proper events allowing marketplaces which index NFTs to catch all their transfers. Additionally the TokenURI will continue to work allowing these NFTs to point to images, videos, html, and whatever else the heart desires.

Let’s jump into our quite simple ERC721C `_mint()` implementation. Minting one NFT costs 29,828 units of gas.

        function _mint(address to, uint256 id) internal virtual {
            require(to != address(0), "INVALID_RECIPIENT");
    
            require(ownerOf[id] == address(0), "ALREADY_MINTED");
    
            ownerOf[id] = to;
    
            emit Transfer(address(0), to, id);
        }
    

As you can see, we do some basic checks, which we chose not to remove as you may need them, even if someone else’s contract may not. Then we update the owner of the token and emit the Transfer event. Now the user can interface with the token, just like they would _almost_ any other ERC721.

One element to consider when implementing ERC721C is the goals of your NFT. When building large, NFT-centric communities, `balanceOf` may be useful to build token-gated access. Functional NFTs such as Uniswap LP positions on the other hand, would benefit greatly from the reduced gas costs, increasing accessibility of the protocol.

---

*Originally published on [Chuba](https://paragraph.com/@itsover/we-do-a-little-minting-erc721c)*
