Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Reverse Resolution

Reverse resolution maps an address back to an ENS name (the "primary name"). ENSv1 already supports multi-chain reverse resolution via per-chain L2 Reverse Registrars with signature-based claims (ENSIP-19). ENSv2 refines the signature-based claim system and integrates reverse resolution into the v2 registry hierarchy.

At Launch

At launch, the reverse namespace stays on v1 infrastructure. The reverse TLD is registered in the RootRegistry with ENSV1Resolver as its resolver. This configuration, called the ReverseMirror, lets the ENSv2 Universal Resolver read the existing v1 reverse records. There is no separate ReverseRegistry contract. Existing primary names continue to work without any user action.

Ethereum primary names (addr.reverse): The v1 ReverseRegistrar remains the write path. Its setName() and setNameForAddr() methods set the name record. claimForAddr() claims the reverse node and sets its owner and resolver, after which an authorized caller can write the name record on that resolver.

Default primary names: The v1 DefaultReverseRegistrar continues to store default names through setName() and setNameForAddr(). The ReverseMirror preserves the existing reverse-resolution routing, including fallback to a default primary name.

Contract Account Adapters

Contract accounts (multisigs, smart wallets, protocol contracts) can use two adapters that are controllers on the v1 registrars. Each adapter accepts an explicit account and checks whether the caller may name it before forwarding the update:

AdapterMethodForwards to
ReverseRegistrarAdapterclaim(account, resolver)ReverseRegistrar.claimForAddr()
DefaultReverseRegistrarAdaptersetName(account, name)DefaultReverseRegistrar.setNameForAddr()

Both adapters authorize the caller with the same "namer" check: the caller must be the account itself, the account's Ownable owner, or approved by the account's own IContractNamer.isContractNamer() implementation.

claim(account, resolver) assigns ownership of the reverse node to the caller. It does not set the name record. The caller must then set that record on the chosen resolver. For examples and deployment addresses, see Naming Contracts and mainnet deployments.

Migration to v2-native

The reverse namespace will be migrated to v2-native infrastructure post-launch. The same migration pattern applies to both testnet and mainnet. The full multi-chain reverse resolution system described below will be rolled out as L2 partner integrations are completed.

Multi-Chain Reverse Resolution (Upcoming)

ENSv2 introduces a new L2ReverseRegistrar designed to be deployed on each chain individually. Each deployment stores the mapping from addresses to their primary names for that chain. The Universal Resolver V2 resolves reverse lookups via the inherited reverse(lookupAddress, coinType) function, which queries the appropriate reverse registrar based on the coin type.

Setting a Primary Name

The L2ReverseRegistrar provides four methods for setting a primary name, covering different authorization models:

MethodAuthorizationUse case
setName(name)msg.sender onlyEOA setting its own primary name
setNameForAddr(addr, name)Caller is the address, its Ownable owner, or approved via the address's IContractNamerSetting from a different caller context
setNameForAddrWithSignature(claim, signature)ERC-191 signature from the addressGasless or cross-chain claims for EOAs
setNameForContractWithSignature(claim, owner, signature)owner passes the namer check (Ownable or IContractNamer) and provides an ERC-191 signature (ERC-1271/6492 supported)Contracts owned by smart contract wallets (Safe, ERC-4337)

Signature-Based Claims

For gasless or cross-chain primary name claims, the signature methods accept a NameClaim struct:

struct NameClaim {
    string name;       // The ENS name to set as primary
    address addr;      // The address to set it for
    uint256[] chainIds; // Chain IDs where this claim applies
    uint256 signedAt;  // Timestamp for replay protection
}

The chainIds array allows a single signature to set the primary name across multiple chains simultaneously. Chain IDs must be in strictly ascending order.

Signature Format

Signatures use ERC-191 plaintext format:

You are setting your ENS primary name to:
{name}
 
Address: {address}
Chains: {chainList}
Signed At: {signedAt}

Where {chainList} is a comma-separated list of chain IDs and {signedAt} is an ISO 8601 UTC datetime string.

For contracts (via setNameForContractWithSignature), the format includes an additional Owner field:

You are setting the ENS primary name for a contract you own to:
{name}
 
Contract Address: {address}
Owner: {owner}
Chains: {chainList}
Signed At: {signedAt}

Replay Protection

Signature-based methods use an inception timestamp system. Each address has a stored inception timestamp on-chain. For a signature to be valid:

  1. The signature's signedAt must be strictly greater than the current inception for that address
  2. The signedAt must not be in the future (signedAt <= block.timestamp)

When a valid signature is used, the inception is updated to the signedAt value. This ensures each signature can only be used once per chain, and newer signatures always supersede older ones. Query the current inception via inceptionOf(address).

Contract Name Sync

The L2ReverseRegistrar also supports syncName(addr) for contracts that implement the IContractName interface. This allows anyone to sync a contract's primary name without requiring a signature, using the name the contract itself declares.

Contracts

ContractStatusPurpose
RootRegistryDeployed at launchHolds the reverse TLD entry pointing to ENSV1Resolver
ENSV1ResolverDeployed at launchMirrors the v1 reverse namespace through the ReverseMirror configuration
ReverseRegistrarAdapterDeployed at launchContract-account adapter for addr.reverse claims
DefaultReverseRegistrarAdapterDeployed at launchContract-account adapter for default.reverse name setting
L2ReverseRegistrarUpcomingPer-chain reverse registrar with signature-based claims
StandaloneReverseRegistrarUpcomingAbstract base for L2ReverseRegistrar
L2ReverseRegistrarWithMigrationUpcomingVariant supporting migration from older reverse registrar deployments