NameWrapper updates (including testnet deployment addresses)

Bumping this: can the wrapper interface (0x019a38fe) be set on the Goerli .eth-resolver? This is very useful for auto-discovery, unless there is a better method than: ENS Registry (hardcode) → resolve("eth") → interfaceImplementer("0x019a38fe").

Also, could the Price Oracle get defined as an interface too? I’m currently plucking it out of slot 2 from the .ethcontroller via interfaceImplementer(“0x018fac06”).


Will do.

Edit: Done!

You can get this by calling prices on the controller.


It looks to be the case that the metadata service on Goerli has still not been updated.

CC @mdt @nick.eth @jefflau.eth

1 Like

We have deployed the ENS contracts to Sepolia. For completeness, I have updated the NameWrapper contract here, however for the full list of contracts you can check the ens-contracts repo here:


Thanks Jeff… Is there also a subgraph for this?

1 Like


Does this update include the gasless dns import? i saw a lot of files reference dns

I recently discovered a new bug in the NameWrapper, that has a particularly tricky way in which it can be exploited.

The bug was classified as a “Note” with a small bounty paid out, because it doesn’t risk any funds, or affect the ownership of any names, but it may have some consequences for anyone who depends on the isWrapped function.

The attacker can:

  1. register and wrap a 2LD .eth name
  2. let the name expire
  3. register (and not wrap) the name again
  4. set the owner in the registrar to the NameWrapper contact address, (keeping the controller as the attacker’s address)

A bug in the NameWrapper isWrapped function means it will now return true instead of false(!)

    function isWrapped(
        bytes32 parentNode,
        bytes32 labelhash
    ) public view returns (bool) {
        bytes32 node = _makeNode(parentNode, labelhash);
        bool wrapped = _isWrapped(node);
        if (parentNode != ETH_NODE) {
            return wrapped;
        try registrar.ownerOf(uint256(labelhash)) returns (address owner) {
            return owner == address(this) /*->>*/ && wrapped /*<<-*/; // add "&& wrapped" for the fix.  
        } catch {
            return false;

and the attacker has full control over the name as the owner of the controller

and if the attacker wants to sell, or “unwrap” the name, all she has to do is change the address of the controller to the NameWrapper, and call the renew() function. This will basically rewrap the name for the hacker, which is also technically a another bug because the event,

emit NameWrapped(node, name, wrappedOwner, fuses, expiry);

is never called, even though the name was just effectively wrapped.