The emergence of ERC-6551 marks a significant milestone in the domain of non-fungible tokens (NFTs), potentially revolutionizing digital ownership. ERC-6551 introduces innovative features that could redefine the concept of NFTs and expand their applications. This guide aims to provide a comprehensive understanding of the standard and how it enhances NFT functionality.

ERC-6551 is a novel NFT standard developed on the Ethereum blockchain, which allows NFTs to function as smart contract wallets. Essentially, it enables NFTs to store additional tokens and other NFTs, facilitating interaction with other smart contracts. Later in this guide, we’ll walk through a step-by-step implementation of creating an ERC-6551 account.

Prerequisites

  • Basic understanding of ERC-1155 and ERC-721.

  • Familiarity with Ethereum and smart contracts.

  • Development environment setup: Remix and Metamask.

  • Testnet Token, e.g., Sepolia testnet (available here).

Why ERC-6551

The introduction of ERC-6551 is not just a development; it's a response to a set of challenges posed by its predecessor, ERC-721. To fully grasp the significance of ERC-6551, it's essential to understand why it was created and the limitations it aims to overcome.

Exploring ERC-721 Limitations

ERC-721, while revolutionary in its own right, had inherent limitations that became increasingly apparent as the NFT space evolved. While ERC-721 NFTs effectively proved ownership of digital items on the blockchain, they fell short in offering support for easy composability with other tokens and smart contracts. Their utility is relatively isolated. They essentially serve as a link between the asset and its owner's account without a broader context. Today, the demand for NFTs with enhanced features has become increasingly apparent.

Introduction of ERC-6551

ERC-6551 was introduced as a forward-looking solution to address these challenges. This new standard is like a game changer in the NFT space, aiming to transform the way we perceive and utilize digital assets. It allows NFTs to function as smart contract wallets.

ERC-6551 enables NFTs to store not only additional tokens but also other NFTs, much like a standard smart contract wallet. This means NFTs can become multifunctional, with the capacity to communicate with other smart contracts, thereby expanding their use cases. The introduction of ERC-6551 significantly broadens the horizons of what NFTs can achieve.

Use Cases of ERC-6551

ERC-6551, with its capacity to transform NFTs into smart contract wallets, triggers a range of exciting use cases across the blockchain landscape. Let’s explore some possible use cases:

On-Chain Gaming

The gaming industry has been quick to embrace NFTs, and ERC-6551 takes this to the next level. In on-chain gaming, ERC-6551 allows NFTs to serve as dynamic in-game assets that can hold not only the game item itself but also interact with various in-game smart contracts. For example, an in-game character's NFT can own and interact with weapons and even blockchain currency within the game world. This creates a dynamic gaming experience where in-game assets are truly owned and can have additional utility, enhancing the player's

On-Chain Investment

ERC-6551 introduces a novel approach to creating on-chain investment portfolios. NFTs can represent unique investment assets, and these assets can be further diversified and managed within the NFT itself. For instance, an NFT can embody a digital art collection and also own multiple ERC-20 tokens representing investments in various DeFi protocols. This offers an innovative way for investors to manage their portfolios while maintaining a clear record of ownership and diversified holdings within a single NFT. The composability of ERC-6551 NFTs with other smart contracts allows for automated portfolio management and real-time tracking of asset performance.

NFT Composability

Composability is a fundamental concept in the blockchain space, and ERC-6551 takes it to new heights. NFT composability refers to the ability of these tokens to interact with other NFTs and smart contracts seamlessly. For example, an ERC-6551 NFT representing a virtual real estate property can interact with other NFTs, like digital furniture or artwork, to create a fully furnished virtual living space. Furthermore, these NFTs can participate in DeFi protocols, allowing users to collateralize their NFTs to access loans or yield farming opportunities.

Architecture of ERC-6551

This diagram illustrates the interplay between NFTs, NFT holders, Token Bound Accounts, and the Registry.

Image Source

In the illustration provided, we can observe a system where ERC-721 tokens are owned by User Accounts. These ERC-721 tokens each have their dedicated accounts known as Token Bound Accounts. These accounts effectively function as secure repositories for a variety of assets, resembling traditional wallets. To initiate any operation within these accounts requires the User Account to trigger a transaction. The extent of an account's capabilities is determined by the implementation logic, which is maintained in a separate smart contract. This account, acting as a proxy, enables these functionalities. These Token Bound Accounts are not spontaneously generated; they are created through the Registry contract.

Let’s now explore the specific intricacies of the Registry and the Interface designed for Token Bound Accounts.

ERC-6551 Registry

The registry serves as a vital component in this system. Conceptually, it keeps track of NFTs (ERC-721 tokens) and their corresponding Token Bound Accounts. This registry is essentially a smart contract that can be deployed on any Ethereum Virtual Machine (EVM)-compatible blockchain. Its primary purpose is to establish a standardized framework for all Token Bound Account addresses, ensuring consistency and compatibility. Notably, it operates in a permissionless and immutable manner, devoid of any central ownership.

The Registry contract implements two core functions, which are:

  • createAccount: This function plays a pivotal role in generating Token Bound Accounts for specific NFTs. It requires several parameters, including the implementation address, chain ID, NFT address, token ID, salt, and init data. The chainId parameter is a crucial addition, as it permits the persistence of Token Bound Accounts across multiple blockchain networks. This logic empowers Token Bound Accounts to communicate effectively across different chains, ensuring their functionality remains intact even when transitioning between blockchains.

  • account: The second function, account, is responsible for computing the precise Token Bound Account address associated with an NFT. It utilizes the implementation address, chain ID, NFT address, token ID, and salt to generate this address.

ERC-6551 Account Implementation

The core functionality of the account implementation logic comprises several key functions:

  • executecall: The execute function serves a critical role in the logic. It first verifies whether the caller is authorized by utilizing the _isValidSigner function. Additionally, it checks that the operation argument passed is set to 0 and executes the specified amount of ether transfer alongside a function call. This function also maintains a record of function invocations by incrementing a state variable. In the event of a problematic call, the entire transaction is reverted, ensuring the integrity and security of the process.

  • owner: The owner function is responsible for returning the current owner of the particular ERC-721 token. It provides transparency regarding the ownership of the associated NFT.

  • isValidSigner: This function plays a pivotal role in verifying that the signer making the call is indeed the owner's address. It adds a layer of security to ensure that only authorized parties can execute functions.

  • isValidSignature: The isValidSignature function is designed to validate that the provided signature matches the one belonging to the owner. It further reinforces the security framework of the system.

  • token: The token function furnishes details about which ERC-721 token is linked to the Token Bound Account. This function provides clarity on the association between the Token Bound Account and the specific NFT.

Proxy Implementation

ERC-6551 utilized a customized ERC-1167 proxy implementation. This implementation is designed to store essential data, including the salt, chain ID, token contract address, and token ID. This data is ABI-encoded and then appended to the contract bytecode. The significance of this approach lies in its ability to enable Token Bound Account implementations to seamlessly access this data while maintaining its persistence.

Tutorial: How to Create an ERC-6551 Token Bound Account

By implementing a custom ERC-6551, you’ll learn how to:

  • Create an ERC-6551-compliant contract.

  • Deploy your contract to the Sepolia testnet using Remix.

  • Test your ERC-6551 (Token Bound Account) by interacting with it.

Without further ado, let’s dive in!

Step 1: Scaffolding the Project

Go to Remix IDE here. Next, on the remix interface in the top left corner, click on the file and create a new file. Here, we created three files. MyNft.sol, TokenBoundAccount.sol, and TokenRegistry.sol. Alongside these contracts, two interfaces were created IERC6551Registry.sol and IER6551Account.sol.

Step 2: Creating the Contracts

To start with, we’ll first implement the NFT contract, which allows us to mint an NFT that will have the Token Bound Account.

The pragma solidity statement specifies the version of the Solidity compiler to use. In this case, it's version 0.8.20.

Imports

  • ERC721.sol: This contract is for creating NFTs based on the ERC-721 standard. It allows us to inherit its functionalities to implement our NFT.

  • Ownable.sol: This contract provides functionality for ownership control, allowing an address to have special control over a contract.

Constructor

The constructor allows us to set the name and symbol for our NFT using the ERC-721 standard and makes the contract owned by the address that deploys it.

Functions

  • function safeMint(address to, uint256 tokenId) public onlyOwner: This function allows the owner to create and assign a new NFT to a specified address. It ensures that only the owner can call this function.

  • _baseURI() internal pure override: This is an internal function that overrides the base URI for the NFT. It returns a predefined URL pointing to an IPFS resource, where additional information about the NFT can be found.

Registry Contract

The registry contract is responsible for creating the Token Bound Accounts for our ERC-721 NFT.

Imports

  • Create2.sol: This imports a library from OpenZeppelin called Create2, which provides us utilities related to factory contract creation using the CREATE2 opcode.

  • IERC6551Registry.sol: This imports the interface from the IERC6551 interface we created. This defines a set of functions for the registry contract.

  • error InitializationFailed: This is a custom error that can be raised if an initialization process fails.

Functions

  • function createAccount(): This function is used to create a Token Bound Account. It takes six arguments, which include the implementation contract, chain ID, token contract address, token ID, and salt value.

  • implementation: This is the address of the deployed smart contract that will serve as the template for creating new Token Bound Accounts.

  • chainId: This represents the ID of the specific chain on which the Token Bound Account will be created.

  • tokenContract: This is the address of the NFT smart contract.

  • tokenId: It refers to the unique identifier (ID) of a specific NFT within the given NFT smart contract.

  • salt: This is a random or unique value used to calculate the account address. It ensures that the account address is different for each unique combination of implementation, chainId, tokenContract, tokenId, and salt.

  • function account: This function provides a way to determine the address of a Token Bound Account without actually creating the account. It also takes five arguments:

  • implementation: The address of the deployed account smart contract.

  • chainId: The unique ID of the blockchain network where the account is to be deployed.

  • tokenContract: The address of the NFT smart contract to which the Token Bound Account will be associated.

  • tokenId: The unique identifier (ID) of a specific NFT within the given NFT smart contract for which the Token Bound Account is being created.

  • salt: A random or unique value used to calculate the account address.

Account Contract

This smart contract serves as a template for creating new accounts within the Registry contract system. The Registry contract uses the deployed account contract address to create accounts.

Imports

  • IERC721.sol: This imports the ERC721 interface from the OpenZeppelin library.

  • IERC20.sol: This imports the ERC20 interface from the OpenZeppelin library.

  • IERC1271.sol: This imports the IERC1271 interface from the OpenZeppelin library. IERC1271 provides a standard for contract signature validation.

  • SignatureChecker.sol: This imports SignatureChecker from the OpenZeppelin library. It's used for verifying cryptographic signatures in smart contracts.

  • IERC1155Receiver.sol: IERC1155Receiver is a standard for multi-fungible tokens.

  • IERC165.sol: IERC165 is a standard for contract detection and publishes what interfaces a smart contract implements.

  • IERC6551Account.sol: This imports the account interface for the smart contract to be utilized.

Functions

  • function executeCall: This function is designed to execute a call to another contract. It allows Token Bound Accounts to execute arbitrary calls on behalf of the NFT owner. It accepts three arguments:

    • to: The address of the contract or EOA to which the call is made.

    • value: The amount of cryptocurrency (ETH) sent along with the call.

    • data: The data that specifies the function and its arguments to be executed in the target address.

  • function token: This function retrieves information about the token associated with the account,

  • function owner: This function determines the owner of the account by querying the associated NFT. It checks whether the chain ID matches the current block's chain ID and then uses the ERC-721 standard to find the owner of the specified token. It returns the owner's address or address(0) if the conditions are not met.

  • function supportsInterface: This function checks whether this contract supports specific interfaces. It checks if the provided interface ID matches the interface IDs of IERC165 (contract introspection) and IERC6551Account (a custom interface for this contract).

  • function balance: This function returns the Ether balance of the contract, indicating how much cryptocurrency is in the account.

  • function isValidSignature: This function validates a cryptographic signature. It uses the SignatureChecker to determine if the provided signature is valid for the owner of the account based on the given hash. If the signature is valid, it returns the selector of the isValidSignature function from IERC1271 (contract signature validation). Otherwise, it returns an empty string.

Step 3: Compiling and Deploying the Smart Contract

To compile our contract, navigate to the Compiler tab on the left and click on Compile. Once you've successfully compiled the contract, proceed to the Deploy tab to initiate the deployment. Select Injected Provider - Metamask from the available environments.

Proceed to deploy your NFT contract. A successful deployment should present a confirmation screen.

Next, deploy the TokenBoundRegistry and the TokenBoundAccount contracts in the same manner.

TokenBoundRegistry Deployment:

TokenBoundAccount deployment:

Step 4: Minting the NFT

Now, we'll mint an NFT for the Token Bound Account. For this guide, I will demonstrate minting the NFT to my address. To mint the token, follow these steps:

  1. Select the deployed NFT contract.

  2. Click on Safe Mint.

  3. Enter your wallet address (copiable from MetaMask) and assign it a token ID.

Step 5: Computing the Token Bound Address

To obtain your NFT's Token Bound address, interact with the registry contract by:

  1. Clicking on account.

  2. Inputting the required fields: the implementation address (account contract address), the chain ID (for this example, the Sepolia testnet chain ID), the NFT token contract, token ID, and salt to compute the address.

To instantiate the computed address, use the createAccount function in the registry contract. This will create the Token Bound Account on the blockchain, which can be confirmed by matching the decoded output with the computed address.

To check if the minted NFT is associated with the Token Bound Account, access the token feature in the Token Bound Account contract.

Step 6: Testing the Token Bound Account

To execute a call from the newly created Token Bound Account:

  1. Select the owner's address from the drop-down menu to ensure that the call is made by the account's owner.

  2. Specify the recipient address, which could be another address from your wallet.

  3. Execute the call using the Token Bound Account. This action will transfer 1 ETH from the owner's address to the specified recipient address.

For us to verify if the ETH was sent successfully, let’s go to the Sepolia testnet explorer.

If you check the recipient address, the address should have 1 ETH in it, as shown:

Let’s now receive ETH to our NFT Token Bound Account. To do this, go to your metamask and send 1 ETH to the Token Bound Account address. If we click on balance on our Token Bound Account, we should receive the 1 ETH as shown.

And there we have it! We have successfully created an ERC-6551 for generating Token Bound Accounts associated with a specific ERC-721 token.

The Future of Token Bound Accounts

ERC-6551 is on the verge of transforming the NFT landscape, bringing about a wave of innovation and new possibilities. They're not just redefining what NFTs can do; they're turning them into highly flexible, dynamic, and interactive assets.

Token Bound Accounts and ERC-4337

What's more, when you combine ERC-6551 with the recent introduction of account abstraction on Ethereum (ERC-4337), the Web3 user experience gets a significant upgrade. This dynamic duo empowers wallet providers and decentralized applications (dApps) to perform an impressive feat: users can mint NFTs while seamlessly creating Token Bound Accounts. This groundbreaking approach simplifies the onboarding process for users, sparing them from the complexities of wallet creation and seed phrase management. In essence, Token Bound Accounts, coupled with account abstraction, will rewrite the rules of user interaction with blockchain technology, making it more user-friendly and accessible than ever before.

Conclusion

Token Bound Accounts offer incredible flexibility and customization options to suit a wide range of specific needs and use cases. The ability to tailor these accounts to your exact requirements beyond what was explored in this guide opens up a world of possibilities. Throughout this tutorial, we've delved into the inner workings of ERC-6551, exploring how it functions and the steps involved in creating and deploying it. As you continue your journey in working with Token Bound Accounts, remember that the versatility and adaptability of this standard empower you to create unique and innovative solutions for various applications. By leveraging its potential, you can unlock new opportunities and shape the future of decentralized applications and digital assets. Happy coding!

References & Further Reading