Abstract
This proposal activates ENSv2 on Ethereum mainnet. Once executed, it:
- freezes new
.ethregistrations on the v1 registrar; - authorises the contracts that keep unmigrated names renewable and clean up after migrated ones;
- hands ownership of the v1
BaseRegistrarto a renew-only contract; - points the Universal Resolver at a proxy that will carry the switch to v2 resolution.
Afterwards, ENS Labs will:
- run a final pre-migration sync so every live v1 name is reserved for its current owner on v2;
- open registrations on the v2
ETHRegistrar; - cut resolution over to v2;
- transfer every admin role it holds over the v2 contracts to the DAO.
When that's done, the DAO controls ENSv2 just as it controls v1 today, and Labs holds no privileged role in either.
Motivation
The ENS registry we deployed in 2017 is a single flat mapping from namehash to owner, resolver and TTL. Everything built since then - the permanent registrar, the NameWrapper, fuses, wildcard resolution, CCIP-read - has been layered on top of that mapping rather than built into it. It's held up well, but the cost shows: the NameWrapper exists largely to bolt on permissions the registry can't express, and it's the single most complex and least well understood part of ENS today.
ENSv2 replaces the flat registry with a hierarchy of registries. Every name can have its own registry for its subnames, and owners can bring their own registry and resolver implementations rather than relying on standard implementations. Permissions are fine-grained roles on each name instead of irreversible fuses, so it's possible to give a subname owner exactly the rights you intend - set a resolver but not transfer, say - without wrapping anything.
How activation works
Activation runs in five stages, and at the end of them the DAO holds every privileged role over both v1 and v2. Only stage 2 needs a vote; every other stage either has already happened or is something Labs commits to carry out once this proposal executes.
- Deployment and initial pre-migration (Labs, done before this vote). Labs has deployed the full v2 contract set to mainnet, with the v2
ETHRegistrardeployed but not authorised to register names. Labs has then reserved every active or in-grace v1.ethsecond-level name on v2 for its current owner, via aBatchRegistrarthat only Labs controls. Reserved names are owned by the migration controller in v2; they continue to resolve throughENSV1Resolver, which reads their existing v1 records. - This proposal executes (DAO). In a single atomic transaction, the DAO:
- points the v1
.ethresolver atENSV2Resolverand authorises the v2 reverse registrar adapters on the v1 reverse registrars; - approves the two current v1
PublicResolvers in v2'sPublicResolverSet, so names that use them move to the v2PublicResolverwhen they migrate; - approves the standalone HCA implementation in the
StandaloneHCAFactory, so the factory can deploy HCA accounts; - removes every remaining controller from the v1
BaseRegistrar, freezing new v1 registrations; - authorises
ETHRenewerV1, so names that haven't migrated yet stay renewable; - authorises the
Graveyard, which holds migrated v1 tokens and reclaims v1 names once they've expired past grace; - transfers ownership of the v1
BaseRegistrartoETHRenewerV1, which can renew but cannot add controllers or register names; - points the Universal Resolver proxy at an intermediate proxy that, for now, still serves v1 resolution.
- points the v1
- Final pre-migration sync (Labs). Labs exports a fresh snapshot of v1 registrations taken after the freeze and re-runs pre-migration. This picks up any name registered or renewed between the first pre-migration run and the freeze.
- v2 goes live (Labs). Labs revokes the
BatchRegistrar's roles, ending pre-migration for good; enables the two migration controllers and grantsETHRegistrarthe right to register and renew.ethnames. Labs asks the security council to upgrade the UniversalResolver implementation to point at UR v2. From this point, new registrations happen on v2, and resolution of every name goes through the v2 registry. - Handover to the DAO (Labs). Labs transfers every admin role it holds over v2 to the DAO timelock and renounces its own: root roles on the v2 root and
.ethregistries, and ownership of theBatchRegistrars used for.ethand DNS suffix seeding. Labs transfers the.ethand.reversetokens in the v2 root registry to a Safe (0x5B716D6587d241166bC8914858640F8684F3A2F3) whose sole owner is the DAO timelock. The tokens go to a Safe rather than to the timelock itself because the timelock can't receive ERC-1155 tokens. The intermediate Universal Resolver proxy is administered by the security council, not Labs, and stays with the security council. Labs will publish each transaction and a script that checks the deployer holds no remaining role.
The registrar, renewer and other ownable v2 contracts are deployed with the DAO timelock (0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7) as owner from the start. Registration and renewal fees on v2, including renewals of unmigrated names through ETHRenewerV1, are paid directly to the ENS Endowment (endowment.ensdao.eth, 0x4F2083f5fBede34C2714aFfb3105539775f7FE64), which is owned by the ENS Foundation and managed by Karpatkey. The fee recipient is fixed at deployment, so nothing about revenue changes hands in stage 5. The time between stages 2 and 4 is set by how long the final sync takes; we expect it to be a few hours. During this time, registrations won’t be possible on either ENSv1 or ENSv2, but all other name operations continue as normal on ENSv1. Renewals of unmigrated names will be possible once the DAO proposal executes, via the new renewer contract.
What changes for name owners
If you own a .eth name and do nothing, it keeps working. It resolves exactly as it does today, and you can keep renewing it as usual; renewing it also extends its reservation on v2. There's no deadline to migrate.
When you're ready, you can move your name to v2 using the ENS app. Wrapped names with locked permissions keep them, so any guarantees you've given to holders of your subnames carry across. Once a name has moved, it's managed on v2 from then on.
A few details worth knowing:
- Expiry. Your name lapses on exactly the same day on v2 as it would have on v1. v2 has a shorter grace period, 28 days rather than 90, so each name's v2 expiry is extended by 62 days to make up the difference.
- Expired names. Names that have already lapsed past their grace period aren't carried across, and become available for anyone to register on v2.
- New registrations and renewals. Between this proposal executing and v2 going live, new names can't be registered. Existing names can still be renewed, through
ETHRenewerV1. - Pricing. Registrations and renewals on v2 use the pricing the DAO approved in
EP 6.43, paid in USDC or DAI. This applies from the moment this proposal executes, including to renewals of names that haven't migrated yet. - Apps and integrations. All apps and integrations need to be updated to resolve against the
UniversalResolverto make them v2-compatible. The DevRel team have been working hard to get this done and the majority of integrations are already v2-ready.
Risks and rollback
The v1 freeze is reversible; migrating a name is not. Until stage 4, nothing a name owner does on v2 is final, and the DAO can undo stage 2 with a further executable proposal: as owner of ETHRenewerV1, it can call transferRegistrarOwnership to hand the BaseRegistrar back to RegistrarSecurityController and then re-add the v1 controllers. Once owners start migrating, their v1 tokens are held by the Graveyard, which has no means of returning them.
Five things change about how ENS is protected:
- No emergency disable on v1. Today
RegistrarSecurityControllerlets an emergency controller (0xaA5cD05f6B62C3af58AE9c4F3F7A2aCC2Cdc2Cc7) disable a registrar controller without a vote. OnceETHRenewerV1owns theBaseRegistrar, that path no longer applies. The only controllers left areETHRenewerV1, which can only renew names already reserved on v2, and theGraveyard, which can only claim names that have expired past grace. - No v1 registrations, ever.
ETHRenewerV1has no function to add a controller, so v1 can't be reopened for registration without the DAO first reclaiming ownership. - Some v2 roles are deliberately broader than v2 needs long-term. For example, the
.ethtoken in the root registry carries every role, including the right to unregister.ethfrom the root. Keeping these lets the DAO fix any errors found after launch without a full redeployment. Once v2 has run safely, a follow-up executable proposal will revoke the roles that aren't needed, making v2 as trustless as v1. - The security council administers the intermediate Universal Resolver proxy. Once call 15 executes, the canonical Universal Resolver forwards to a proxy the security council can upgrade without a vote. That's how resolution moves to v2 in stage 4. The DAO keeps the final say, since it can repoint the Universal Resolver proxy itself with an executable proposal.
- Labs holds admin over v2 between stages 1 and 5. That's unavoidable if Labs is to run pre-migration without a vote per batch. It's bounded by stage 5, and the v2 contracts that handle funds are owned by the DAO from deployment.
Specification
The executable makes 15 calls, executed in order from the DAO timelock. Calls 7 to 11 remove every controller currently authorised on the v1 BaseRegistrar, as read from mainnet on 11 October 2026; the previous WrappedETHRegistrarController (0x253553366Da8546fC250F225fe3d25d0C782303b) was never a BaseRegistrar controller. It registers and renews through the NameWrapper, so it stops working once call 8 removes the NameWrapper. Calls 12 and 13 must come before call 14, because the registrar's owner can't change controllers once ownership has moved to ETHRenewerV1.
| # | Target | Call | Purpose |
|---|---|---|---|
| 1 | RegistrarSecurityController 0x7dd4d97653A67C2FD7fbA0a84825eC09524D4E1b | setRegistrarResolver(0x3071AD643cE4Ed8b3D67b289845b45dB82b068A4) | Point .eth at ENSV2Resolver |
| 2 | DefaultReverseRegistrar 0x283F227c4Bd38ecE252C4Ae7ECE650B0e913f1f9 | setController(0xd86E32499eCAFe9c181dd7410f93A1a9bB61ef0d, true) | Let DefaultReverseRegistrarAdapter write v1 default reverse records |
| 3 | ReverseRegistrar 0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb | setController(0x349151735790269a9C14668B58D7C83b5ecb9607, true) | Let ReverseRegistrarAdapter write v1 reverse records |
| 4 | PublicResolverSet 0xfFCedA021CBDF20f1a66ebbef32E49d208cAbf62 | approve(0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63, true) | Mark the 2023 PublicResolver as a v1 public resolver, so migrated names move to the v2 PublicResolver |
| 5 | PublicResolverSet | approve(0xF29100983E058B709F3D539b0c765937B804AC15, true) | Same, for the current v1 PublicResolver |
| 6 | StandaloneHCAFactory 0x742bf21897a78e2C98cC5f5C5473A370a081e561 | setImplementationApproval(0x116F462FA078ec0009e9b25DCd60309E70aaC4F4, true) | Approve the StandaloneSingleOwnerHCA implementation, so the factory can deploy HCA accounts |
| 7 | RegistrarSecurityController | removeRegistrarController(0x59E16fcCd424Cc24e280Be16E11Bcd56fb0CE547) | Disable current ETHRegistrarController |
| 8 | RegistrarSecurityController | removeRegistrarController(0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401) | Disable NameWrapper |
| 9 | RegistrarSecurityController | removeRegistrarController(0x60C7C2A24b5e86C38639Fd1586917a8FEF66a56d) | Disable 2020 RegistrarMigration |
| 10 | RegistrarSecurityController | removeRegistrarController(0xCF60916b6CB4753f58533808fA610FcbD4098Ec0) | Disable legacy 4-of-7 Safe |
| 11 | RegistrarSecurityController | removeRegistrarController(0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5) | Disable original 2020 ETHRegistrarController |
| 12 | RegistrarSecurityController | addRegistrarController(0xDa021A2C1C2F99574D861Ef8c6fA745851BEB7F6) | Authorise the Graveyard to reclaim expired v1 names |
| 13 | RegistrarSecurityController | addRegistrarController(0x56c447F308F463A01121C41E72b0E7e7557fCb68) | Authorise ETHRenewerV1, keeping unmigrated names renewable |
| 14 | RegistrarSecurityController | transferRegistrarOwnership(0x56c447F308F463A01121C41E72b0E7e7557fCb68) | Hand the v1 BaseRegistrar to ETHRenewerV1, locking down v1 |
| 15 | Universal Resolver proxy 0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe | upgradeTo(0xcFFd2Ae680CD110D28739a70922636B5937b022B) | Route resolution via the managed proxy (administered by the security council), which still serves the v1 UniversalResolver |
After execution, anyone can confirm the result by checking that:
BaseRegistrarImplementation.owner()returnsETHRenewerV1;BaseRegistrarImplementation.controllers()is true forETHRenewerV1and theGraveyard, and false for the five addresses in calls 7 to 11;ENSRegistry.resolver(namehash("eth"))returnsENSV2Resolver;controllers()on theReverseRegistrarandDefaultReverseRegistraris true for their respective adapters;PublicResolverSet.includes()is true for both v1PublicResolveraddresses;StandaloneHCAFactory.approvedImplementations()is true for the HCA implementation;- the Universal Resolver proxy's
implementation()returns the managed proxy.