Understanding the ERC721 Token¶
Before we start with the actual implementation, let's get the elephant in the room out of the way: understanding the ERC721 token.
In a sentence, the ERC721 is an ERC20 token where each token has a unique ID and can have an URL for more MetaData.
It actually has its roots in real estate deeds. A big misconception is that NFT MetaData should be immutable. But the initial idea was that the Token itself, the logic to mint, transfer and potentially even burn tokens, is in a Smart Contract. But the MetaData - so, who owns the building - is changeable. Or can be even extended.
That's why a good practice is to put the MetaData, which is just a regular json file, somewhere on a regular host.
But more on that in a minute.
The initial token standard came from the Ethereum Request for Comments number 721 and simply summarizes it as "A standard interface for non-fungible tokens, also known as deeds."
The Token ID¶
The simplest method to determine the token ID is to increment a counter when a new token is minted. But you don't have to do it this way. The only requirement is that the each token is represented by a unique uint256 value. If you increment by one or two or count down is up to you, as long as the token ID is a unique uint256 in your contract.
MetaData¶
Each NFT contract can optionally add the MetaData extension. In reality, most have. The extension defines that a json file is downloaded at a specific URI.
The content for that json file can look something like this for example:
{
"title": "Asset Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this NFT represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this NFT represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
}
}
}
If you'd deploy an ERC721 token that points to this MetaData and you look at it on OpenSea, you'd see the content parsed.
Example Token¶
Let's have a look at an existing example. Take Token #4 from the RTFKT Collection:
Besides the price, you see three things here:
The Animation or a Picture A Description A couple of properties Where do they come from? Let's check out Etherscan...
If you query the tokenUri for Token #4 On Etherscan then you'd see an ipfs url pointing to a json file:
Now, you don't know what's IPFS yet, because we haven't talked about it. It's a decentralized file storage and all you need to know at this point is that it can host files. But how can you access IPFS files? There are two major ways:
You install the IPFS daemon and can browse files locally You use an IPFS gateway. If you open the file on an IPFS Gateway, like the one from ipfs.io: https://ipfs.io/ipfs/QmU1CNuwJZTxc6FZqKLsUPVjPrR1Fg2U79sNDYQozpBj7w/genesis/4.json, you see the following json file:
{
"name": "CLONE X Genesis Socks 🧬",
"description": "CLONE X FORGING SEASON 1 🧬⚒️\n\nIntroducing the future of Fashion.\n\nRTFKT invented the world merging Forging mechanic, allowing its collectors to redeem exclusive physical products from NFTs.\n\nToday RTFKT takes Forging to the next level with Clone X Forging. ⚒️\n\n10 unique Brands and bespoke fashion collections for Clone X Holders. Each brand will be accessible for Clone X holders based on the DNA of the Clone they own. 🧬🌸\n\nSee the full collection: [http://lookbook.rtfkt.com](http://lookbook.rtfkt.com) 👀\n\n*Not equipped with NFC Tag 🔗.\n\nDigital Collectible terms and conditions apply, see [https://rtfkt.com/legal-2D](https://rtfkt.com/legal-2D) 👨⚖️\n\nDigital Collectible: Wearable & Forging-Eligible (this 1155 Token will be swapped for a 721 Token when forging)\n\nForging terms apply, see: [https://rtfkt.com/legal-1B](https://rtfkt.com/legal-1B) 👨⚖️",
"image": "ipfs://QmWpbme9ECzeNZDbpe5kJKRmiL6WhKGJJZ9RbHb5ioLeHD/genesis/4.webp",
"animation_url": "ipfs://QmWpbme9ECzeNZDbpe5kJKRmiL6WhKGJJZ9RbHb5ioLeHD/genesis/4.mp4",
"external_url": "https://rtfkt.com",
"attributes": [
{
"trait_type": "Artefact",
"value": "Socks"
},
{
"trait_type": "Collection",
"value": "Genesis"
}
]
}
Compare this to the sample MetaData Schema from above and the screenshot from OpenSea.
At this point you might be a bit disappointed how simple NFTs are?!
Let's do our own NFT now. If you think this was actually not so complicated until here, it gets even easier...
Prototype in Remix¶
Before we get started with Truffle, Hardhat and Foundry, I still want to prototype the Smart Contract in Remix quickly.
We're going to create a limited edition of Space Teddybears. I used DALL-E to create 4 cute teddybears floating in space, and I have uploaded them including a json to a subfolder here, so you don't need to find a hoster for images and json files. But you could, for example, either use github (github pages), or Pinata for IPFS hosting json and image files (as the RTFKT collection does).
The Smart Contract is not the show of this section, so its good to have it covered quickly.
Let's open the OpenZeppelin Wizard and create a Teddybear Token:
Select the ERC721 Token. Then
- Set the Name and Symbol as "Spacebear" and "SBR"
- Set the Base-URI as "https://ethereum-blockchain-developer.com/2022-06-nft-truffle-hardhat-foundry/nftdata/"
- Check Mintable with Auto-Increment IDs. So every time you mint a token it gets a new number.
- Enable URI Storage, so your token URIs for MetaData are not the token-ID but can be different. You'll see in a second why.
I have prepared a JSON for your first four tokens on this site, so this can be used without uploading it to any github pages or S3 or IPFS:
{
"name": "Spacebear Token 🧸",
"description": "Introducing the future of Cuteness. A Teddybear Token. Floating in Space. Save them by getting this NFT. Cuddle each one of them. You need them. Buy them now. Also, they are coming from ethereum-blockchain-developer.com",
"image": "https://ethereum-blockchain-developer.com/2022-06-nft-truffle-hardhat-foundry/nftdata/spacebear_1.webp",
"external_url": "https://ethereum-blockchain-developer.com",
"attributes": [
{
"trait_type": "Artefact",
"value": "Teddybear"
},
{
"trait_type": "Collection",
"value": "Genesis"
}
]
}
Deploy and See on OpenSea¶
Using Test-Networks is a bit tricky, but we can go ahead and deploy the token either on Görli or Ropsten and then look on OpenSea at the token.
Deploy your ERC721 Token.
Then mint one token with the uri being "spacebear_1.json", so it will resolve to "https://ethereum-blockchain-developer.com/2022-06-nft-truffle-hardhat-foundry/nftdata/spacebear_1.json".
Once the ERC721 Token is deployed to Rinkeby or Görli (I deployed it here to three test-networks, Rinkeby, Ropsten and Görli), you can actually open the address and the token on opensea-testnet to check if it looks ok. Caveat: Görli did work only half on Opensea and Rinkeby will be deactivated in the future. So, if NFTs are not showing up correctly, just understand, the testnet site isn't as maintained as the production version. Our token here is this one: https://testnets.opensea.io/assets/rinkeby/0x363dc339dd9c9cc72d2badb17732d120dbfaf103/0
and
https://testnets.opensea.io/assets/goerli/0x62c8e878d5df2e500989181bd760542ee468aea2/0
As the ERC721 Contract owner, you can also setup your collection on Opensea, give it a description and logo, banner and so on, but that's beyond of the scope of this tutorial.
There is one more thing, before wrapping it up. You can also have secondary sales commissions and they don't work in a standardized way. If you are getting serious about NFTs, then checkout my other mini course on Secondary Sales commissions in the Mini-Course section on ethereum-blockchain-developer.com.
Now, let's bring our Token offline to Truffle!