Skip to content

Terminology

New terminology (beyond the official ENS glossary) has been needed in the course of building ENSNode. The following should be understood as a draft that is open to community feedback. Each definition below aims to maximize alignment with the official ENS glossary where possible, and reduce instances where a piece of terminology may have multiple meanings in the context of the protocol.

The following concepts extend the core ENS protocol to handle multichain and off-chain scenarios that arise in modern ENS usage.

A Subregistry is any data structure outside of the Registry that manages supplemental state for a set of subnames. Each name has the potential for association with at least 1 subregistry (through the Name Wrapper) and may optionally be associated with multiple subregistries. When a name is associated with multiple subregistries, this means that the full state of a name must be combined across the Registry and each associated subregistry. For example, the state of all direct subnames of .eth is distributed across the Registry and two subregistries: the BaseRegistrar and the Name Wrapper. The ENS protocol does not currently define standards for subregistries: subregistries currently exist outside the scope of ENS protocol standards. For example, subregistries could live on L1, on L2s, or offchain (in a database or even in a Google Sheet). The ENS protocol currently provides no standardized mechanism to discover subregistries or to interact with subregistries.

Some specific implementations of subregistries include:

  • The BaseRegistrar that holds supplemental state for direct subnames of .eth. This includes state for ERC721 NFTs and expiry times.
  • The NameWrapper, which serves as a subregistry for the entire ENS root (all ENS names). This includes state for ERC1155 NFTs, expiry times, and fuses.
    • Note how direct subnames of .eth are an example of multiple subregistries potentially holding supplemental state for a name outside the Registry.
  • The contracts on Base that manage supplemental state for direct subnames of base.eth.
  • The contracts on Linea that manage supplemental state for direct subnames of linea.eth.
  • The contracts on Base / Optimism that manage supplemental state for DNS names managed by 3DNS.
  • The offchain databases that manage supplemental state for direct subnames of uni.eth.
  • The offchain databases that manage supplemental state for direct subnames of cb.id.
  • DNS nameservers for (essentially) all DNS names. Since ENS is a superset of DNS, (essentially) any DNS name is an ENS name. Therefore, whenever supplemental state associated with a DNS name is updated in a DNS nameserver, a subregistry is being updated.

A Subregistrar is any system that is a Registrar or that writes to a subregistry.

This definition expands the definition of Registrar to include cases such as:

  • The ETHRegistrarController that writes to BaseRegistrar (the owner of the “eth” TLD). Note how the definition of “Registrar” in the official ENS glossary only includes contracts that are pointed to by the owner field of the Registry. Therefore, the BaseRegistrar is a Registrar (and a Subregistry), while the ETHRegistrarController is a Subregistrar.
  • The contracts on Base that write to the Subregistry for direct subnames of base.eth. These contracts live on Base, therefore they cannot meet the definition of Registrar because they can’t be set as the owner in the Registry on Ethereum mainnet.
  • The offchain systems that write to the offchain databases associated with direct subnames of uni.eth and cb.id.
  • Any NFT marketplace that supports the exchange of an NFT representing ownership of an ENS name. Each time a NFT is exchanged, state about that NFT must be updated within a related subregistry. Therefore the marketplace enabling that trade is a Subregistrar.
  • Any DNS registrar, as ENS is a superset of DNS.

A Shadow Registry is a Subregistry meeting ALL of the following constraints:

  1. Not the Registry;
  2. Implemented as a smart contract exposing the same interface as the Registry;
  3. Used as part of the source of truth for a CCIP-Read Gateway Server for ENSIP-10 (wildcard resolution) powered subnames.

A specific implementation of a Shadow Registry can be found in this contract storing a subset of the state of base.eth subnames on Base.

Understanding how ENS names are processed and displayed requires precise terminology around name components and their various states. The following sections build from basic name resolution concepts to the specific classification and encoding systems used in ENSNode.

A name is a human-readable string like "vitalik.eth" composed of labels. A name may or may not be normalized.

Normalization is process of canonicalizing a name before running it through the Namehash algorithm. source

The namehash function computes a UUID 32-byte hash of a given name. If the name provided to namehash is not normalized then the resulting node is considered invalid.

The node is a hex-encoded 32-byte value that is derived from the name using the namehash algorithm defined in ENSIP-1. source

For the normalized name vitalik.eth, its node is 0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835.

https://docs.ens.domains/resolution/names#namehash

ENSNode must process labels from various onchain and offchain sources, each potentially in different states of normalization and availability. This section defines the core label processing concepts.

A Label is a human-readable string used as a segment of a name — i.e. vitalik and eth are the Labels of vitalik.eth. Labels are arbitrary unicode strings and may or may not be: normalized or unnormalized, known or unknown.

In the ENS Registry contract, only the name’s node is registered on-chain. Because of this there is no guarantee that a registered node is composed of normalized Labels or that those Labels are known. That is, when observing the Registry in isolation, the human-readable Labels that make up a name are not available (either on-chain or off-chain). That said, in many cases the Labels that make up a name can be made known: human-readable Labels can be emitted by contracts (i.e. the ETHRegistrarController or the NameWrapper), and in other cases the human-readable Label for a given LabelHash can be determined via rainbow table lookups and other strategies.

When rendering a name, one must take care to differentiate between an unknown Label (only identifiable by its 32-byte LabelHash) and a known Label potentially composed of hex characters. To do so, the unknown Label’s LabelHash is encoded as [{LabelHash}]. Examples are likely helpful:

  • vitalik.eth — a normalized name w/ normalized & known Labels
  • [731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22].eth — a name composed of two Labels
    1. an unknown Label (of unknown normalization): 0x731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22
    2. a normalized, known Label: eth
  • 731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22.eth — a normalized name composed of two Labels
    1. a normalized, known Label (that just so happens to be a set of 64 literal hex characters): 731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22
    2. a normalized, known Label: eth

In this terminology reference, we say that the LabelHash of a Label is the 32-byte hashed result of calling the labelhash function with that Label as input.

That is, 0xaf2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc is the LabelHash of vitalik, which is the result of calling the labelhash function like so:

import { labelhash } from 'viem';
const labelHash = labelhash("vitalik");

As ENSNode processes ENS data from multiple sources, labels and names exist in various states depending on normalization and data availability. These classifications are essential for proper display and validation.

A Normalized Label is a Label that has been processed through the ENS normalization algorithm and represents the canonical form of that label. The normalization process ensures consistent representation and prevents homograph attacks.

An Unnormalized Label is a Label that has not been processed through the ENS normalization algorithm, or one that would change if processed through normalization.

An Unknown Label is a Label for which the human-readable string is not available, and only the LabelHash is known. These labels are displayed using the Encoded LabelHash format: [{LabelHash}].

A Normalized Name is a name composed entirely of Normalized Labels. This represents the canonical form of a name that can be safely processed through the namehash function to produce a valid node.

An Unnormalized Name is a name that contains one or more Unnormalized Labels, meaning it has not been fully processed through the ENS normalization algorithm.

An Unknown Name is a name that contains one or more Unknown Labels, meaning the human-readable form of at least one label is not available and must be displayed using Encoded LabelHash format.

When human-readable names or labels are unavailable, ENSNode uses specific encoding formats for consistent display. These formats ensure users can distinguish between actual hex content and placeholder representations.

An Encoded LabelHash is a LabelHash that has been formatted for display when the corresponding Label is unknown. The encoding format wraps the hex representation of the LabelHash in square brackets: [{LabelHash}].

For example, if a LabelHash is 0x731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22, its Encoded LabelHash representation would be [731f7025b488151de311c24abc1f27f02940bde412246fbdb3dea0d4f0663b22].

An Encoded NameHash is a NameHash that has been formatted for display when the corresponding Name is unknown or not human-readable. The encoding format wraps the hex representation of the NameHash in square brackets: [{NameHash}].

For example, if a NameHash is 0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, its Encoded NameHash representation would be [ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835].

ENSNode’s indexing pipeline transforms raw blockchain data into user-friendly formats. This requires distinguishing between literal onchain data and the interpreted forms used in applications.

When processing ENS data, it’s important to distinguish between the literal data read from blockchain sources and the interpreted form used in applications:

A Literal Label is the raw label data as it exists in onchain storage or event data, before any processing or interpretation. This represents the exact bytes or string as emitted by contracts.

An Interpreted Label is a Literal Label that has been processed and classified as either:

  • A Normalized Label (if it passes normalization)
  • An Unknown Label (if it cannot be normalized or the human-readable form is unavailable)

A Literal Name is composed of Literal Labels as they appear in raw onchain data.

An Interpreted Name is composed of Interpreted Labels after processing, where each label has been classified and potentially converted to its appropriate display format (using Encoded LabelHash for unknown labels).