ENS (Ethereum Name Service) resolution and namehash computation.
Does
- Compute EIP-137 namehash for ENS names (
namehash/1) - Normalize names via UTS-46 / ENSIP-15 before hashing (case-fold, NFC, strip trailing dot)
- Validate name structure (reject empty labels, disallowed code points)
- Forward resolution: ENS name → ETH address (
resolve/2) - Multi-coin address resolution via
addr(bytes32,uint256)(address/3, ENSIP-9/11) - ENSIP-10 wildcard resolution + EIP-3668 CCIP-Read off-chain lookups (
address/3) - Reverse resolution: ETH address → ENS name (
reverse/2) - Text record queries (
text/3), contenthash, ABI, pubkey retrieval - Look up resolver contracts (
resolver/2) - UTS-46 / ENSIP-15 name normalization before namehash (
normalize/1) - DNS wire-format name encoding (
dns_encode/1, ENSIP-10) - Configurable registry address via
:registryopt
Does Not
- ENS name registration or management (write operations)
- Caching — consumers manage their own cache
- The ENSIP-15 security filters (confusable / script-mixing / NSM checks) —
normalize/1applies the deterministic Unicode steps (NFC, case-fold, ignored/disallowed code points) but not the data-table-driven confusable detection. See the internal Onchain.ENS.Normalize module for the scope boundary.
Functions
| Function | Purpose |
|---|---|
namehash/1 | ENS name -> 32-byte EIP-137 node hash (normalized first) |
namehash!/1 | Same, raises on error |
normalize/1 | Apply UTS-46 / ENSIP-15 normalization to a name |
normalize!/1 | Same, raises on error |
dns_encode/1 | ENS name -> DNS wire format (ENSIP-10) |
dns_encode!/1 | Same, raises on error |
evm_coin_type/1 | EVM chain id -> ENSIP-11 coin type |
resolver/2 | ENS name -> resolver contract address |
resolver!/2 | Same, raises on error |
resolve/2 | ENS name -> ETH address (forward resolution) |
resolve!/2 | Same, raises on error |
address/3 | ENS name + coin type -> raw address bytes (multi-coin, wildcard + CCIP) |
address!/3 | Same, raises on error |
reverse/2 | ETH address -> ENS name (reverse resolution) |
reverse!/2 | Same, raises on error |
text/3 | Retrieve a text record (avatar, url, etc.) |
text!/3 | Same, raises on error |
contenthash/2 | Retrieve the contenthash record |
contenthash!/2 | Same, raises on error |
pubkey/2 | Retrieve the ECDSA public key |
pubkey!/2 | Same, raises on error |
abi/3 | Retrieve ABI data (ENSIP-7) |
abi!/3 | Same, raises on error |
API Functions
| Function | Arity | Description | Param Kinds |
|---|---|---|---|
abi! | 3 | Retrieve ABI data. Raises on error. | name: value, content_types: value, opts: value |
abi | 3 | Retrieve ABI data from an ENS name's resolver (ENSIP-7). | name: value, content_types: value, opts: value |
pubkey! | 2 | Retrieve the ECDSA public key. Raises on error. | name: value, opts: value |
pubkey | 2 | Retrieve the ECDSA public key from an ENS name's resolver. | name: value, opts: value |
contenthash! | 2 | Retrieve the contenthash record. Raises on error. | name: value, opts: value |
contenthash | 2 | Retrieve the contenthash record from an ENS name's resolver. | name: value, opts: value |
text! | 3 | Retrieve a text record. Raises on error. | name: value, key: value, opts: value |
text | 3 | Retrieve a text record from an ENS name's resolver. | name: value, key: value, opts: value |
reverse! | 2 | Reverse-resolve an ETH address to an ENS name. Raises on error. | address: value, opts: value |
reverse | 2 | Reverse-resolve an ETH address to an ENS name. | address: value, opts: value |
address! | 3 | Resolve an ENS name to a chain-specific address. Raises on error. | name: value, coin_type: value, opts: value |
address | 3 | Resolve an ENS name to a chain-specific address (ENSIP-9 multi-coin). | name: value, coin_type: value, opts: value |
resolve! | 2 | Resolve an ENS name to an ETH address. Raises on error. | name: value, opts: value |
resolve | 2 | Resolve an ENS name to an ETH address (forward resolution). | name: value, opts: value |
resolver! | 2 | Look up the resolver contract address. Raises on error. | name: value, opts: value |
resolver | 2 | Look up the resolver contract address for an ENS name. | name: value, opts: value |
evm_coin_type | 1 | Derive an ENSIP-11 coin type from an EVM chain id. | chain_id: value |
dns_encode! | 1 | Encode an ENS name to DNS wire format. Raises on error. | name: value |
dns_encode | 1 | Encode an ENS name to DNS wire format (ENSIP-10). | name: value |
normalize! | 1 | Apply UTS-46 / ENSIP-15 normalization. Raises on error. | name: value |
normalize | 1 | Apply UTS-46 / ENSIP-15 normalization to an ENS name. | name: value |
namehash! | 1 | Compute the EIP-137 namehash. Raises on error. | name: value |
namehash | 1 | Compute the EIP-137 namehash for an ENS name. | name: value |
Summary
Functions
Retrieve ABI data from an ENS name's resolver (ENSIP-7).
Retrieve ABI data. Raises on error.
Resolve an ENS name to a chain-specific address (ENSIP-9 addr(bytes32,uint256)).
Resolve an ENS name to a chain-specific address. Raises on error.
Retrieve the contenthash record from an ENS name's resolver.
Retrieve the contenthash record. Raises on error.
Encode an ENS name to DNS wire format (ENSIP-10).
Encode an ENS name to DNS wire format. Raises on error.
Derive an ENSIP-11 coin type from an EVM chain id.
Compute the EIP-137 namehash for an ENS name.
Compute the EIP-137 namehash. Raises on error.
Apply UTS-46 / ENSIP-15 normalization to an ENS name.
Apply UTS-46 / ENSIP-15 normalization. Raises on error.
Retrieve the ECDSA public key from an ENS name's resolver.
Retrieve the ECDSA public key. Raises on error.
Resolve an ENS name to an ETH address (forward resolution).
Resolve an ENS name to an ETH address. Raises on error.
Look up the resolver contract address for an ENS name.
Look up the resolver contract address. Raises on error.
Reverse-resolve an ETH address to an ENS name.
Reverse-resolve an ETH address to an ENS name. Raises on error.
Retrieve a text record from an ENS name's resolver.
Retrieve a text record. Raises on error.
Functions
@spec abi(String.t(), non_neg_integer(), keyword()) :: {:ok, {non_neg_integer(), binary()}} | {:error, term()}
Retrieve ABI data from an ENS name's resolver (ENSIP-7).
Parameters
name- ENS name (e.g., "vitalik.eth") (value)content_types- Bitmask of content types: 1=JSON, 2=zlib, 4=CBOR, 8=URI (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Tuple of {content_type, abi_data} ({:ok, {non_neg_integer(), binary()}} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
content_types: %{
description: "Bitmask of content types: 1=JSON, 2=zlib, 4=CBOR, 8=URI",
kind: :value
}
},
returns: %{
type: "{:ok, {non_neg_integer(), binary()}} | {:error, term()}",
description: "Tuple of {content_type, abi_data}"
}
}
@spec abi!(String.t(), non_neg_integer(), keyword()) :: {non_neg_integer(), binary()}
Retrieve ABI data. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)content_types- Bitmask of content types: 1=JSON, 2=zlib, 4=CBOR, 8=URI (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Tuple of {content_type, abi_data} ({non_neg_integer(), binary()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
content_types: %{
description: "Bitmask of content types: 1=JSON, 2=zlib, 4=CBOR, 8=URI",
kind: :value
}
},
returns: %{
type: "{non_neg_integer(), binary()}",
description: "Tuple of {content_type, abi_data}"
}
}
@spec address(String.t(), non_neg_integer(), keyword()) :: {:ok, binary()} | {:error, term()}
Resolve an ENS name to a chain-specific address (ENSIP-9 addr(bytes32,uint256)).
Unlike resolve/2 (which returns an EIP-55 checksummed string for Ethereum
mainnet only), this returns the raw address bytes for any SLIP-44 / ENSIP-11
coin type. Resolution goes through the ENSIP-10 extended-resolver path when the
resolver supports it (interface 0x9061b923), which transparently handles
wildcard subdomains and EIP-3668 CCIP-Read off-chain lookups.
@spec address!(String.t(), non_neg_integer(), keyword()) :: binary()
Resolve an ENS name to a chain-specific address. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)coin_type- SLIP-44 / ENSIP-11 coin type (default 60 = ETH) (default:60, value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Raw address bytes for the coin type (binary())
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
coin_type: %{
default: 60,
description: "SLIP-44 / ENSIP-11 coin type (default 60 = ETH)",
kind: :value
}
},
returns: %{
type: "binary()",
description: "Raw address bytes for the coin type"
}
}
Retrieve the contenthash record from an ENS name's resolver.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Raw contenthash bytes (ENSIP-7 encoded) ({:ok, binary()} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "{:ok, binary()} | {:error, term()}",
description: "Raw contenthash bytes (ENSIP-7 encoded)"
}
}
Retrieve the contenthash record. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Raw contenthash bytes (binary())
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{type: "binary()", description: "Raw contenthash bytes"}
}
Encode an ENS name to DNS wire format (ENSIP-10).
Parameters
name- ENS name, e.g. "foo.eth" (value)
Returns
Length-prefixed labels with a null terminator, e.g. "foo.eth" -> <<3, "foo", 3, "eth", 0>>. The name is normalized first. ({:ok, binary()} | {:error, term()})
# descripex:contract
%{
params: %{name: %{description: "ENS name, e.g. \"foo.eth\"", kind: :value}},
returns: %{
type: "{:ok, binary()} | {:error, term()}",
description: "Length-prefixed labels with a null terminator, e.g. \"foo.eth\" -> <<3, \"foo\", 3, \"eth\", 0>>. The name is normalized first."
}
}
Encode an ENS name to DNS wire format. Raises on error.
Parameters
name- ENS name to encode (value)
Returns
DNS wire-format encoded name (binary())
# descripex:contract
%{
params: %{name: %{description: "ENS name to encode", kind: :value}},
returns: %{type: "binary()", description: "DNS wire-format encoded name"}
}
@spec evm_coin_type(pos_integer()) :: pos_integer()
Derive an ENSIP-11 coin type from an EVM chain id.
Parameters
chain_id- EVM chain id, e.g. 1 (mainnet), 10 (Optimism), 8453 (Base) (value)
Returns
ENSIP-11 coin type = 0x80000000 | chain_id. Pass this to address/3 to resolve an L2 address. Note Ethereum mainnet's canonical coin type is the SLIP-44 value 60, not the ENSIP-11 form. (pos_integer())
# descripex:contract
%{
params: %{
chain_id: %{
description: "EVM chain id, e.g. 1 (mainnet), 10 (Optimism), 8453 (Base)",
kind: :value
}
},
returns: %{
type: "pos_integer()",
description: "ENSIP-11 coin type = 0x80000000 | chain_id. Pass this to address/3 to resolve an L2 address. Note Ethereum mainnet's canonical coin type is the SLIP-44 value 60, not the ENSIP-11 form."
}
}
Compute the EIP-137 namehash for an ENS name.
Parameters
name- ENS name, e.g. "vitalik.eth" (value)
Returns
32-byte keccak256 node hash per EIP-137 ({:ok, <<_::256>>} | {:error, term})
# descripex:contract
%{
params: %{
name: %{description: "ENS name, e.g. \"vitalik.eth\"", kind: :value}
},
returns: %{
type: "{:ok, <<_::256>>} | {:error, term}",
description: "32-byte keccak256 node hash per EIP-137"
}
}
Compute the EIP-137 namehash. Raises on error.
Parameters
name- ENS name, e.g. "vitalik.eth" (value)
Returns
32-byte keccak256 node hash (<<_::256>>)
# descripex:contract
%{
params: %{
name: %{description: "ENS name, e.g. \"vitalik.eth\"", kind: :value}
},
returns: %{type: "<<_::256>>", description: "32-byte keccak256 node hash"}
}
Apply UTS-46 / ENSIP-15 normalization to an ENS name.
Parameters
name- ENS name, e.g. "VITALIK.eth" or "café.eth" (value)
Returns
Normalized name (case-folded, NFC, ignored code points stripped). See Onchain.ENS.Normalize for the scope boundary — the ENSIP-15 confusable/script-mixing filters are NOT applied. ({:ok, String.t()} | {:error, {:invalid_name, term()}})
# descripex:contract
%{
params: %{
name: %{
description: "ENS name, e.g. \"VITALIK.eth\" or \"café.eth\"",
kind: :value
}
},
returns: %{
type: "{:ok, String.t()} | {:error, {:invalid_name, term()}}",
description: "Normalized name (case-folded, NFC, ignored code points stripped). See Onchain.ENS.Normalize for the scope boundary — the ENSIP-15 confusable/script-mixing filters are NOT applied."
}
}
Apply UTS-46 / ENSIP-15 normalization. Raises on error.
Parameters
name- ENS name to normalize (value)
Returns
Normalized name (String.t())
# descripex:contract
%{
params: %{name: %{description: "ENS name to normalize", kind: :value}},
returns: %{type: "String.t()", description: "Normalized name"}
}
Retrieve the ECDSA public key from an ENS name's resolver.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Tuple of {x, y} 32-byte coordinates ({:ok, {binary(), binary()}} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "{:ok, {binary(), binary()}} | {:error, term()}",
description: "Tuple of {x, y} 32-byte coordinates"
}
}
Retrieve the ECDSA public key. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Tuple of {x, y} 32-byte coordinates ({binary(), binary()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "{binary(), binary()}",
description: "Tuple of {x, y} 32-byte coordinates"
}
}
Resolve an ENS name to an ETH address (forward resolution).
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
EIP-55 checksummed ETH address ({:ok, String.t()} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "{:ok, String.t()} | {:error, term()}",
description: "EIP-55 checksummed ETH address"
}
}
Resolve an ENS name to an ETH address. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
EIP-55 checksummed ETH address (String.t())
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{type: "String.t()", description: "EIP-55 checksummed ETH address"}
}
Look up the resolver contract address for an ENS name.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
EIP-55 checksummed resolver address ({:ok, String.t()} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "{:ok, String.t()} | {:error, term()}",
description: "EIP-55 checksummed resolver address"
}
}
Look up the resolver contract address. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
EIP-55 checksummed resolver address (String.t())
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
}
},
returns: %{
type: "String.t()",
description: "EIP-55 checksummed resolver address"
}
}
Reverse-resolve an ETH address to an ENS name.
Parameters
address- ETH address as 0x hex string or 20-byte binary (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
ENS name (e.g., "vitalik.eth") ({:ok, String.t()} | {:error, term()})
# descripex:contract
%{
params: %{
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
address: %{
description: "ETH address as 0x hex string or 20-byte binary",
kind: :value
}
},
returns: %{
type: "{:ok, String.t()} | {:error, term()}",
description: "ENS name (e.g., \"vitalik.eth\")"
}
}
Reverse-resolve an ETH address to an ENS name. Raises on error.
Parameters
address- ETH address as 0x hex string or 20-byte binary (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
ENS name (e.g., "vitalik.eth") (String.t())
# descripex:contract
%{
params: %{
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
address: %{
description: "ETH address as 0x hex string or 20-byte binary",
kind: :value
}
},
returns: %{
type: "String.t()",
description: "ENS name (e.g., \"vitalik.eth\")"
}
}
Retrieve a text record from an ENS name's resolver.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)key- Text record key (e.g., "avatar", "url", "com.twitter") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Text record value ({:ok, String.t()} | {:error, term()})
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
key: %{
description: "Text record key (e.g., \"avatar\", \"url\", \"com.twitter\")",
kind: :value
}
},
returns: %{
type: "{:ok, String.t()} | {:error, term()}",
description: "Text record value"
}
}
Retrieve a text record. Raises on error.
Parameters
name- ENS name (e.g., "vitalik.eth") (value)key- Text record key (e.g., "avatar", "url", "com.twitter") (value)opts- Options: :rpc_url, :timeout, :registry (default:[], value)
Returns
Text record value (String.t())
# descripex:contract
%{
params: %{
name: %{description: "ENS name (e.g., \"vitalik.eth\")", kind: :value},
opts: %{
default: [],
description: "Options: :rpc_url, :timeout, :registry",
kind: :value
},
key: %{
description: "Text record key (e.g., \"avatar\", \"url\", \"com.twitter\")",
kind: :value
}
},
returns: %{type: "String.t()", description: "Text record value"}
}