Universal Resolver Matrix: Non-EVM Resolution and Architecture
1. Introduction
1.1. Document Purpose
This document provides a comprehensive breakdown of how ENSIP-19: Multichain Primary Names can be extended to support primary name resolution for non-EVM chains (Cosmos, Solana, etc.) via a new resolver profile in the Universal Resolver Matrix (URM).
It examines the current limitations of ENSIP-19 for non-EVM chains and defines the infrastructure requirements, trust models, proof systems, and implementation frameworks needed to enable bidirectional resolution (forward + reverse) for non-EVM blockchains.
It expands the normative specification in ENSIP-19 into a single technical reference for implementing non-EVM primary names as a URM profile, with additional sections covering implementation details:
- Contract & Namespace Inventory
- URM Mapping (Resolver Profiles)
- Edge Cases & Client Requirements
1.2. Universal Resolver Matrix Framework
The Universal Resolver Matrix (URM) is a systematic framework for mapping resolution pathways across namespaces using four core dimensions:
- Trust Model,
- Proof System,
- Rules & Lifecycle, and
- Verification Path.
This document structures non-EVM primary name implementation around these dimensions, with additional sections covering implementation details.
2. Scope & Goals
2.1. ENSIP-19 Overview & Non-EVM Limitations
ENSIP-19 standardizes primary name resolution for all coin types in EVM-based ecosystems, but currently provides forward resolution only for non-EVM chains (name → address via addr(node, coinType)). Reverse resolution (address → name) is not available for non-EVM chains due to missing infrastructure: chain-specific registrar contracts, state commitment bridges to L1, and verifier contracts.
2.2. Non-EVM Chain Resolution Scope
This profile extends ENSIP-19 to enable bidirectional resolution for SLIP-44 coin types where chainFromCoinType(coinType) = 0 (non-EVM chains). It requires additional infrastructure per chain to enable primary name support.
2.3. EVM vs Non-EVM Chains (Bidirectional vs Forward-only)
EVM chains (mainnet coinType=60, rollups via ENSIP-11) support full bidirectional resolution. Non-EVM chains (Cosmos, Solana, etc.) currently support forward resolution only; reverse resolution requires infrastructure (chain-specific registrars, state bridges, verifier contracts) that this profile defines.
2.4. Non-EVM Resolver Profile & Future Framework
Non-EVM chains cannot have primary names via current ENSIP-19 without additional infrastructure. This profile defines the required components (bridges, registrars, verifiers) needed for each chain type, creating an implementation roadmap that can be adapted for specific chains (Cosmos, Solana, etc.).
2.5. Deployment Architecture: Hybrid L1 + Namechain (Surge)
This profile requires a hybrid deployment architecture across Ethereum L1, Namechain (built on Nethermind's Surge framework), and target non-EVM chains:
2.5.1. Architecture Overview
ENS infrastructure migrates to Namechain, a based ZK rollup built on Nethermind's Surge framework, enabling fast preconfirmations and TEE-based proofs for low-latency CCIP-Read operations:
| Deployment Location | Component | Purpose |
|---|---|---|
| Ethereum L1 | ENS Registry | Canonical root of trust for all ENS name registrations and resolver assignments |
| Namechain (Surge) | Non-EVM Resolvers | Cost-effective wildcard resolvers per chain with dual-path proof validation: native TEE proof validation in CCIP callbacks (seconds) + fallback to L1 DA + settled ZK proofs |
| Namechain (Surge) | Bridge Verifiers | Validates non-EVM state proofs against L1-committed state roots (cross-chain verified) |
| Ethereum L1 | Universal Resolver | Routes resolution requests to appropriate namespace-specific resolvers |
| Non-EVM Chains | Chain Registrars | Per-chain registrars maintaining address → name mappings |
| Non-EVM Chains | State Bridges | Commit non-EVM chain state roots to Ethereum L1 |
2.5.2. Contract Inventory (Per Chain)
Existing Infrastructure (3 Contracts - No Deployment Needed):- ENS Registry (L1) - Central registry mapping names to resolvers (
0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e) - Bridge Verifiers (Namechain) - Validates non-EVM state proofs against L1-committed state roots
- Universal Resolver (L1) - Resolution entry point (optional but recommended)
- Chain Registrar (Non-EVM Chain) - Stores address → name mappings on target chain
- State Bridge (Non-EVM Chain → L1) - Commits chain state roots to Ethereum L1
- Chain Resolver (Namechain) - Handles chain-specific resolution with CCIP-Read validation
2.5.3. Roots of Trust & Security
The canonical root of trust consists of:
- ENS Registry on Ethereum L1: Primary source of truth for all name registrations and resolver assignments
- Chain registrar contracts: Store reverse mappings on non-EVM chains
- State bridge infrastructure: Commits non-EVM chain state roots to Ethereum L1
- Bridge verifiers on Namechain: Validate state proofs against L1-committed state roots via cross-chain communication
Security is inherited from both non-EVM chain consensus and Ethereum L1 consensus. Primary names are valid only if reverse and forward mappings agree.
2.5.4. Benefits & Tradeoffs
This hybrid architecture enables:
- Trustlessness: Core infrastructure (Registry, verifiers) remains on L1 for maximum security
- Cost-effectiveness: Chain-specific resolvers on Namechain benefit from lower gas costs
- Scalability: Dual-path proof validation enables flexible latency/security tradeoffs:
- Fast path: Resolvers validate pre-settled TEE proofs natively in CCIP callbacks (seconds latency)
- Secure path: Fallback to L1 DA + settled ZK proofs via cross-chain calls to bridge verifiers
- High performance: CCIP-Read latency reduced from hours to seconds using based preconfirmations and TEE proofs
- ENSv2 integration: Migration path for existing infrastructure
2.5.5. Governance Requirements
DAO Approval: When Is It Needed?While not strictly required for basic resolver operation, a production-ready non-EVM resolver should go through ENS DAO governance for integration into core ENS infrastructure. DAO approval is required if you want your resolver to be:
- Set as the default resolver for ENS (e.g., for the reverse registrar or for .eth names)
- Integrated at the protocol level (e.g., replacing the public resolver, or being referenced in official ENS contracts)
DAO approval is a matter of governance and trust. If you want your resolver to be widely used, trusted, or set as a default in ENS infrastructure, DAO approval:
- Signals community trust and security review
- Ensures the resolver is maintained and meets ENS standards
- Protects against unauthorized trust anchor modifications and bridge deployments
For non-EVM chains, governance approval is particularly important due to the additional infrastructure complexity (state bridges, cross-chain verifiers) and the higher security implications of integrating fundamentally different blockchain architectures into the ENS ecosystem.
Non-EVM Chain Integration enables:
- Primary name reverse resolution (
address → name) for non-EVM blockchains - Trustless verification of non-EVM chain state on Ethereum L1
- Standardized framework for integrating any SLIP-44 coin type into ENS primary name system
- Bridge infrastructure connecting non-EVM chains to Ethereum L1 trust model
ENSIP-19 currently only supports:
- ✅ Forward resolution: Non-EVM addresses can be stored and resolved via
addr(node, coinType) - ❌ Reverse resolution: Primary name reverse resolution (
address → name) is not available for non-EVM chains
Non-EVM chains lack the required infrastructure needed for trustless reverse resolution:
- Chain-specific registrar contracts — No onchain contracts storing reverse mappings (
address → name) on the non-EVM chain - State commitment bridges to L1 — No mechanism to commit non-EVM chain state roots to Ethereum L1 (similar to rollup state commitments)
- Verifier contracts — No bridge verifier contracts on Namechain that validate non-EVM state proofs against L1-committed state roots
This profile's goals:
- Provide a URM-ready framework for implementing primary name support for non-EVM chains
- Define the required infrastructure components (bridges, registrars, verifiers) needed for each chain type
- Establish trust models and verification paths for non-EVM chain integration
- Create an implementation roadmap that can be adapted for specific chains (Cosmos, Solana, etc.)
- Serve as a research agenda and funding guide for ENS DAO to prioritize chain integrations
- ENSIP-9: Multichain Address Resolution (coinType standard based on SLIP-44)
- ENSIP-10: Extended Resolver interface (CCIP-Read support)
- ENSIP-11: EVM-Compatible Chain Address Resolution (EVM coinType mapping)
- Forward resolution infrastructure (
addr(node, coinType)already works for all SLIP-44 coin types)
- State Bridge — Commits non-EVM chain state roots to Ethereum L1
- Chain Registrar Contract — Stores reverse mappings on the non-EVM chain (if chain supports smart contracts)
- Bridge Verifier Contract — Validates non-EVM state proofs on Namechain
- Address Format Standardization — Encoding/decoding layer for non-EVM address formats
- Chain-Specific Cryptographic Primitives — Signature verification, hash functions, proof formats
3. Trust Model
1.1 Roots of Trust
Canonical root of trust:The root of trust for non-EVM chain primary names requires a two-tier trust model:
- Ethereum L1 Consensus — The ENS Registry and resolver contracts on Ethereum L1 serve as the ultimate trust anchor
- Non-EVM Chain Consensus — The non-EVM chain's consensus mechanism (validators, miners, etc.) provides the trust anchor for chain state
- Bridge Trust — State commitment bridge that connects non-EVM chain state to Ethereum L1
Similar to rollup trust models (Profile 2 in ENSIP-19), non-EVM chains need a bridge that commits their state roots to L1, creating a trustless verification path. The bridge serves as the "rollup" for non-EVM chains.
Trust chain:- Non-EVM Chain State — Registrar contract (or equivalent data structure) stores
address → namemappings - State Commitment — Bridge posts non-EVM chain state roots to Ethereum L1 (periodic commitments)
- Bridge Verifier on L1 — Verifier contract validates storage proofs against L1-committed state roots
- ENS Registry — Canonical root on L1 maps reverse namespaces to resolvers
- Resolver on Namechain — Resolver uses bridge verifier to validate reverse resolution requests
Key principle: Trust flows from non-EVM chain consensus → state commitment bridge → Ethereum L1 consensus → ENS resolution.
1.2 Security Guarantees
Security properties:- Cryptographic authenticity — State proofs prove that reverse mappings exist in the non-EVM chain's state. Proofs cannot be forged without access to the chain's private keys or state.
- State integrity — Bridge commitments ensure state roots are correctly committed to L1. Invalid state proofs are rejected by the verifier contract.
- Consensus security — Security inherits from both the non-EVM chain's consensus mechanism and Ethereum L1 consensus
- Trust minimization — Security depends only on bridge correctness (state commitment) and chain consensus, not on gateways or oracles
- State spoofing — Attackers cannot forge state proofs because proofs must validate against L1-committed state roots
- Bridge manipulation — Invalid state commitments are rejected by verifier contract
- Replay attacks — State proofs include block numbers/height, preventing reuse of old proofs
- Cross-chain address confusion — CoinType ensures addresses are bound to the correct chain
- Non-EVM chain consensus security — The non-EVM chain's consensus mechanism is secure (e.g., Cosmos validators, Solana validators)
- Bridge correctness — The state commitment bridge correctly posts state roots to L1
- Verifier contract correctness — The bridge verifier contract correctly validates state proofs
- Namechain consensus — Namechain consensus guarantees the immutability of verifier contracts and L1 bridge commitments
1.3 Trust Assumptions
Users trust:
- Ethereum L1 and ENS contracts — Ethereum L1 consensus is secure, ENS Registry correctly maps namespaces, resolver contracts correctly implement verification logic
- Non-EVM chain consensus — The non-EVM chain's consensus mechanism (validators, miners, etc.) is secure and correctly maintains chain state
- State commitment bridge — The bridge correctly commits non-EVM chain state roots to Ethereum L1 and does not post invalid or manipulated state roots
- Bridge verifier contract — The verifier contract on Namechain correctly validates state proofs and rejects invalid proofs
- Gateway availability — While gateways are untrusted for correctness, users assume at least one honest gateway is available to fetch state proofs when needed (availability, not correctness)
- Bridge operators — Users trust that bridge operators correctly post state roots (trust can be minimized through cryptographic verification)
- Chain-specific infrastructure — Users trust that registrar contracts (if deployed) correctly store reverse mappings and are not compromised
4. Proof System
4.1. Inputs & Core Definitions
ENSIP-19's resolution process takes an address and coin type as inputs, converts them to hex-encoded strings for namespace construction, and uses a mapping function to determine which non-EVM chain (if any) the coin type represents. The system relies on ENSIP-10's resolve() function (with CCIP-Read support) to perform the actual resolution queries against onchain state.
All inputs are derived from ENSIP-9 (coin types) and address format standardization, ensuring compatibility with the broader multichain ENS ecosystem.
Core Definitions:addressBytes: Target address as bytes (ENSIP-9 address encoding for non-EVM chains)[addressAsHex]: Prefix-free lowercase hex representation ofaddressBytes. Example: Cosmos address encoded as bytes → hex representationcoinType: Coin type per ENSIP-9. Non-EVM chains havechainFromCoinType(coinType) = 0[coinTypeAsHex]: Prefix-free lowercase hex representation ofcoinType(no leading zeros)resolve(name, data): An ENSIP-10 implementation (CCIP-Read capable)
For reverse resolution (address → name), given addressBytes = cosmos1abc123... and coinType = 118:
- Construct
reverseName = "encoded_cosmos_address.76.reverse" - Compute
reverseNode = namehash(reverseName) - Call
resolve(reverseName, abi.encodeCall(INameResolver.name, (reverseNode))) - Returns the primary name (e.g.,
"alice.eth")
For forward resolution (name → address), given name = "alice.eth" and coinType = 118:
- Compute
node = namehash("alice.eth") - Call
resolve("alice.eth", abi.encodeCall(IAddressResolver.addr, (node, coinType))) - Returns the Cosmos address
4.2. Cryptographic Primitives
4.2.1. Chain-Specific Signature Algorithms
Non-EVM chains use different signature algorithms than Ethereum's ECDSA secp256k1:
Cosmos:- Signature Algorithm: Ed25519, secp256k1 (chain-dependent)
- Hash Function: SHA-256, RIPEMD-160
- Address Format: Bech32 encoding (e.g.,
cosmos1...,osmo1...) - Merkle Tree: IAVL tree (key-value Merkle tree) for state proofs
- Signature Algorithm: Ed25519
- Hash Function: SHA-256
- Address Format: Base58 encoding (public keys)
- State Structure: Account-based model
4.2.2. Namehash
Namehash creates deterministic, collision-resistant node identifiers from names using the recursive namehash function (ENSIP-1). It converts reverse names like "[encodedAddress].[coinTypeAsHex].reverse" into nodes. Key properties include: one-way function, no collisions, and deterministic behavior across all implementations.
4.2.3. Non-EVM State Proofs
Merkle and storage proofs prove non-EVM chain registrar state to L1 verifier contracts. Proof types vary by chain architecture: account-based chains use IAVL tree proofs (Cosmos) or Sparse Merkle Tree proofs (Solana). Bridge verifier contracts on Namechain validate proofs against L1-committed state roots.
4.3. Proof Types (URM Terms)
4.3.1. non_evm_state_proof(chainId) — Non-EVM Chain State Proof
When Used:
- Reverse resolution for non-EVM chains via Namechain resolvers
- Validating that
address → namemapping exists on the non-EVM chain
- State proof required — Non-EVM state must be proven to Namechain verifier
- Trust Source: Non-EVM chain consensus + L1 state root commitments
- Verification: Dual-path validation enables flexible latency/security tradeoffs:
- Fast path: Namechain resolvers validate pre-settled TEE proofs natively in CCIP callbacks (seconds latency)
- Secure path: Fallback to L1 DA + settled ZK proofs via cross-chain calls to Namechain bridge verifiers
- Gas Cost: Variable (native TEE validation vs cross-chain proof verification: ~200k-500k gas)
General Flow: See the Trustless Gateway Model below for the complete resolution flow.
Chain-Specific Example: See the Cosmos Examplefor a concrete implementation.
4.3.2. Proof Formats
ENSIP-19 requires the trustless gateway model for all non-EVM resolution, ensuring security guarantees and maintaining decentralization.
Trustless Gateway Model (Required Default)Gateway Role: Untrusted data fetcher
- Gateway fetches raw non-EVM state data
- Gateway may construct proof structure, but does not validate
- Onchain verifier contract generates/validates proof
- Protocol: CCIP-Read (EIP-3668) is the standard protocol used for offchain data fetching
-
How proof construction works:
- Gateway calls non-EVM chain RPC methods to fetch proof data:
- For Cosmos: Calls
abci_queryfor IAVL tree proof of registrar contract storage - For Solana: Calls
getAccountInfowith proof request for Sparse Merkle Tree proof
- For Cosmos: Calls
- Gateway receives raw proof data from non-EVM chain
- Gateway packages this raw data into the proof structure format expected by the bridge verifier contract
- Gateway returns the proof bundle via CCIP-Read response HTTP endpoint
- Gateway calls non-EVM chain RPC methods to fetch proof data:
- Gateway implementation: Any HTTP server that implements CCIP-Read (EIP-3668) can serve as a gateway. Multiple competing gateways can exist—the protocol is trustless because validation happens onchain. Gateways provide availability and latency; they cannot compromise correctness because invalid proofs are rejected by the bridge verifier contract.
Proof Format: Full cryptographic proof structure
Cosmos (Account-Based):{
stateRoot: bytes32, // IAVL state root committed to L1
blockHeight: uint64, // Block height of state
accountAddress: bytes, // Address of registrar contract
storageKey: bytes32, // Storage key for reverse mapping
storageValue: bytes, // Reverse mapping value (name)
merkleProof: bytes[], // IAVL tree proof path
blockHash: bytes32, // Block hash at this height
timestamp: uint64 // Block timestamp
}{
stateRoot: bytes32, // Sparse Merkle Tree root
blockHeight: uint64, // Block height
accountAddress: bytes, // Registrar account address
accountData: bytes, // Account data containing reverse mapping
merkleProof: bytes[], // Sparse Merkle Tree proof
blockHash: bytes32, // Block hash
timestamp: uint64 // Block timestamp
}Validation: Dual-path verification enables flexible latency/security tradeoffs
- Fast path: Namechain resolvers validate pre-settled TEE proofs natively in CCIP callbacks (low latency, lower gas cost)
- Secure path: Bridge verifier contract on Namechain validates full proofs against L1-committed state root (higher security, higher gas cost)
- Security: Trustless—gateway cannot lie; invalid proofs are rejected by verifier (TEE or onchain)
- Gas Cost: Variable (native TEE validation vs onchain proof verification)
- Example: Gateway returns proof bundle; resolver validates TEE proof natively or falls back to
bridgeVerifier.verifyStateProof(proof)on Namechain
ENSIP-19 Default: Trustless gateway model with onchain bridge verifiers is the required implementation approach. This aligns with the URM principle: "Data at the edge, trust at the root." Gateways provide availability and latency, but correctness is verified onchain. The trustless model ensures that any gateway can be used without requiring trust in the gateway operator—invalid proofs are rejected by the bridge verifier contract.
4.4. ENSIP-10 Resolution Results & ABI Encoding
ENSIP-10 is an optional extension that introduces a universal entry point for advanced and wildcard resolution. The standard resolver interface is defined by EIP-137 and related EIPs, which all resolvers must implement for basic functionality.
ENSIP-10 Overview:- Purpose: ENSIP-10 defines the resolve(bytes calldata name, bytes calldata data) function, enabling advanced features like wildcard resolution and unified querying.
- Adoption: Not all resolvers implement ENSIP-10. Many legacy and basic resolvers only support the standard methods (e.g., addr, text, contenthash).
- Input
name: The ENS name (or reverse name) as a bytes representation (e.g., "alice.eth" or encoded reverse name). - Input
data: ABI-encoded function call specifying what you want to resolve. This encodes both the function selector (what function to call) and the parameters (like the node hash). - Output
return value: ABI-encoded return value containing the resolved data (as raw bytes). - Format: Return values are ABI-encoded, following Ethereum's Application Binary Interface encoding standard. This ensures consistent, machine-readable data formats across resolver implementations that support ENSIP-10.
- Direct contract call results: (if data is stored onchain)
- CCIP-Read responses: (if resolver needs offchain data, it triggers EIP-3668 OffchainLookup, client fetches data, then calls callback)
- For onchain data: Results are verified by re-executing the resolution logic—the EVM executes the resolver contract's code, which reads from contract storage, and the result is verified by Ethereum consensus
- For offchain/cross-chain data: Results are validated through cryptographic proofs (Merkle proofs, IAVL proofs, SPV proofs) validated onchain by bridge verifier contracts
// Client wants to resolve an address
resolve(
"alice.eth",
abi.encodeCall(IAddrResolver.addr, (namehash("alice.eth")))
)
// Returns: Cosmos address (ABI-encoded bytes)// Client wants to find primary name for an address
resolve(
"encoded_cosmos_address.76.reverse",
abi.encodeCall(INameResolver.name, (namehash("encoded_cosmos_address.76.reverse")))
)
// Returns: "alice.eth" (ABI-encoded string)- Standardization: All resolvers return data in the same format, so clients know how to decode results
- Type safety: The function signature in
dataspecifies what type of data to return - Efficiency: Binary encoding is more gas-efficient than string-based formats for onchain operations
4.5. Algorithms
4.5.1. Namehash Algorithm
- Input: DNS-style name string (e.g.,
"encoded_address.76.reverse") - Process: Recursive hash of labels from right to left
- Output:
bytes32node identifier - Standard: ENSIP-1 namehash specification
4.5.2. Chain-Specific State Proof Verification
- Algorithm: Varies by chain type:
- Cosmos: IAVL tree proof verification + state root comparison
- Solana: Sparse Merkle Tree proof verification
- Purpose: Validates non-EVM chain state without requiring full chain execution on L1
- Implementation: Bridge verifier contracts (chain-specific implementations)
4.6. Proof Generation & Validation Flow
4.6.1. Proof Generation (Trustless Gateway Model)
Generation (Trustless Gateway Model):- Client/Gateway queries non-EVM chain RPC for registrar state
- Gateway constructs state proof structure:
- For Cosmos: Fetches IAVL tree proof of registrar storage from chain RPC
- For Solana: Fetches Sparse Merkle Tree proof of account state
- Gateway packages proof with state root, block number, and chain metadata
- Gateway returns full proof structure via CCIP-Read response (does not validate)
- Note: Gateway is untrusted—it may return invalid proofs, but they will be rejected onchain
- Resolver receives proof via
ccipCallback - Resolver validates proof natively (fast path):
- Namechain resolvers can validate pre-settled TEE proofs directly in CCIP callbacks
- TEE proofs are cryptographic attestations of L2 state that have already been verified and settled
- This enables native validation without requiring cross-chain calls to L1 bridge verifiers
- Resolver falls back to L1 DA + settled ZK proofs (secure path):
- If TEE proof validation fails or is unavailable
- Resolver calls bridge verifier contract on Namechain with full proof via cross-chain call
-
Verifier checks onchain:
- Proof is valid (chain-specific proof verification)
- State root matches L1-committed root
- Block height is recent enough (within validity window)
- Verifier returns validated state value (or reverts if invalid)
- Resolver uses value to complete resolution
- Security: Gateway cannot lie—invalid proofs are rejected by verifier (TEE or onchain)
4.7. Comparison to Other Proof Systems (DNSSEC, EVM Rollups)
| Aspect | Non-EVM State Proofs | DNSSEC P-256 | EVM Rollup Proofs |
|---|---|---|---|
| Proof Type | Chain-specific Merkle proofs | Cryptographic signatures | Merkle/SNARK proofs |
| Primitive | Chain-specific (IAVL, SPV, SMT) | ECDSA P-256 | EVM state + bridge proofs |
| Verification | Bridge verifier contracts | P-256 precompile | Bridge verifier contracts |
| Trust Anchor | Ethereum L1 + Non-EVM consensus | DNS root KSK | Ethereum L1 + rollup consensus |
| Proof Format | Chain-specific Merkle structures | DNSKEY/DS/RRSIG chain | Storage/Merkle proofs |
| Gas Cost | Medium (100k-300k gas) | Low (with EIP-7951) | Medium-High (200k-500k gas) |
Key Difference: Non-EVM proofs require chain-specific cryptographic primitives and bridge infrastructure, unlike EVM rollups which can reuse Ethereum's ECDSA and state proof infrastructure.
5. Rules & Lifecycle
5.1. High-Level Rules for Primary Names
To establish a primary name for an address on a non-EVM chain:
- Set the address for the name (forward resolution)
- Set the reverse record for the address (reverse resolution)
- The primary name is valid only if reverse and forward mappings are consistent
- Register: Map address → name via the relevant registrar
- Update: Change mappings (either forward or reverse)
- Remove: Unset mappings (e.g., unset resolver or name)
- Fallback: If chain-specific primary name is missing, resolution fails (no default fallback for non-EVM)
5.2. Reverse Resolution Rules
Given (addressBytes, coinType) where chainFromCoinType(coinType) = 0:
- Compute
[addressAsHex]fromaddressBytes(using chain-specific encoding) - Compute
[coinTypeAsHex]andchainFromCoinType(coinType) - Build
reverseNamebased oncoinType:"[encodedAddress].[coinTypeAsHex].reverse" - Compute
reverseNode = namehash(reverseName) - Call
name = resolve(reverseName, abi.encodeCall(INameResolver.name, (reverseNode))) - If
nameis empty: no primary name exists; stop and display the address - If
nameis non-empty: continue to forward verification (see Section 6)
5.3. Address Format Standardization
Problem: Non-EVM chains use different address formats that don't directly map to ENS's addressBytes format.
Solution: Address encoding/decoding layer:
- Encoding (for ENS storage): Convert native address → standardized
addressBytesformat - Decoding (for resolution): Convert
addressBytes→ native address format for chain queries
| Chain | Native Format | ENS Format | Encoding |
|---|---|---|---|
| Cosmos | cosmos1abc123... | Variable bytes | Decode bech32 → bytes |
| Solana | 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM | 32 bytes | Decode base58 → public key bytes |
6. Verification Path
4.1 Component Responsibilities
Gateway Responsibilities:- Query non-EVM chain: Gateway queries non-EVM chain RPC for registrar contract/account state
- Fetch state proof: Gateway requests Merkle proof of storage value from chain's RPC
- Package proof bundle: Gateway packages proof with state root, block height, and chain metadata
- Return via CCIP-Read: Gateway returns proof bundle to client
Untrusted role: Gateway can lie; invalid proofs are rejected onchain by bridge verifier.
Bridge Verifier Contract Responsibilities (on Namechain):
- State root storage: Stores state root commitments from bridge contract
- Proof validation: Validates Merkle proofs against committed state roots
- Chain-specific verification: Implements chain-specific proof verification logic (IAVL tree, SPV proofs, etc.)
- Validity window checks: Verifies block height/timestamp is within acceptable window
- Return validation result: Returns
(bool valid, bytes value)to resolver
Trusted role: Verifier contract is the security boundary; all proof validation happens onchain.
Resolver Contract Responsibilities (on L1):
- Receive reverse resolution request: Resolver receives request for
(address, coinType)→ name - Trigger CCIP-Read (if needed): Resolver reverts with OffchainLookup to fetch proof from gateway
- Validate state proof: Resolver calls bridge verifier to validate proof
- Extract name: If valid, resolver extracts name from proof
- Forward verification: Resolver verifies forward mapping (
name → address) matches - Return result: If both directions match, return name; otherwise revert
Key principle: Gateway provides proof data (untrusted), bridge verifier validates proofs onchain (trustless), resolver orchestrates verification (trustless).
6.1. Generic Primary Name Verification (Two-Phase Flow)
Given (addressBytes, coinType) where chainFromCoinType(coinType) = 0 (non-EVM chain):
- Compute
[addressAsHex]fromaddressBytes(using chain-specific encoding) - Compute
[coinTypeAsHex]and verifychainFromCoinType(coinType) = 0 - Build
reverseNameaccording to chain-specific encoding:"[encodedAddress].[coinTypeAsHex].reverse" reverseNode = namehash(reverseName)- Call
name = resolve(reverseName, abi.encodeCall(INameResolver.name, (reverseNode))) - If
nameis empty → no primary name; abort and display the address
- Compute
node = namehash(name) - Resolve
resolvedAddress = resolve(name, abi.encodeCall(IAddressResolver.addr, (node, coinType))) - Compare the resulting address to
addressBytes - If equal →
nameis a verified primary name for(addressBytes, coinType)- If not equal → treat as invalid (mismatch between reverse and forward)
6.2. Resolver / Gateway Topology
The following actors participate in non-EVM primary name resolution:
- ENS Registry (L1): Maintains resolver assignments for all namespaces
- ENSIP-10 wildcard resolvers: Chain-specific resolvers on Namechain for
"[coinTypeAsHex].reverse"namespaces with dual-path proof validation - Bridge verifiers on Namechain: Validate non-EVM state proofs against L1-committed state roots (secure fallback)
- State bridges: Commit non-EVM chain state roots to Ethereum L1
- Chain registrars: Per-chain contracts/accounts maintaining address → name mappings
- CCIP-Read gateways: Fetch proof data from non-EVM chains with preconfirmation support
- Based preconfirmers: L1 validators providing preconfirmations for fast TEE proof generation
- Trusted Execution Environments (TEEs): Generate pre-settled proofs for native validation
6.3. Minimal Client-Side Pseudocode
A simplified client-side function for "get primary name":
async function getPrimaryName(addressBytes: Uint8Array, coinType: bigint): Promise<string | null> {
// Encode address for ENS (chain-specific)
const encodedAddress = encodeAddressForENS(addressBytes, coinType);
const addressAsHex = toLowerHex(encodedAddress);
const coinTypeAsHex = coinType.toString(16);
// Build reverse name
const reverseName = `${addressAsHex}.${coinTypeAsHex}.reverse`;
const reverseNode = namehash(reverseName);
// Call resolver (may trigger CCIP-Read)
const name = await ensip10ResolveName(reverseName, reverseNode);
if (!name) return null;
// Forward verification
const node = namehash(name);
const resolved = await resolverAddr(node, coinType);
if (!resolved) return null;
return bytesEqual(resolved, encodedAddress) ? name : null;
}6.4. Chain-Specific Example: Cosmos Chain
6.4.1. Prerequisites & Contract Inventory
Cosmos-Specific Implementation: For Cosmos integration:
Existing Infrastructure: 3 contracts (ENS Registry, Bridge Verifier, Universal Resolver)
Cosmos-Specific Contracts: 3 new contracts (Cosmos Registrar, Cosmos State Bridge, Cosmos Resolver)
6.4.2. Resolution Flow (Trustless Gateway Model)
Setup Phase:- Deploy Cosmos Registrar contract on Cosmos chain
- Deploy Cosmos State Bridge on Cosmos → Ethereum L1 bridge
- Deploy Cosmos Resolver on Namechain (Surge), configured for
"76.reverse"namespace with dual-path proof validation - Submit ENS DAO governance proposal to register Cosmos Resolver at
namehash("76.reverse") - ENS DAO approves and executes registration
Resolution Flow: Leverages based preconfirmations and TEE proofs for low-latency CCIP-Read with Cosmos-specific parameters:
- Reverse Name:
"encoded_cosmos_address.76.reverse"(Cosmos coinType =118=0x76) - Cosmos Registrar: Stores
address → namemappings on Cosmos chain - Cosmos State Bridge: Commits Cosmos IAVL state roots to Ethereum L1
- Cosmos Resolver: Handles resolution on Namechain with dual-path validation:
- Fast path: Native TEE proof validation in CCIP callbacks (seconds)
- Secure path: Fallback to L1 DA + settled ZK proofs
- Proof Type: IAVL tree proof with TEE attestation
- Cost-effective: Resolver operations on Namechain (~$0.01-0.30 per operation)
- High performance: CCIP-Read latency reduced from hours to seconds using based preconfirmations
- Security: Inherits Cosmos validator security + Ethereum L1 finality with slashable preconfirmers
- Flexible validation: Applications can choose latency vs security tradeoffs
6.4.3. Gateway Implementation Requirements
Critical: Trustless gateways must be built according to the proof system of the chain they're interacting with.
Chain-Specific Proof Systems: 1. Cosmos (IAVL Tree):- Proof Format: IAVL tree proof of storage slot
- RPC Method:
abci_querywith proof request -
Proof Structure:
{ stateRoot: bytes32, storageSlot: bytes32, storageValue: bytes32, merkleProof: bytes[], blockHeight: uint256 } - Bridge Verifier: Validates IAVL proof against L1-committed state root
- Proof Format: Sparse Merkle Tree proof of account state
- RPC Method:
getAccountInfowith proof request -
Proof Structure:
{ stateRoot: bytes32, accountAddress: bytes, accountData: bytes, merkleProof: bytes[], blockHeight: uint256 } - Bridge Verifier: Validates account state proof
- Multi-Chain Support: A single gateway can support multiple chains, but requires chain-specific logic for each
- Resolver Configuration: Each chain resolver must be configured with the correct bridge verifier address
- Proof Compatibility: The gateway must construct proofs in the exact format expected by the chain's bridge verifier
4.4 Minimal Pseudocode (Client-Side)
// Type definitions
interface NonEVMStateProof {
stateRoot: string;
blockHeight: number;
accountAddress: string;
storageKey: string;
storageValue: string; // name
merkleProof: string[];
blockHash: string;
timestamp: number;
chainId: string;
}
interface ReverseResolutionResult {
name: string | null;
valid: boolean;
}
// Reverse resolution for non-EVM chains
async function resolveNonEVMPrimaryName(
address: string, // Native address format (e.g., Cosmos bech32, Solana base58)
coinType: number, // SLIP-44 coin type
resolverAddress: string, // NonEVMResolver on L1
chainId: string // Chain identifier (e.g., "cosmos", "solana")
): Promise<ReverseResolutionResult> {
// Step 1: Encode address to ENS format
const addressBytes = encodeAddressForENS(address, coinType);
const addressAsHex = bytesToHex(addressBytes).replace('0x', '');
const coinTypeAsHex = coinType.toString(16);
// Step 2: Build reverse name
const reverseName = `${addressAsHex}.${coinTypeAsHex}.reverse`;
const reverseNode = namehash(reverseName);
// Step 3: Call resolver (may trigger CCIP-Read)
const resolver = new ethers.Contract(resolverAddress, RESOLVER_ABI, provider);
try {
let name: string;
try {
// Try direct resolution first
name = await resolver.name(reverseNode);
} catch (error) {
if (isOffchainLookupError(error)) {
// Handle CCIP-Read for state proof fetching
const lookup = parseOffchainLookupError(error);
const proof = await fetchStateProofViaCCIP(lookup, address, coinType, chainId);
// Call callback with proof
name = await resolver.ccipCallback(
encodeProofBundle(proof),
lookup.extraData
);
} else {
throw error;
}
}
// Step 4: Verify forward mapping
const forwardNode = namehash(name);
const resolvedAddress = await resolver.addr(forwardNode, coinType);
if (resolvedAddress.toLowerCase() !== addressBytes.toLowerCase()) {
return { name: null, valid: false };
}
return { name, valid: true };
} catch (error) {
console.error('Reverse resolution failed:', error);
return { name: null, valid: false };
}
}
// Fetch state proof via CCIP-Read
async function fetchStateProofViaCCIP(
lookup: OffchainLookupError,
address: string,
coinType: number,
chainId: string
): Promise<NonEVMStateProof> {
const response = await fetch(lookup.urls[0], {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
callData: lookup.callData,
address,
coinType,
chainId
})
});
if (!response.ok) {
throw new Error(`Gateway error: ${response.statusText}`);
}
const data = await response.json();
return decodeProofBundle(data.proofBundle);
}
// Helper functions
function encodeAddressForENS(address: string, coinType: number): Uint8Array {
// Chain-specific encoding logic
// Cosmos: Decode bech32 → bytes
// Solana: Decode base58 → 32 bytes
// Implementation depends on coinType
}
function isOffchainLookupError(error: any): boolean {
return error?.errorName === 'OffchainLookup' ||
error?.message?.includes('OffchainLookup');
}
function parseOffchainLookupError(error: any): OffchainLookupError {
return {
sender: error.args[0],
urls: error.args[1],
callData: error.args[2],
callbackFunction: error.args[3],
extraData: error.args[4],
};
}
function encodeProofBundle(proof: NonEVMStateProof): string {
// ABI-encode proof bundle for contract call
}
function decodeProofBundle(hex: string): NonEVMStateProof {
// Decode hex-encoded proof bundle
}4.5 Example Implementation Flow
Scenario: Enabling primary name reverse resolution for Cosmos chain (coinType = 118)
Deploy registrar contract on Cosmos chain:
// Cosmos Registrar Contract (Cosmos SDK smart contract)
contract CosmosRegistrar {
mapping(bytes => string) public reverseNames; // address → name
function setName(bytes calldata address, string calldata name) external {
require(msg.sender == address, "Only address owner can set name");
reverseNames[address] = name;
}
function name(bytes calldata address) external view returns (string memory) {
return reverseNames[address];
}
}Deploy bridge contract on Ethereum L1 that commits Cosmos state roots:
// Cosmos State Bridge Contract (on L1)
contract CosmosStateBridge {
struct StateRootCommitment {
bytes32 stateRoot;
uint64 blockHeight;
uint64 timestamp;
}
mapping(uint64 => StateRootCommitment) public commitments;
address[] public bridgeOperators; // Multisig or validator set
function commitStateRoot(
bytes32 stateRoot,
uint64 blockHeight,
bytes[] calldata signatures
) external {
require(validateSignatures(stateRoot, blockHeight, signatures), "Invalid signatures");
commitments[blockHeight] = StateRootCommitment({
stateRoot: stateRoot,
blockHeight: blockHeight,
timestamp: block.timestamp
});
}
}Deploy verifier contract on L1 that validates IAVL tree proofs:
// Cosmos Bridge Verifier (on L1)
contract CosmosBridgeVerifier {
CosmosStateBridge public bridge;
function verifyIAVLProof(
bytes32 stateRoot,
bytes memory key,
bytes memory value,
bytes[] memory proof,
uint64 blockHeight
) external view returns (bool) {
// Verify state root matches committed root
bytes32 committedRoot = bridge.commitments(blockHeight).stateRoot;
require(stateRoot == committedRoot, "State root mismatch");
// Verify IAVL tree proof (implementation depends on IAVL library)
return verifyIAVLTreeProof(stateRoot, key, value, proof);
}
}Deploy resolver on L1 that uses bridge verifier:
// NonEVMResolver (on L1)
contract NonEVMResolver {
CosmosBridgeVerifier public verifier;
function name(bytes32 node) external view returns (string memory) {
// Extract address and coinType from reverse node
// Fetch state proof via CCIP-Read
// Validate proof via verifier
// Return name
}
}User sets reverse mapping on Cosmos:
User → CosmosRegistrar.setName(cosmosAddress, "alice.eth")Bridge operator commits Cosmos state root to L1:
Bridge Operator → CosmosStateBridge.commitStateRoot(cosmosStateRoot, blockHeight, signatures)- Client requests:
resolve("cosmos1abc123....800076.reverse", nameCallData) - Resolver triggers CCIP-Read for state proof
- Gateway queries Cosmos RPC for IAVL proof of registrar storage
- Gateway returns proof bundle
- Resolver validates proof via CosmosBridgeVerifier
- Verifier checks proof against L1-committed state root
- If valid → return "alice.eth"
- Resolver verifies forward:
addr("alice.eth", 118) == cosmosAddress - If match → return "alice.eth"; otherwise revert
7. Contract & Namespace Inventory
7.1. Core Constants & Helpers
DEFAULT_EVM_COIN_TYPE = 0x8000_0000ETHEREUM_MAINNET_COIN_TYPE = 60chainFromCoinType(coinType)as defined in Section 4.1- Chain Identifiers:
CHAIN_ID_COSMOS = "cosmos",CHAIN_ID_SOLANA = "solana" - Coin Types (SLIP-44):
COIN_TYPE_BITCOIN = 0,COIN_TYPE_COSMOS = 118,COIN_TYPE_SOLANA = 501
7.2. Reverse Namespaces & Registrars
| Chain | CoinType | reverseNamespace | Registrar Contract |
|---|---|---|---|
| Cosmos | 118 | "76.reverse" | CosmosRegistrar (on Cosmos) |
| Solana | 501 | "1f5.reverse" | SolanaRegistrar (on Solana) |
7.3. Resolver Types
7.3.1. Chain-Specific Resolvers (Namechain)
ENSIP-10 wildcard resolvers for non-EVM chains that:
- Deployed on Namechain (ENS L2) for cost-effective operations
- Accept CCIP-Read requests for
name()of"[encodedAddress].[coinTypeAsHex].reverse" - Validate state proofs natively via bridge verifier calls
- Fallback to default primary name if chain-specific name is missing
8. URM Mapping (Resolver Profiles)
This profile defines the non-EVM resolver profile for the Universal Resolver Matrix. It extends ENSIP-19 to support primary name resolution for non-EVM chains using a trustless gateway model with state proof validation.
| Profile | Scope | Trust Model | Proof System | Rules | Verification Path |
|---|---|---|---|---|---|
| non-evm-primary-names | Non-EVM chains (Cosmos, Solana) with chainFromCoinType(coinType) = 0 | Non-EVM chain consensus + L1 state commitment bridge + ENS Registry | non_evm_state_proof(chainId) - Chain-specific Merkle proofs (IAVL, SMT) | Reverse: "[encodedAddress].[coinTypeAsHex].reverse", Forward: addr(node, coinType), no default fallback | CCIP-Read → Gateway → Bridge verifier validates non-EVM state proofs against L1-committed state roots |
8.1. Profile Definition: non-evm-primary-names
Scope:- Enables primary name reverse resolution (
address → name) for non-EVM blockchains from SLIP-44 - Extends ENSIP-19 to support bidirectional resolution for Cosmos, Solana, and other non-EVM chains
- Requires chain-specific infrastructure: state bridges, registrars, verifiers per chain
- Use case: Cross-chain identity resolution, unified naming across all blockchains
- Root of trust: Two-tier model: (1) Non-EVM chain consensus (validators/miners), (2) Ethereum L1 consensus
- Bridge trust: State commitment bridge connects non-EVM chain state to L1
- Verification: State proofs validated onchain via bridge verifier against L1-committed state roots
- Security: Inherits security from both chain consensuses, bridge correctness, and Ethereum L1 finality
- Reverse namespaces per SLIP-44 coin type:
"[encodedAddress].[coinTypeAsHex].reverse"- Examples: Cosmos (
coinType = 118), Solana (coinType = 501) - Forward resolution uses standard ENS namespaces (
.eth, subdomains, etc.)
- Examples: Cosmos (
non_evm_state_proof(chainId)— Non-EVM chain state proof- Format varies by chain: IAVL tree proofs (Cosmos), Sparse Merkle Tree proofs (Solana)
- Validated against L1-committed state roots via bridge verifier
- Client initiates:
resolve("[encodedAddress].[coinTypeAsHex].reverse", nameCallData) - ENS Registry routes: Universal Resolver → ENS Registry → NonEVMResolver (Namechain)
- CCIP-Read triggered: Resolver detects need for non-EVM state, returns CCIP-Read request with based preconfirmation
- Gateway fetches proof: Gateway queries non-EVM chain RPC + requests preconfirmation from L1 validators
- Pre-settled proof generation: Preconfirmer generates TEE proof for preconfirmed block state
- Gateway returns proof: Full proof bundle with TEE proof returned via CCIP-Read response
- Resolver validates (fast path): Resolver validates pre-settled TEE proof natively in CCIP callback (seconds latency)
- Resolver validates (secure path): Falls back to
bridgeVerifier.verifyStateProof(proof)on Namechain if TEE validation fails - Bridge verifier checks: Validates proof against L1-committed state root (onchain validation)
- Result returned: If valid → name returned; if invalid → revert
- Forward verification: Client resolves
addr(name, coinType), compares toaddressBytes
Trust Anchor: Ethereum L1 consensus (ENS Registry + slashable preconfirmers) + Namechain consensus (bridge verifier contracts). Non-EVM chain state is proven to L1 via state commitment bridge. Dual-path validation enables applications to balance latency vs security: TEE proofs for speed, ZK proofs for maximum security. Final trust is Ethereum L1 consensus + Namechain consensus + non-EVM chain consensus.
9. Edge Cases & Client Requirements
9.1. Chain-Specific Edge Cases
Smart Contract Chains (Cosmos, Solana):- Registrar contracts store reverse mappings directly
- State proofs use native Merkle trees (IAVL, Sparse Merkle Tree)
- Address formats need encoding/decoding for ENS compatibility
- Encoding errors: Invalid address encodings should be rejected gracefully
- Length variations: Different chains have different address lengths requiring standardization
9.2. State Root Commitment Edge Cases
- Stale state roots: State roots must be recent enough (within validity window)
- Missing state roots: If bridge hasn't committed state root for requested block height, resolution fails
- Bridge downtime: If bridge is unavailable, reverse resolution cannot proceed (availability dependency)
9.3. Client Requirements
Clients must:
- Handle CCIP-Read errors: If resolver reverts with OffchainLookup, perform HTTP request to gateway
- Validate address formats: Verify address format matches expected coinType before resolution
- Verify forward mappings: Always verify forward mapping matches reverse result (two-phase verification)
- Handle chain-specific encoding: Encode/decode addresses according to chain-specific formats
- Check state root freshness: Verify state root is recent enough (within validity window)
Clients must not:
- Skip forward verification: Don't trust reverse resolution alone; always verify forward mapping
- Assume address format: Don't assume address format; decode according to coinType
- Cache stale proofs: Don't cache state proofs beyond validity window
- Ignore bridge status: Don't attempt resolution if bridge hasn't committed recent state roots