DEV Community

Cover image for Understanding ERC721: Non-Fungible Tokens
Nicholas
Nicholas

Posted on

Understanding ERC721: Non-Fungible Tokens

Introduction
In the realm of blockchain technology, tokens serve as digital representations of assets. While ERC20 tokens facilitate fungible assets, ERC721 tokens cater to non-fungible assets, where each token is unique. This uniqueness is crucial in domains such as real estate, digital collectibles, and gaming assets, where items possess varying values based on factors like rarity or utility. This article delves into the ERC721 standard, elucidating its significance, structure, and implementation.

What is ERC721
ERC721, short for Ethereum Request for Comments 721, is a standard interface for non-fungible tokens (NFTs) on the Ethereum blockchain. Unlike ERC20 tokens, where each token is interchangeable, ERC721 tokens are distinct entities with individual properties, making them ideal for representing ownership of unique assets.

Understanding ERC721 Contracts
ERC721 is a more intricate standard compared to ERC20, comprising multiple optional extensions and being divided across various contracts. The OpenZeppelin Contracts library offers a comprehensive suite of ERC721-compliant contracts, providing developers with flexibility in combining these contracts and incorporating custom extensions tailored to specific use cases.

Code Implementation
Below is a simplified implementation of an ERC721 token using OpenZeppelin Contracts in Solidity:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyNFT is ERC721, Ownable {
    constructor() ERC721("MyNFT", "MNFT") {}

    function mint(address to, uint256 tokenId) public onlyOwner {
        _safeMint(to, tokenId);
    }
}
Enter fullscreen mode Exit fullscreen mode

The code defines a contract named MyNFT, inheriting from ERC721 and Ownable contracts.

The constructor initializes the ERC721 token with the name "MyNFT" and symbol "MNFT".

The mint function allows the contract owner to create new NFTs and assign them to specific addresses.
Here are some ERC721-compliant contracts provided by the OpenZeppelin Contracts library:

ERC721.sol
This contract implements the core ERC721 standard, providing functions for token creation, transfer, and ownership management. It serves as the foundational building block for ERC721-compliant contracts.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract MyERC721 is ERC721 {
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
Enter fullscreen mode Exit fullscreen mode

ERC721Enumerable.sol
Extends ERC721 with enumeration capabilities, allowing enumeration of all token IDs within the contract. This is useful for scenarios where enumeration of tokens is required, such as displaying all available tokens.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

contract MyERC721Enumerable is ERC721Enumerable {
        constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
Enter fullscreen mode Exit fullscreen mode

ERC721Metadata.sol
Extends ERC721 with metadata capabilities, enabling each token to have associated metadata such as name, symbol, and URI. This is essential for providing additional information about each token, facilitating better user experience and interoperability.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Metadata.sol";

contract MyERC721Metadata is ERC721Metadata {
    constructor(string memory name, string memory symbol, string memory baseURI) ERC721Metadata(name, symbol) {
        _setBaseURI(baseURI);
    }
}
Enter fullscreen mode Exit fullscreen mode

ERC721URIStorage.sol
Provides a storage abstraction for token URIs, allowing token metadata URIs to be stored separately from the contract logic. This separation enhances gas efficiency by avoiding redundant storage of metadata on-chain.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract MyERC721URIStorage is ERC721URIStorage {
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
Enter fullscreen mode Exit fullscreen mode

ERC721Burnable.sol
Adds burn functionality to ERC721 tokens, allowing token owners to burn (destroy) their tokens irreversibly. This feature is useful for implementing token redemption or token destruction mechanisms.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";

contract MyERC721Burnable is ERC721Burnable {
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
Enter fullscreen mode Exit fullscreen mode

ERC721Pausable.sol
Introduces pausable functionality to ERC721 tokens, enabling contract owners to pause and unpause token transfers. This is beneficial in situations where temporary suspension of token transfers is necessary, such as during security audits or emergency situations.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";

contract MyERC721Pausable is ERC721Pausable {
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
Enter fullscreen mode Exit fullscreen mode

ERC721Receiver.sol
Defines the interface for contracts that wish to receive ERC721 tokens. Contracts implementing this interface can handle incoming ERC721 token transfers securely and efficiently.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

contract MyERC721Receiver is IERC721Receiver {
    function onERC721Received(address, address, uint256, bytes memory) external override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}
Enter fullscreen mode Exit fullscreen mode

These contracts, when combined and customized as needed, offer developers a robust foundation for creating ERC721-compliant smart contracts tailored to specific use cases.

Conclusion
ERC721 tokens play a pivotal role in representing ownership of unique assets on the Ethereum blockchain. With its flexibility and extensibility, developers can leverage the ERC721 standard to tokenize a wide array of non-fungible assets, ranging from digital art to real estate properties. By understanding the structure and implementation of ERC721 contracts, developers can unlock a myriad of possibilities in the realm of decentralized ownership and digital asset management.

Top comments (0)