ENSv2 Smart Contracts Overview
Welcome to the next evolution of the Ethereum Name Service!
ENSv2 introduces a suite of upgraded smart-contracts designed to make the protocol more scalable, modular and future-proof. This section will outline the high-level architecture, guiding principles and migration strategy for ENSv2.
What's new in ENSv2?
- Native L2 Support – contracts have been designed with Namechain and other Layer 2 deployments with cross-chain resolution in mind, building on existing CCIP-Read support in ENSv1.
- Hierarchical Registries – while ENSv1 used a single flat registry for all names, ENSv2 allows each name to provide its own registry implementation for subnames. This provides name owners and developers with direct control over the ownership and transfer rules for names and subnames.
- Permissions as Standard - All of the functionality enabled by the Name Wrapper in ENSv1 has been integrated into the core of ENSv2, using a new, highly flexible, role-based permissions model.
- No Grace Period - The grace period is no longer a part of the ENS protocol, meaning names expire when they say they expire. Upon expiration, names immediately enter into the temporary premium period. The owner of a recently-expired name doesn't have to pay the premium fee during this period.
- Contract Factories - Rather than relying on large multi-user contracts such as the default public resolver, every name gets its own resolver, and every name with subnames gets its own registry contract. This is made possible by the low cost of L2 transactions, and simplifies the contracts significantly, while offering users new functionality such as the possibility of 'aliasing' multiple domains to the same records.
What hasn't changed?
- Resolvers - while we have developed new resolver contracts to take advantage of the changed environment enabled by ENSv2 and Namechain, the interface used by resolvers remains the same, and all existing ENSv1 resolvers will continue to work seamlessly in ENSv2.
- True Ownership - ENSv2 continues to prioritize trust minimization, enabling you to own your name fully, without having to worry about interference from centralized third-parties.
- Truly multi-chain - Although ENSv2 hosts .eth names on Namechain by default, ENS continues to support all L2s. Names can be 'ejected' from Namechain to L1, and from there can either be managed directly on L1 or delegated to another L2.
ENSv2 Registry Architecture
Overview
ENSv1 used a simple architecture, where a single flat registry maintained a mapping from all names to their owner and resolver addresses. Hierarchical ownership was enforced through the use of namehash to calculate IDs for subnames. This has the advantage of simplicity, but means that ownership rules are enforced by a single, non-upgradeable contract, and changes in the status of a parent name do not automatically ripple down to affect subnames.
In ENSv2, registries are hierarchical: each name can have a resolver and a subregistry:
Here, registries are shown as rectangles, while resolvers are shown as notched rectangles.
Note that the registry for .eth has both a subregistry and a resolver defined for montoya.eth.
Note also that there's a resolver defined for inigo.montoya.eth but no subregistry, while
domingo.montoya.eth has a subregistry but no resolver. A name only needs to have a subregistry
defined if it wants the ability to create subnames, and it only needs a resolver defined if it wants to
define records to resolve for that name or its subnames.
Resolution follows a process that conceptually mirrors the process from ENSv1: first, we find the resolver
responsible for the name being resolved, which is the resolver that covers the longest available suffix
of the name. In the example above, inigo.montoya.eth is resolved by Resolver 1, while domingo.montoya.eth
and any other subdomains of montoya.eth that are not present in the tree are resolved by Resolver 2. After
the resolver responsible for a name is found, it is queried for the desired record.
One consequence of this tree structure is that it becomes possible to delete or reassign entire subtrees in a
single operation. For example, suppose montoya.eth is transferred to a new owner, who wants to
configure his own set of subdomains; he can simply replace the subregistry responsible for subnames of
montoya.eth with his own new subregistry:
All resolvers and subregistries previously associated with montoya.eth are thus removed in a single operation!
The new owner will still need to replace the resolver for montoya.eth if he wishes to change how the bare
name itself is resolved, however.
This hierarchical structure need not be limited to trees, either; by reusing the same subregistry for more than one name, entire namespaces can be aliased to each other:
In this example, both inigo.montoya.eth and inigo.wallet.eth resolve identically, as would any other
subnames with resolvers set. Notably, domingo.montoya.eth will resolve using Resolver 1, while
domingo.wallet.eth will not resolve at all - there are no resolvers set anywhere in its hierarchy! If we
set a resolver for domingo in Registry 3, both names would resolve identially using it, just as they do
for inigo.
This example also exposes one other crucial fact about ENSv2: registries have no individual concept of 'their name'. In earlier diagrams we labelled each registry with a name for convenience, but as these examples demonstrates, there's no requirement that a registry have exactly one name associated with it - it can have thousands, or none at all!
Token Representation and permissions
Although it's not required by the ENSv2 registry interface specification, typically registries are implemented as ERC1155 token contracts, and standardized tooling is likely to expect as much. Each registry has an overall owner, who is responsible for the registry itself, as well as owners for individual subnames, which are represented as tokens. Because of the hierarchical nature of the registry structure as demonstrated above, merely owning a subname token on a registry does not guarantee anything in isolation: to be meaningful, the registry must be referenced by a parent registry, and so on up to the root registry. Client authors must therefore take care in how they represent names to users, to ensure users are not given a false impression of what they are looking at.
Standardized registries in ENSv2 use a sophisticated permissions model similar to Open Zeppelin's Roles model. Each name has a set of roles, such as the ability to set the resolver or subregistry for that name. Each role has a corresponding 'admin role', which allows granting or revoking that role (as well as the admin role itself). Roles can also be granted for the registry contract as a whole, and an account may exercise the privileges of a role if it has the role granted for the specific name or on the contract as a whole. Some roles, such as creating new subnames, are available only as contract-wide roles.
Typically the owner of a name will have some set of resource roles over the name in the registry it is defined in, and some set of root roles over the name in that name's subregistry. For example, the owner of a .eth name would have resource roles that allow setting subregistry and resolver addresses and transferring the name in the .eth registry, as well as root roles allowing all privileges in that name's subregistry.
By selectively revoking roles, all the functionality of the ENSv1 name wrapper can be replicated - for example, the owner of wallet.eth can grant a registrar contract the 'registrar' role on the wallet.eth registry, while revoking their own contract-wide 'set resolver' and 'set subregistry' roles and admin roles on the same registry. If they then revoke the 'set subregistry' role and admin role for the 'wallet' subname on the 'eth' registry, they will no longer be able to modify wallet.eth subnames they don't own - giving the same effect as 'emancipating' a name in the ENSv1 name wrapper.
When a subname is transferred to a new owner, any roles that were granted to the previous owner are automatically transferred to the new owner, but roles granted to other accounts remain unmodified - so it is important that apps facilitating trading of names verify the set of roles granted to external accounts.
Permissioned Registry Roles: Some roles are 'root-only'; this means that having such a role is meaningful only if granted as a root role.
Some roles are 'admin-only'; this means that posession of the admin role confers a privilege but posession of the user role has no effect.
- Registrar: Allows creating new names in this registry. Root-only.
- Renew: Allows extending the expiration timestamp of a name.
- Set Subregistry: Allows changing the subregistry address of a name.
- Set Resolver: Allows changing the resolver address of a name.
- Set Token Observer: Allows changing the token observer address of a name.
- Can Transfer: Allows transferring the name using standard ERC-1155 transfers. Admin-only.
- Burn: Allows burning the name.
Deployment Diagrams
Names are depicted as follows:
Each name represents the registry entry in the parent registry as well as the subregistry for that name (if present).
Principals - addresses that own resources in ENS - are depicted as follows:
Roles are shown as a label on the edge, with each character representing a role that the principal has on the name. If the principal also owns the name, the edge is depicted in bold. Admin roles are in upper-case, and user roles are in lower case. By convention, if an account has the admin role, they also have the user role. Resource roles on the name's own registry are shown on the first line, and root roles on the subregistry are shown on the second line. The following characters are used:
| Character | Meaning |
|---|---|
| R | Registrar. Omitted from the parent registry role mask. |
| N | Renew |
| S | Set Subregistry |
| E | Set Resolver |
| O | Set Token Observer |
| B | Burn |
| T | Can Transfer. Omitted from the subregistry role mask. |
| -- | -- |
Thus, a principal with all rights over a name in both the parent registry and its subregistry would look like this:
NSEOBT
RNSEOBHowever, for succinctness an account that has all rights to a name is depicted with a simple *.
It's important to understand the distinction between resource roles on the name's registry and root roles on a subregistry. If a principal has a role mask of e| on example.eth, they are allowed (only) to set the resolver for example.eth. In contrast if they have a role mask of |e, they are allowed to set the resolver on any subdomain of example.eth. The same logic applies for other roles.
Note that if anyone has the right to set a name's subregistry, they can effectively delete or replace all subnames of that name - so any rights granted by the subregistry can be overriden by a principal with the 'set subregistry' role in the name's registry.