AlertSourceDiscuss
Skip to content

ERC-2544: ENS Wildcard Resolution

Adds support for "wildcard" resolution of subdomains in ENS.

🚧 StagnantERC

Stagnant

This EIP has had no recent activity for at least 6 months, and has automatically been marked as stagnant. This EIP should not be used in production.

If you are interested in helping move this EIP to final, create a PR to move this EIP back to Draft and add yourself as an author, and an EIP editor will help guide you through the process. Thank you!

AuthorsNick Johnson (@arachnid), 0age (@0age)
Created2020-02-28

Abstract ​

The Ethereum Name Service Specification (EIP-137) establishes a two-step name resolution process. First, an ENS client performs the namehash algorithm on the name 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 changes the name resolution process by adding an additional step if a resolver is not set for a domain. 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. This step is repeated until a node with a resolver is found.

Further, this specification defines a new way for resolvers to resolve names, using a unified resolve() method that permits more flexible handling of name resolution.

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 existing 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.

Let:

  • namehash be the algorithm defined in EIP 137.
  • dnsencode be the process for encoding DNS names specified in section 3.1 of RFC1035, with the exception that there is no limit on the total length of the encoded name. The empty string is encoded identically to the name '.', as a single 0-octet.
  • parent be a function that removes the first label from a name (eg, parent('foo.eth') = 'eth'). parent('tld') is defined as the empty string ''.
  • ens is the ENS registry contract for the current network.

EIP-2544-compliant ENS resolvers MAY implement the following function interface:

interface ExtendedResolver {
    function resolve(bytes calldata name, bytes calldata data) external view returns(bytes);
}

If a resolver implements this function, it MUST return true when supportsInterface() is called on it with the interface's ID, 0xTBD.

ENS clients will call resolve with the DNS-encoded name to resolve and the encoded calldata for a resolver function (as specified in EIP-137 and elsewhere); the function MUST either return valid return data for that function, or revert if it is not supported.

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

  1. Set currentname = name
  2. Set resolver = ens.resolver(namehash(currentname))
  3. If resolver is not the zero address, halt and return resolver.
  4. If name is the empty name ('' or '.'), halt and return null.
  5. Otherwise, set currentname = parent(currentname) and go to 2.

If the procedure above returns null, name resolution MUST terminate unsuccessfully. Otherwise, EIP-2544-compliant ENS clients MUST perform the following procedure when resolving a record:

  1. Set calldata to the ABI-encoded call data for the resolution function required - for example, the ABI encoding of addr(namehash(name)) when resolving the addr record.
  2. Set supports2544 = resolver.supportsInterface(0xTBD).
  3. If supports2544 is true, set result = resolver.resolve(dnsencode(name), calldata)
  4. Otherwise, set result to the result of calling resolver with calldata.
  5. Return result after decoding it using the return data ABI of the corresponding resolution function (eg, for addr(), ABI-decode the result of resolver.resolve() as an address).

Note that in all cases the resolution function (addr() etc) and the resolve function are supplied the original name, not the currentname found in the first stage of resolution.

Pseudocode ​

function getResolver(name) {
    for(let currentname = name; currentname !== ''; currentname = parent(currentname)) {
        const node = namehash(currentname);
        const resolver = ens.resolver(node);
        if(resolver != '0x0000000000000000000000000000000000000000') {
            return resolver;
        }
    }
    return null;
}

function resolve(name, func, ...args) {
    const resolver = getResolver(name);
    if(resolver === null) {
        return null;
    }
    const supports2544 = resolver.supportsInterface('0xTBD');
    let result;
    if(supports2544) {
        const calldata = resolver[func].encodeFunctionCall(namehash(name), ...args);
        result = resolver.resolve(dnsencode(name), calldata);
        return resolver[func].decodeReturnData(result);
    } else {
        return resolver[func](...args);
    }
}

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.

While introducing an optional resolve function for resolvers, taking the unhashed name and calldata for a resolution function increases implementation complexity, it provides a means for resolvers to obtain plaintext labels and act accordingly, which enables many wildcard-related use-cases that would otherwise not be possible - for example, a wildcard resolver could resolve id.nifty.eth to the owner of the NFT with id id in some collection. With only namehashes to work with, this is not possible. Resolvers with simpler requirements can continue to simply implement resolution functions directly and omit support for the resolve function entirely.

The DNS wire format is used for encoding names as it permits quick and gas-efficient hashing of names, as well as other common operations such as fetching or removing individual labels; in contrast, dot-separated names require iterating over every character in the name to find the delimiter.

Backwards Compatibility ​

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. Resolvers wishing to implement the new resolve function for non-wildcard use-cases (eg, where the resolver is set directly on the name being resolved) should consider what to return to legacy clients that call the individual resolution functions for maximum compatibility.

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.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Nick Johnson, 0age, "ERC-2544: ENS Wildcard Resolution[DRAFT]," Ethereum Improvement Proposals, no. 2544, 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2544.