ENS Logo

Naming Contracts

While it's commonly known that regular user accounts can have primary names, it's less known that smart contracts can also have names.

In order for you to manage the primary name of your smart contract, you need to own the reverse node for the contract address. There are several ways of doing this, depending on if you are actively developing your contract or if it is already deployed.

New Contracts

Depending on your use case, there are a few different approaches to setting the primary name of a new smart contract.

First, let's assume you want to be able to change the name in the future. The two ways to do this are:

  • Take ownership of the reverse node ({address}.addr.reverse) for the contract address.
  • (Recommended) Make the contract Ownable, which is may already be, and set the owner to yourself.

The Ownable approach is recommended because it's possible that your contract will already have it implemented, and Etherscan will index the events correctly.

If you are deploying a new contract that does not have any admin permissions, and you don't want to be able to change the name in the future, you can set the reverse name in the constructor of the contract directly.

Let's look at a few examples.

ReverseClaimer.sol

This is a simple drop-in module that transfers ownership of the reverse node to an address of your choice, which can then update the reverse name at any time.

import "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import "@ensdomains/ens-contracts/contracts/reverseRegistrar/ReverseClaimer.sol";

contract MyContract is ReverseClaimer {
    constructor (
        ENS ens
    ) ReverseClaimer(ens, msg.sender) {}
}

When you deploy your contract, the deployer account (msg.sender) will be given ownership of the reverse node for that contract address. This gives you authorization to call setName(node, newName) on the latest public resolver (resolver.ens.eth), where node is the reverse node for the contract address and newName is the name you want to set it to.

To find the reverse node for your contract address, you can use the following viem script:

import { namehash } from 'viem/ens'
import { Hex, keccak256 } from 'viem'

function getNodeFromParentNodeAndLabelhash(parentNode: Hex, labelhash: Hex) {
  return keccak256((parentNode + labelhash.split('0x')[1]) as Hex)
}

const myContractAddress = '0x...' // replace with your contract address

const node = getNodeFromParentNodeAndLabelhash(
  namehash('addr.reverse'),
  labelhash(myContractAddress.slice(2).toLowerCase())
)

console.log(node)

If you want to be able to change the name in the future, you can make your smart contract Ownable.

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract Contract is Ownable {
    constructor(address initialOwner) Ownable(initialOwner) {}
}

The ReverseRegistrar supports the Ownable interface and will let the owner of a contract set its primary name without having to add any ENS-specific code.

Once this contract is deployed, call setNameForAddr(address, address, address, string) on the Reverse Registrar (reverse.ens.eth) from your authorized owner account.

  • The first address argument is the address of your contract
  • The second address argument is the owner of your smart contract
  • The third address argument is the defaultResolver() from the Reverse Registrar
  • The fourth argument is the ENS name to set it to

Set a name in the constructor

If you don't want to be able to change the name in the future, you can inherit the following contract and assign an ENS name directly in the constructor.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

interface ENS {
    function owner(bytes32 node) external view returns (address);
}

interface IReverseRegistrar {
    function setName(string memory name) external returns (bytes32);
}

// Variation of ReverseClaimer.sol from @ensdomains/ens-contracts that sets the reverse name directly.
contract ReverseSetter {
    /// @dev The ENS registry
    ENS private constant ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);

    /// @dev Output of namehash("addr.reverse")
    bytes32 private constant ADDR_REVERSE_NODE =
        0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

    /// @param name The reverse name to set for this contract's address.
    constructor(string memory name) {
        IReverseRegistrar reverseRegistrar = IReverseRegistrar(
            ens.owner(ADDR_REVERSE_NODE)
        );
        reverseRegistrar.setName(name);
    }
}

Using this in your contract is as simple as:

import {ReverseSetter} from "./ReverseSetter.sol";

contract Contract is ReverseSetter {
    constructor(string memory name) ReverseSetter(name) {}
}

Existing Contracts

If your contract is already deployed you might still be able to set a name for it. If your contract supports the Ownable interface from OpenZeppelin, read the section above.

Safe, Multisig & DAO

If your contract is a Safe, Multisig, DAO, or has a function that can send arbitrary ETH calls, you can use the ReverseRegistrar contract directly to set a name for it. You might even be able to use the ENS Manager App inside of your safe app to set a primary name.

Last Modified
14 hours ago