EIP-2544 ENS Wildcard Resolution

EIP 2544 (ENS Wildcard Resolution)

author: Nick Johnson (@arachnid), 0age (@0age)

Simple Summary

EIP-2544 extends ENS client behavior to support “wildcard” resolution of subdomains. This is accomplished by using a parent domain’s resolver if none is set on a given subdomain.

Abstract

The Ethereum Name Service Specification (EIP-137) establishes a two-step name resolution process. First, an ENS client takes a provided name, performs the namehash algorithm to determine the associated “node”, and supplies that node to the ENS Registry contract to determine the resolver. Then, if a resolver has been set on the Registry, the client supplies that same node to the resolver contract, which will return the associated address or other record.

As currently specified, this process terminates if a resolver is not set on the ENS Registry for a given node. This EIP extends the existing name resolution process by adding an additional step if a resolver is not set for subdomain. This step strips out the leftmost label from the name, derives the node of the new fragment, and supplies that node to the ENS Registry. If a resolver is located for that node, the client supplies the original, complete node to that resolver contract to derive the relevant records.

Motivation

Many applications such as wallet providers, exchanges, and dapps have expressed a desire to issue ENS names for their users via custom subdomains on a shared parent domain. However, the cost of doing so is currently prohibitive for large user bases, as a distinct record must be set on the ENS Registry for each subdomain.

Furthermore, users cannot immediately utilize these subdomains upon account creation, as the transaction to assign a resolver for the node of the subdomain must first be submitted and mined on-chain. This adds unnecessary friction when onboarding new users, who coincidentally would often benefit greatly from the usability improvements afforded by an ENS name.

Enabling wildcard support allows for the design of more advanced resolvers that deterministically generate addresses and other records for unassigned subdomains. The generated addresses could map to counterfactual contract deployment addresses (i.e. CREATE2 addresses), to designated “fallback” addresses, or other schemes. Additionally, individual resolvers would still be assignable to any given subdomain, which would supersede the wildcard resolution using the parent resolver.

Another critical motivation with EIP-2544 is to enable wildcard resolution in a backwards-compatible fashion. It does not require modifying the current ENS Registry contract or any assigned resolvers, and continues to support existing ENS records — legacy ENS clients would simply fail to resolve wildcard records.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

EIP-2544-compliant ENS clients MUST perform the following sequence when determining the resolver for a given name:

  1. Apply the namehash algorithm to the supplied name as specified in EIP-137 to derive the node.
  2. Call the ENS Registry contract, supplying the node as the argument to function resolver(bytes32 node) constant returns (address).
  3. If an address other than the null address is returned, the client MUST use the returned address as the resolver.
  4. If the null address is returned, the client MUST strip the leftmost label from the name to derive a new name.
  5. If the only remaining label is a top-level domain, or if no labels remain, the client MUST refuse to interact with the resolver.
  6. Apply the namehash algorithm to the new name as specified in EIP-137 to derive the parentNode.
  7. Call the ENS Registry contract, supplying the parent node as the argument to function resolver(bytes32 node) constant returns (address) to determine the resolver.
  8. If the null address is returned from this second request, the client MUST refuse to interact with the resolver.

In the event that a non-null resolver is located via this process, the client MUST supply the full, original node to the resolver to derive the address or other records. As with EIP-137, clients attempting to resolve an address via function addr(bytes32 node) constant returns (address) MUST refuse to interact with the returned address when the null address is returned.

Pseudocode

function getNodeAndResolver(name) {
    // 1. Apply the namehash algorithm to supplied name to determine the node.
    const node = namehash(name);
    
    // 2. Attempt to retrieve a resolver from the ENS Registry using the node.
    let resolver = ENS_REGISTRY.methods.resolver(node).call();
    
    // 3. Use the resolver if a non-null result is returned from the registry.
    if (resolver != "0x0000000000000000000000000000000000000000") {
        return (node, resolver);
    }
    
    // 4. Remove the leftmost label from the name.
    const labelsWithoutLeftmost = name.split(".").slice(1);
    
    // 5. Do not continue if only the top-level domain (or no domain) remains.
    if (labelsWithoutLeftmost.length < 2) {
        throw new Error("ENS resolver not found.");
    }
    
    // 6. Apply the namehash algorithm to new name to determine the parent node.
    const parentNode = namehash(labelsWithoutLeftmost.join("."));
    
    // 7. Attempt to retrieve a resolver from registry using the parent node.
    resolver = ENS_REGISTRY.methods.resolver(parentNode).call();
    
    // 8. Do not continue if a null result is returned from the registry.
    if (resolver == "0x0000000000000000000000000000000000000000") {
        throw new Error("ENS resolver not found.");
    }

    // Return the located resolver along with the original node.
    return (node, resolver);
};

Rationale

The proposed implementation supports wildcard resolution in a manner that minimizes the impact to existing systems. It also reuses existing algorithms and procedures to the greatest possible extent, thereby easing the burden placed on authors and maintainers of various ENS clients.

It also recognizes an existing consensus concerning the desirability of wildcard resolution for ENS, enabling more widespread adoption of the original specification by solving for a key scalability obstacle.

By not recursively applying the namehash operation after removing successive leftmost subdomains, round-trip requests are reduced and edge cases around overriding ownership of nested subdomains are adequately handled. ENS clients may optimize further for reduced latency by utilizing a helper contract that performs the logic necessary to support wildcard resolution.

Backwards Compatibility

There are no backwards compatibility concerns — existing ENS clients that are compliant with EIP-137 will fail to resolve wildcard records and refuse to interact with them, while those compliant with EIP-2544 will continue to correctly resolve, or reject, existing ENS records.

Security Considerations

While compliant ENS clients will continue to refuse to resolve records without a resolver, there is still the risk that an improperly-configured client will refer to an incorrect resolver, or will not reject interactions with the null address when a resolver cannot be located.

Additionally, resolvers supporting completely arbitrary wildcard subdomain resolution will increase the likelihood of funds being sent to unintended recipients as a result of typos. Applications that implement such resolvers should consider making additional name validation available to clients depending on the context, or implementing features that support recoverability of funds.

There is also the possibility that some applications might require that no resolver be set for certain subdomains. For this to be problematic, the parent domain would need to successfully resolve the given subdomain node — to the knowledge of the authors, no application currently supports this feature or expects that subdomains should not resolve to a record.

Example Implementation

Copyright

Copyright and related rights waived via CC0.

3 Likes

I remember discussion this exact mechanism at the ENS meetup in Osaka (just before Devcon 5). An issue that was raised is:

How is the parent node’s resolver supposed to know what the values for the child node are?

There also is the issue of who has the right to set these values, considering the node they refer to might not have an owner. A usecase we consider could benefit from wildcard resolution is that of counterfactually deployed wallet accounts, before the deployment actually goes through. We believed in that case, the resolver would need to know the leftmost label + parent’s node. Having the child’s node alone would be very limited.

I’d be curious what usecases could be built with the resolution mechanism. Considering the new ENS registry allows for accelerated setup, just saving the “setResolver” transaction seems not such a great improvement if you still need to create a subnode with the right ownership anyway.

I think these are all valid points, and they certainly merit discussion. The main motivating factor with this EIP is not to work out the ideal structure for wildcard resolution mechanics or ownership rights, but rather to simply enable shared, “fallback” resolvers via a modification that is as straightforward as possible to implement and that does not introduce any new interfaces, algorithms, or other new procedures.

Imagine a dApp where 10,000 users have checked out the frontend and chosen a username, but only 1,000 of those users have actually interacted with the on-chain contracts. If that project wants to support ENS for every user, they would currently need to set a unique resolver for each and every one of their users — this is a pretty extreme cost to bear when you consider that many of those users will never use the name at all.

With even basic wildcard resolution, this limitation evaporates. Every single user gets an ENS name right away, for free, and a more targeted resolver and owner can be assigned as soon as they’ve used it for the first time (for instance, this setup could happen during contract creation when deploying to the counterfactual address returned for the given subdomain).

The last leg of this process (i.e. what gets passed to the resolver) is a great area for future exploration, but the primary rationale for this EIP is pretty tightly focused on how to locate a resolver for wildcard addresses. There is a prescription for how to proceed once a resolver has been located, but this is mostly just designed to clear up any ambiguity and could be extended in future EIPS:

In the event that a non-null resolver is located via this process, the client MUST supply the full, original node to the resolver to derive the address or other records.

Does an incremental approach like the one outlined here seem reasonable to you, @Amxx?

Exciting improvement and simple solution. I remember discussion from @ricmoo about further utilization of wildcards at the Osaka meetup. It might be out of scope for this topic but would be great to have a reference to it recorded here as well. Was there ever anything formally or informally written about those extensions and what the blockers were?

1 Like

It’s true that the current proposal doesn’t convey that. In my mind there are two compelling reasons to go with the current solution:

  • Doing otherwise would require changing every profile (record type) of every resolver in order to support a new parameter for wildcard domains. Even then, resolvers would only get keccak256('label'), not the plaintext label.
  • Most uses for the hashed label can also be achieved with the namehash of the whole name. It’s easy to go from plaintext label and parent namehash to the namehash of the child node when looking things up.
1 Like