ERCs
ERC-181 — Reverse ENS resolution
ERC-137 maps name → address. ERC-181 maps address → name. Resolved via the addr.reverse subdomain: <address-without-0x>.addr.reverse resolves to the canonical name for an address.
import { eip155_1 } from "@ethernauta/chain/eip155-1";
import { AddressSchema } from "@ethernauta/core";
import { get_ens_name } from "@ethernauta/ens";
import { create_reader, encode_chain_id, http } from "@ethernauta/transport";
import { parse } from "valibot";
const CHAIN_ID = encode_chain_id({ namespace: "eip155", reference: eip155_1.chainId });
const reader = create_reader([
{ chainId: CHAIN_ID, transports: [http("https://ethereum-rpc.publicnode.com")] },
]);
const address = parse(AddressSchema, "0xd8dA6BF26964aF9D7eED9e03E53415D37aA96045");
const name = await get_ens_name({ address })(reader({ chain_id: CHAIN_ID }));
// → "vitalik.eth" or null Surface
The lower-level method bindings live under @ethernauta/erc/181. Most dapps use get_ens_name from @ethernauta/ens instead, which composes both the reverse record lookup and the forward verification step.
| Method | Shape | Purpose |
|---|---|---|
name({ node }) | Callable<string> | Read the name text record at a reverse node. |
set_name({ name }) | Signable<Hash32> | Owner sets their primary name. |
Forward verification
A reverse record alone is claim-only — an attacker could set bob.eth as their reverse name without owning it. The canonical resolution flow does the round trip:
- Reverse:
address→claimed_name. - Forward:
claimed_name→forward_address. - Valid iff
forward_address === address.
get_ens_name performs both steps. If the verification fails it returns null.
See also
- @ethernauta/ens —
get_ens_name. - ERC-137 — forward resolution.