Skip to main content

Installation

This guide covers everything you need to set up your development environment for working with ENS v2 contracts.

System Requirements

Node.js

Version 24 or higher

Foundry

Version 1.3.2 or higher

Bun

Version 1.2 or higher

Install Prerequisites

1

Install Node.js

Install Node.js v24 or higher:
brew install node@24
Verify installation:
node --version
# Should output v24.x.x or higher
2

Install Foundry

Foundry is a blazing fast Ethereum development toolkit written in Rust.
curl -L https://foundry.paradigm.xyz | bash
foundryup
Verify installation:
forge --version
# Should output forge 1.3.2 or higher
For detailed installation instructions, see the Foundry Book.
3

Install Bun

Bun is a fast JavaScript runtime and package manager.
curl -fsSL https://bun.sh/install | bash
Verify installation:
bun --version
# Should output 1.2.x or higher
4

Install lcov (Optional)

Required only if you want to run coverage tests.
brew install lcov

Clone and Setup

1

Clone the Repository

git clone https://github.com/ensdomains/contracts-v2.git
cd contracts-v2
2

Install Dependencies

Navigate to the contracts directory and install dependencies:
cd contracts
bun i
forge i
This installs:
  • JavaScript dependencies via Bun
  • Solidity dependencies via Forge
3

Build Contracts

Compile both Foundry and Hardhat contracts:
forge build
bun run compile:hardhat
You can also use bun run compile to build both at once.

Project Structure

After installation, your project structure will look like this:
contracts/
├── src/                          # Solidity source files
│   ├── registry/                 # Registry contracts
│   │   ├── PermissionedRegistry.sol
│   │   ├── UserRegistry.sol
│   │   └── libraries/
│   ├── registrar/                # Registrar contracts
│   │   └── ETHRegistrar.sol
│   ├── resolver/                 # Resolver contracts
│   │   └── PermissionedResolver.sol
│   ├── universalResolver/        # Universal resolver
│   │   └── UniversalResolverV2.sol
│   ├── migration/                # ENS v1 migration
│   ├── access-control/           # Access control system
│   │   └── EnhancedAccessControl.sol
│   ├── erc1155/                  # ERC1155 singleton
│   └── dns/                      # DNS integration
├── test/                         # Test files
│   ├── unit/                     # Unit tests (Foundry)
│   └── e2e/                      # End-to-end tests (Hardhat)
├── deploy/                       # Deployment scripts
├── lib/                          # Forge dependencies
├── foundry.toml                  # Foundry configuration
├── hardhat.config.ts             # Hardhat configuration
└── package.json                  # Node.js dependencies

Configuration

Foundry Configuration

The project uses these Foundry settings (from foundry.toml):
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
gas_reports = ["*"]
evm_version = "cancun"
optimizer = true
optimizer_runs = 200

[fuzz]
runs = 4096

Environment Variables

Create a .env file in the contracts directory for custom configuration:
# Optional: Custom RPC URLs
ETH_RPC_URL=https://eth-mainnet.alchemyapi.io/v2/YOUR-API-KEY

# Optional: Etherscan API key for verification
ETHERSCAN_API_KEY=your-etherscan-api-key

# Optional: Private key for deployment (testnet/mainnet)
PRIVATE_KEY=0x...
Never commit your .env file or expose private keys. The repository’s .gitignore excludes .env by default.

Running Tests

Verify your installation by running the test suite:
Run the complete test suite:
bun run test
This runs both Foundry and Hardhat tests.

Before Running Tests

Before running tests, compile the ENS v1 contracts dependency:
cd lib/ens-contracts
bun run compile
cd ../..
This only needs to be done once after initial setup.

Development Workflow

Start Local Devnet

The easiest way to develop is using the local devnet:
Recommended approach:
bun run devnet
This starts a local chain at:
  • URL: http://localhost:8545
  • Chain ID: 31337
The devnet includes:
  • All ENS v2 contracts deployed
  • Pre-configured test accounts with ETH
  • ETH Registry with .eth TLD
  • Universal Resolver
  • Mock ERC20 tokens for testing

Code Formatting

Format Solidity code:
forge fmt

Linting

Run Solidity linter:
bun run lint

Gas Snapshots

Generate gas usage snapshots:
forge snapshot

Coverage Reports

Generate test coverage reports:
bun run coverage
This generates:
  • Foundry coverage (coverage/forge.lcov)
  • Hardhat coverage (coverage/hardhat.lcov)
  • Combined HTML reports

IDE Setup

Visual Studio Code

Recommended extensions:
  1. Solidity by Juan Blanco
  2. Hardhat Solidity by Nomic Foundation
  3. Prettier - Code formatter

VSCode Settings

Add to .vscode/settings.json:
{
  "solidity.compileUsingRemoteVersion": "v0.8.25",
  "solidity.formatter": "forge",
  "editor.formatOnSave": true,
  "[solidity]": {
    "editor.defaultFormatter": "JuanBlanco.solidity"
  }
}

Vim/Neovim

Install Solidity syntax highlighting:
Plug 'tomlion/vim-solidity'

Troubleshooting

If you encounter compilation errors:
  1. Clean build artifacts:
    forge clean
    bun run clean
    
  2. Reinstall dependencies:
    rm -rf node_modules lib
    bun i
    forge i
    
  3. Rebuild:
    forge build
    bun run compile:hardhat
    
If tests fail:
  1. Ensure ENS v1 contracts are compiled:
    cd lib/ens-contracts
    bun run compile
    cd ../..
    
  2. Run tests with verbose output:
    forge test -vvv
    
  3. Run specific test:
    forge test --match-test testFunctionName -vvv
    
If the devnet fails to start:
  1. Check if port 8545 is in use:
    lsof -i :8545
    
  2. Kill any existing processes:
    kill -9 $(lsof -t -i:8545)
    
  3. Try restarting:
    bun run devnet
    
If you encounter out of memory errors during compilation:
  1. The project is configured to NOT use --via-ir to avoid stack too deep errors
  2. If you modify contracts and hit stack too deep, refactor the code instead of enabling --via-ir
  3. Increase Node.js memory limit:
    export NODE_OPTIONS="--max-old-space-size=8192"
    

Additional Tools

Foundry provides additional useful tools:

Cast

Command-line tool for Ethereum RPC calls:
# Get block number
cast block-number

# Call a contract
cast call <address> "balanceOf(address)" <address>

# Send a transaction
cast send <address> "transfer(address,uint256)" <to> <amount> --private-key <key>

Anvil

Local Ethereum node (used by devnet):
# Start Anvil directly
anvil

# With specific options
anvil --port 8545 --chain-id 31337

Chisel

Solidity REPL for testing snippets:
chisel

Next Steps

Quickstart

Deploy and interact with contracts

Core Concepts

Learn the architecture

Testing Guide

Write and run tests

Deployment

Deploy to testnet or mainnet

Getting Help

If you run into issues:
For the latest updates and best practices, check the repository’s README and CONTRIBUTING guidelines.

Build docs developers (and LLMs) love