A map of all ENS contracts

This is a work in progress and continuation of an earlier thread about threat assessments. ENS is made of many contracts and this is an attempt to clarify. It’s also has been a great understanding path for me to get more acquainted with all the governance changes. But most importantly it answers the question: what is the worst that can happen with my names?

Let’s start at the ENS Registry itself. This is the most important contract, the root of where ownership exists, you can even notice this by the care that was taken in choosing an address with lots of 0s. This makes it harder to spoof and creates tiny gas savings. It’s the contract deployed on all chains including for testing. It’s a very simple contract that uses a nested logic: if you own the root, you can create top level domains, which allows you to create domains, subdomains etc etc etc. You can check who owns the root by going in the contract and asking it for the owner of 0x000…

It should return the root.ens.eth contract, which is just a contract that passes direct orders from its owner–unless the owner specifically forbids that. It has only one locked contract which you can check by passing the keccak256 of “eth”, which will allow to confirm that nobody, not even the root, can change the owner of .eth anymore.

You’ll notice that the owner of .eth is the contract I named “The NFT” because it is the NFT address you add to your wallet. You’ll also notice that the multisig is still the owner of the root contract, per design as requested on EP1. We should expect this to change for the DAO in the future.

Why is the owner of .eth set to the NFT contract and not, let’s say, the dao itself? Great question. If you look at the code in the NFT you’ll see that when you transfer the NFT you are not at all changing the Registry, just the NFT ownership. But the owner can execute the “reclaim()” function which will allow you to set the owner of the NFT to the owner in the ENS registry. So the NFTs in your wallet are not actually the claim on the registry itself, but rather a special token that allows the owner to claim it.

The NFT contract is owned by the wallet.ensdao.eth which is the proper DAO. What can the DAO do to the NFT? It can call the following contracts:

  • Change Ownership: this will transfer ownership to someone else
  • Revoke Ownership: similar to transferring ownership to a null address
  • Set Controller: adds an address as a controller. There can be more than one.
  • Remove Controller: revoke controller permissions from the address
  • Set Resolver: this is just for setting metadata on the .eth address itself. Not something people usually do.

What are controllers? They are addresses authorized to call these functions:

  • Register: sets the new owner of a name that has expired and updates the ens registry
  • RegisterOnly: does the same but doesn’t update the registry (cheaper, but user will have to later reclaim it)
  • renew: extends the existing period

As you can see, there’s no option that will change the ownership of an address that has an owner. The easiest way to check for this without having to read the whole code is to look for instances of “onlyOwner” and “onlyController”, so you can verify it yourself.

Finally for the governance side. Both the NFT contract, Registrar Controller and token contracts are owned by wallet.ensdao.eth. The only thing the registrarController owner can do is call it to withdraw the money.

The owner of the Token contract has the right to mint up to 2% of the current total supply, once a year. Notice it’s not “per year” but rather it’s an action that, after done, requires waiting another year. Meaning that if the DAO calls to mind 0.5% of new tokens for some usage, that will be the limit that year.

The token contract is then used as the token inside the governor contract, which is part of an elaborate governance contract from Open Zepellin that I haven’t done researching, but suffice to say it’s the thing that counts the votes and creates a 48h delay before they can be executed by the DAO. It’s also interesting to notice that 65% of the token supply, owned both by the DAO and in minor scale, some contributors, is still locked in the time lock contract.

I urge you to verify all these contracts by going yourself on etherscan and checking the code: you don’t need to read everything, but you can start by searching keywords like “owner” to understand what can happen.

So name ownership is quite locked down. Only a owner of a token NFT (or the previous owner until they reclaim it) can change the ENS registry. This is enforced by a locked contract that is the true owner of the ENS root, which itself is under the control of the multisig. Unless there’s some bug in either of those contracts, then no matter how the token holders vote, people cannot lose their domains.

Threat scenarios

One scenario that could be more sensitive is the controller. The DAO can add and remove controllers as will, so while it can’t do anything to existing names, it could stifle or limit the growth of ENS names. Examples that a bad controller could do:

  • While it can’t change the expiry date down, a controller could refuse to renew a name for a user for any reason. This would go against the article I of the constitution but right now it’s relatively easy to change that.
  • A bad controller could also limit who can acquire new names. It could decide to only accept KYC USD token that required its users to doxx themselves. Or it could require that any new user have a specific token that would identify them as a member of some special club. Or it could straightaway create allow and block lists for who can acquire names. Again, goes against the constitution, but if you have votes to control the wallet, you have votes to change the constitution.

Security suggestions

It’s too soon for us to lock down controllers. There are probably more creative and clever ways to deal with registration than the simple $5 a month, which also requires an oracle and ties itself to the dollar. But we can add more than one controller, and we could transfer ownership of the NFT contract to a locked contract similar to the one at root.ens.eth, which would prevent a few actions or add more delays.

  • We could add a last recourse controller that created a fixed price for ENS names at a higher point. This controller could not be removed, not even by the DAO. Maybe it would say that you could always use/burn X amounts of ether or ENS to acquire a year of domain names. It would of course be more expensive than the other avenue, but at least it would guarantee that someone who couldn’t access whatever other restrictions could be put in place. Of course it’s hard to figure out how to price something in this scenario, but that is a contract that is not meant to be used, rather a lever saying “you can’t add restrictions because there’s already a backdoor”.

  • Add greater delays on controller changes. Maybe any controller changes should have a minimum delay of 30 days, so that if some change is about to happen that you disagree with, you still have 30 days to add 100 years to your current domains.

15 Likes

Thanks for breaking down all the contracts. Is it worth mentioning ReverseRegistrar as well?

2 Likes

Good idea. Although I don’t think it interact much with the others.

1 Like

This is an amazing resource, thanks Alex! Would you be happy to see it as a page on the ENS technical docs?

It’s probably worth noting that the DAO timelock provides users with a time window to register and extend names that are affected by a change, too.

I’m not sure we’ll ever be able to lock in a permanent controller; the controller depends on the price oracle, and oracles have a tendency to change from time to time.

This is a great idea! Another option would be to enforce a timelock not on adding controllers, but on removing them.

4 Likes

It would have to be a very simple contract like—and I’m not saying we should do this—burn 1 $ens get 1 year on your registration. This would create the scenario where there was a floor price for ens: registration was either $5 or 1 ens per year, so if the price of ens drops below $5 then people would start using it instead and therefore burning the supply. This of course can create some other bad effect.

But it’s an idea to prepare for the imaginary threat which might be unlikely. I think adding a long delay (even maybe up to a year) for removing controllers could also work as a nice protection.

1 Like

One risk with this is that if a bug was discovered in a controller, we would not be able to disable it for that long.

1 Like

Yes, this is the whole conundrum: lock it too much and you can’t protect it from future bugs, let it too loose and you can’t protect from the future community

This is awesome to see, I had a vision of a ENS info graphic flowchart much like this for “non.coiners”. This will help to with on-boarding. cheers …creating a sudo buy and burn to make a “floor price” is neat my concern would be at the price end points of ENS both high and low. Drastic changes to the ENS price, the discount/premium to the user becomes a mute point and they will just use eth. As to floor price I suggest we make ENS socks . lol

Wow amazing, thanks for making this :pray:, this will be really helpful for all frENS :fire:

1 Like

@AvsA It would be great if you also list the list of ENS contracts so we can copy and paste that and see in etherscan also used to interact with the contract.

It’s very difficult to copy the address from the image :bowing_man:

Here’s an update on the map, now including the functions that each contract can call

3 Likes

This is very clear! A couple of suggestions:

  • NFT owners can also call ‘transferFrom’ etc on the registrar.
  • The registry controller should probably have a title.
  • It should probably be ‘primary’ rather than the wallet, since it has a more direct relationship to the registrar than the DAO wallet does.
3 Likes

I’m using the names assigned at ens.eth subdomains. I’ve also found a few others worth mentioning like the dnssec and the priceoracle which I’m adding now

also, @nick.eth I’m not sure what to make of this:

One is the resolver that at resolver.ens.eth, the other for some reason etherscann says is where it will be migrated to, and another is the actual resolver being used on the app…

Screen Shot 2022-02-14 at 8.25.22 PM

Not even sure it should be in the scope here since resolver is defined per domain

Right, but in the case of the controller, which doesn’t have an ENS name, it’d help to label it with something.

resolver.ens.eth should always point to the latest one. Etherscan likely is pointing to a previous version.

Agreed! It might make sense to mention the .eth resolver specifically, though, since it’s used in the discovery mechanism.

You weren’t kidding when you said v3 is much better. Might go ahead and make this interactive with GoJS later :fire:

2 Likes

@nick I added the latest version as a PR here: https://github.com/ensdomains/docs/pull/93

I believe it’s ready for review. I can update it as the contract changes or new addresses are found.

2 Likes

Amazing, thank you. I’ve merged the PR.

1 Like

I went down the rabbit hole with @AvsA’s mapping of ENS contracts since it overlapped with my ongoing threat analysis discussed in another thread. I cleaned things up into multi-layered SVG separating text, pointers, containers and labels across 4 layers but kept everything else as it was to a very large extent. I can now implement this as an animation by hacking the XML. I’ll post results down here as I have them; you can keep track of things on GitHub as well where the source SVG files also reside if anybody wants them.

ENS-compressed

You can find the GIF in high-res at ens.inplco.eth, or on IPFS

3 Likes

One minor nitpick on both layouts - I really think the controller and the price oracle belong in ENS, not in the DAO.

1 Like