Deploying Domains on a Private Chain

If you’d like to deploy Domains on your own network, or deploy your own copy of Domains on a public network, this guide shows you how. If you want to use an existing Domains deployment, see Resolving Names, Managing Names, and Registering & Renewing Names instead.

On this page we will use Javascript, Web3, and Hardhat with npm for simplicity. You will find a complete migration file example at the bottom of this page.

Please be aware that existing frameworks such as waffle and embark have support for local Domains deployment as well.

Importing contracts

The essential smart contracts are published as npm modules. You can install them in your npm project with npm install @tdnsdomains/tdns-contracts. Now, you can require them in a migration script as follows (see the Truffle Documentation on working with contract artifacts and npm for details)

import {
  ENS, ENSRegistry, PublicResolver
} from '@ensdomains/ens-contracts'

Including them within your smart contract is as follows

import '@ensdomains/ens-contracts/contracts/registry/ENS.sol'

Domains contains only an interface while tDNSRegistry includes the actual implementation.

Deploy the Registry

The registry is Domains central component and stores, among other things, who owns which domain. This is the example using ethers and hardhat.

const ENSRegistry = await ethers.getContractFactory("ENSRegistry")
await ENSRegistry.deploy()

Once deployed, you will have a fresh Domains registry, whose root node is owned by the account that submitted the transaction. This account has total control over the Domains registry - it can create and replace any node in the entire tree.

From here, it's possible to create and manage names by directly interacting with the registry, as described in Managing Names. However, you will probably want to deploy a resolver, and you may want to deploy a registrar so other users can register names.

Deploy a Resolver

Records in the registry can point to resolver contracts which store additional domain information. The most common use-case is to store an address for a domain, but storing a contract ABI or text is also possible. For most purposes on private networks it's convenient to have an unrestricted general-purpose resolver available. Deploying one is straightforward:

The PublicResolver looks up ownership in the registry, which is why the registry's address is required at deployment.

For ease of use, we can give this resolver a name:

Above, we first create a new top-level domain, "resolver", then set its resolver address to our newly deployed public resolver. Finally, we set up an address record for "resolver", pointing back to the resolver address. In effect, the resolver is answering queries about its own address. After this, anyone can find the public resolver at the special Domains name "resolver". We call this function after deploying the public resolver in a .then() block as we did with the resolver.

Deploy a Registrar

So far, domains can only be registered manually by the owner of the registry's root node. Fortunately, contracts can also own nodes. This means we can set up a registrar contract as the owner of a node, e.g. "test", in the registry which enables it to distribute subdomains such as "mycontract.test". It allows us to have custom, on-chain logic which governs domain allocation. Once we own a (sub-)node we are free to repeat this process and set up another registrar. If you are part of the "myorg" organisation you could register "myorg.test" and let it point to your custom registrar which only allows certified members of your organisation to claim subdomains such as "bob.myorg.test". For our private network, we'll use the simple 'first come, first served' FIFSRegistrar, and set it as the owner of the top-level domain "test" in our migration script:

Deploy the Reverse Registrar

Similarly, if you wish to enable reverse resolution on your deployment, you will need to deploy the reverse registrar:

Migration File Example

We can combine the steps above in a single hardhat migration file. This allows us to deploy Domains in one go:

contracts/deps.sol

script/deploy.js

To execute the migration file on hardhat, run the following command line.

Deploying Domains in a single transaction

Alternately you may wish to deploy a test registrar and its dependencies with a single transaction. This is useful for example in unit tests where you wish to start from a clean slate in each test. In many cases it will also be faster than sending a series of separate transactions.

This can be done by deploying a new contract that creates and sets up all the other contracts in its constructor. The below code creates all the Domains contracts and assigns the tomi TLD to the FIFS Registrar so that any tomi domain may be registered in the unit tests.

Last updated