Skip to main content

Introduction

The ENS v2 migration system enables seamless transition of names from the ENS v1 NameWrapper to the new v2 registry architecture. The migration process preserves ownership, configuration, and permissions while upgrading to the enhanced v2 system.
Migration is a one-way process. Once a name is migrated to v2, it cannot be reverted to v1.

Migration Types

ENS v2 provides two distinct migration controllers based on the locked state of names:

Locked Migration

For .eth 2LD names with CANNOT_UNWRAP fuse set (locked names)

Unlocked Migration

For unwrapped .eth 2LD names and wrapped names without CANNOT_UNWRAP

Key Differences

Locked vs Unlocked Migration

AspectLocked MigrationUnlocked Migration
Target NamesWrapped .eth 2LDs with CANNOT_UNWRAPUnwrapped .eth 2LDs or wrapped without lock
ControllerLockedMigrationControllerUnlockedMigrationController
Fuse TranslationConverts fuses to v2 rolesN/A
SubregistryCreates WrapperRegistry via factoryStandard registration
Transfer MethodERC1155 safeTransferFromERC721/ERC1155 transfer
Pre-migrationRequires name to be RESERVEDDirect registration

Migration Architecture

Component Overview

Core Components

Handles migration of locked .eth 2LD names from the NameWrapper. Inherits from WrapperReceiver to:
  • Receive ERC1155 transfers from NameWrapper
  • Translate v1 fuses to v2 role bitmaps
  • Deploy deterministic WrapperRegistry subregistries
  • Register names in the ETH Registry with RESERVED permission
Handles migration of unlocked names (both wrapped and unwrapped). Features:
  • Accepts ERC721 transfers from the v1 Registrar (unwrapped names)
  • Accepts ERC1155 transfers from NameWrapper (unlocked wrapped names)
  • Unwraps locked names before migration
  • Registers names directly in ETH Registry v2
Abstract base contract providing ERC1155 receiver functionality for migration:
  • Implements IERC1155Receiver interface
  • Handles single and batch token transfers
  • Validates migration data against token IDs
  • Translates v1 fuses to v2 role bitmaps
  • Deploys subregistries via VerifiableFactory

Migration Process Flow

Locked Name Migration

1

Prepare Migration Data

Encode migration data including label, owner, resolver, and salt for CREATE2 deployment.
2

Transfer to Controller

Call NameWrapper.safeTransferFrom() sending the locked name to LockedMigrationController with migration data.
3

Receive and Validate

Controller receives token via onERC1155Received(), validates the data matches the token ID.
4

Deploy Subregistry

VerifiableFactory creates a deterministic WrapperRegistry using CREATE2 with the provided salt.
5

Translate Fuses

Convert v1 fuses to v2 role bitmaps for both token roles and subregistry roles.
6

Register in v2

Call ETH_REGISTRY.register() with the new owner, subregistry, resolver, and roles.
7

Burn Migration Fuses

If fuses not frozen, burn migration-specific fuses on the v1 token.

Unlocked Name Migration

1

Prepare Migration Data

Create MigrationData with transfer details (name, owner, resolver, roles, expiry).
2

Transfer to Controller

For unwrapped names: Transfer ERC721 from v1 Registrar. For wrapped unlocked: Transfer ERC1155 from NameWrapper.
3

Unwrap if Needed

If name is wrapped but unlocked, controller calls unwrapETH2LD() first.
4

Validate Token ID

Verify token ID matches the label hash from the encoded name.
5

Register in v2

Call ETH_REGISTRY.register() with migration data to create v2 registration.

Fuse to Role Translation

The migration process converts ENS v1 fuses to ENS v2 role-based permissions:

Token Roles (Parent Registry)

v1 Fusev2 RoleAdmin Role
CAN_EXTEND_EXPIRYROLE_RENEWROLE_RENEW_ADMIN
Not CANNOT_SET_RESOLVERROLE_SET_RESOLVERROLE_SET_RESOLVER_ADMIN
Not CANNOT_TRANSFERROLE_CAN_TRANSFER_ADMIN-

Subregistry Roles (Child Registry)

v1 Fusev2 RoleAdmin Role
Not CANNOT_CREATE_SUBDOMAINROLE_REGISTRARROLE_REGISTRAR_ADMIN
Always grantedROLE_RENEWROLE_RENEW_ADMIN
Admin roles are only granted if CANNOT_BURN_FUSES is not set, allowing future permission modifications.

Migration Data Structures

TransferData

Contains the core migration information:
struct TransferData {
    bytes dnsEncodedName;   // DNS-encoded name (e.g., "\x04nick\x03eth\x00")
    address owner;          // New owner in v2
    address subregistry;    // Subregistry contract (can be zero)
    address resolver;       // Resolver address
    uint256 roleBitmap;     // Role permissions bitmap
    uint64 expires;         // Expiration timestamp
}

MigrationData

Extends TransferData with deployment parameters:
struct MigrationData {
    TransferData transferData;  // Core transfer data
    uint256 salt;              // CREATE2 salt for deterministic deployment
}

Security Considerations

Critical Security Requirements:
  • Only locked names with CANNOT_UNWRAP are accepted by LockedMigrationController
  • Token ID must match the label hash to prevent name mismatch attacks
  • Owner cannot be zero address (enforced by ERC1155 standard)
  • Expired names cannot be transferred (enforced by NameWrapper)
  • LockedMigrationController requires ROLE_REGISTER_RESERVED permission

Validation Checks

The migration controllers perform strict validation:
  1. Caller Authorization: Only NameWrapper or Registrar can trigger migration
  2. Token ID Verification: namehash(parentNode, labelHash) must equal token ID
  3. Lock Status: Locked migration requires CANNOT_UNWRAP fuse
  4. Owner Validation: Owner address cannot be zero
  5. Expiry Check: Name must not be expired
  6. Data Size: Migration data must meet minimum size requirements

Reserved Names

For locked migration, names must be pre-reserved in the v2 ETH Registry:
The RESERVED status ensures names cannot be registered through normal registration flows before migration completes.

Reservation Process

  1. Administrator marks names as RESERVED in ETH Registry v2
  2. Locked migration can register reserved names
  3. Attempting to register reserved names through other flows reverts

Batch Migration

Both controllers support batch migration for gas efficiency:
// Batch migrate multiple locked names
NameWrapper.safeBatchTransferFrom(
    owner,
    lockedMigrationController,
    tokenIds,
    amounts,
    abi.encode(migrationDataArray)
);
Batch migration is more gas-efficient when migrating multiple names. The ERC1155 batch transfer reduces overhead compared to individual transfers.

Error Handling

Common migration errors:
Cause: Transfer not from NameWrapper or RegistrarSolution: Use the correct transfer function from the appropriate contract
Cause: Attempting locked migration on unlocked nameSolution: Use UnlockedMigrationController instead
Cause: Token ID doesn’t match computed namehashSolution: Verify label and parent node are correct
Cause: Token ID doesn’t match label hash in migration dataSolution: Ensure DNS-encoded name matches the token being migrated
Cause: Unlocked controller received a locked nameSolution: Use LockedMigrationController for locked names
Cause: Migration data too small or malformedSolution: Ensure data is properly ABI-encoded with required fields

Post-Migration State

After successful migration:
  • Name registered in ETH Registry v2 with owner and roles
  • Subregistry bound to deterministic WrapperRegistry
  • v1 fuses translated to v2 role permissions
  • Migration-specific fuses burned on v1 token (if not frozen)
  • Resolver transferred or cleared based on CANNOT_SET_RESOLVER
  • Original v1 token remains in controller
  • Name registered in ETH Registry v2 with specified configuration
  • Subregistry and resolver set according to migration data
  • Expiry timestamp preserved from v1
  • Original v1 token (ERC721 or ERC1155) held by controller

Best Practices

Verify Lock Status

Always check if a name is locked before choosing the migration controller.

Use Deterministic Salts

Choose salt values carefully for predictable subregistry addresses.

Preserve Resolver

Ensure resolver addresses are correct in migration data to maintain name resolution.

Batch When Possible

Use batch transfers for multiple names to save gas.

Test First

Test migration on testnet before migrating valuable names.

Verify Roles

Confirm role bitmaps grant expected permissions after migration.

Next Steps

Locked Migration

Learn about migrating locked .eth 2LD names

Unlocked Migration

Learn about migrating unlocked names

Build docs developers (and LLMs) love