ERC-137 Ethereum Name Service (ENS) specification (Ethereum Domain Name Service - Specification)
Final · Names & metadata · created 2016-04-04
Defines the rules of a naming service that turns human-readable names such as 'vitalik.wallet' into resources such as contract addresses or content hashes. The name stays the same even when the resource changes.
Why it is needed
Without name resolution, users must memorize or copy long hexadecimal addresses, and must announce a new address every time a wallet or host changes. The original points out that existing Ethereum name resolution specifications and implementations also have limits. All names go into a single global namespace, and one central resolver handles resolution. There is almost no ability to delegate subdomains, and there is only one record type, so multiple resources cannot be attached to the same name. Also, because there is one global implementation, different name allocation schemes cannot be used, and name resolution, registration, and owner lookup (whois) are mixed together in one place. As a result, it is hard to have subnames such as live.mysite.tld, to put a Swarm app, a Whisper address and a mail server under one name, or to bring existing DNS records onto the blockchain.
What to implement
function owner(bytes32 node) constant returns (address);: Returns the address of the owner (registrar) of node.function resolver(bytes32 node) constant returns (address);: Returns the address of the resolver responsible for node.function ttl(bytes32 node) constant returns (uint64);: Returns the maximum time (TTL) for which node information may be cached.function setOwner(bytes32 node, address owner);: Transfers ownership of node to another registrar. Only the current owner can call it, and it emits a Transfer event.function setSubnodeOwner(bytes32 node, bytes32 label, address owner);: Creates a subnode with sha3(node, label) and sets its owner, or updates the owner if it already exists. It emits a NewOwner event.function setResolver(bytes32 node, address resolver);: Sets the resolver address of node. Only the owner can call it, and it emits a NewResolver event.function setTTL(bytes32 node, uint64 ttl);: Sets the TTL of node. It applies to both the registry record and the information returned by the resolver.function supportsInterface(bytes4 interfaceID) constant returns (bool): The only required function of a resolver. It returns true if the resolver implements the given 4-byte interface ID.function addr(bytes32 node) constant returns (address);: Returns the contract address linked to node. If there is no record, it returns the zero address.event AddrChanged(bytes32 indexed node, address a);: An event that must be emitted when the address record of node changes.
In depth
Three parts: registry, resolver, registrar
ENS consists of three parts. The registry is a single contract that links every registered name to its responsible resolver and lets the name owner change the resolver address or create subnames. A subname can have a different owner from its parent name. The resolver handles the actual resource lookup for a name and returns a contract address, content hash, IP address and so on. The registrar allocates names to users and is the only entity that can update ENS. In the registry, the owner of a node is that node's registrar. A registrar can be a contract or an externally owned account, but the root and top-level registrars are expected to be implemented at least as contracts. Name resolution has two steps. First, the name is hashed and the resolver address is obtained from the registry, and then the function matching the resource type is called on the resolver. Because namehash is determined by the name alone, it can be computed in advance and put into a contract, and lookup is O(1) regardless of the number of components in the name.
Name syntax and length recommendations
A name is a sequence of labels separated by dots. Each label must be a normalized label under UTS46, with the options transitional=false and useSTD3AsciiRules=true. In JavaScript, the idna-uts46 library can be used for normalization and validation. Both uppercase and lowercase letters can be used, but UTS46 normalization folds case before hashing, so two names with the same spelling that differ only in case produce the same namehash. There is no limit on label and domain length, but for compatibility with existing DNS it is recommended that labels be 64 characters or fewer and the full ENS name be 255 characters or fewer. For the same reason, it is recommended that labels not start or end with a hyphen and not start with a digit.
The namehash algorithm and test vectors
A name is hashed with namehash before it is used in ENS, and the result is called a node. The empty name is 32 zero bytes. Otherwise, the name is split at the first dot into a label and the remainder, and sha3(namehash(remainder) + sha3(label)) is computed recursively. That is, starting from the last component, the previous output and the label hash are concatenated and hashed again. 'mysite.swarm' is processed in the order node = 32 zero bytes, node = sha3(node + sha3('swarm')), node = sha3(node + sha3('mysite')). An implementation must satisfy the following test vectors. namehash('') is 0x0000000000000000000000000000000000000000000000000000000000000000, namehash('eth') is 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae, and namehash('foo.eth') is 0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f.
Registry functions and events
owner(node) returns the owner (registrar) of node, resolver(node) returns the resolver address, and ttl(node) returns the TTL, the maximum time for which node information may be cached. setOwner(node, owner) transfers ownership to another registrar. Only the current owner can call it, and on success it emits a Transfer(bytes32 indexed, address) event. setSubnodeOwner(node, label, owner) creates a new node with sha3(node, label) and sets its owner, or updates the owner if it already exists. Again only the current owner of node can call it, and it emits NewOwner(bytes32 indexed, bytes32 indexed, address). setResolver(node, resolver) sets the resolver address. Only the owner can call it, and it emits NewResolver(bytes32 indexed, address). setTTL(node, ttl) sets the TTL. The TTL applies not only to the registry's owner and resolver records but also to all information returned by the linked resolver.
Common resolver rules and supportsInterface
A resolver can implement any subset of the record types defined here. If a record type requires multiple functions, it must implement all of them or none. A resolver must have a fallback function that throws. The only required function is supportsInterface(bytes4 interfaceID). Defined in EIP-165, this function returns true if the resolver implements the interface with the given 4-byte identifier. An interface identifier is the XOR of the function signature hashes belonging to that interface, and if there is only one function it equals that function's signature hash. If it returns true, the resolver must actually implement the corresponding functions. It must always return true for 0x01ffc9a7, the ID of supportsInterface itself. The standardized interfaces are addr (0x3b3b57de, this document), name (0x691f3431, #181), ABI (0x2203ab56, #205) and pubkey (0xc8690233, #619), and other EIPs may add new interfaces.
The addr interface and zero address handling
A resolver that supports contract address resources must provide addr(bytes32 node). If it supports addr lookup but has no addr record for the requested node, it must return the zero address. A client that resolves an addr record must check for a zero return value and treat it exactly like a name with no resolver set, refusing to send funds to or interact with that address. If this is not followed, a user may accidentally send funds to the zero address. When the address changes, the resolver must emit the AddrChanged(bytes32 indexed node, address a) event.
What this document does not define, and appendix examples
The normative part of this document does not prescribe a specific implementation. Its purpose is to record the protocol so that different resolver implementations can resolve names consistently. It also does not cover how domains are registered or renewed, or how the party responsible for a domain is found. Registration is the registrar's job and is a governance matter that differs for each top-level domain. Record updates can also be handled separately from resolution, and a separate standard is expected for systems that need an update interface, such as Swarm. The appendices are examples only. Appendix A shows a registry implementation. Appendix B shows a built-in resolver that uses itself as the resolver, a standalone resolver that only the owner can update, and a public resolver that decides update permission by the registry's owner. Appendix C shows FIFSRegistrar, which gives names for free to whoever requests them first. The built-in resolver must throw on unknown calls, which can interfere with the normal operation of some contracts.