ERC721A Contract Example: A Step-by-Step Guide to Implementing an Advanced NFT Contract

By Brad Jaeger  - Director of Content
6 Min Read

If you’re venturing into the world of Non-Fungible Tokens (NFTs), you’ve probably come across the term ERC721A contract. An evolution of the original ERC721 standard, ERC721A contracts offer additional features and improvements that make them ideal for creating and managing NFTs in various industries. In this article, we’ll provide a detailed example of an ERC721A contract and walk you through the steps to implement one for your own NFT project.


Understanding the ERC721A Contract

Before diving into the example, it’s essential to understand what makes ERC721A contracts different from their predecessor, the ERC721 standard. ERC721A is an extension of the original ERC721, incorporating improvements and additional functionality, such as:

  1. Batch Transfers: ERC721A enables batch transfers, which means multiple NFTs can be transferred simultaneously, reducing the overall gas cost and enhancing the efficiency of your NFT project.
  2. Token Metadata Extensions: ERC721A supports token metadata extensions that allow for easier management and retrieval of metadata, simplifying the process of updating and maintaining your NFT collection.
  3. Enumerable Interface: The ERC721A contract includes an enumerable interface, providing a straightforward way to list and track the tokens within the contract, making it easier to manage and organize your NFT collection.

    Now that we have a clear understanding of the benefits of ERC721A, let’s dive into the example.

ERC721A Contract Example

In this section, we’ll provide an example of an ERC721A contract written in Solidity, the programming language used for Ethereum smart contracts. The contract will include the essential features and improvements mentioned above. We’ll break down the code into sections, explaining each part as we go along.

Please note that this example is for educational purposes only and should not be used as-is for a live NFT project. You should consult with a professional developer to create a customized, secure, and fully functional ERC721A contract for your specific use case.

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFT is ERC721Enumerable, Ownable {
    using Strings for uint256;

string public baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.05 ether;
uint256 public maxSupply = 10000;
uint256 public maxMintAmount = 20;
bool public paused = false;

constructor() ERC721("MyNFT", "MNFT") {
    setBaseURI("https://ipfs.io/ipfs/");
}

// Setters
function setCost(uint256 _newCost) public onlyOwner() {
    cost = _newCost;
}

function setMaxMintAmount(uint256 _newMaxMintAmount) public onlyOwner() {
    maxMintAmount = _newMaxMintAmount;
}

function setBaseURI(string memory _newBaseURI) public onlyOwner() {
    baseURI = _newBaseURI;
}

function setBaseExtension(string memory _newBaseExtension) public onlyOwner() {
    baseExtension = _newBaseExtension;
}

function pause(bool _state) public onlyOwner {
    paused = _state;
}

// Getters
function _baseURI() internal view virtual override returns (string memory) {
    return baseURI;
}

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    _require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");string memory currentBaseURI = _baseURI();
    return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension)) : "";
}

// Minting Functions
function mint(uint256 _mintAmount) public payable {
    uint256 supply = totalSupply();
    require(!paused, "Minting is paused");
    require(_mintAmount > 0, "Mint amount must be greater than 0");
    require(_mintAmount <= maxMintAmount, "Cannot mint more than the maximum allowed");
    require(supply + _mintAmount <= maxSupply, "Exceeds maximum supply");

    if (msg.sender != owner()) {
        require(msg.value >= cost * _mintAmount, "Ether value sent is not correct");
    }

    for (uint256 i = 1; i <= _mintAmount; i++) {
        _safeMint(msg.sender, supply + i);
    }
}

function mintTo(address _to, uint256 _mintAmount) public onlyOwner() {
    uint256 supply = totalSupply();
    require(_mintAmount > 0, "Mint amount must be greater than 0");
    require(supply + _mintAmount <= maxSupply, "Exceeds maximum supply");

    for (uint256 i = 1; i <= _mintAmount; i++) {
        _safeMint(_to, supply + i);
    }
}

function withdraw() public payable onlyOwner {
    require(payable(msg.sender).send(address(this).balance));
}

Implementing the ERC721A Contract

Now that we’ve gone through the example, let’s discuss how to implement the ERC721A contract for your own NFT project. Here are the essential steps to follow:

  1. Customize the Contract: Modify the example contract to suit your specific NFT project, adjusting parameters such as the token name, symbol, maximum supply, and minting cost.
  2. Deploy the Contract: Use a development environment such as Remix, Truffle, or Hardhat to compile and deploy your customized contract to the Ethereum network.
  3. Interact with the Contract: Once deployed, you can interact with your contract using popular web3 libraries like Web3.js or Ethers.js to create, manage, and transfer your NFTs.

Conclusion

The ERC721A contract offers several improvements over the original ERC721 standard, making it an excellent choice for NFT projects that require additional features and optimizations. By understanding the differences and using the provided example as a starting point, you can implement an advanced NFT contract tailored to your project’s specific needs.

Share this Article
By Brad Jaeger Director of Content
Follow:
Director of Content. Encouraging everyone to join web3. Father, husband, dad joke teller. 333🦉 bradjaeger.eth.