ERC-6551: Non-fungible Token Bound Accounts

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.

Would love to hear more about the use case you’re working on!

I don’t think an interface check at the registry level is necessary. Implementations are welcome to check for these interfaces, but I don’t think the proposal should require implementations to do so.

I’m fascinated by ERC-6551.

I’ve been working on a very similar vision at Locksmith Wallet (locksmithwallet.com). Quick shill to please read my white paper if you are interested in this ERC.

It uses a specific ERC-1155 contract that enables account owners to mint their own private collection of NFTs. Major departures from the base ERC-6551 vision is:

  1. Multiple NFTs per Account: Each Account can have its own collection of NFTs, with permissions. Can enable multi-sig schemes as well.
  2. Multiple Storage Locations: Store your assets in an on-chain vault, inside of a liquidity pool, or somewhere else, and the account can keep track and maintain security and permissions.
  3. Account owners can mint, burn, or “soulbind” tokens to specific addresses to embed in contracts or prevent phishing scams, signature risk, or re-selling/collateralization.

I’ve looked at the spec and I feel like I can make the VirtualKeyAddress and PostOffice contracts compatible with the IERC6551Account, as well as the Registry. In this way, I can offer my users a ERC-6551 compatible experience even though the project existed before the ERC.

A couple of questions I have (hopefully did not miss the details above):

  1. Do I have to integrate with a specific registry, or is having my own considered to be ERC-6551 compatible enough?

  2. Today, I assume that the EOA simply holds the NFT, and all of the assets (except gas, looking at you EIP-3074) are all on-chain. Does ERC-6551 prevent 4337 set-ups, and/or does it also require an EOA and gas (I imagine it would?)

  3. Does the custom-made ERC-1155 for Locksmith (And all of its admin capabilities) somehow proclude it from being ERC-6551 compliant? It’s not entirely clear to me.

  4. Why does IAccount return an address for the owner field? I would expect it to return an address and token ID, because isn’t the account owner an NFT holder, not a specific address? What design decision went into that choice?

Thanks for this awesome ERC and looking forward to contributing to the 6551 ecosystem going forward!

1 Like

I am working on a vault system that add extra-protection to the owning NFT (if not already deployed) and the owned assets. Both ERC6551 and ERC3652 work for me. Basically the Vault deploys an utility NFT that is owned by the Vault and that will have a bound account. The advantage of this approach is that as long as the user trusts the vault, they can let the Vault managing the assets, but at any moment the account can be “ejected” transferring the corresponded utility NFT to the owner of the OwningNFT.
In another variant, the contract that owns the bound account is not an NFT.

I agree. Also because applying IERC721 to the address and calling ownerOf would do the same.

@scotthconner awesome to have you here, thanks for the comments and questions!

  1. One of the goals of 6551 is to have a single registry that can handle all token bound account implementations. This has the benefit of giving the ecosystem a single entry point to query for addresses, and ensures that every address is deterministic so that it can receive assets prior to deployment. If there’s something about the existing registry that makes it incompatible with your use case, I’d love to better understand the issue and explore some potential solutions with you.
  2. Any account (EOA or smart contract) can own the NFT, and is granted execution permissions. Token bound accounts can be 4337 compatible (allowing them to pay their own gas fees) and/or be directly callable (allowing the NFT owner to pay gas).
  3. There are a few paths toward ERC-1155 support that are outlined earlier in this thread. It depends a little bit on how Locksmith 1155 tokens are structured (the biggest being whether they have a single owner per token ID or multiple). With a custom account implementation contract 1155 tokens can be handled in most cases.
  4. This is to enable (partial) support for EIP-173 and (full) support for EIP-5313, which are used to determine contract ownership in some applications. Since returning token information from the owner function would break compatibility with these types of applications, an additional token method was included to query the this data. In the case of ERC-1155 tokens with multiple token owners the owner method is not useful. Changes to this function have been heavily requested, and we’re planning to change it to explicitly support use cases without a single canonical owner.