Skip to content

Naming Contracts

Learn how to name your smart contracts with ENS

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.

Skip to Naming Tools for a frontend solution to naming your smart contracts.

New Contracts

Depending on your use case, there are a few ways to set a smart contract's primary name.

If you want to be able to change the name later, you have two options:

  • (Recommended) Make the contract Ownable and set yourself as the owner.
  • Take ownership of the reverse node ({address}.addr.reverse) for the contract.

The Ownable method is preferred since it's widely used and works well with Etherscan.

For contracts without admin permissions, you can set the reverse name in the constructor. This name can't be changed later.

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 { Hex, keccak256 } from 'viem'
import { namehash } from 'viem/ens'
 
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)

Ownable (recommended)

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.

Naming Tools

Enscribe is a tool designed to simplify the process of naming smart contracts with ENS names. The application enables users to deploy new smart contracts with a primary name directly and easily name existing smart contracts.

Enscribe simplifies what is otherwise a multi-step, error-prone process by offering:

  • Atomic contract deployment using CREATE2
  • Naming Ownable, ERC173, ReverseClaimer and ReverseSetter contracts as described above
  • ENS subname creation, forward resolution and reverse record assignment
  • Naming of existing contracts, with an easy way to locate contracts that you've already deployed

Even if you don't own an ENS name, you can still utilize Enscribe's hosted ENS parent, deployd.eth, to create subnames like my-app.deployd.eth and set them as the primary name for your contract.

To learn more, refer to the Enscribe Docs.