Reader small image

You're reading from  Mastering Blockchain Programming with Solidity

Product typeBook
Published inAug 2019
Reading LevelIntermediate
PublisherPackt
ISBN-139781839218262
Edition1st Edition
Languages
Concepts
Right arrow
Author (1)
Jitendra Chittoda
Jitendra Chittoda
author image
Jitendra Chittoda

Jitendra Chittoda is a blockchain security engineer at ChainSecurity. His day job is to perform security audit on smart contracts and expose security vulnerabilities in Solidity and Scilla contracts. He has also developed a non-custodial, decentralized, P2P lending contracts for ETHLend. The Solidity contracts that he has developed or audited handle over $100 million worth of cryptoassets. He also served as a tech and security advisor in various ICO projects. Before finding his passion for blockchain, he coded in Java for over 11 years. He is the founder and leader of Delhi-NCR-JUG, a non-profit meetup group for Java. He holds a master's degree in computer applications and is regularly invited as a speaker at various conferences and meetups.
Read more about Jitendra Chittoda

Right arrow

ERC721 Non-Fungible Token Standard

We looked into the ERC20 token standard in Chapter 7, ERC20 Token Standard. ERC20 is a fungible token standard; however, ERC721 is a Non-Fungible Token (NFT) standard. This standard is used in many cases where you want to transfer a whole item that cannot be broken into multiple parts, for example, a house deed or collectible cards. These items are non-fungible as these represent a whole entity and cannot be sub-divided into multiple pieces. For example, a collectible card in itself is a whole entity and has some economic value.

In this chapter, we will have a look into the ERC721 standard functions and its implementation in detail. We will also look into optional ERC721 metadata and enumeration-related interfaces and implementation.

We will cover the following topics in this chapter:

  • Overview of the ERC721 non-fungible token...

Technical requirements

Overview of the ERC721 NFT standard

In Chapter 7ERC20 Token Standard, we looked into the ERC20 token standard, which is the standard that's mostly used for minting and transferring the tokens. However, the ERC20 token standard has a state variable, decimals, and by using that variable, each token of the token contract can be fungible to the defined number of decimal places. For example, an ERC20 token with 18 decimal places would enable each of its minted tokens to be fungible up to 18 decimal places. The Solidity language does not support decimal or floating data types; hence, one full unit of a token will have 18 zeros followed by 1, which we can also refer to as 118 or 10 * 18.  These tokens are also identical to each other, which means that one token is equal to another token. For example, if there are two people who both have 1 OmiseGo...

The ERC721 NFT standard API interface

The specification of the ERC721 standard interface that we are discussing in this section is taken from the EIP standard document at https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md.

The ERC721 NFT standard interface is defined as follows:

interface ERC721 is ERC165 {
event Transfer(address indexed _from, address indexed _to,
uint256 indexed _tokenId);

event Approval(address indexed _owner, address indexed _approved,
uint256 indexed _tokenId);


event ApprovalForAll(address indexed _owner, address indexed _operator,
bool _approved);

function balanceOf(address _owner) external view returns (uint256);

function ownerOf(uint256 _tokenId) external view returns (address);

function safeTransferFrom(address _from, address _to,
...

Understanding the ERC721 implementation

As we have seen the ERC721 standard interface, now let's look at the ERC721 basic implementation. Here, for the implementation, we are going to use the code provided in Zeppelin's openzeppelin-solidity 2.1.1 release. However, developers must keep checking for new releases of the OpenZeppelin project to ensure that any bug fixes or gas improvements are updated in the latest code. You can always check for latest releases and the included bug fixes of OpenZeppelin on https://github.com/OpenZeppelin/openzeppelin-solidity/releases.

We will look into the following in this section:

  • State variables used in the ERC721 implementation
  • The different functions of ERC721 and their implementation
  • Internal functions provided by OpenZeppelin's ERC20 implementation
  • Events present in the ERC721 implementation and their usage

The...

Events

The ERC721 standard has mainly three events, Transfer, Approval, and ApprovalForAll. These events are emitted from the different function calls of the ERC721 implementation, as we have seen in the ERC721 implementation section. For example, the _mint() function triggers the Transfer event upon successful execution of the function.

The Transfer event is triggered when any token-transfer-related function is called. However, for approvals, there are two types of approval an owner can give:

  • Single Token Approval: The owner of the token gives approval for a single NFT to another address. This triggers the Approval event.
  • Operator Approval: The owner can give access to all of the tokens they own to an operator. This triggers the ApprovalForAll event.

As the blockchain is a series of transactions, the events are also stored along with the transaction...

The ERC721TokenReceiver interface

As the name suggest, the ERC721TokenReceiver interface is to receive the callback for an ERC721 NFT. If you are writing a contract that would receive some NFTs, the ERC721TokenReceiver interface may be inherited in your contract. So, it would enable your contract to get a callback function call from the ERC721 NFT contract to your contract. When someone transfers an ERC721 NFT to your contract, you would receive the callback call to the onERC721Received() function, and you would be able to perform some action accordingly. However, the pre-requisite for this callback is that the ERC721 token sender must call the safeTransferFrom() function present on the ERC721 implementation.

If your receiving contract does not inherit from the ERC721TokenReceiver contract and does not have the onERC721Received() function...

The ERC721Metadata interface

The ERC721Metadata interface is an optional interface to add other metadata details to your ERC721 NFTs. The developers can choose to add a token name, a token symbol, and a token URI as metadata to an ERC721 token. If they want to use these metadata fields for their token, they can use the ERC721Metadata contract; otherwise, they can ignore this. The interface provides the following view functions:

  • name(): The function returns the full name of the ERC721 NFT as a string datatype.
  • symbol(): The function returns the token symbol of the ERC721 NFT as a string datatype.
  • tokenURI(): The function returns the Uniform Resource Identifier (URI) as a string datatype. The URI may contain a location to a JSON file. The JSON schema file is present on GitHub,  at https://github.com/PacktPublishing/Mastering-Solidity/blob/master...

The ERC721 enumerable

The ERC721Enumerable interface is an optional interface for adding more features to the ERC721 NFT.

The interface defines the following view functions:

  • totalSupply(): The function returns the total number of NFTs issued by the contract that are not burned. Also, each token has a valid owner address that is not address(0).
  • tokenByIndex(): The function returns the tokenId of an NFT that is stored at the provided index.
  • tokenOfOwnerByIndex(): The function returns the tokenId of an NFT that is stored at a particular index of the owner's list of tokens.

Let's look at the ERC721Enumerable interface code:

interface ERC721Enumerable is ERC721 {
function totalSupply() external view returns (uint256);
function tokenByIndex(uint256 _index) external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index...

The ERC721 full implementation

In an ERC721 NFT full implementation, the basic ERC721 functions and events are supported. It also supports the features of the ERC165ERC721Enumerable, and ERC721Metadata contracts. The full implementation in the OpenZeppelin library is defined as follows in the ERC721Full.sol file:

import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./ERC721Metadata.sol";

contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
constructor (string memory name, string memory symbol)
public
ERC721Metadata(name, symbol)
{
}
}

As shown in the preceding code, ERC721Full inherits from the implementations of ERC721ERC721Enumerable, and ERC721Metadata.

Summary

In this chapter, we have seen the ERC721 NFT standard, which is a bit different from the ERC20 token standard. Both the ERC20 and ERC721 standards serve different purposes and applications. ERC20 should be used when you need fungible tokens and each token has the same economic value. However, the ERC721 token should be used when you would need each token to be unique, and each of them can have different economic values. 

We have seen the ERC721 NFT standard implementation that the OpenZeppelin 2.1.1 library provides. As a developer, you must keep checking the OpenZeppelin library for any recent fixes or improvements to the ERC721 source code. There are many other libraries and contract files that OpenZeppelin provides, which we will have a deeper look into in the next chapter.

Questions

  1. What is the use of the ERC165 standard?
  2. Where should the ERC721 NFT standard be used?
  3. Why are the _mint() and _burn() functions present in the ERC721.sol file?
  4. Are there any advanced token standards for non-fungible tokens?
  5. Why isn't there a transfer() function in ERC721 like the one in the ERC20 standard?
  6. How can we find out whether a new token has been minted, or an existing token has been burned, using the Transfer event?
  7. Why is there a bytes data parameter present in the IERC721Receiver.onERC721Received() function?
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Mastering Blockchain Programming with Solidity
Published in: Aug 2019Publisher: PacktISBN-13: 9781839218262
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Jitendra Chittoda

Jitendra Chittoda is a blockchain security engineer at ChainSecurity. His day job is to perform security audit on smart contracts and expose security vulnerabilities in Solidity and Scilla contracts. He has also developed a non-custodial, decentralized, P2P lending contracts for ETHLend. The Solidity contracts that he has developed or audited handle over $100 million worth of cryptoassets. He also served as a tech and security advisor in various ICO projects. Before finding his passion for blockchain, he coded in Java for over 11 years. He is the founder and leader of Delhi-NCR-JUG, a non-profit meetup group for Java. He holds a master's degree in computer applications and is regularly invited as a speaker at various conferences and meetups.
Read more about Jitendra Chittoda