Overview
The Ethereum Name Service (ENS) is an open, extensible naming system built on the Ethereum blockchain, currently the most widely used naming protocol within the Ethereum ecosystem. ENS transforms hard-to-read Ethereum addresses like 0x742d35Cc6634C0532925a3b844Bc454e4438f44e
into human-friendly names such as vitalik.eth
.
This guide assumes readers have intermediate Solidity programming knowledge. If you can understand standard ERC-20 contract implementations, you’ll be able to follow this material. For beginners, we recommend first studying Foundry Tutorial: Writing, Testing and Deploying ERC-20 Smart Contracts.
👉 Discover how ENS revolutionizes blockchain accessibility
Core Architecture
The ENS resolution system comprises two fundamental components:
1. Registry Contract
The Registry
serves as the foundational smart contract for ENS queries, maintaining three critical pieces of information:
- Domain owner (
owner
) - Domain resolver (
resolver
) - Time-to-live cache duration (
TTL
)
Domain owners can delegate management privileges to operators through the registry.
solidity
struct Record {
address owner;
address resolver;
uint64 ttl;
}
mapping(bytes32 => Record) records;
mapping(address => mapping(address => bool)) operators;
2. Resolver Contracts
Resolvers execute actual domain resolution. Any smart contract complying with ENS standards can function as a resolver, allowing custom record types. Current resolver implementations support:
- Ethereum addresses
- Cross-chain addresses (EVM-compatible chains)
- Content hashes (IPFS, Swarm)
- Text records (DNS, email, social profiles)
For complete specifications, consult ENS Improvement Proposals (ENSIPs) and the reference Resolver.sol implementation.
Resolution Process Flow
- Namehash Conversion: Applications first convert human-readable names to
namehash
identifiers - Resolver Lookup: The registry’s
resolver()
function retrieves the associated resolver contract - Record Query: The resolver’s specific functions (e.g.,
addr()
) return requested data
solidity
function resolver(bytes32 node) public view returns (address) {
return records[node].resolver;
}
Namehashing Mechanism
ENS uses a hierarchical hashing system called namehash
to maintain domain relationships. For vitalik.wallet.eth
:
- Name Normalization: Applies UTS46 standard for ASCII compatibility (case-insensitive)
- Recursive Hashing: Processes labels right-to-left to preserve hierarchy
“`python
from Crypto.Hash import keccak
def namehash(name: str):
labels = name.split(“.”)[::-1] # Reverse for processing
node = b’\x00′ * 32
for label in labels:
label_hash = keccak.new(data=label.encode(), digest_bits=256).digest()
node = keccak.new(data=node + label_hash, digest_bits=256).digest()
return node.hex()
“`
Key properties:
– Parent domains control subdomains through setSubnodeOwner()
– Enables permission management across domain levels
– Implemented in Solidity via keccak256(abi.encodePacked())
Address Resolution
Resolvers implement multi-chain address support through standardized coin types:
“`solidity
mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;
function addr(bytes32 node, uint256 coinType) public view returns (bytes memory) {
return versionable_addresses[recordVersions[node]][node][coinType];
}
“`
Reference implementations:
– Ethereum (CoinType 60): ENSIP-1
– Multi-chain: ENSIP-9
– CoinType registry: SLIP-0044
👉 Explore multi-chain address management with ENS
ENS Registration System
.ETH Registrar Contract
- Address:
0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85
- Function: Manages .eth domain registrations as ERC-721 NFTs
- TokenID:
keccak256(label)
of the registered name (e.g.,vitalik
)
Registration flow via register()
:
solidity
function _register(uint256 id, address owner, uint256 duration, bool updateRegistry) internal {
require(available(id));
expiries[id] = block.timestamp + duration;
if (_exists(id)) _burn(id);
_mint(owner, id);
if (updateRegistry) ens.setSubnodeOwner(baseNode, bytes32(id), owner);
}
Controller Architecture
Registration occurs through authorized controllers:
- Legacy Controller:
0x283Af0B28c62C092C9727F1Ee09C02CA627EB7F5
- Name Wrapper:
0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401
- Governance:
0xCF60916b6cb4753f58533808fA610FCbD4098EC0
(Safe multisig)
ENS Name Wrapper
Introduced to solve key limitations:
1. Subdomains couldn’t be NFTs
2. Parent domains lacked granular control over subdomains
3. Permission management was all-or-nothing
Wrapping Process
solidity
function wrapETH2LD(string calldata label, address wrappedOwner, uint16 fuses, address resolver) public {
uint256 tokenId = uint256(keccak256(bytes(label)));
registrar.transferFrom(registrant, address(this), tokenId);
registrar.reclaim(tokenId, address(this));
_wrapETH2LD(label, wrappedOwner, fuses, expiry, resolver);
}
Fuse Permission System
Bitmask-based permissions with expiration:
Fuse | Bit | Description |
---|---|---|
CANNOT_UNWRAP | 1 | Prevents unwrapping |
CANNOT_TRANSFER | 4 | Locks NFT transfers |
CANNOT_CREATE_SUBDOMAIN | 32 | Disables subdomain creation |
PARENT_CANNOT_CONTROL | 65536 | Emancipates from parent control |
Domain States
- Unwrapped: Traditional ENS record
- Wrapped: Parent maintains control
- Emancipated: Parent control revoked
- Locked: Permanent wrapper state
Frequently Asked Questions
How do I check if a domain is available?
Query the registrar’s available()
function with the name’s keccak256
hash. Domains are available if expired beyond the 90-day grace period.
Can I transfer a wrapped subdomain?
Only if the CANNOT_TRANSFER
fuse isn’t burned. Parent domains can restrict this permission before emancipating subdomains.
What’s the difference between .eth and other TLDs?
.eth domains:
– Are native ENS NFTs
– Have automatic emancipation
– Use the permanent registrar
– Support ETH payment for registration
How do I set up multi-chain addresses?
Use the resolver’s setAddr(bytes32 node, uint256 coinType, bytes memory address)
function with the appropriate SLIP-0044 coin type.
Can I recover an expired domain?
During the 90-day grace period, only the previous owner can renew. After grace period, anyone can register the expired name.
How does name wrapper improve security?
It enables:
– Granular permission controls
– Non-fungible subdomains
– Permanent locking mechanisms
– Hierarchical management structures