Creating immutable / locked ENS records with the Name Wrapper

This is an example / proof-of-concept: Lockable resolver by serenae-fansubs · Pull Request #262 · ensdomains/ens-contracts · GitHub

Deployed on:

I wrote about this use-case a while ago (and also in that Mirror article): Lock resolved records | ENS Support

At the time I left that “custom resolver contract” as an exercise for the user to create. Well here is one I created and you can play around with now! It’s just a fork of the PublicResolver that allows the owner to “lock” various record types (or everything):

Lock specific record types

  • lockABI(node)
  • lockAddr(node)
  • lockContenthash(node)
  • lockDNS(node)
  • lockInterface(node)
  • lockName(node)
  • lockPubkey(node)
  • lockText(node)

Lock specific text record keys but not others

  • lockText(node, 'avatar')
  • lockText(node, 'url')

Lock everything

  • lockAll(node)

Once a specific record type (or everything) is locked, it cannot be unlocked.

This can be used in conjunction with the CANNOT_SET_RESOLVER fuse on wrapped names to create an immutable name that is guaranteed to resolve to records forever (or at least until the name expires).

Example steps (on mainnet):

  1. Set the resolver on your name to 0x7759277C7E6c34230840c4C28d799fBb643CB23f
  2. Set the contenthash for your name:
  3. Lock the contenthash for your name:
  4. Revoke the wrapped “set resolver” permission

Now your ENS name/subname will resolve to that decentralized website and it cannot be changed (not even if name ownership changes).

With this solution, you do not need to send the name to a burn address to make a name immutable. You can retain ownership, and even retain the ability to edit whatever other records you want. So you can “lock all records” if you want, or you can pick-and-choose which ones to make immutable.

Hope it helps!


Thanks for writing and deploying this @serenae! I’ve already put it to use on my hackathon project from this weekend :slight_smile:

A minor piece of feedback: I found myself wanting something like setAndLockContenthash(node) in addition to having the two separate functions. The good news is, of course, that anyone can deploy a new contract with that functionality – I just didn’t have time during the hackathon so figured I’d share the thought here.


Glad to hear it!

Another gotcha right now is that the official manager UI does not properly recognize custom resolver contracts as valid and “wrapper-aware”.

So you’ll see this, even though that is not true (this contract is compatible with wrapped names):

Right now the manager app just hard-codes the latest Public Resolver as wrapper-aware, and never actually checks any custom resolvers to see if they are or not.

cc: @Leon @taytems


This is pretty amazing!