Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Issuing Subnames in ENSv2

An ENSv2 name can serve subnames through its resolver, its subregistry, or both. Choose the setup based on who should own the subnames and who should update their records.

Subnames as Resolver Records

If you manage every subname, you can keep their records in one Permissioned Resolver. Set that resolver on your parent name, such as wallet.eth, and write records for full names such as alice.wallet.eth and bob.wallet.eth.

The Universal Resolver finds the parent's resolver and passes it the full name through wildcard resolution. No subregistry or subname token is required. These are onchain records, even though there is no token for each subname.

The resolver's role holders control the records. Giving Alice an address record does not give her ownership of alice.wallet.eth or permission to edit it.

Subnames stored as resolver recordsOne parent token points to one resolver. Full names, including deeper subnames, map to record bundles inside that resolver. The subnames have no tokens of their own. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.Permissioned Resolverwallet.ethToken owned by youresolverpay.wallet.ethRecord 1ETH addressblog.wallet.ethRecord 2Contenthashl2.pay.wallet.ethRecord 3Base address
One parent token points to one resolver. Full names, including deeper subnames, map to record bundles inside that resolver. The subnames have no tokens of their own.

Share Records Across Names

A Permissioned Resolver can link several names to the same record bundle. Updating that bundle updates the records returned for every linked name.

Names without their own record bundle use the resolver's default bundle. Write that bundle using the DNS-encoded empty name (0x00). This can provide a shared website, avatar, or address for subnames without individual setup.

A shared default record bundleEach name without its own bundle falls back to the default bundle. Giving a name any record of its own ends fallback for that entire name. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.Permissioned Resolverwallet.ethToken owned by youresolveralice.wallet.ethbob.wallet.ethcarol.wallet.ethFallback for the whole nameDefault bundleWebsite + avatarEmpty name: 0x00
Each name without its own bundle falls back to the default bundle. Giving a name any record of its own ends fallback for that entire name.

Subnames as Owned Tokens

Use a UserRegistry when subnames need separate owners or should appear as tokens in wallets.

  1. Deploy and initialize a UserRegistry with the required roles.
  2. Attach it to the parent name using setSubregistry() on the registry that holds that name.
  3. Register each label with an owner, resolver, expiry, and role bitmap. For alice.wallet.eth, register alice in the registry attached to wallet.eth.

Each owned entry is an ERC-1155 token. The registry stores its resolver and optional child registry. Several entries can use one resolver, or each can point to a different resolver.

Token ownership and resolver permissions are separate. Giving Alice a token does not grant her roles on an operator's shared Permissioned Resolver. If Alice should control her own records, she can use a resolver she controls, provided her token roles allow changing the resolver.

Subnames with separate token ownersThe parent points to a UserRegistry. Alice and Bob own separate tokens, each pointing to the same resolver. Token ownership does not automatically grant write access to that resolver. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.UserRegistryPermissioned Resolverwallet.ethToken owned by yousubregistryalice.wallet.ethToken owned by AliceresolverRecord 1ETH address + avatarbob.wallet.ethToken owned by BobresolverRecord 2ETH address + URL
The parent points to a UserRegistry. Alice and Bob own separate tokens, each pointing to the same resolver. Token ownership does not automatically grant write access to that resolver.

Choose the Owner's Permissions

The registration's role bitmap determines what the owner may do:

  • ROLE_SET_RESOLVER: change the name's resolver.
  • ROLE_SET_SUBREGISTRY: attach a registry for further subnames.
  • ROLE_RENEW: extend the expiry.
  • ROLE_CAN_TRANSFER_ADMIN: permit the owner to transfer the token, subject to the registry's transfer checks.

Also decide which roles the operator retains on the registry's root resource. Root permissions can allow the operator to change resolvers, replace child registries, unregister names, or upgrade the registry. Tokenizing a name alone does not remove that control. See Permissioned Registry for emancipation and safe-transfer requirements.

Automate Registration with a Registrar

For a registration service, grant a registrar contract ROLE_REGISTRAR on the registry. That contract can enforce your pricing and eligibility rules. Grant ROLE_RENEW as well if it should handle renewals. The contract developer tutorial walks through this approach.

A registrar enforces your registration policyA registrar contract holds registration and, optionally, renewal roles on the UserRegistry. It applies your rules before calling the registry. The registry holds the tokens, and the resolver holds the records. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.UserRegistryPermissioned Resolverwallet.ethToken owned by yousubregistryalice.wallet.ethToken owned by AliceresolverRecord 1ETH address + avatarbob.wallet.ethToken owned by BobresolverRecord 2ETH address + URLRegistrar contractYour pricing and eligibility rulesRegister / renew
A registrar contract holds registration and, optionally, renewal roles on the UserRegistry. It applies your rules before calling the registry. The registry holds the tokens, and the resolver holds the records.

Reserved Entries Without Tokens

A registry entry can have an expiry, resolver, and child registry without having an owner. Registering with the zero address as owner and a zero role bitmap creates a reserved entry without minting a token.

Use reserved entries to route a subtree to a different resolver or to hold protected labels. An unexpired reservation cannot be registered through the ordinary registration path. Assigning it an owner requires ROLE_REGISTER_RESERVED.

Delegate Record Updates

Root Roles and Individual Keys

Roles on a resolver's ROOT_RESOURCE apply across that resolver. A root ROLE_SET_TEXT grant allows updates to every text key. A grant scoped to the url key permits URL updates across the resolver's records, without permitting avatar updates.

Root roles and permissions for individual text keysA root text role covers every text key. A role scoped to the URL key lets the bot edit that key across this resolver’s records, but not the avatar key. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.Permissioned ResolverRoot resourceROLE_SET_TEXT + its admin roleKey: avatarAvatar text recordsKey: urlURL text recordsOwnerAll text keysRoot role covers both keysStatus botURL text role
A root text role covers every text key. A role scoped to the URL key lets the bot edit that key across this resolver’s records, but not the avatar key.

Delegate a Single Address Field

Permissioned Resolver roles can be restricted to a setter argument, such as a text key or address coin type. For example, grantSetterRoles() can authorize a payment service to change Bitcoin addresses without allowing it to change Ethereum addresses or avatars.

For a code example using a text key, see Delegating a Single Text Key.

A delegated writer can update one field across a resolverThe payment agent can update Bitcoin addresses in both record bundles. Its BTC role does not permit changes to Ethereum addresses, but it is not restricted to a single name. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.Permissioned Resolverwallet.ethToken owned by youresolveralice.wallet.ethRecord 1ETH: unchangedBTC: writablebob.wallet.ethRecord 2ETH: unchangedBTC: writablePayment agentBTC address roleOn this resolver
The payment agent can update Bitcoin addresses in both record bundles. Its BTC role does not permit changes to Ethereum addresses, but it is not restricted to a single name.

These permissions apply across every record bundle in that resolver. They are not restricted to one name.

Limit a Writer to a Group of Names

To give a writer access to only a group of names, point those names at a separate resolver instance and grant the role there. Registry entries, including reserved entries, let you assign those resolver pointers.

Separate resolvers limit which names a writer can changeThe agent has a BTC write role only on resolver A. Alice’s records use A, while Bob’s use B. Registry entries can also be reserved without owners when only separate routing is needed. Solid blue arrows show pointers or name-to-record links. Dashed blue arrows show fallback. Dashed arrows in the text color show permissions.UserRegistryResolver AResolver B: no agent rolewallet.ethToken owned by yousubregistryPayment agentBTC address role on A onlyWrite permissionalice.wallet.ethToken owned by AliceresolverRecord 1BTC: writable by agentbob.wallet.ethToken owned by BobresolverRecord 1BTC: unchanged
The agent has a BTC write role only on resolver A. Alice’s records use A, while Bob’s use B. Registry entries can also be reserved without owners when only separate routing is needed.

Choose a Starting Point

  • For subnames whose records you manage, start with resolver records.
  • For separately owned or transferable subnames, use a UserRegistry and choose the token roles deliberately.
  • For routing or holding labels without ownership, use reserved entries.
  • For automated record updates, limit setter permissions and use separate resolver instances where writers need different access.

These approaches can be combined. Adding a subregistry later does not require replacing existing resolver records, but its resolver pointers determine whether resolution continues to reach those records.

This guide and its diagrams adapt Exploring Subnames in ENSv2. The registry template and Permissioned Resolver pages cover the contract APIs.