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_UNWRAPKey Differences
Locked vs Unlocked Migration
| Aspect | Locked Migration | Unlocked Migration |
|---|---|---|
| Target Names | Wrapped .eth 2LDs with CANNOT_UNWRAP | Unwrapped .eth 2LDs or wrapped without lock |
| Controller | LockedMigrationController | UnlockedMigrationController |
| Fuse Translation | Converts fuses to v2 roles | N/A |
| Subregistry | Creates WrapperRegistry via factory | Standard registration |
| Transfer Method | ERC1155 safeTransferFrom | ERC721/ERC1155 transfer |
| Pre-migration | Requires name to be RESERVED | Direct registration |
Migration Architecture
Component Overview
Core Components
LockedMigrationController
LockedMigrationController
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
WrapperRegistrysubregistries - Register names in the ETH Registry with
RESERVEDpermission
UnlockedMigrationController
UnlockedMigrationController
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
WrapperReceiver
WrapperReceiver
Abstract base contract providing ERC1155 receiver functionality for migration:
- Implements
IERC1155Receiverinterface - 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
Prepare Migration Data
Encode migration data including label, owner, resolver, and salt for CREATE2 deployment.
Transfer to Controller
Call
NameWrapper.safeTransferFrom() sending the locked name to LockedMigrationController with migration data.Receive and Validate
Controller receives token via
onERC1155Received(), validates the data matches the token ID.Deploy Subregistry
VerifiableFactory creates a deterministic WrapperRegistry using CREATE2 with the provided salt.Unlocked Name Migration
Prepare Migration Data
Create
MigrationData with transfer details (name, owner, resolver, roles, expiry).Transfer to Controller
For unwrapped names: Transfer ERC721 from v1 Registrar.
For wrapped unlocked: Transfer ERC1155 from NameWrapper.
Fuse to Role Translation
The migration process converts ENS v1 fuses to ENS v2 role-based permissions:Token Roles (Parent Registry)
| v1 Fuse | v2 Role | Admin Role |
|---|---|---|
CAN_EXTEND_EXPIRY | ROLE_RENEW | ROLE_RENEW_ADMIN |
Not CANNOT_SET_RESOLVER | ROLE_SET_RESOLVER | ROLE_SET_RESOLVER_ADMIN |
Not CANNOT_TRANSFER | ROLE_CAN_TRANSFER_ADMIN | - |
Subregistry Roles (Child Registry)
| v1 Fuse | v2 Role | Admin Role |
|---|---|---|
Not CANNOT_CREATE_SUBDOMAIN | ROLE_REGISTRAR | ROLE_REGISTRAR_ADMIN |
| Always granted | ROLE_RENEW | ROLE_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:MigrationData
ExtendsTransferData with deployment parameters:
Security Considerations
Validation Checks
The migration controllers perform strict validation:- Caller Authorization: Only NameWrapper or Registrar can trigger migration
- Token ID Verification:
namehash(parentNode, labelHash)must equal token ID - Lock Status: Locked migration requires
CANNOT_UNWRAPfuse - Owner Validation: Owner address cannot be zero
- Expiry Check: Name must not be expired
- 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
- Administrator marks names as
RESERVEDin ETH Registry v2 - Locked migration can register reserved names
- Attempting to register reserved names through other flows reverts
Batch Migration
Both controllers support batch migration for gas efficiency:Error Handling
Common migration errors:UnauthorizedCaller(address caller)
UnauthorizedCaller(address caller)
NameNotLocked(uint256 tokenId)
NameNotLocked(uint256 tokenId)
Cause: Attempting locked migration on unlocked nameSolution: Use
UnlockedMigrationController insteadNameDataMismatch(uint256 tokenId)
NameDataMismatch(uint256 tokenId)
Cause: Token ID doesn’t match computed namehashSolution: Verify label and parent node are correct
TokenIdMismatch(uint256 tokenId, uint256 expectedTokenId)
TokenIdMismatch(uint256 tokenId, uint256 expectedTokenId)
Cause: Token ID doesn’t match label hash in migration dataSolution: Ensure DNS-encoded name matches the token being migrated
MigrationNotSupported()
MigrationNotSupported()
Cause: Unlocked controller received a locked nameSolution: Use
LockedMigrationController for locked namesInvalidData()
InvalidData()
Cause: Migration data too small or malformedSolution: Ensure data is properly ABI-encoded with required fields
Post-Migration State
After successful migration:For Locked Names
For Locked Names
- 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
For Unlocked Names
For Unlocked Names
- 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