How the Ethereum Name Service (ENS) and Chainlink Data Feeds Simplify the Smart Contract Developer Experience

The Ethereum Name Service or ENS provides human-readable names for blockchain addresses, offering Ethereum users and developers alike a simplified experience. With legible addresses, users can interact with smart contracts without the hassle of using long character hashes, which can be confusing and lead to mistakes.

Chainlink is moving toward using ENS as the source of truth for Data Feeds addresses. With this in mind, it is important to understand what ENS is and how it works.

What Is ENS?

ENS is a service that enables distributed, open, and extensible naming on the Ethereum blockchain. Or, to put it simply, it is a lookup service. ENS has a simple job: It maps human-readable names to machine-readable addresses. In this sense, it is similar to the Domain Name Service, or DNS, which replaces IP addresses with domain names. But rather than IP addresses, ENS replaces blockchain addresses with human-readable names.

ENS provides a naming service for addresses, hashes, and other identifiers. Without ENS, users need to know the full 64-character address of a contract or wallet on the Ethereum blockchain in order to interact with it. 

ENS provides the ability to use human-readable addresses. These addresses can be used as domains, which enables domain hierarchy, meaning subdomains can be assigned to an ENS address.

What Does ENS Mean for Chainlink?

Top-level ENS domains are owned by smart contracts called registrars. These registrars supply the rules governing the allocation of subdomains. On the `.eth` top-level domain, Chainlink has collaborated extensively with ENS to provide the `data.eth` domain, which contains an identifiable index of Chainlink Price Feed addresses, making it easier to discover Chainlink oracle networks on the Ethereum blockchain. This means developers are able to use human-readable addresses like `eth-usd.data.eth` in place of contract addresses such as `0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419`.

Using ENS in Javascript

Using ENS to resolve domain names is straightforward in Javascript libraries that support Web3. Using web3.js, this is as simple as

var address = ens.getAddress('eth-usd.data.eth');

Other libraries that support ENS can be found in the ENS documentation.

Crafting a Node Hash

​Things get more interesting when ENS addresses are used on-chain. 

The ENS documentation makes reference to node hashes. A node hash is constructed with a recursive algorithm that takes each component of the domain, separated by `.`s, and hashes them together. Based on the specifications for EIP-137 the pseudo-code for this algorithm is:

def namehash(name):
 if name == '':
   return '\0' * 32
 else:
   label, _, remainder = name.partition('.')
   return sha3(namehash(remainder) + sha3(label))

The name is split into its components, then, starting with the last component, concatenated together. The resulting node hash for `eth-usd.data.eth` would be created through the following steps.

node = '\0' * 32
node = sha3(node + sha3('eth'))
node = sha3(node + sha3('data'))
node = sha3(node + sha3('eth-usd'))

It is important to note that in order to produce the correct output from the hashing algorithm, the name must first be normalized. ENS requires that anyone using it must follow UTS46 for normalization and validation.

Given the complexity of this process, it is recommended to pass the node hash to a contract rather than computing it on-chain. The eth-ens-namehash npm package performs both the normalization and hashing for you.

Additionally, The Graph has an API available for finding data about ENS domains; `labelhash` is the specific field that contains this information, but there is also much more information available.

Resolving On-Chain

​Once the node hash for an ENS address has been defined, it can be used to resolve the contract address on-chain. Again, this is useful as, to the resolver, the node hash and the human-readable address are the same. The resolver acts as the source of truth for the address of the entity we are resolving. In this case, that would be one of the Chainlink Data Feeds.

In the on-chain Solidity contract, you would need to implement a couple of interfaces for the ENS contract and resolver.

abstract contract ENS {
   function resolver(bytes32 node) public virtual view returns (Resolver);
}

abstract contract Resolver {
   function addr(bytes32 node) public virtual view returns (address);
}

Once those interfaces have been defined, a simple resolver can be created to convert the node hash to an address.

contract MyContract {
   // This is the ENS registry address
   // It is the same address for Mainet, Ropsten, Rinkerby, Gorli and other networks;
   ENS ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);

   function resolve(bytes32 node) public view returns(address) {
       Resolver resolver = ens.resolver(node);
       return resolver.addr(node);
   }
}

Wrapping Up

Chainlink has chosen to use ENS to act as a source of truth for Data Feeds addresses. ENS eliminates the need to use long addresses and helps ensure interactions occur with the correct blockchain address. To learn more about ENS and Chainlink, head to the Chainlink documentation. You can also explore how to create your own NFT domain name using ENS or Unstoppable Domains, which you can use to direct users to your website or dApp.

Learn more about Chainlink by visiting chain.link or read the documentation at docs.chain.link. To discuss an integration, reach out to an expert.

Need Integration Support?
Talk to an expert
Faucets
Get testnet tokens
Read the Docs
Technical documentation