ENSIP-28: ENS Name Owned Accounts

An ENS name represents an identity for both human users and AI agents. One identity commonly controls several accounts on a single chain, such as a Safe, a token-bound account, and one or more agent wallets. An ENS name resolves one primary address per chain, so there is nowhere to put the others, and no standard for associating them with the name. Every application that needs the association today invents its own convention or keeps it off-chain. No two implementations agree, and a client holding a name cannot discover the accounts behind it.

ENSIP-28 defines that association as a listing. The listing is an ENSIP-24 data record on the name’s own node, keyed by chain and index, holding the account’s address. The name owner writes it, and any client that resolves ENSIP-24 data can read it. It adds no new resolver profile methods and changes no existing resolution standards.

The pull request into the main ENSIP repository can be found here.

A name lists an additional account as an ENSIP-24 data record on its own node, under a reserved key of the form

account[<chain-id>][<index>]

The chain-id is an ERC-7930 Chain Identifier, the index distinguishes multiple accounts on the same chain, and the value is the account’s address. The ENSIP covers discovery, the relation to address records, and the security considerations.

One point is worth repeating here. A listing is a claim by the name owner and nothing more, and anyone who controls a name can list any address. Clients must not display the listing name in place of the account address, and should not send funds to a listed account.

Verification is out of scope of this draft, and may be defined in a future ENSIP or a future draft revision of ENSIP-28. I would like to use this thread to work out what the mechanisms should be.

Account types differ in how control can be proven. An EOA can sign. A contract account needs something like ERC-1271. Some accounts, a minimal vault for example, can neither sign nor make outbound calls, and may not be verifiable at all. The open questions include how the assertions are made, whether a proof expires, where it lives, and how it is revoked. I invite proposals for mechanisms, and for account types not covered here.


I would be appreciative of any feedback from the ENS community, and am happy to answer any questions.

3 Likes

I wonder if we could explore a more clever solution leveraging existing ENSIP-9 multichain address functionality. ENSIP-9’s coinType parameter is a uint256 being used to store a 32-bit SLP-0044 coin type, which leaves a lot of unused space!

For example, starting with address number n on a chain with coin type c, you would derive the “indexed coin type” by doing:

indexedCoinType = c << 32 + n

You would then call setAddr(node, indexedCoinType, addresses[n]) for each of your addresses. This would allow you to store an array of 4 billion addresses per chain (and 75% of the addressable space would still be unused!).

To retrieve someone’s list of addresses for a specific chain, you would follow the same steps above to generate indexed coin type values and query addr(node, indexedCoinType) (starting with n=0 and incrementing it each time, until you find a gap)

This seems more sophisticated than using text records for something which is very much not a text record (addresses) and takes advantage of existing infra that is already set up to store lists of addresses across multiple chains, tied to one ENS name.

It’s not using text records. It’s using ENSIP-24 data records.

I also think that a distinction between addresses and owned accounts makes it clear that the additional accounts are not payment addresses, but instead are part of the overall profile.

That being said, allowing an ENS name to specify more than one account per chain is the primary objective of this ENSIP, and I am open to other ways of achieving it.

You’re right, it is using data records (for something that is not data :wink:)

There is no guarantee that any address a user’s ENS points to is a valid payment address. It’s a bad idea to send funds to someone without confirming first where they want it sent. Therefore, I think it would be perfectly appropriate to list accounts under addr() (and since internally we already have a segregation of text, data (bytes), and address types, it seems the most “correct” to me).

I could see this setup. I think the downside is that it adds more complexity to the coinType, which is already complicated and irregular.

The ENSIP-28 keys are fairly self-explanatory and easy to understand. I actually think that ENS should “evolve” to use ENSIP-24 for addresses as well. It’s a lot easier to read and solves the irregular coinType issue.

With ENS mandating the use of the Universal Resolver, this would also be easier to upgrade because it would be possible to check both the addr function and address[chain-id] as a fallback.

Can you explain what you mean by irregular? There might be an aspect I’m not aware of.

I think it would also be helpful to better understand the intended use case. If this list of accounts is there mostly as a way to publish arbitrary values for humans to consume or use off-chain, the format doesn’t matter so much. But if you want them to be accessible to smart contracts for on-chain logic, they need to be designed with that purpose in mind (which would probably involve a new resolver type, which I know you want to avoid).

coinType was expanded in ENSIP-11 to make it possible to save multiple EVM chain IDs alongside SLIP-44 coin types.

ENSIP-11 is only used in ENS and therefore is not an industry-wide standard. ERC-7930 is an attempt to create an industry-wide standard for chain-specific addresses as well as chain identifiers.

It is generally not possible to guarantee onchain resolution of any ENS records because of CCIP-Read.

The goal is to continue to make ENS profiles support the real-world use cases of onchain identities. There has been a long-felt need for both human users and AI agents to have owned accounts as part of their onchain profiles.

Subnames are owned accounts, and they are already verifiable on-chain. You can prove that they belong to the parent ENS name, and if you configure each as a primary name, you can also prove that the address it points to opted in to being listed as a subname. Additionally, you can name and describe each with text records, to give even more context. That seems like a better solution for this particular use case, in my opinion. It also matches how people do things currently (e.g. create subnames for their different wallets).

The existence of a subname doesn’t inherently provide any relationship to the parent name. It could be associated, such as when a user uses wallet.name.eth , or it could be unassociated, as with name.base.eth .

ENSIP-28 makes it possible for an ENS name to establish an “owned” association between the ENS name and an account, which can also be verified. The owned account can also be a subname or not.

1 Like

It does if they are both owned by the same address. That address is called the “owner” for this very reason :slightly_smiling_face:

Oftentimes, subnames don’t even have an owner because they are offchain. Even with the same owners, all it says is that the subname and the parent name are controlled by the same account, but it says nothing about accounts that are controlled by an ENS name.

Even if the subname has a primary name set and the owners are the same, it still does not mean that the account that set its reverse name to the subname, which has the same owner as the parent name, is “owned” by the parent name. That would be adding a meaning that setting the primary name doesn’t have.

Another example is if a parent ENS name is transferred to a different owner. The subname account would lose its association with that parent ENS name. With ERC-6551, the accounts are actually controlled by the ENS NFT, so when the ENS name is transferred, they are still controlled by the ENS NFT.

That is why ENSIP-28 is called ENS Name Owned Accounts, because the accounts can actually be owned by the ENS name.

Finally, there can be many reasons why the owner of both a subname and a parent name might match, but that doesn’t mean that the subname is controlled by the parent name. For example, a smart contract might be set up to issue subnames and own the parent name, but the contract might make it impossible for the parent name to control the subnames.

ENSIP-28 creates a standard for express ownership of more than one account by an ENS name that also doesn’t block those accounts from using ENS subnames.

This is a good point, you never know if someone wants to use a contract to manage control of many different names.

You asked for feedback, and my final impression is that if the design boils down to not much more than declaring a key name for storing some records, I’m not sure if an ENSIP is warranted. Perhaps it will expand over time to describe a more complicated process, but if that is the case I would have rather seen it submitted when it is ready for a more in-depth review.