Compass Quarterly Online

ens history

How ENS History Works: Everything You Need to Know

June 14, 2026 By Noa Hayes

Introduction to ENS History

The Ethereum Name Service (ENS) transforms human-readable names like "alice.eth" into machine-readable identifiers such as Ethereum addresses, content hashes, and metadata records. But beyond its core naming functionality, ENS maintains a comprehensive, immutable history for every registered domain. Understanding how ENS history works is critical for developers building dApps that rely on name resolution, for domain investors verifying ownership chains, and for auditors tracking configuration changes over time.

ENS history is not a single data structure but a composite of multiple on-chain events, off-chain signatures, and resolver interactions. This article dissects the architecture behind ENS history, explains how past states are reconstructed, and provides actionable techniques for querying historical data.

The Core Components of ENS History

ENS history is built on three foundational layers: the Registry, the Resolver, and the Registrar. Each component logs its own set of events, and together they form a complete audit trail.

1. The ENS Registry

The ENS Registry is the central smart contract that stores the owner of each domain, the resolver address, and the Time-to-Live (TTL) for caching. Every change to these parameters emits an event:

  • NewOwner(bytes32 indexed node, bytes32 indexed label, address owner) — logged when ownership of a domain (or subdomain) is transferred.
  • NewResolver(bytes32 indexed node, address resolver) — emitted when the resolver contract for a domain is updated.
  • NewTTL(bytes32 indexed node, uint64 ttl) — recorded when the caching TTL for a domain is changed.
  • Transfer(bytes32 indexed node, address owner) — a legacy event from earlier registry versions.

These events are append-only. Once written, they cannot be altered, ensuring an immutable history of ownership and resolver assignments. To reconstruct the state of a domain at any past block number, one must scan these events up to that block and apply the most recent change.

2. The Resolver

The Resolver is a separate smart contract that maps a domain to its actual records—addresses, texts, content hashes, etc. Resolver history is tracked via the ABIChanged, AddrChanged, ContenthashChanged, NameChanged, PubkeyChanged, TextChanged, and DNSRecordChanged events. Each event includes the node (namehash) and the updated value.

Notably, resolver history is not automatically linked to the registry. If a domain switches to a new resolver contract, the old resolver's historical events remain in that contract's logs. To get a complete view, you must combine registry events (to know which resolver was active when) with resolver events from that contract.

3. The Registrar

The Registrar (e.g., the .eth permanent registrar) handles name registration, renewal, and expiration. Key events include:

  • NameRegistered(string indexed name, bytes32 indexed label, address owner, uint256 cost, uint256 expires)
  • NameRenewed(string indexed name, bytes32 indexed label, uint256 cost, uint256 expires)
  • NameTransferred(string indexed name, bytes32 indexed label, address newOwner) (in some registrar implementations)

These events allow you to determine when a domain was first registered, how many times it has been renewed, and when it will expire. Because the registrar contract interacts with the registry (to set the initial owner), cross-referencing registrar events with registry events is often necessary.

How ENS History Is Stored and Indexed

ENS history does not reside in a single database. Instead, it is distributed across:

  1. Ethereum blockchain logs — Every event described above is stored in the transaction receipt logs of the respective smart contracts. These logs are immutable and accessible via any Ethereum node (e.g., via eth_getLogs).
  2. ENS subgraph (The Graph) — The official ENS subgraph indexes all registry, resolver, and registrar events into a GraphQL endpoint. This provides a queryable, relational view of history, including derived fields like domain.events and resolver.addrEvents.
  3. DNS record history (off-chain) — For DNS-based names (e.g., .com domains imported into ENS), history is stored off-chain via the DNS oracle. These records are not on Ethereum but are verified through SPV proofs.

For most practical purposes, developers query the subgraph because it offers fast, filtered access to history without scanning raw logs. However, for mission-critical applications (e.g., verifying ownership at a specific block for a legal dispute), raw log queries directly from the registry contract are recommended due to their trustlessness.

Practical Methods for Querying ENS History

Below are three concrete approaches to retrieve ENS history, ordered by increasing complexity and trust assumptions.

Method 1: Using the ENS Subgraph (Recommended for Most Cases)

The ENS subgraph at https://api.thegraph.com/subgraphs/name/ensdomains/ens exposes entities like Domain, Resolver, NameRegistered, and NameRenewed. Example GraphQL query to get ownership history for "vitalik.eth":

{
  domains(where: {name: "vitalik.eth"}) {
    events {
      type
      blockNumber
      transactionID
      from
      to
    }
  }
}

This returns a chronological list of ownership changes, resolver updates, and TTL modifications. The subgraph also provides resolver.addrEvents to track address record changes over time. Note that the subgraph is updated with a ~10-second delay from the latest block, so for real-time data, use Method 2.

Method 2: Direct Log Queries via RPC (Trustless, Real-Time)

For a trustless, block-level reconstruction, use the eth_getLogs JSON-RPC method. The registry contract address is 0x00000000000C2e074eC69A0dFb2997BA6C7d2e1e. To get all ownership events for a domain with namehash 0x1234...:

curl -X POST https://mainnet.infura.io/v3/YOUR_KEY \
  -H "Content-Type: application/json" \
  --data '{
    "jsonrpc":"2.0",
    "method":"eth_getLogs",
    "params":[{
      "address":"0x00000000000C2e074eC69A0dFb2997BA6C7d2e1e",
      "topics":["0xb7d7b9db8e6d8795c4e2e0a8f26f5b5e1e9e5f5a5c5e5d5e5f5g5h5i5j5k5l5m5","0x1234..."],
      "fromBlock":"0x0",
      "toBlock":"latest"
    }],
    "id":1
  }'

You must convert the domain name to its namehash (a bytes32 Keccak-256 hash) using the namehash algorithm. The returned logs include the block number, transaction index, and log index, allowing you to sort events chronologically. To reconstruct the state at block B, filter events with blockNumber <= B and take the last occurrence of each event type. This method is computationally intensive for frequent queries but gives absolute finality.

Method 3: Combining Registrar and Resolver History

To track the full lifecycle of a domain (registration → ownership changes → resolver updates → address changes), you must join events from the registrar, registry, and resolver contracts. The registrar for .eth is 0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5. Its NameRegistered event provides the initial owner and expiration date. Then, registry NewOwner events show subsequent owner transfers. Finally, resolver events (e.g., AddrChanged) show address record changes for each resolver that was active at the time. This combined view is what the ENS subgraph provides out-of-the-box, but doing it manually gives you maximum control and auditability.

Historical Name Resolution: The Ens Pubkey Use Case

One specific application of ENS history is retrieving the public key record associated with a domain at a past point in time. The Ens Pubkey record stores an ECDSA public key (x, y coordinates) that can be used for encryption, identity verification, or authentication protocols. To fetch the historical pubkey, you need to query the resolver contract's PubkeyChanged events for the given domain namehash. Then, you must determine which resolver was active at the target block by checking the registry's NewResolver events. Only after combining these can you confirm the public key that was valid at block height B. This process is essential for applications like secure messaging dApps that need to encrypt messages to a user's past key (e.g., before they rotated it).

Limitations and Tradeoffs

ENS history is not without constraints. Here are the key limitations to consider:

  • Log pruning — Full Ethereum nodes typically prune old logs after ~128 blocks for performance. Unless you run an archival node, direct log queries beyond this window may return empty results. The ENS subgraph does not suffer from this issue because it indexes logs continuously.
  • Resolver migrations — If a domain switches resolvers, the old resolver's events are no longer linked to the domain in the registry. You must know the old resolver's address to query its logs. The subgraph handles this by storing resolver-address-to-block mappings, but manual queries require tracking these migrations.
  • Off-chain records — Some ENS records (e.g., text records pointing to IPFS content) may reference off-chain data that can change independently of on-chain history. ENS history only covers the on-chain pointer, not the off-chain content's history.
  • Gas cost of queries — Scanning large ranges of logs (e.g., from genesis) is expensive in terms of RPC compute units. For production systems, incremental indexing or subgraph caching is far more efficient.

Best Practices for Developers

When building applications that rely on ENS history, follow these guidelines:

  1. Use the ENS subgraph for 95% of use cases. It is maintained by the ENS team, updated within seconds, and free to query. For critical data, double-check with raw logs.
  2. Always fetch the resolver address from the registry before querying resolver events. A stale resolver means outdated records.
  3. For time-sensitive operations (e.g., verifying an address at the time of a transaction), filter all events by block number descending and pick the first match. Do not rely on event order within the same block—use log index as a secondary sort key.
  4. Cache historical results if your application queries the same domain repeatedly. ENS history is immutable, so a given block number will always return the same data.
  5. When participating in an ENS Domain Auction, note that auction history (e.g., bids, reveals) is stored in the old registrar contract (0x6090A6e47849629b7245Dfa1ca21D94cd15878ef for the .eth temporary registrar). These events are distinct from the permanent registrar's history and may require separate queries.

Conclusion

ENS history is a rich, immutable record of domain ownership, resolver assignments, and record changes. By understanding the three core components—Registry, Resolver, and Registrar—and how their events interrelate, you can reconstruct any past state of an ENS domain with precision. Whether you use the convenient subgraph or query raw logs for maximum trustlessness, the principles remain the same: event ordering, block height filtering, and resolver-to-domain linking. As ENS continues to evolve with off-chain data and layer-2 integrations, the foundational mechanics of its history will remain a bedrock for decentralized naming infrastructure.

See Also: How ENS History Works:

Explore the mechanics of ENS history, from name registration and renewal to resolver updates and record retrieval. A technical deep dive for developers and domain investors.

Key takeaway: How ENS History Works:

External Sources

N
Noa Hayes

Reader-funded analysis and commentary