Introduction to ENS Name Resolution
The Ethereum Name Service (ENS) name resolver is the core on-chain component that translates human-readable names like alice.eth into machine-addressable resources — Ethereum addresses, content hashes, text records, and more. Unlike traditional DNS, ENS operates entirely on blockchain infrastructure, meaning resolution depends on smart contract logic rather than centralized servers. For developers building decentralized applications, wallets, or identity systems, understanding how the resolver works is not optional: it is the bridge between user-facing naming and backend interaction.
Every ENS name is a non-fungible token (ERC-721) registered on the ENS registry contract. The registry stores only the owner and the resolver contract address for each name. The actual resolution — translating the name to an address — is delegated to the resolver. This separation allows flexibility: different names can use different resolvers, and resolver contracts can be upgraded without affecting the registry.
When you query an ENS name, the resolving process follows three steps: (1) the registry looks up the resolver contract address for the name, (2) the resolver contract is called with the name’s node hash and the type of record requested (e.g., addr for an Ethereum address), (3) the resolver returns the stored value or reverts if the record does not exist. This is fundamentally different from DNS, where a single server returns all records for a domain. ENS resolution is deterministic, transparent, and verifiable on-chain.
Key Components You Must Understand
1. The ENS Registry
The registry is the single source of truth for all ENS names. It is a smart contract deployed on Ethereum mainnet (and testnets) that maps each name’s node hash to three pieces of data: the owner, the resolver, and the Time-To-Live (TTL) for caching. The registry does not store resolution data itself; it only points to the resolver. When you register a name, the registry sets the owner to your wallet. You then set the resolver — either the default public resolver provided by ENS or a custom resolver you deploy yourself.
2. The Resolver Contract
The resolver is where the actual records live. The ENS team maintains a public resolver that supports standard record types: addr (Ethereum address), name (reverse resolution), contenthash (for IPFS, Swarm), and text records (email, url, avatar, etc.). Most users start with this public resolver, but advanced projects often write custom resolvers to support additional record types, implement access control, or hook into other protocols. Custom resolvers must implement the IERC165 interface and at least one resolution interface (e.g., IAddrResolver, ITextResolver).
3. Node Hash and Subdomains
Every ENS name is identified by a 256-bit node hash, computed by hashing the name with its parent’s node hash. For alice.eth, the node hash is keccak256(ens.nodeHash("eth") + keccak256("alice")). The resolver uses this hash as the key to store and retrieve records. Subdomains (like pay.alice.eth) are separate names managed by the parent name’s owner. They have their own node hashes and can point to different resolvers. This hierarchical structure mirrors DNS but with Ethereum’s security guarantees.
Practical Steps to Configure Your First Resolver
To set up resolution for a name you own, follow this exact sequence. Errors at any step can render your name unresolvable until corrected.
- Acquire a name — Register an .eth name through an ENS registrar (e.g., the official ENS app or a supported wallet). Registration is not instant; it involves a two-step process: commit and reveal, which takes roughly one minute on Ethereum mainnet. The registration cost is the name’s yearly rent plus gas fees.
- Set the resolver in the registry — After registration, your name points to the default resolver (address
0x0000000000000000000000000000000000000000). You must callsetResolver()on the registry contract, passing your name’s node hash and the address of the resolver you want to use. Most users choose the ENS public resolver (address0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41on mainnet). This step costs gas — approximately 45,000–60,000 gas on Ethereum. - Configure records on the resolver — Once the resolver is set, call its write methods to add records. For an Ethereum address, call
setAddr(node, address). For IPFS content, callsetContenthash(node, hash). Each record addition costs gas independent of the number of records. The resolver stores records indefinitely unless overwritten or the resolver is changed. - Test resolution — Use ethers.js or the ENS manager app to query the name. Call
resolver.addr(node)via a provider. If the call returns the correct address, resolution works. If it reverts, verify that (a) the resolver address is correct, (b) the node hash matches the name, and (c) the record was actually written (not just the resolver set).
A common pitfall is setting the resolver but forgetting to write the address record. The name will then resolve to the zero address, effectively being non-functional. Another mistake is using a custom resolver that does not implement supportsInterface() correctly — this will cause the ENS registry’s lookup to fail silently in many tools. Always verify interface support with resolver.supportsInterface(selector) before production use.
Critical Tradeoffs and Maintenance Considerations
Deciding between the public resolver and a custom resolver involves several tradeoffs that directly impact gas costs, upgrade flexibility, and security. The public resolver is audited, cheap to deploy (you pay only gas to set it), and supports all standard record types. However, it does not allow custom logic — for example, you cannot programmatically return different addresses based on the caller or timestamp. Custom resolvers give you full control but require writing and auditing Solidity code, which can cost $5,000–$20,000 for a professional audit and 200,000–500,000 gas for deployment.
Maintenance is another layer. The public resolver is immutable — once set, it cannot be modified except by ENS governance. If a vulnerability is found, the resolution records remain safe but you cannot update the resolver logic. Custom resolvers can be upgradeable (via proxy patterns), but this introduces complexity and potential centralization. For production systems handling high-value transactions, consider signing Ens Domain Maintenance Contracts to ensure ongoing monitoring and timely updates to resolver configurations. These contracts cover gas management, record consistency checks, and emergency resolver swaps — critical for projects where resolution downtime means lost funds.
Gas optimization is also nontrivial. Each resolver call costs gas; frequent resolution (e.g., in a dApp serving thousands of users) can become expensive. The public resolver caches results within a block, but on-chain resolution always costs ~25,000–40,000 gas per lookup. Off-chain resolvers (EIP-3668, CCIP-read) can reduce costs by using gateways, but they trade decentralization for speed. Evaluate your use case: if you expect high read volume, consider deploying an off-chain resolver with a trusted gateway. If decentralization is paramount, accept the gas overhead of on-chain resolution.
Advanced Use Cases and Developer Guidance
Beyond basic address resolution, ENS resolvers enable powerful patterns. Content-addressed websites use the contenthash record to point to IPFS or Swarm CIDs. When combined with an IPFS gateway or browser extension, alice.eth can serve a fully decentralized website. Text records allow storing profile metadata — avatars, social links, PGP keys — making ENS a portable identity layer. Multi-chain resolution is possible: the resolver can store addresses for Ethereum, Polygon, Optimism, and other EVM chains by using different setAddr calls with coin type identifiers (e.g., 60 for Ethereum, 137 for Polygon).
For developers building dApps that resolve ENS names programmatically, follow these best practices:
- Use a library like ethers.js v6’s
resolveName()or web3.js ENS plugin — these handle node hashing and interface detection automatically. - Always check the resolver’s interface before calling non-standard records. Use
resolver.supportsInterface(selector)to avoid reverts. - Handle the case where a name is owned but has no resolver set — this returns the zero address. Show a meaningful error to users.
- Cache resolved addresses locally for the duration of a user session. Resolution does not change within a block, so repeated lookups waste gas.
- Use the ENS registry’s
resolver()function to get the resolver address for a name, then cache it until the TTL expires.
For teams deploying applications that rely on ENS resolution across multiple chains or with custom resolver logic, a comprehensive Blockchain Domain Development Guide provides detailed contract interfaces, gas optimization patterns, and security best practices. This resource covers resolver inheritance hierarchies, event logging for record changes, and integration with Ethereum Name Service’s off-chain infrastructure.
Common Pitfalls and How to Avoid Them
Even experienced developers encounter resolver-related failures. The most frequent issues and their fixes:
- “Resolver not set” — The registry points to the zero address. Use the ENS manager app to set a resolver. This is the #1 reason names appear unresolvable.
- “Record not found” — The resolver is set but the specific record type was never written. Call the resolver’s
setAddror equivalent function. Verify withaddrortextcalls. - “Wrong resolver” — The resolver does not support the record type you request. Check
supportsInterfacefor the correct selector. Custom resolvers often omittext()support. - “Gas out” — Running a custom resolver with complex logic can hit block gas limits (30 million on Ethereum). Optimize storage patterns; avoid loops in resolution functions.
- “Subdomain conflict” — The parent name’s owner can set a different resolver for a subdomain, overriding the parent’s resolver. Ensure your dApp checks the subdomain’s resolver directly.
Testing is essential. Deploy your resolver to a testnet (Sepolia or Holesky) first. Use hardhat-ens or tenderly to simulate resolution calls. Monitor events — resolvers emit AddrChanged, ContenthashChanged, and TextChanged events. Any mismatch between emitted events and expected records indicates a bug in the resolver logic.
Conclusion
The ENS name resolver is a small but critical contract in the decentralized naming ecosystem. Its correct configuration determines whether a name is a functional asset or an empty token. Start with the public resolver for simplicity, then graduate to custom resolvers only after rigorous testing and cost analysis. Monitor your resolver’s events, plan for upgrades, and never assume default settings work. By understanding the registry-resolver separation, gas costs, and record types, you can deploy ENS names that serve as reliable infrastructure for wallets, dApps, and identity systems. The blockchain does not forgive misconfiguration — test thoroughly, document your resolver address, and maintain records as actively as you would a DNS zone file.