Current situation for unwrapped names
Unwrapped ENS names can be made immutable.
No one and no group can steal a name from someone. The ENS DAO can prevent renewals, but they cannot transfer a name away from a user or edit the records of that name. If the user transfers the name to a burner address, the name is functionally immutable until it expires.
Current situation for wrapped names
Wrapped ENS names cannot be made immutable.
ENS DAO has the ability to steal any wrapped name from any user, regardless of fuses burnt or ownership being transferred to a burner address. There is no way for a user to revoke this power for a wrapped name once the CANNOT_UNWRAP
fuse is burnt other than by the ENS DAO “stealing” the name and giving it back to the user in unwrapped form.
Proposed Change
Remove ENS DAO’s ability to steal wrapped names
ENS DAO should not have the ability to take names from people, and a name that has the appropriate fuses/ownership burnt should be truly immutable until expiry.
Technical options for resolution
There are two reasonable options to resolve this that I can see from a cursory look at the NameWrapper
contract.
- Revoke ownership of
NameWrapper
. This would take away this ability, but it would have the side effect of removing the ability of the DAO to call thesetMetadataService
function. I’m not sure what that does, but it may be necessary to retain power over. - Transfer ownership of
NameWrapper
to a contract that can only call thesetMetadataService
function. The currentTimelockController
owner would become theowner
of this new intermediate contract.
Technical details of how The DAO can steal a name from an individual
The NameWrapper
has the following function on it:
/**
* @notice Set the address of the upgradeContract of the contract. only admin can do this
* @dev The default value of upgradeContract is the 0 address. Use the 0 address at any time to make the contract not upgradable.
* @param _upgradeAddress address of an upgraded contract
*/
function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) public onlyOwner {
if (address(upgradeContract) != address(0)) {
registrar.setApprovalForAll(address(upgradeContract), false);
ens.setApprovalForAll(address(upgradeContract), false);
}
upgradeContract = _upgradeAddress;
if (address(upgradeContract) != address(0)) {
registrar.setApprovalForAll(address(upgradeContract), true);
ens.setApprovalForAll(address(upgradeContract), true);
}
}
This function can only be called by the NameWrapper
owner, which is a TimeLockController
presumably owned by the ENS DAO (it is difficult to verify the actual owners of the TimeLockController
as they are stored in a mapping, so one needs to write a script that searches all event logs to find current ownership set).
The TimeLockController
(e.g., The DAO) can call that method and provide any address (EOA or contract) as the upgradeAddress
. That address will then gain the ability to transfer any name away from the NameWrapper
and give it to any address they choose.