# ERC 6551: Token Bound Accounts (TBA)

### **Basic Understanding**

ERC-6551 allows NFTs to have associated smart contract accounts. These accounts can hold tokens, interact with decentralized applications (dApps), and execute transactions—just like a regular Ethereum account.

Before ERC-6551, NFTs were static assets. With TBAs, an NFT can own ERC-20 tokens, other NFTs, or interact with DeFi protocols.

**How it works:**

1. Each NFT gets an associated **Token Bound Account (TBA)**, which is a smart contract wallet.
2. The TBA is **linked to the NFT** and managed by the NFT's owner.
3. The NFT can **store tokens** or **execute on-chain actions**.

### **Use Cases**

1. **GameFi & Metaverse**
   * A game character NFT can hold in-game assets (weapons, potions, tokens).
   * When the character is sold, the new owner also gets the stored items.
2. **On-Chain Identity**
   * Users can own an NFT-based identity with on-chain history, achievements, and credentials.
3. **DAO & Governance**
   * An NFT membership card can hold voting power and interact with DAO governance contracts.
4. **DeFi & Financial Instruments**
   * NFT-backed loans: An NFT with a TBA can hold staked assets or act as collateral.
5. **Composable NFTs**
   * A fashion NFT (e.g., a digital avatar) can own wearable NFTs (clothing, accessories).

### **Advantages**

* **NFTs Become Wallets** – NFTs can own assets, removing the need for separate wallets.
* **Better Composability** – Enables richer interactions between NFTs and DeFi, DAOs, gaming.
* **Improved Security** – Smart contract-controlled accounts reduce risks of external wallets.
* **Gas Efficiency** – Reduces the need for multiple transactions to move assets.

### **Disadvantages**

* **Smart Contract Complexity** – More complex than standard NFTs, requiring secure contract audits.
* &#x20;**Adoption Curve** – Wallets, marketplaces, and dApps need to support ERC-6551.
* &#x20;**Higher Gas Costs** – Deploying smart contract accounts for NFTs adds gas costs.

### **Architecture & Code Structure**

#### **1. Key Components**

* **ERC-721 NFT**: The main NFT that will have an associated wallet.
* **Token Bound Account (TBA) Smart Contract**: A contract that acts as the NFT’s wallet.
* **Registry Contract**: Deploys and manages TBAs for NFTs.

2. Diagram

```
+----------------------+
| ERC-721 NFT         |  
| (e.g., Game Avatar) |
+----------------------+
        |
        | Links to TBA
        v
+----------------------+
| Token Bound Account  |  
| (Smart Contract)     |
+----------------------+
        |
        | Can store tokens, interact with dApps
        v
+----------------------+
| ERC-20, NFTs, dApps |
| (Assets & Contracts)|
+----------------------+

```

#### **3. Code Structure**

Here’s a basic implementation of an **ERC-6551 Token Bound Account**:

**A.  ERC-6551 Registry (Factory to deploy TBAs)**

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

interface IERC6551Registry {
    function createAccount(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external returns (address);
}

contract ERC6551Registry {
    mapping(bytes32 => address) public accounts;

    function createAccount(
        address implementation,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external returns (address) {
        bytes32 salt = keccak256(abi.encodePacked(chainId, tokenContract, tokenId));
        require(accounts[salt] == address(0), "Account already exists");

        ERC6551Account account = new ERC6551Account();
        accounts[salt] = address(account);
        return address(account);
    }
}

```

**B. Token Bound Account (Smart Contract Wallet for NFT)**

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

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

contract ERC6551Account is Ownable {
    event Executed(address target, uint256 value, bytes data);

    constructor() {
        transferOwnership(msg.sender);
    }

    function execute(address target, uint256 value, bytes calldata data) external onlyOwner {
        (bool success, ) = target.call{value: value}(data);
        require(success, "Execution failed");
        emit Executed(target, value, data);
    }

    receive() external payable {} // Accept Ether
}

```

**C. NFT Contract (Uses ERC-6551)**

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

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

contract MyNFT is ERC721URIStorage, Ownable {
    IERC6551Registry public registry;
    address public implementation;

    constructor(address _registry, address _implementation) ERC721("MyNFT", "MNFT") {
        registry = IERC6551Registry(_registry);
        implementation = _implementation;
    }

    function mint(address to, uint256 tokenId, string memory tokenURI) public onlyOwner {
        _mint(to, tokenId);
        _setTokenURI(tokenId, tokenURI);
        
        // Create Token Bound Account for NFT
        registry.createAccount(implementation, block.chainid, address(this), tokenId);
    }
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.anandisheladiya.com/protocols/ercs-and-eips/erc-6551-token-bound-accounts-tba.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
