ERC-6551: Non-fungible Token Bound Accounts

@INastro Great question! The proposal leaves open the possibility of cross-chain token bound accounts if implementations would like to support that. This would mean you could have an account on one chain bound to an NFT that exists on another chain. This line of code checks whether the NFT an account is bound to exists on the current chain, and returns the zero address if it is bound to an NFT on another chain.

I took a look at your reference implementation.
It would be good to add a test showing how you make a simple transfer of an ERC721 from a bound account to a recipient address. There is a transfer at the end of testOwnershipChain, but it is a complex case and a simpler case would help understand how to implement your proposal.

I figured it out :slight_smile:
But an example in the tests would be useful anyway.

Really awesome and forward thinking idea! Very easy to read and love it, hoping to work on this for a test project in the future.

1 Like

Glad you figured it out! Feel free to submit a PR to the reference repo to add tests for this case :slight_smile:

1 Like

I will think about it, but for me it would be probably easier to make an hardhat version of the entire repo.

This EIP seems to be a blend of a standard (a central Registry of smart-contract-wallets keyed to specific NFTs) and implementation (forcing them to be proxies). For clients interacting with this standard, they’d not have a need to know if the NFT-keyed-accounts are proxies or not, right?

The logic of a token-controlled smart-contract-wallet (how it gates access) seems like the bulk of the logic of this EIP (since the Registry is fairly simple as a lookup mapping)? Rather than having these wallets be forced to be one-to-one (one NFT gives access to one wallet), having it be flexible enough to also create multi-sig wallets (similar to a DAO that gives out membership “shares”, granting access to a specific set of NFT identifiers) would enable more use-cases, I believe?

Token bound accounts MAY implement additional authorization mechanisms which limit the ability of the ERC-721 token holder to execute calls.

Token bound accounts MAY implement additional execution functions which grant execution permissions to other non-owner accounts.

So is the intention to encourage many different platforms to launch ERC6551 Registries, each that generate different types of token-bound accounts? If a project wishes to add more roles (in addition to “Owner”, pulling in the “Approved” from the ERC721 contract, as well as other delegated roles), the expectation is they’d design and launch their own Registry with their project’s custom logic? So over time we’ll end up with each NFT having many different accounts scattered across different registries, and wallet/portfolio software that wants to enumerate all the things “owned” by a given NFT will need to have a cached/known list of Registry addresses to iterate through?

2 Likes

The registry is agnostic about the implementation, and you can use the same registry for any kind of account.

1 Like

@jay I am implementing ERC-6551 in a project. Initially I wanted to use EIP-3652: Hierarchical NFT which solves a similar problem. I am currently evaluating the pros and cons of the twos. I would appreciate your opinion about it.

Sad that EIP-3652 was not even mentioned here, bit I believe this EIP is probably inspired by it.

1 Like

Aha! Thanks for that tip; I delved more into the example code of the intended Registry contract. I was expecting the Registry to be a 1:1 mapping tool for each NFT to have one Token-Bound Account. But the current proposed code is the one master registry allows anyone to proxy any address for any NFT token. There’s no enumeration functions in the Registry, so no on-chain looping through all addresses generated for a specific NFT token. Off-chain, there’s an Event log of AccountCreated that can be used to find previously-generated addresses, but none of the parameters of that Event are Indexed, so off-chain iteration would need to grab ALL the events to find the ones for specific tokens?

This proposal grants every ERC-721 token the full capabilities of an Ethereum account while maintaining backwards compatibility with previously deployed ERC-721 token contracts.

I realized that this EIP doesn’t actually require the “token” be ERC-721-compliant in order to be the “key” used to unlock a token-bound account (there’s no ERC-165-check or other introspection of the collection contract when deploying a token-bound account to ensure it’s ERC-721-compliant at all). The only aspects of the token that are used is an address and a uint256. Any protocol that is able to determine a unique “owner” for a distinct combination of an address and a uint256 would technically work with this Registry concept?

This could open the idea of token-bound account implementations that use custom token-ownership-determining logic, so collections that don’t use a specific token standard (e.g. historic collections that existed before the ERC-721 standard existed) could use an ERC-6551 Registry. Therefore, is it important to lean so heavily into referencing ERC-721 in the EIP writeup, as opposed to just referring to them as “Tokens” (and noting that any standard that is able to determine unique ownership from a uint256 is compatible, including ERC-721)?

1 Like

Great to have you here @k06a! We’ve been trying to reach you to chat about this proposal for some time.

Yes, this proposal takes a similar approach to the one that EIP-3652 takes, but uses a registry instead of embedding the account creation logic into the NFT contract. Unfortunately due to quirks of the EIP process (not being able to reference EIPs that have not made it to draft status) we were not able to mention 3652 specifically in the proposal document. We would love your contributions to this proposal as someone who has thought deeply about the concept of NFTs having accounts, and would be happy to have you as an author.

Good question! By deploying accounts using 1167 proxies, it allows the bytecode for all token bound accounts to be knowable and computable, which makes generating deterministic deployment addresses easier. The alternative would be to have a single central implementation (not good) or require users to pass the entire bytecode of the contract they would like to deploy to the registry (which would be much more calldata and would require bytecode lookups).

This is correct. The goal is to have a single entry point for all clients to be able to query token bound account addresses and deploy them, which avoids the fragmentation of multiple registries. Using the current registry, any NFT can have an unlimited number of addresses using an unlimited number of implementations / salts. This gives NFTs the same “rights” when it comes to wallet creation as users of EOA wallets.

This is a great catch! There has been some conversation around which of the arguments should be indexed, as there are more arguments than can be indexed in a single event. Would love your opinion here! Indexing on the events will be added based on feedback collected as folks review the EIP.

This is correct! It would require a custom implementation if you’re using something other than ownerOf to determine the canonical owner, but the choice of how to determine the canonical owner based on an address and a uint256 is left to the implementation. This does open the door to support for other types of tokens than ERC-721. We’re working on an update to the proposal that tones down the focus on ERC-721 tokens and allows for more flexibility when determining the owner of the account.

What do you think of minimising proxy bytecode? Example here: Extract lib, add getters for proxies by k06a ¡ Pull Request #4 ¡ 1inch/ERC3652 ¡ GitHub

@k06a would love to explore this! I think it’s important that the first 45 bytes of the bytecode match the existing ERC-1167 proxy bytecode in order to allow for wide compatibility with existing proxy detection mechanisms, but would love to see the encoded data at the end of the proxy compressed further.

Did you have any initial thoughts around how you’d like to see the bytecode of the proxy changed?

My vote would be to index the token collection address, the token ID, and the implementation address. That would allow answering the queries of:

  • Which token-bound accounts does token X have?
  • What token-bound accounts belong to tokens in collection X?
  • What token-bound accounts use implementation X?

Which I think are the most common introspection queries that will be needed.

Queries that cannot be answered by those indexed values include:

  • What token-bound accounts exist that used nonce X to deploy?
  • What token does the token-bound wallet at address X belong to?
  • When was the token-bound wallet at address X created?

The first query I think would be rare to need/use. The other two can be answered using other blockchain cues, so don’t need to have event topics indexed to supply them.

2 Likes

I am working on that specific case, where the bound wallet is bound to a non-ERC721 contract.
I was thinking of an interface like:

interface IERC6551Owned {
   function ownerOf(uint id) external view returns (address);
}

In this case, the protocol would check if the contract supports the interfaceID IERC721 or IERC6551Owned

Love this proposal! So, so many use cases. I’m excited that this and other proposals are really working towards optimizing not just the gas but also the work needed to be done by front end devs. I’m new to this whole process, how long does it usually take for these to be pushed through? Can’t wait to try it out.