How to create an ERC721 Solidity smart contract

In this tutorial we will explain how to create an ERC721 Solidity smart contract. First we will review differences between an ERC20 and ERC721. Then we will create two ERC721 NFT contracts.

There are many differences between an ERC20 and an ERC721 Ethereum token contracts. ERC20 contract create identical tokens that do not have characteristics to make them unique. Tokens from an ERC20 contract are fungible and are exchanged one for one. It does not matter which one you buy or sell because they are all the same. An ERC721 contract is used to create unique tokens or NFTs (non fungible tokens). Tokens from the same ERC721 contract are unique and can not be duplicated because each token has a unique id. This means each token from the same contract can have a different value or characteristic due to its age, rarity or other attribute.

ERC721 Contract

ERC721 tokens supports many of the same features as ERC20 tokens. Both of these token contracts support many of the same types of functions (transfer, approve, get total supply, etc.). In addition just like an ERC20 contract an ERC721 contract requires basic metadata as an example name and symbol are required when creating a contract.

ERC721 tokens have a few characteristics that are not found in an ERC20 token. Every ERC721 token minted from a contract can have a unique id. Think of this unique id like the number on a 1 out of 200 baseball card. Every ERC721 token minted can include a URI (a link to something). A URI or Uniform Resource Locator is an identifier for a specific resource file for example a picture, book, or document. These URI’s are usually pointers on IPFS (Inter Planetary File System).

Example ERC721 NFT smart contracts with URI

The Solidity code below is an ERC721 smart contract. You can use this contract to mint NFT tokens. In the contract below when you call the create NFT function you can pass in a URI to associate it with the NFT that you mint. So if you have a URI on IPFS that links to a picture you can include it in the contract below. The contract is extendable and could contain additional functions. Read the code comments to get a better understanding of how the contract works.

pragma solidity ^0.6.6;


import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC721/ERC721.sol";


//this contract inherits ERC721
contract SampleNFTContract is ERC721 {
    uint256 public tokenCounter;
    
    
    //constructor for an ERC721 is a name and symbol
    constructor () public ERC721 ("astronaut", "STAR"){
        tokenCounter = 0;
    }

    //a token url is a ipfs url
    //after we mint the token we are going to return the id of the token
    function createNFT(string memory tokenURI) public returns (uint256) {

    //get number from token counter
        uint256 newNFTTokenId = tokenCounter;

    //safely mint token for the person that called the function
        _safeMint(msg.sender, newNFTTokenId);
    
    //set the token uri of the token id of the uri passed
        _setTokenURI(newNFTTokenId, tokenURI);
    
    //increment the counter
        tokenCounter = tokenCounter + 1;
        
    //return the token id
        return newNFTTokenId;
    }

}

Try it in Remix

Example ERC721 NFT smart contracts with characteristics

In programming there are many ways to implement a solution so now lets look at a different NFT smart contract implementation.

In the ERC721 smart contract below you can create an NFT that can have a trait or specific characteristic (example; red, tall, fast, strong, anything). Maps store NTF traits. The map is checked every time a new NFT is minted to prevent duplicate tokens from being created. This prevents tokens from having the same traits or characteristics.


pragma solidity 0.5.0;

import "./ERC721Flattened.sol";

contract Astronaut  is ERC721Full {
  
  //create an array of traits to keep track of different traits
  //no traits can be the same
  string[] public trait;
  mapping(string => bool) _traitExists;

    //constructor for an ERC721 is a name and symbol
  constructor() ERC721Full("astronaut", "STAR") public {
  }

  
  //create a new token by calling the mint function
  //every token needs to be different
  //need to pass in a trait that does not exist
  function createNFT(string memory _trait) public {
    
    //check the mapping to determine if trait exists
    require(!_traitExists[_trait]);
    
    //if trait does not exist mint token and create a new token id
    //mint for the msg.sender
    //add trait to array and set trait in mapping to true
    uint _id = trait.push(_trait);
    _mint(msg.sender, _id);
    _traitExists[_trait] = true;
  }

}

Try it in Remix

The best way to learn how a NFT works is to experiment and create a smart contract in Remix. Take these contracts to the next level and add your creativity. Extend these contracts to:

  • Allow for multiple traits
  • Implement a Chainlink oracle to generate a truly random number and have the number represent a characteristic (value, strength, speed, etc)
  • Create a website so visitors can mint their own NFTs.
  • Combine the two contracts above so your NFT can have a URI and traits

ERC721 contracts support many different use cases from document ownership to issuing domain names.

This code is for learning and entertainment purposes only. The code has not been audited. Use at your own risk. Remember smart contracts are experimental and could contain bugs.

Add a custom image or logo to your token

Click here for more information about how to use the Ethereum test network and how to obtain test ETH.

Next Review – How to swap tokens on Uniswap using a smart contract

2 thoughts on “How to create an ERC721 Solidity smart contract

Leave a Reply