Durin is an opinionated approach to ENS L2 subnames. Durin consists of:
- Registry factory on supported chains
- Registrar template
- Gateway server
- L1 resolver
This repo is meant to be used in conjuction with Durin.dev, which provides a frontend for deploying the registry & enabling name resolution.
Go to Durin.dev. Choose Sepolia or Mainnet ENS name resolution. Pick a supported L2. Deploy.
Once complete, note the deployed L2 registry address.
To connect your newly deployed L2 registry with your ENS name on L1, change the name's resolver to 0x8A968aB9eb8C084FBC44c531058Fc9ef945c3D61 and call setL2Registry() with the L2 registry's address and chain ID.
Both of these steps can be done via durin.dev or the ENS manager app.
Note
Durin uses Foundry. To install it, follow the instructions.
Durin provides a registrar template that is meant to be customized. Common customizations include adding pricing, implementing allow lists, and enabling token gating.
You can either clone this repo and modify L2Registrar.sol directly, or write a new contract in your existing project. If you prefer the latter, simply import IL2Registry.sol to your project so you can interact with the registry you deployed earlier and skip to step 5.
To get started, clone this repo:
git clone https://github.com/namestonehq/durin.git
cd durinOnce cloned, modify L2Registrar.sol as needed.
To deploy the L2Registrar contract, you will need to prepare a .env file and run the deploy script.
cp .env.example .envOpen the new .env file and set the variables that are marked as required at the top, then run the following command:
bash ./bash/DeployL2Registrar.shOnly approved Registrars can call createSubnode() on the Registry. The owner of the registry can add as many Registrars as they want.
To add a Registrar, visit your Registry on Etherscan and call addRegistrar() with the newly deployed Registrar's address.
Finally, you'll be able to mint subnames via the Registrar.
This repo includes all of the smart contract (L1 and L2) required to enable subname issuance.
- L1Resolver: L1 contract that forwards ENS queries to the L2.
- L2RegistryFactory: L2 contract for creating new registries.
- L2Registry: L2 contract that stores subnames as ERC721 NFTs. This contract is also responsible for storing data like address and text records.
- L2Registrar: An example registrar contract that can mint subnames. This is meant to be customized.
| L2 | Registry Factory |
|---|---|
| Arbitrum | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Arbitrum Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Base | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Base Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Celo | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Celo Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Linea | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Linea Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Optimism | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Optimism Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Polygon | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Polygon Amoy | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Scroll | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Scroll Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Worldchain | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
| Worldchain Sepolia | 0xDddddDdDDD8Aa1f237b4fa0669cb46892346d22d |
Note
A dependency for supporting -withSignature methods on new chains is a deployment of UniversalSigValidator to 0x164af34fAF9879394370C7f09064127C043A35E9. The deployment is permissionless and can be found here.
Note
Developers that want to issue subnames on one of the chains listed above in the Active Registry Factory Deployments section do not need to read any further.
- Create a
.envfile viacp .env.example .env. You don't need to change anything. - Add/uncomment the chains you want to deploy to in foundry.toml and DeployL2Contracts.s.sol.
- Run
./bash/DeployL2Contracts.shto deploy the registry implementation and factory contracts to the specified chains. - Run
./bash/VerifyL2Contracts.shfor each chain you deployed to, changingNETWORKandBLOCK_EXPLORER_API_KEYin the files, to verify all the contracts you just deployed. - Add your chain(s) to query.ts in the gateway config.
Run ./bash/DeployL1Resolver.sh followed by ./bash/VerifyL1Resolver.sh to deploy and verify the L1 Resolver. This is L2 chain agnostic, so only needs to be done once.
For generating a CREATE2 salt to deploy the L2RegistryFactory, run the command below. Use ./scripts/L2RegistryFactoryInitCode.s.sol to calculate the init code hash.
export FACTORY="0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2"
export INIT_CODE_HASH="<HASH_OF_YOUR_CONTRACT_INIT_CODE_GOES_HERE>"
cast create2 --starts-with dddddd --deployer $FACTORY --init-code-hash $INIT_CODE_HASHOnce you have a salt that you're happy with, update L2_REGISTRY_FACTORY_SALT in .env so it's used in the deployment script.

