- Makes all ENS names at any level into ERC1155 tokens.
- Supports ‘emancipating’ names by allowing the owner of a parent name to revoke control over subdomains.
- Supports ‘locking’ names by allowing the owner of a name to revoke control over changes in resolver, creation of subdomains, and other parameters.
- Wrapped names can expire; a name that is emancipated or locked has a built in expiration at which the name (and that status) expires.
- UIs and Smart Contracts can check the status of a name with a single function call, allowing them to ensure security guarantees are upheld.
- .eth names can be registered and renewed via the wrapper, removing any need to wrap names separately after registration.
- Owners of names can create wrapped subdomains directly, without having to register-then-wrap.
Glossary of Terms
Wrap
Transfers ownership of the ENS name to the Name Wrapper. The wrapper then issues an ERC1155 token for the name.Unwrap
Reverses the wrap process and transfers the name to an address of the token owner’s choice.Fuse
The term for a flag that can be set irreversibly until expiry. Fuses can do many things, including controlling permissions for the name itself.Emancipation
The process of the owner of a parent name revoking its control over a subname.Locking
The process of the owner of a name revoking some level of control over its own name.Owner-controlled Fuses
Fuses that can be burned by the owner of a name or the owner of the parent name if the name is not emancipated.Parent-controlled Fuses
Fuses that can be burned by the owner of the parent name.Expiry
Expiry is the date when the name expires and is no longer able to be owned. Expiry only comes into effect when a name is emancipated or locked. Expiry can be extended by parent or approved addresses, and if the parent burnt the parent controlled fuses (PCF), then the subnames can extend their expiry by themselves. However, the PCF can be unburnt later if the parent name expires.Checking if a Name is Wrapped
To check if a name has been wrapped, callisWrapped(). This checks that the owner in the NameWrapper is non-zero.
Registering Wrapped Names
Names can be registered as normal using the current .eth registrar controller. However, the new .eth registrar controller will be a controller on the NameWrapper, and the NameWrapper will be a controller on the .eth base registrar. The NameWrapper exposes aregisterAndWrapETH2LD() function that can be called by the new .eth registrar to directly register wrapped names. This new function removes the need to first transfer the owner to the contract itself before transferring it to the final owner, which saves gas.
Both .eth registrar controllers will be active during a deprecation period, giving time for front-end clients to switch their code to point at the new and improved .eth registrar controller.
Ownership of the NameWrapper
The NameWrapper is anOwnable() contract and this owner has a few limited admin functions. Most of the functionality of the NameWrapper is trustless and names cannot be interfered with in any way even by the owner of the contract.
The contract owner can:
- Change the metadata service URL.
- Add and remove controllers to the NameWrapper.
- Specify an upgrade target for a new name wrapper instance.
Controllers can call:
registerAndWrapETH2LD()renew()setUpgradeContract()
Upgrading the Name Wrapper
The Name Wrapper has a built-in upgrade function that allows the owner of the Name Wrapper to set a new contract for all names to be migrated to as a last resort migration. Upgrading a name is optional and is only able to be done by the owner of the name in the original NameWrapper. A name can only be migrated when the parent has been migrated to the new registrar. By default theROOT_NODE and ETH_NODE should be wrapped in the constructor of the new Name Wrapper.
The upgraded namewrapper must include the interface INameWrapperUpgrade.sol, which mandates two functions that already exist in the new wrapper: wrapETH2LD and setSubnodeRecord. The wrapETH2LD function can be used as-is, however the setSubnodeRecord needs one additional permission, which checks for if the parent of the name you are wrapping has already been wrapped and the msg.sender is the old wrapper.
It is recommended to have this check after the normal checks, so normal usage in the new wrapper does not cost any additional gas (unless the require actually reverts).
wrap() and wrapETH2LD() and then translates them into the new function signatures to avoid a situation where the old NameWrapper cannot call the new NameWrapper.