Objectives
By the end of this lesson you should be able to:- Analyze the anatomy of an ERC-721 token
- Compare and contrast the technical specifications of ERC-20 and ERC-721
- Review the formal specification for ERC-721
- Build and deploy an ERC-721 compliant token
- Use an ERC-721 token to control ownership of another data structure
Implementing the OpenZeppelin ERC-721 Token
JPGs may be all the rage right now but in the future, the selfie you post on social media, a text message you send to your mother, and the +4 battleaxe you wield in your favorite MMO might all be NFTs.Import and Setup
Start by opening the OpenZeppelin ERC-721 in Github. Copy the link and use it to import the ERC-721 contract. Create your own contract, calledMyERC721
, that inherits from ERC721Token
. Add a constructor that initializes the _name
and _symbol
.
Reveal code
Reveal code
Minting NFTs
The minting function that is provided by OpenZeppelin,_safeMint
, is internal
. To use it to let your customers mint NFTs, you’ll need to implement a function in your contract that calls the one in the imported contract.
Before you can do that, you need a way to supply the two parameters needed for _safeMint
:
address to
- the owner of the new NFTuint256 tokenId
- the ID number for the new NFT
msg.sender
to grant ownership to the wallet doing the minting.
ID is slightly more challenging. A common practice is to simply assign the total number of NFTs, including the one being minted, as the tokenId
. Doing so is straightforward, makes it easier to find all of the NFTs within a collection, and helps lean in to the common community perception that lower-number NFTs are better, just like other limited-edition collectibles.
Obfuscating certain information, such as customer IDs, is often considered a best practice. Doing so might make it harder for an attacker who has circumvented other security functions from getting access to more data. If
134
is a valid customer_id
, it is likely that 135
is too. The same can’t be said for bfcb51bd-c04f-42d5-8116-3def754e8c32
.This practice is not as useful on the blockchain, because all information is public.uint
called counter
to storage and initialize it as 1, either at declaration or in the constructor.
Now, you can add a function called redeemNFT
that calls safeMint
using the msg.sender
and counter
, and then increments the counter
:
Reveal code
Reveal code
As a programmer, you’ve probably gone through great pains to internalize the idea of zero-indexing. Arrays start at 0. The pixel in the top-left corner of your screen is located at 0, 0.As a result, you need to be very careful when working with Solidity because there isn’t the concept of
undefined
, and “deleted” values return to their default value, which is 0 for numbers.To prevent security risks, you’ll need to make sure that you never give an ID or array index of 0 to anything. Otherwise, attempting to delete a value, such as a struct
member called authorizedSellerID
might give the wallet address stored at index 0 access to that resource.- Mint several NFTs
- Transfer an NFT from one Remix account to another
- Try to transfer an NFT to
0x0000000000000000000000000000000000000000
ERC-721 URIs
The ERC-721 standard includes the option to define a URI associated with each NFT. These are intended to point to ajson
file following the ERC721 Metadata JSON Schema
_baseURI
is virtual
and must be overridden by an inheriting contract.
NFT Switcheroo
Doodles is another NFT collection that uses IPFS to store metadata. Let’s modify our contract to swap metadata back and forth from one collection to the other. Start by saving the IPFS metadata bases as constants, at the contract level. Add an enum to enable selection between these two choices, and an instance of that enum.Reveal code
Reveal code
_baseURI
that returns the appropriate selection based on which collection is active, and a function to swap the URI.
Reveal code
Reveal code
tokenURI
to find the information for token number 1. You should get:
switchURI
function and then call tokenURI
again for token 1.
Now, you’ll get a new link for metadata: