Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Decentralized Naming Service for User Handles

A technical guide to building a decentralized naming service from scratch. Covers core smart contracts for registration, renewal, and resolution, plus integration patterns for social profiles.
Chainscore © 2026
introduction
GUIDE

Setting Up a Decentralized Naming Service for User Handles

A practical guide to implementing user-friendly, blockchain-based naming systems for your application, covering core concepts and integration steps.

Decentralized naming services (DNS) translate human-readable names, like alice.eth, into machine-readable identifiers such as wallet addresses, content hashes, or smart contract addresses. Unlike traditional DNS controlled by centralized entities, blockchain-based systems like the Ethereum Name Service (ENS) and Unstoppable Domains are managed by smart contracts on public networks. This provides censorship resistance, user ownership, and interoperability across the Web3 ecosystem. For developers, integrating a DNS allows users to replace long, complex hexadecimal addresses with memorable handles, significantly improving the user experience for sending payments, logging into dApps, or displaying verified profiles.

The core technical component is a registry smart contract that maintains a mapping of names to resolvers. A name, like username.eth, is registered by a user who becomes its controller. The registry points that name to a resolver contract, which then holds the actual records, such as the associated Ethereum address (ETH), Bitcoin address (BTC), or IPFS content hash. When your dApp needs to resolve username.eth, it queries the registry for the resolver address, then queries that resolver for the specific record type. This two-step architecture allows for flexible record management and future upgrades without modifying the central registry.

To integrate a DNS like ENS into your application, you'll primarily interact with its smart contracts. For Ethereum, the mainnet ENS Registry address is 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e. Using a library like ethers.js or web3.js, you can resolve names programmatically. For example, to get the Ethereum address for vitalik.eth, you would call the resolver's addr() function with the name's namehash (a unique, normalized hash of the name). Most libraries provide abstractions for this. The ENS Public Resolver (address: 0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41) is the standard contract for storing common record types.

Registering a new name typically involves a two-step process: requesting the name and finalizing the registration after a short wait period to prevent front-running. This is managed by the ENS Registrar controller contracts. For .eth names, registration is an annual subscription paid in ETH. Your application can facilitate this by estimating gas costs, checking name availability via the registrar's available() function, and guiding the user through the commit-reveal transaction sequence. Always direct users to the official ENS Manager app (app.ens.domains) for direct management, as handling user funds and private keys in your dApp introduces significant security risks.

Beyond simple address resolution, modern DNS support text records for rich metadata. You can store and retrieve profile information like an avatar URL (avatar), website link (url), Discord handle (com.discord), or a GitHub username (com.github). This enables decentralized identity and verifiable social profiles. When designing your application, consider querying these records to display verified user information. The Cross-Chain Interoperability Protocol (CCIP) allows resolvers to be smart contracts themselves, enabling names to be resolved via logic on other chains (L2s, non-EVM), which is crucial for a multi-chain future.

Key considerations for production use include caching resolutions to reduce RPC calls and latency, handling expiration and renewal states gracefully, and providing clear UX for when a name is unavailable or points to a zero address. Always use the latest contract addresses from official documentation (docs.ens.domains) and consider using a service like The Graph for indexed historical queries. By abstracting away cryptographic addresses, decentralized naming services are a fundamental primitive for building accessible, user-owned, and interoperable Web3 applications.

prerequisites
DECENTRALIZED IDENTITY

Prerequisites and Setup

Essential tools and concepts required to build with decentralized naming services like ENS and Unstoppable Domains.

Before interacting with a decentralized naming service (DNS) like Ethereum Name Service (ENS) or Unstoppable Domains, you need a foundational setup. This includes a Web3 wallet, access to a blockchain network, and a basic understanding of smart contract interactions. The primary prerequisite is a wallet such as MetaMask or Rainbow that holds the native cryptocurrency (e.g., ETH for Ethereum, MATIC for Polygon) to pay for transaction fees, known as gas. You will use this wallet to register, manage, and resolve names on-chain.

You must also choose which blockchain network to build on. While ENS is native to Ethereum, its .eth names are now resolvable on many Layer 2 networks like Arbitrum, Optimism, and Polygon via the CCIP-Read protocol. Unstoppable Domains primarily mints NFTs on Polygon. For development, you'll need a connection to an RPC endpoint. You can use public providers like Infura or Alchemy, or run a local node. For testing, configure your wallet to use a testnet like Sepolia or Goerli to avoid spending real funds.

From a development perspective, you need a JavaScript or TypeScript environment. The most common library for interacting with these services is ethers.js (v6) or viem. You'll also need the official smart contract ABIs. For ENS, the core contracts are the ENS Registry, the Registrar Controller, and the Public Resolver. Install the necessary packages using npm or yarn: npm install ethers or npm install viem. For direct contract interaction, you can find verified contract addresses on Etherscan for mainnet and testnets.

Understanding the two core actions is crucial: registration and resolution. Registration is the process of minting a new name (like alice.eth) by calling a registrar contract and paying a fee, which is often an annual subscription. Resolution is the reverse process: converting a human-readable name into a machine-readable address or other resource. This is done by querying the resolver contract associated with a name. Each name is an NFT (ERC-721), giving the owner full control and transferability.

Finally, consider the data you want to associate with a name. Beyond a simple cryptocurrency address, modern resolvers can store and serve multicoin addresses (BTC, LTC), IPFS content hashes for decentralized websites, Socials (like Twitter handle), and text records (email, description). Setting these records requires calling specific methods on the resolver contract. Always estimate gas costs and test thoroughly on a testnet before proceeding to mainnet to ensure your transactions execute correctly and your application logic is sound.

core-architecture
CORE SYSTEM ARCHITECTURE

Setting Up a Decentralized Naming Service for User Handles

This guide explains how to architect and deploy a decentralized naming system for user handles, similar to ENS or Unstoppable Domains, using smart contracts on Ethereum.

A decentralized naming service maps human-readable names like alice.eth to machine-readable identifiers such as Ethereum addresses, content hashes, or other metadata. The core architecture typically involves three key smart contracts: a registry, a registrar, and a resolver. The registry is the central authority that stores the mapping from a namehash (a cryptographic hash of the name) to the owner's address and the resolver contract. The registrar handles the business logic for registering and renewing names, often implementing an auction or fixed-price model. The resolver is responsible for returning the specific records (like an ETH address or IPFS hash) associated with a name when queried.

To build this system, you first deploy the core ENSRegistry contract, which implements the ERC-721 standard for non-fungible tokens (NFTs), making each name a transferable asset. The registry's crucial function is setResolver(node, resolver), which allows the owner of a name to specify which resolver contract holds its records. A common practice is to use a public resolver like the PublicResolver contract from the ENS codebase, which supports standard record types defined in EIPs such as EIP-137 for address resolution and EIP-634 for text records.

Next, you need a registration mechanism. For a simple, first-come-first-served system, you can deploy a FIFSRegistrar. For a more sophisticated approach that prevents name squatting, implement a Vickrey auction or a commit-reveal scheme as used in early ENS. Modern systems often use a permanent registrar with a renewable lease model. Here, users register names by calling register(string name, address owner, uint duration) on the registrar contract, which then calls the registry's setOwner and setResolver functions. The registration cost usually scales with the name length and duration.

The final component is the resolver. While you can use a standard public resolver, you may need a custom resolver to store application-specific data. A basic resolver contract must implement the EIP-137 interface, specifically the addr(bytes32 node) function. For example, a resolver storing a Twitter handle would implement a text(bytes32 node, string key) function where the key could be "com.twitter". All data reads are gas-free calls, while writes (setting records) are transactions that can only be performed by the name's owner.

Integrating this system into a dApp involves using a library like ethers.js or web3.js to interact with the contracts. To resolve alice.eth to an address, your frontend would: 1) Compute the namehash using a library like eth-ens-namehash. 2) Query the registry for the resolver address: registry.resolver(namehash). 3) Query the resolver for the address record: resolver.addr(namehash). For registration, you would guide the user through approving the transaction to the registrar contract. Always ensure your UI handles edge cases like expired names or unset records gracefully.

Key considerations for production include implementing wrapped names (ERC-1155 for better UX), setting a sensible price oracle for renewal fees, and planning for upgradability of the resolver logic. Security audits are critical, especially for the registrar logic handling funds. By following this architecture, you can create a censorship-resistant foundation for user identity within your application's ecosystem, leveraging battle-tested patterns from established protocols.

registration-logic
SMART CONTRACT DEVELOPMENT

Implementing Registration and Renewal Logic

This guide details the core smart contract logic for a decentralized naming service, focusing on secure registration and automated renewal mechanisms.

The foundation of a decentralized naming service is a smart contract that maps a unique handle (like alice.eth) to an owner's address and associated metadata. The primary data structure is a mapping: mapping(string => Record) public records;. The Record struct typically contains the owner's address, an expiration timestamp, and a resolver address for storing additional data like an avatar or social links. Registration logic must first check that the handle is not already taken and that the caller has paid the required registration fee, often denominated in the network's native token or a designated ERC-20 token.

A critical security consideration is preventing front-running during registration. A naive register function that simply checks availability and writes to storage is vulnerable. A common pattern is to implement a commit-reveal scheme. First, a user submits a hash of their desired handle, a secret salt, and their address. After a short delay, they call a second function to "reveal" and claim the handle, providing the original data. The contract recalculates the hash to verify the commitment, ensuring no one can snipe the handle after it's revealed. The Ethereum Name Service (ENS) documentation provides a detailed example of this pattern.

Renewal logic is essential for the service's sustainability. Handles are typically registered for a fixed period, such as one year. The contract must track an expiration timestamp for each record. A renew function allows the current owner (or any payer) to extend this timestamp by paying a renewal fee, which can be identical to or differ from the initial registration fee. It's crucial that this function updates the existing record's expiration in a way that prevents overflow and correctly calculates the new time: record.expires = record.expires + extensionDuration;. Automated renewal reminders can be built off-chain by monitoring these public expiration timestamps.

For advanced functionality, consider implementing a grace period and a release mechanism. After a handle expires, a grace period (e.g., 90 days) allows only the previous owner to renew it, preventing immediate squatting. If the grace period lapses, the handle should enter a release state where anyone can register it anew. This requires additional state tracking but provides a better user experience. Furthermore, integrating with a price oracle or a governance token can allow for dynamic pricing models, where registration costs fluctuate based on handle length, demand, or protocol treasury needs.

Finally, all monetary transactions should follow the checks-effects-interactions pattern to prevent reentrancy attacks. Always transfer fees to a designated treasury address after updating the contract's internal state. Thorough testing with frameworks like Foundry or Hardhat is non-negotiable. Write tests for: successful registration and renewal, failed registration (handle taken, insufficient fee), front-running mitigation, correct expiration math, and proper access control for admin functions like fee withdrawal. A well-audited contract is the bedrock of user trust in your naming service.

resolution-integration
TUTORIAL

Name Resolution and Frontend Integration

A practical guide to implementing decentralized naming services for user-friendly Web3 applications.

Decentralized naming services, like the Ethereum Name Service (ENS) or Unstoppable Domains, map human-readable names (e.g., alice.eth) to machine-readable identifiers such as blockchain addresses, content hashes, and metadata. This process, called name resolution, is fundamental for creating accessible user experiences. Instead of requiring users to copy and paste long hexadecimal strings like 0x71C7656EC7ab88b098defB751B7401B5f6d8976F, they can simply use a memorable handle. Frontend integration involves querying these services to resolve names to their underlying data and vice-versa, abstracting blockchain complexity from the end-user.

To resolve a name in your application, you interact with the naming service's smart contracts or APIs. For ENS on Ethereum, the core contract is the Public Resolver. Using a library like ethers.js or viem, you can resolve a .eth name to an address. For example, the function provider.resolveName('alice.eth') returns the associated Ethereum address. The reverse process—resolving an address to a primary name—uses the reverse() function on the ENS registry. It's crucial to handle network states and fallbacks, as a name may not be registered or could expire.

Beyond simple address resolution, modern naming services support multichain addresses and text records. An ENS name can store addresses for Bitcoin (BTC), Litecoin (LTC), and layer-2 networks like Arbitrum and Optimism. Text records can hold profile metadata such as an email, website URL (url), or Discord handle (com.discord). Querying this enriched data allows you to build richer profiles. Always verify the resolver address for a name is set and points to an up-to-date contract, as outdated resolvers may not support newer record types.

For production frontends, consider performance and caching. Resolving names requires on-chain calls or API requests, which can be slow. Implement client-side caching using tools like React Query or SWR to store resolution results and minimize redundant network calls. For a seamless experience, you can also use client-side libraries like ENSjs or the Unstoppable Domains Resolution library, which handle cross-chain resolution logic and provide TypeScript support. Always provide clear user feedback during resolution and have fallback UI states for pending, successful, and failed lookups.

Security is paramount. When displaying a resolved name, you must validate the resolution result. A malicious contract could return incorrect data. For critical operations like sending funds, consider performing a reverse resolution to confirm the name is correctly associated with the address. Be aware of homoglyph attacks where names use similar-looking characters (e.g., etherеum.eth with a Cyrillic 'е'). Using libraries that normalize names to their canonical form (like ENS's namehash algorithm) helps mitigate this. Always refer to the official documentation for the specific naming service you are integrating.

PROTOCOL OVERVIEW

Comparison of Naming Service Features

Key technical and operational differences between leading decentralized naming services for on-chain user handles.

FeatureENS (Ethereum)Lens ProtocolUnstoppable Domains

Primary Chain

Ethereum Mainnet

Polygon

Polygon

Underlying Standard

ERC-721

ERC-721 with Profile Metadata

Polygon NFT (ERC-721)

Registration Model

Annual renewable lease

Mint-once, own forever

One-time purchase, own forever

Primary Use Case

Wallet addresses, website URLs

Social media handles, identity graphs

Web3 websites, crypto payments

Resolver System

Modular, customizable

Built-in social graph resolver

Centralized gateway with decentralized storage

Annual Renewal Fee

Subdomain Support

Text Record Support

Default TLD

.eth

.lens

.crypto, .x, .nft

Gas Fee for Registration

High (Ethereum mainnet)

Low (Polygon L2)

Low (Polygon L2)

Primary SDK/Library

ethers.js / wagmi

Lens SDK / API

Resolution Libraries

DECENTRALIZED NAMING

Frequently Asked Questions

Common questions and troubleshooting for developers implementing decentralized naming services like ENS, Unstoppable Domains, and Lens Protocol for user handles.

A decentralized naming service (DNS) is a blockchain-based system that maps human-readable names to machine-readable identifiers like cryptocurrency addresses, content hashes, or metadata. It functions as a public, permissionless registry, replacing centralized domain name authorities.

Core components:

  • Registry: A smart contract (e.g., ENS's ENSRegistry) that maintains a list of domains and their owners.
  • Registrar: A smart contract (e.g., BaseRegistrar) that handles the rules for registering new names, often via an auction or fixed-price sale.
  • Resolver: A smart contract that translates a name into the actual resource, like an Ethereum address or IPFS hash. You must set a resolver for a name to be usable.

When a user queries vitalik.eth, their wallet first asks the ENS Registry who owns it and which Resolver to use, then queries that Resolver for the associated Ethereum address.

conclusion-next-steps
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have successfully configured a decentralized naming service for user handles. This guide covered the core concepts and setup process.

You have now established a foundational system for managing user identities on-chain. The key components you've implemented include: a registry smart contract to map human-readable names to addresses, a resolver contract to attach metadata like avatars or social links, and a basic frontend for user interaction. This architecture provides censorship-resistant, user-owned identities that can be integrated across dApps, moving beyond traditional, platform-locked usernames. The next step is to enhance this system's utility and security.

To build upon your implementation, consider these advanced features: integrating with an oracle like Chainlink for off-chain data verification, adding subdomain delegation for organizational structures, or implementing a reputation system where on-chain activity builds a verifiable score linked to the handle. For production, you must also implement a robust minting strategy, such as a commit-reveal scheme to prevent frontrunning, and establish clear renewal and expiration logic to manage namespace scarcity. Security audits for your custom resolver logic are essential before mainnet deployment.

For further learning, explore established protocols like the Ethereum Name Service (ENS) to understand their architecture for inspiration, or Lens Protocol's handle system which integrates social graph data. The Decentralized Identity Foundation (DIF) provides specifications for verifiable credentials you could attach to your handles. Continue by testing cross-dApp interoperability with your new handles and contributing to open standards that define the future of decentralized identity on the web.

How to Build a Decentralized Naming Service for User Handles | ChainScore Guides