or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

chai-matchers.mdcompiler-utilities.mdcontract-deployment.mdens-utilities.mdindex.mdmock-contracts.mdoptimism-provider.mdprovider-testing.md
tile.json

ens-utilities.mddocs/

ENS Utilities

ENS (Ethereum Name Service) testing utilities that provide comprehensive domain management and resolution testing infrastructure for smart contract development with Waffle.

Capabilities

ENS Deployment

Core functions for setting up ENS testing infrastructure with registries, resolvers, and reverse registrars.

/**
 * Deploy complete ENS system for testing
 * @param signer - Signer to deploy ENS contracts with
 * @returns Promise resolving to ENS instance
 */
function deployENS(signer: Signer): Promise<ENS>;

/**
 * Create resolver contract for ENS domain resolution
 * @param signer - Signer to deploy resolver with
 * @param ens - ENS registry contract
 * @returns Promise resolving to resolver contract
 */
function createResolver(signer: Signer, ens: Contract): Promise<Contract>;

/**
 * Create reverse registrar for reverse DNS lookups
 * @param signer - Signer to deploy reverse registrar with
 * @param ens - ENS registry contract
 * @param resolver - Resolver contract
 * @returns Promise resolving to reverse registrar contract
 */
function createReverseRegistrar(
  signer: Signer, 
  ens: Contract, 
  resolver: Contract
): Promise<Contract>;

Usage Examples:

import { deployENS } from "@ethereum-waffle/ens";

// Deploy complete ENS system
const provider = new MockProvider();
const [wallet] = provider.getWallets();

const ens = await deployENS(wallet);

// ENS system is now ready for domain registration and testing
await ens.createTopLevelDomain("test");
await ens.setAddress("example.test", wallet.address);

ENS Management Class

Comprehensive ENS management system providing domain registration, address resolution, and reverse lookup functionality.

/**
 * Complete ENS management system for testing
 */
class ENS {
  /** signer used for ENS operations */
  signer: Signer;
  /** ENS registry contract */
  ens: Contract;
  /** Default resolver contract */
  resolver: Contract;
  /** Map of TLD registrars */
  registrars: Record<string, Contract>;
  /** Reverse registrar contract */
  reverseRegistrar: Contract;

  constructor(
    signer: Signer, 
    ens: Contract, 
    resolver: Contract, 
    reverseRegistrar: Contract
  );

  /**
   * Create top-level domain (e.g., "test", "eth")
   * @param domain - TLD name without dot
   */
  createTopLevelDomain(domain: string): Promise<void>;

  /**
   * Create domain with optional recursive parent creation
   * @param domain - Full domain name (e.g., "example.test")
   * @param options - Domain registration options
   */
  createDomain(domain: string, options?: DomainRegistrationOptions): Promise<void>;

  /**
   * Create subdomain under existing domain
   * @param domain - Full subdomain name (e.g., "sub.example.test")
   * @param options - Domain registration options
   */
  createSubDomain(domain: string, options?: DomainRegistrationOptions): Promise<void>;

  /**
   * Ensure domain exists, creating parent domains if needed
   * @param domain - Domain name to ensure exists
   * @param options - Domain registration options
   */
  ensureDomainExist(domain: string, options?: DomainRegistrationOptions): Promise<void>;

  /**
   * Set address for domain resolution
   * @param domain - Domain name
   * @param address - Ethereum address to resolve to
   * @param options - Domain registration options
   */
  setAddress(domain: string, address: string, options?: DomainRegistrationOptions): Promise<void>;

  /**
   * Set address with reverse DNS entry
   * @param domain - Domain name
   * @param signer - Signer whose address to set
   * @param options - Domain registration options
   */
  setAddressWithReverse(domain: string, signer: Signer, options?: DomainRegistrationOptions): Promise<void>;
}

/**
 * Options for domain registration operations
 */
interface DomainRegistrationOptions {
  /** Create parent domains recursively if they don't exist */
  recursive?: boolean;
}

Usage Examples:

import { deployENS, ENS } from "@ethereum-waffle/ens";

const provider = new MockProvider();
const [wallet, otherWallet] = provider.getWallets();

// Deploy and setup ENS
const ens = await deployENS(wallet);

// Create domains
await ens.createTopLevelDomain("test");
await ens.createDomain("example.test");
await ens.createSubDomain("api.example.test");

// Set addresses
await ens.setAddress("example.test", wallet.address);
await ens.setAddress("api.example.test", otherWallet.address);

// Set with reverse lookup
await ens.setAddressWithReverse("wallet.test", wallet);

// Use with provider for name resolution
await provider.setupENS(wallet);
const resolvedAddress = await provider.resolveName("example.test");
console.log(resolvedAddress); // wallet.address

Domain Management Patterns

Advanced patterns for managing complex ENS domain hierarchies and testing scenarios.

Recursive Domain Creation:

import { deployENS } from "@ethereum-waffle/ens";

const ens = await deployENS(wallet);

// Create nested domain structure automatically
await ens.createDomain("deeply.nested.example.test", { recursive: true });
// This creates: "test" -> "example.test" -> "nested.example.test" -> "deeply.nested.example.test"

// Set addresses for the entire hierarchy
await ens.setAddress("test", registryAddress);
await ens.setAddress("example.test", exampleAddress);
await ens.setAddress("nested.example.test", nestedAddress);
await ens.setAddress("deeply.nested.example.test", deepAddress);

Multi-TLD Setup:

import { deployENS } from "@ethereum-waffle/ens";

const ens = await deployENS(wallet);

// Create multiple top-level domains
await ens.createTopLevelDomain("test");
await ens.createTopLevelDomain("local"); 
await ens.createTopLevelDomain("dev");

// Create domains under different TLDs
await ens.createDomain("api.test");
await ens.createDomain("frontend.local");
await ens.createDomain("backend.dev");

// Set different addresses for each
await ens.setAddress("api.test", apiContractAddress);
await ens.setAddress("frontend.local", frontendAddress);
await ens.setAddress("backend.dev", backendAddress);

Integration with Contract Testing:

import { deployENS, deployContract, MockProvider } from "ethereum-waffle";

// Setup ENS and contracts
const provider = new MockProvider();
const [wallet] = provider.getWallets();

const ens = await deployENS(wallet);
const registry = await deployContract(wallet, RegistryJson);
const token = await deployContract(wallet, TokenJson);

// Register contracts with ENS
await ens.createTopLevelDomain("contracts");
await ens.setAddress("registry.contracts", registry.address);
await ens.setAddress("token.contracts", token.address);

// Setup provider to use ENS
await provider.setupENS(wallet);

// Test contract interactions using ENS names
const resolvedRegistry = await provider.resolveName("registry.contracts");
expect(resolvedRegistry).to.equal(registry.address);

// Use in other contracts
const client = await deployContract(wallet, ClientJson, ["registry.contracts"]);

Testing ENS Functionality:

import { expect } from "chai";
import { deployENS, MockProvider } from "ethereum-waffle";

describe("ENS Integration", () => {
  let provider: MockProvider;
  let wallet: Wallet;
  let ens: ENS;

  beforeEach(async () => {
    provider = new MockProvider();
    [wallet] = provider.getWallets();
    ens = await deployENS(wallet);
    await provider.setupENS(wallet);
  });

  it("should resolve domain names", async () => {
    await ens.createTopLevelDomain("test");
    await ens.setAddress("example.test", wallet.address);
    
    const resolved = await provider.resolveName("example.test");
    expect(resolved).to.equal(wallet.address);
  });

  it("should handle subdomains", async () => {
    await ens.createTopLevelDomain("test");
    await ens.createDomain("example.test");
    await ens.createSubDomain("api.example.test");
    await ens.setAddress("api.example.test", wallet.address);
    
    const resolved = await provider.resolveName("api.example.test");
    expect(resolved).to.equal(wallet.address);
  });

  it("should support reverse lookups", async () => {
    await ens.createTopLevelDomain("test");
    await ens.setAddressWithReverse("wallet.test", wallet);
    
    const reverseName = await provider.lookupAddress(wallet.address);
    expect(reverseName).to.equal("wallet.test");
  });
});