Skip to main content

Overview

Resolver profiles are modular components that implement specific functionality as defined by various EIPs (Ethereum Improvement Proposals). The PublicResolver combines all these profiles to provide a complete resolver solution. Each profile inherits from ResolverBase and implements a specific interface, providing both read and write functions for a particular type of data.

Profile Architecture

All profiles follow this pattern:
  1. Inherit from ResolverBase: Gets versioning and authorization support
  2. Implement specific interface: Defines the data type’s read functions
  3. Use versioned storage: Data is stored by version to prevent stale reads
  4. Require authorization: Write functions use the authorised(node) modifier

ABIResolver

EIP-205

ENS support for contract ABIs

Description

Stores contract ABIs (Application Binary Interfaces) associated with ENS names. ABIs can be stored in multiple formats (JSON, Solidity, etc.) identified by content type.

Interface: IABIResolver.sol:contracts/resolvers/profiles/IABIResolver.sol

Functions

function ABI(
    bytes32 node,
    uint256 contentTypes
) external view returns (uint256 contentType, bytes memory data)
Parameters:
  • node: The ENS node to query
  • contentTypes: Bitwise OR of accepted ABI formats (e.g., 1 for JSON, 2 for zlib-compressed JSON)
Returns:
  • contentType: The content type of the returned ABI
  • data: The ABI data in the returned format
Description: Returns the ABI for a name in the requested format. The function searches through available formats and returns the first match.
function setABI(
    bytes32 node,
    uint256 contentType,
    bytes calldata data
) external
Parameters:
  • node: The node to update
  • contentType: The content type identifier (must be a power of 2)
  • data: The ABI data
Authorization: Requires authorization for the nodeEvents:
event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
Description: Sets or updates the ABI for a name. Content types must be powers of 2 (1, 2, 4, 8, etc.).

Usage Example

// Store a JSON ABI (content type 1)
string memory abiJson = '[{"type":"function","name":"transfer",...}]';
resolver.setABI(node, 1, bytes(abiJson));

// Retrieve the ABI (requesting JSON or compressed formats)
(uint256 contentType, bytes memory abi) = resolver.ABI(node, 3); // 3 = 1 | 2

AddrResolver

EIP-137

Ethereum Domain Name Service

EIP-2304

Multichain address resolution

Description

Resolves ENS names to cryptocurrency addresses. Supports Ethereum addresses (coin type 60) and addresses for other blockchains using SLIP-44 coin type identifiers.

Interface: IAddrResolver.sol, IAddressResolver.sol:contracts/resolvers/profiles/IAddrResolver.sol

Functions

function addr(bytes32 node) external view returns (address payable)
Parameters:
  • node: The ENS node to query
Returns:
  • Ethereum address associated with the node
Description: Returns the Ethereum address (coin type 60) for a name. This is a convenience function for addr(node, 60).
function addr(
    bytes32 node,
    uint256 coinType
) public view returns (bytes memory)
Parameters:
  • node: The ENS node to query
  • coinType: SLIP-44 coin type identifier (e.g., 0 for Bitcoin, 60 for Ethereum, 118 for Cosmos)
Returns:
  • Address bytes in the format appropriate for the coin type
Description: Returns the address for any supported cryptocurrency. For EVM chains with no address set, falls back to the default EVM address.
function setAddr(bytes32 node, address addr) external
Parameters:
  • node: The node to update
  • addr: The Ethereum address to set
Authorization: Requires authorization for the nodeEvents:
event AddrChanged(bytes32 indexed node, address a);
event AddressChanged(bytes32 indexed node, uint256 coinType, bytes newAddress);
function setAddr(
    bytes32 node,
    uint256 coinType,
    bytes memory addressBytes
) public
Parameters:
  • node: The node to update
  • coinType: SLIP-44 coin type identifier
  • addressBytes: The address in bytes format
Authorization: Requires authorization for the nodeValidation: For EVM chains, address must be 0 or 20 bytesEvents:
event AddressChanged(bytes32 indexed node, uint256 coinType, bytes newAddress);
function hasAddr(
    bytes32 node,
    uint256 coinType
) external view returns (bool)
Parameters:
  • node: The ENS node to query
  • coinType: The coin type to check
Returns:
  • true if an address is set for the given coin type

Usage Example

// Set Ethereum address
resolver.setAddr(node, 0x742d35Cc6634C0532925a3b844Bc454e4438f44e);

// Set Bitcoin address (coin type 0)
bytes memory btcAddr = hex"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa";
resolver.setAddr(node, 0, btcAddr);

// Get Ethereum address
address ethAddr = resolver.addr(node);

// Get Bitcoin address
bytes memory btcAddress = resolver.addr(node, 0);

// Check if Cosmos address exists (coin type 118)
bool hasCosmosAddr = resolver.hasAddr(node, 118);

Common Coin Types

BlockchainCoin TypeExample Usage
Bitcoin0resolver.addr(node, 0)
Litecoin2resolver.addr(node, 2)
Dogecoin3resolver.addr(node, 3)
Ethereum60resolver.addr(node, 60) or resolver.addr(node)
Cosmos118resolver.addr(node, 118)
BNB Smart Chain60resolver.addr(node, 60) (EVM chain)

ContentHashResolver

EIP-1577

ENS support for contenthash

Description

Stores content hashes for decentralized storage systems like IPFS, Swarm, Arweave, and others. This enables ENS names to resolve to decentralized websites and content.

Interface: IContentHashResolver.sol:contracts/resolvers/profiles/IContentHashResolver.sol

Functions

function contenthash(bytes32 node) external view returns (bytes memory)
Parameters:
  • node: The ENS node to query
Returns:
  • Content hash in binary format (includes codec identifier)
Description: Returns the content hash associated with the name. The hash format includes a multicodec identifier prefix.
function setContenthash(
    bytes32 node,
    bytes calldata hash
) external
Parameters:
  • node: The node to update
  • hash: The content hash to set (with codec prefix)
Authorization: Requires authorization for the nodeEvents:
event ContenthashChanged(bytes32 indexed node, bytes hash);

Usage Example

// Set IPFS content hash
// Format: 0xe3 (IPFS codec) + 0x01 (SHA-256) + [32 bytes hash]
bytes memory ipfsHash = hex"e3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f";
resolver.setContenthash(node, ipfsHash);

// Get content hash
bytes memory hash = resolver.contenthash(node);

// Clear content hash
resolver.setContenthash(node, "");

Supported Protocols

  • IPFS: 0xe3 codec prefix
  • Swarm: 0xe4 codec prefix
  • Arweave: 0xe5 codec prefix
  • Onion: 0xbc codec prefix (Tor)
  • Onion3: 0xbd codec prefix (Tor v3)

TextResolver

EIP-634

ENS support for text records

Description

Stores arbitrary key-value text data associated with ENS names. Commonly used for email addresses, URLs, social media handles, avatars, and more.

Interface: ITextResolver.sol:contracts/resolvers/profiles/ITextResolver.sol

Functions

function text(
    bytes32 node,
    string calldata key
) external view returns (string memory)
Parameters:
  • node: The ENS node to query
  • key: The text record key
Returns:
  • The text value associated with the key
function setText(
    bytes32 node,
    string calldata key,
    string calldata value
) external
Parameters:
  • node: The node to update
  • key: The text record key
  • value: The text value to set
Authorization: Requires authorization for the nodeEvents:
event TextChanged(
    bytes32 indexed node,
    string indexed indexedKey,
    string key,
    string value
);

Usage Example

// Set various text records
resolver.setText(node, "email", "[email protected]");
resolver.setText(node, "url", "https://example.com");
resolver.setText(node, "avatar", "https://example.com/avatar.png");
resolver.setText(node, "description", "My ENS profile");
resolver.setText(node, "com.twitter", "@username");
resolver.setText(node, "com.github", "username");

// Read text records
string memory email = resolver.text(node, "email");
string memory twitter = resolver.text(node, "com.twitter");

// Clear a text record
resolver.setText(node, "email", "");

Standard Text Record Keys

While any key can be used, these are commonly recognized:
KeyDescriptionExample
emailEmail address[email protected]
urlWebsite URLhttps://example.com
avatarAvatar image URLhttps://example.com/avatar.png
descriptionProfile descriptionWeb3 developer
noticeLegal notice© 2024 Example Corp
keywordsKeywordsweb3,ens,ethereum
com.twitterTwitter handle@username
com.githubGitHub usernameusername
com.discordDiscord handleuser#1234
com.redditReddit usernameu/username
com.telegramTelegram username@username
org.telegramTelegram username@username

PubkeyResolver

EIP-619

ENS support for SECP256k1 public keys

Description

Stores SECP256k1 public keys for encryption and signature verification. Useful for encrypted messaging and other cryptographic operations.

Interface: IPubkeyResolver.sol:contracts/resolvers/profiles/IPubkeyResolver.sol

Functions

function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y)
Parameters:
  • node: The ENS node to query
Returns:
  • x: The X coordinate of the public key curve point
  • y: The Y coordinate of the public key curve point
function setPubkey(
    bytes32 node,
    bytes32 x,
    bytes32 y
) external
Parameters:
  • node: The node to update
  • x: The X coordinate of the public key
  • y: The Y coordinate of the public key
Authorization: Requires authorization for the nodeEvents:
event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);

Usage Example

// Set public key coordinates
bytes32 x = 0x1234...;
bytes32 y = 0x5678...;
resolver.setPubkey(node, x, y);

// Get public key
(bytes32 pubX, bytes32 pubY) = resolver.pubkey(node);

// Clear public key
resolver.setPubkey(node, 0, 0);

NameResolver

EIP-181

ENS support for reverse resolution

Description

Stores canonical names for reverse resolution. Used primarily by the reverse registrar to map addresses back to ENS names.

Interface: INameResolver.sol:contracts/resolvers/profiles/INameResolver.sol

Functions

function name(bytes32 node) external view returns (string memory)
Parameters:
  • node: The ENS node to query (typically a reverse record node)
Returns:
  • The canonical name associated with the node
function setName(
    bytes32 node,
    string calldata newName
) external
Parameters:
  • node: The node to update
  • newName: The name to set
Authorization: Requires authorization for the nodeEvents:
event NameChanged(bytes32 indexed node, string name);

Usage Example

// Set reverse record name
// Typically done through the ReverseRegistrar, not directly
bytes32 reverseNode = getReverseNode(myAddress);
resolver.setName(reverseNode, "myname.eth");

// Get reverse record
string memory reverseName = resolver.name(reverseNode);

InterfaceResolver

EIP-165

Standard Interface Detection

Description

Allows ENS names to specify which contract addresses implement specific EIP-165 interfaces. If not explicitly set, automatically checks if the address returned by addr() supports the interface.

Interface: IInterfaceResolver.sol:contracts/resolvers/profiles/IInterfaceResolver.sol

Functions

function interfaceImplementer(
    bytes32 node,
    bytes4 interfaceID
) external view returns (address)
Parameters:
  • node: The ENS node to query
  • interfaceID: The EIP-165 interface ID to check
Returns:
  • Address of the contract implementing the interface, or address(0) if not found
Description: First checks if an implementer is explicitly set. If not, queries the contract at addr() to see if it supports the interface.
function setInterface(
    bytes32 node,
    bytes4 interfaceID,
    address implementer
) external
Parameters:
  • node: The node to update
  • interfaceID: The EIP-165 interface ID
  • implementer: The contract address that implements this interface (or address(0) to use default)
Authorization: Requires authorization for the nodeEvents:
event InterfaceChanged(
    bytes32 indexed node,
    bytes4 indexed interfaceID,
    address implementer
);

Usage Example

// Set explicit interface implementer
bytes4 erc721Interface = 0x80ac58cd;
resolver.setInterface(node, erc721Interface, nftContractAddress);

// Get interface implementer
address implementer = resolver.interfaceImplementer(node, erc721Interface);

// Reset to default (check addr() contract)
resolver.setInterface(node, erc721Interface, address(0));

DNSResolver

DNS-ENS Integration

Experimental support for DNS records in ENS

Description

Provides support for storing DNS records in ENS, enabling DNS-over-ENS functionality. This allows ENS names to serve DNS records and enables DNS domains to be hosted on Ethereum.

Interface: IDNSRecordResolver.sol, IDNSZoneResolver.sol:contracts/resolvers/profiles/IDNSRecordResolver.sol

Functions

function dnsRecord(
    bytes32 node,
    bytes32 name,
    uint16 resource
) external view returns (bytes memory)
Parameters:
  • node: The ENS node to query
  • name: The keccak-256 hash of the fully-qualified DNS name
  • resource: The DNS resource type (e.g., 1 for A, 28 for AAAA, 16 for TXT)
Returns:
  • DNS record in wire format
function setDNSRecords(
    bytes32 node,
    bytes calldata data
) external
Parameters:
  • node: The node to update
  • data: DNS records in wire format
Authorization: Requires authorization for the nodeEvents:
event DNSRecordChanged(bytes32 indexed node, bytes name, uint16 resource, bytes record);
event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);
function zonehash(bytes32 node) external view returns (bytes memory)
Parameters:
  • node: The ENS node to query
Returns:
  • Content hash pointing to a complete zone file
function setZonehash(
    bytes32 node,
    bytes calldata hash
) external
Parameters:
  • node: The node to update
  • hash: The zone hash to set (EIP-1577 format)
Authorization: Requires authorization for the nodeEvents:
event DNSZonehashChanged(bytes32 indexed node, bytes lastzonehash, bytes zonehash);
function hasDNSRecords(
    bytes32 node,
    bytes32 name
) public view returns (bool)
Parameters:
  • node: The ENS node to query
  • name: The DNS name hash to check
Returns:
  • true if DNS records exist for the name

Usage Example

// Set DNS records (requires proper wire format)
bytes memory dnsData = /* wire format DNS records */;
resolver.setDNSRecords(node, dnsData);

// Get a DNS A record
bytes32 nameHash = keccak256("example.com.");
bytes memory aRecord = resolver.dnsRecord(node, nameHash, 1); // 1 = A record

// Set a zone hash pointing to a complete zone file
bytes memory zoneHash = /* IPFS hash of zone file */;
resolver.setZonehash(node, zoneHash);

// Check if DNS records exist
bool hasRecords = resolver.hasDNSRecords(node, nameHash);

Common DNS Resource Types

TypeValueDescription
A1IPv4 address
AAAA28IPv6 address
CNAME5Canonical name
MX15Mail exchange
TXT16Text record
NS2Name server

ResolverBase

All resolver profiles inherit from ResolverBase, which provides:

Record Versioning

mapping(bytes32 => uint64) public recordVersions;

function clearRecords(bytes32 node) public virtual authorised(node)
Clearing records increments the version number for a node, effectively invalidating all previous records without explicitly deleting them.

Authorization

modifier authorised(bytes32 node) {
    require(isAuthorised(node));
    _;
}

function isAuthorised(bytes32 node) internal view virtual returns (bool);
The authorised modifier protects write functions, deferring to the implementation’s isAuthorised() logic.

Interface Detection

function supportsInterface(bytes4 interfaceID) public view virtual returns (bool)
Implements EIP-165 for interface detection.

Complete Integration Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@ensdomains/ens-contracts/contracts/resolvers/PublicResolver.sol";

contract CompleteENSProfile {
    PublicResolver public resolver;
    
    constructor(address resolverAddress) {
        resolver = PublicResolver(resolverAddress);
    }
    
    // Set up a complete profile in one transaction
    function setupCompleteProfile(
        bytes32 node,
        address ethAddress,
        bytes memory btcAddress,
        bytes memory contentHash,
        string memory email,
        string memory twitter,
        bytes32 pubkeyX,
        bytes32 pubkeyY
    ) external {
        bytes[] memory calls = new bytes[](7);
        
        // Ethereum address
        calls[0] = abi.encodeWithSelector(
            resolver.setAddr.selector,
            node,
            ethAddress
        );
        
        // Bitcoin address (coin type 0)
        calls[1] = abi.encodeWithSelector(
            resolver.setAddr.selector,
            node,
            0,
            btcAddress
        );
        
        // Content hash
        calls[2] = abi.encodeWithSelector(
            resolver.setContenthash.selector,
            node,
            contentHash
        );
        
        // Email text record
        calls[3] = abi.encodeWithSelector(
            resolver.setText.selector,
            node,
            "email",
            email
        );
        
        // Twitter text record
        calls[4] = abi.encodeWithSelector(
            resolver.setText.selector,
            node,
            "com.twitter",
            twitter
        );
        
        // Public key
        calls[5] = abi.encodeWithSelector(
            resolver.setPubkey.selector,
            node,
            pubkeyX,
            pubkeyY
        );
        
        // Execute all updates atomically
        resolver.multicall(calls);
    }
    
    // Read complete profile
    function getCompleteProfile(bytes32 node) external view returns (
        address ethAddress,
        bytes memory btcAddress,
        bytes memory contentHash,
        string memory email,
        string memory twitter,
        bytes32 pubkeyX,
        bytes32 pubkeyY
    ) {
        ethAddress = resolver.addr(node);
        btcAddress = resolver.addr(node, 0);
        contentHash = resolver.contenthash(node);
        email = resolver.text(node, "email");
        twitter = resolver.text(node, "com.twitter");
        (pubkeyX, pubkeyY) = resolver.pubkey(node);
    }
}

Summary Table

ProfileEIPPrimary FunctionUse Case
ABIResolver205ABI()Store contract ABIs
AddrResolver137, 2304addr()Resolve to addresses (ETH and multicoin)
ContentHashResolver1577contenthash()Link to IPFS/decentralized content
TextResolver634text()Store key-value text data
PubkeyResolver619pubkey()Store encryption public keys
NameResolver181name()Reverse resolution
InterfaceResolver165interfaceImplementer()Interface detection
DNSResolver-dnsRecord()DNS integration

Next Steps

PublicResolver

Learn about the PublicResolver implementation

Resolvers Overview

Back to resolvers overview

Build docs developers (and LLMs) love