{
  "$schema": "https://evmnow.github.io/contract-metadata/v1/schema.json",
  "chainId": 1,
  "address": "0x59e16fccd424cc24e280be16e11bcd56fb0ce547",
  "meta": {
    "version": 1,
    "lastUpdated": "2026-03-28T00:00:00Z",
    "locale": "en"
  },
  "name": "ENS ETH Registrar Controller",
  "description": "The user-facing controller for registering and renewing .eth names, using commit-reveal to prevent front-running.",
  "about": "## Two-step registration (commit-reveal)\n\nRegistering a .eth name requires two transactions to prevent front-running. First, the user submits a hidden commitment — a hash of the desired name, owner, duration, and a random secret. After waiting at least 60 seconds (but no more than 24 hours), the user reveals the registration details and pays the fee. This prevents miners or bots from seeing a pending registration and stealing the name by submitting their own transaction first.\n\n## Pricing by name length\n\nNames are priced annually in USD, converted to ETH at the current exchange rate via Chainlink. Shorter names cost more: 5+ character names cost approximately $5/year, 4-character names ~$160/year, and 3-character names ~$640/year. Names must be at least 3 characters. The minimum registration duration is 28 days.\n\n## Expired name premiums\n\nWhen a name expires, the owner has a 90-day grace period to renew. After the grace period, the name becomes available but carries a temporary premium that starts extremely high and decays exponentially — halving roughly every day. After about 21 days the premium becomes negligible. This Dutch auction mechanism ensures fair price discovery for desirable expired names and prevents sniping at the moment of expiry.\n\n## The ENS architecture\n\nENS separates concerns across multiple contracts. The ENS Registry maps names to owners and resolvers. The Base Registrar is the ERC-721 NFT contract that tracks .eth name ownership and expiry. This Controller is the user-facing entry point that orchestrates registration: it handles pricing, commit-reveal, and can atomically set a resolver and records (addresses, text records, content hashes) during registration. Resolvers are separate contracts that store the actual records a name points to.",
  "risks": [
    "Names expire — if not renewed, names become available for re-registration after a 90-day grace period",
    "Commit-reveal timing — commitments expire after 24 hours and must wait at least 60 seconds before reveal",
    "ETH price exposure — registration fees are priced in USD but paid in ETH at current exchange rate",
    "Expired name premiums — recently expired names carry a decaying premium that can be very high initially"
  ],
  "category": "identity",
  "tags": ["ens", "identity", "naming", "dns", "infrastructure"],
  "links": [
    { "label": "Etherscan", "url": "https://etherscan.io/address/0x59E16fcCd424Cc24e280Be16E11Bcd56fb0CE547" },
    { "label": "ENS", "url": "https://ens.domains" },
    { "label": "Documentation", "url": "https://docs.ens.domains" },
    { "label": "ENS App", "url": "https://app.ens.domains" }
  ],
  "theme": {
    "accent": "#5284FF"
  },
  "groups": {
    "registration": { "label": "Registration", "order": 1 },
    "renewal": { "label": "Renewal", "order": 2 },
    "info": { "label": "Info", "order": 3 },
    "admin": { "label": "Admin", "order": 4 }
  },
  "actions": {
    "available": {
      "title": "Check Availability",
      "description": "Check whether a .eth name is available to register; false if it is registered or in its 90-day grace period.",
      "stateMutability": "view",
      "group": "info",
      "params": {
        "label": {
          "label": "name",
          "description": "The name to check (without .eth suffix, e.g. \"vitalik\")"
        }
      },
      "examples": [
        { "label": "Check \"vitalik\"", "params": { "label": "vitalik" } },
        { "label": "Check \"ethereum\"", "params": { "label": "ethereum" } }
      ]
    },
    "rentPrice": {
      "title": "Price",
      "description": "Get the registration or renewal price for a name: a base price plus any premium for recently expired names.",
      "stateMutability": "view",
      "group": "info",
      "params": {
        "label": {
          "label": "name",
          "description": "The name to price (without .eth suffix)"
        },
        "duration": {
          "label": "duration",
          "description": "Registration duration in seconds (minimum 28 days / 2419200 seconds)",
          "type": "duration"
        }
      },
      "related": ["available", "register"],
      "examples": [
        { "label": "Price \"alice\" for 1 year", "params": { "label": "alice", "duration": "31536000" } }
      ]
    },
    "valid": {
      "title": "Valid Name",
      "description": "Check whether a name meets the minimum length requirement (3+ characters).",
      "stateMutability": "view",
      "group": "info",
      "params": {
        "label": {
          "label": "name",
          "description": "The name to validate (without .eth suffix)"
        }
      }
    },
    "makeCommitment": {
      "title": "Make Commitment",
      "description": "Generate the commitment hash for the first step of registration, computed off-chain and then submitted via commit().",
      "stateMutability": "pure",
      "group": "registration",
      "params": {
        "registration": {
          "label": "registration",
          "description": "Registration details: label, owner, duration, secret, resolver, records data, reverse record flags, and referrer"
        }
      },
      "related": ["commit", "register"]
    },
    "commit": {
      "title": "Commit",
      "description": "Submit a commitment hash — the first step of registration — then wait before calling register().",
      "group": "registration",
      "params": {
        "commitment": {
          "label": "commitment",
          "description": "The commitment hash from makeCommitment()"
        }
      },
      "related": ["makeCommitment", "register"]
    },
    "register": {
      "title": "Register",
      "description": "Complete a registration — the second step after commit() — by submitting the original details plus ETH payment.",
      "intent": "Register a .eth name",
      "group": "registration",
      "warning": "Sends ETH. Ensure you committed at least 60 seconds ago and that the commitment has not expired (24 hour window).",
      "params": {
        "registration": {
          "label": "registration",
          "description": "The same Registration struct passed to makeCommitment(): label, owner, duration, secret, resolver, data, etc."
        }
      },
      "related": ["commit", "makeCommitment", "rentPrice", "available"]
    },
    "renew": {
      "title": "Renew",
      "description": "Extend a .eth name's registration; anyone can renew any name at the base price, with excess ETH refunded.",
      "intent": "Renew {label}.eth for {duration}",
      "group": "renewal",
      "warning": "Sends ETH to cover the renewal cost.",
      "params": {
        "label": {
          "label": "name",
          "description": "The name to renew (without .eth suffix)"
        },
        "duration": {
          "label": "duration",
          "description": "Additional time to add in seconds",
          "type": "duration"
        },
        "referrer": {
          "label": "referrer",
          "description": "Optional referrer identifier"
        }
      },
      "related": ["rentPrice"]
    },
    "commitments": {
      "title": "Commitment Timestamp",
      "description": "Check when a commitment was submitted, returning its commit block timestamp, or 0 if it doesn't exist.",
      "stateMutability": "view",
      "group": "registration",
      "params": {
        "_0": {
          "label": "commitment hash"
        }
      },
      "returns": {
        "_0": { "type": "timestamp" }
      }
    },
    "minCommitmentAge": {
      "title": "Min Commitment Age",
      "description": "Minimum time (in seconds) that must pass between commit() and register(). Typically 60 seconds.",
      "stateMutability": "view",
      "group": "info",
      "returns": { "_0": { "type": "duration" } }
    },
    "maxCommitmentAge": {
      "title": "Max Commitment Age",
      "description": "Maximum time in seconds a commitment stays valid before it expires and a new one is needed (typically 24 hours).",
      "stateMutability": "view",
      "group": "info",
      "returns": { "_0": { "type": "duration" } }
    },
    "withdraw": {
      "title": "Withdraw",
      "description": "Withdraw accumulated ETH from the contract. Only callable by the contract owner.",
      "group": "admin"
    },
    "recoverFunds": {
      "title": "Recover ERC-20 Tokens",
      "description": "Recover ERC-20 tokens accidentally sent to this contract. Only callable by the contract owner.",
      "group": "admin",
      "params": {
        "_token": { "label": "token address", "type": "address" },
        "_to": { "label": "recipient", "type": "address" },
        "_amount": { "label": "amount" }
      }
    },
    "owner": {
      "title": "Owner",
      "description": "The address that controls admin functions (withdraw, recover funds).",
      "stateMutability": "view",
      "group": "admin",
      "returns": { "_0": { "type": "address" } }
    },
    "supportsInterface": {
      "title": "Supports Interface",
      "description": "Check whether this contract implements a specific interface (EIP-165).",
      "stateMutability": "view",
      "group": "info",
      "params": {
        "interfaceID": { "label": "interface ID" }
      }
    }
  },
  "events": {
    "NameRegistered": {
      "description": "Emitted when a .eth name is successfully registered.",
      "params": {
        "label": { "label": "name" },
        "labelhash": { "label": "labelhash" },
        "owner": { "label": "owner", "type": "address" },
        "baseCost": { "label": "base cost", "type": "eth" },
        "premium": { "label": "premium", "type": "eth" },
        "expires": { "label": "expires", "type": "timestamp" },
        "referrer": { "label": "referrer" }
      }
    },
    "NameRenewed": {
      "description": "Emitted when a .eth name is renewed.",
      "params": {
        "label": { "label": "name" },
        "labelhash": { "label": "labelhash" },
        "cost": { "label": "cost", "type": "eth" },
        "expires": { "label": "new expiry", "type": "timestamp" },
        "referrer": { "label": "referrer" }
      }
    }
  }
}
