From 1d21a9ce69e25b644cf110aabd7662600530376e Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Mon, 6 Apr 2026 22:37:23 +0700 Subject: [PATCH 1/2] ENS: add coinType param to reverse resolver Update generated UniversalResolver reverse read to include a coinType (uint256) parameter and new function selector; adjust FN_INPUTS/FN_OUTPUTS and encode/read params accordingly. Update resolve-name to call the new reverse signature (pass the raw address as reverseName and coinType: 60n), remove packetToBytes/toHex usage and unused imports, simplify error handling, and return the resolved name or null. --- .changeset/every-donuts-stop.md | 5 ++++ .../UniversalResolver/read/reverse.ts | 20 +++++++++++----- .../src/extensions/ens/resolve-name.ts | 24 +++++-------------- 3 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 .changeset/every-donuts-stop.md diff --git a/.changeset/every-donuts-stop.md b/.changeset/every-donuts-stop.md new file mode 100644 index 00000000000..8f624eb26d6 --- /dev/null +++ b/.changeset/every-donuts-stop.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +ENS: add coinType param to reverse resolver diff --git a/packages/thirdweb/src/extensions/ens/__generated__/UniversalResolver/read/reverse.ts b/packages/thirdweb/src/extensions/ens/__generated__/UniversalResolver/read/reverse.ts index f9e4de7d1a1..a33b67961aa 100644 --- a/packages/thirdweb/src/extensions/ens/__generated__/UniversalResolver/read/reverse.ts +++ b/packages/thirdweb/src/extensions/ens/__generated__/UniversalResolver/read/reverse.ts @@ -14,14 +14,22 @@ export type ReverseParams = { type: "bytes"; name: "reverseName"; }>; + coinType: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "coinType"; + }>; }; -export const FN_SELECTOR = "0xec11c823" as const; +export const FN_SELECTOR = "0x5d78a217" as const; const FN_INPUTS = [ { name: "reverseName", type: "bytes", }, + { + name: "coinType", + type: "uint256", + }, ] as const; const FN_OUTPUTS = [ { @@ -33,9 +41,6 @@ const FN_OUTPUTS = [ { type: "address", }, - { - type: "address", - }, ] as const; /** @@ -70,7 +75,10 @@ export function isReverseSupported(availableSelectors: string[]) { * ``` */ export function encodeReverseParams(options: ReverseParams) { - return encodeAbiParameters(FN_INPUTS, [options.reverseName]); + return encodeAbiParameters(FN_INPUTS, [ + options.reverseName, + options.coinType, + ]); } /** @@ -128,6 +136,6 @@ export async function reverse(options: BaseTransactionOptions) { return readContract({ contract: options.contract, method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, - params: [options.reverseName], + params: [options.reverseName, options.coinType], }); } diff --git a/packages/thirdweb/src/extensions/ens/resolve-name.ts b/packages/thirdweb/src/extensions/ens/resolve-name.ts index 0d9c8b70303..758c6427fa8 100644 --- a/packages/thirdweb/src/extensions/ens/resolve-name.ts +++ b/packages/thirdweb/src/extensions/ens/resolve-name.ts @@ -3,8 +3,6 @@ import { ethereum } from "../../chains/chain-definitions/ethereum.js"; import type { Chain } from "../../chains/types.js"; import type { ThirdwebClient } from "../../client/client.js"; import { getContract } from "../../contract/contract.js"; -import { toHex } from "../../utils/encoding/hex.js"; -import { packetToBytes } from "../../utils/ens/packetToBytes.js"; import { withCache } from "../../utils/promise/withCache.js"; import { reverse } from "./__generated__/UniversalResolver/read/reverse.js"; import { UNIVERSAL_RESOLVER_ADDRESS } from "./constants.js"; @@ -44,25 +42,15 @@ export async function resolveName(options: ResolveNameOptions) { client, }); - const reverseName = toHex( - packetToBytes(`${address.toLowerCase().substring(2)}.addr.reverse`), - ); - - const [name, resolvedAddress] = await reverse({ + const [name] = await reverse({ contract, - reverseName, - }).catch((e) => { - if ("data" in e && e.data === "0x7199966d") { - return [null, address] as const; - } - throw e; + reverseName: address as `0x${string}`, + coinType: 60n, + }).catch(() => { + return [null] as const; }); - if (address.toLowerCase() !== resolvedAddress.toLowerCase()) { - return null; - } - - return name; + return name || null; }, { cacheKey: `ens:name:${resolverChain?.id || 1}:${address}`, From 05b9f6cef70ed5c0381c1df8f0fd44aa8c35090d Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Mon, 6 Apr 2026 22:50:48 +0700 Subject: [PATCH 2/2] Improve ENS resolveName error handling Give resolveName an explicit Promise return type and enhance its error handling: re-throw errors that include a data field starting with the ReverseAddressMismatch selector (0xef9c03ce) so callers can surface verification/data-integrity issues, while swallowing expected "no resolver"/"no name" errors. Also minor parameter formatting adjustments. --- .../src/extensions/ens/resolve-name.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/thirdweb/src/extensions/ens/resolve-name.ts b/packages/thirdweb/src/extensions/ens/resolve-name.ts index 758c6427fa8..12ea520214a 100644 --- a/packages/thirdweb/src/extensions/ens/resolve-name.ts +++ b/packages/thirdweb/src/extensions/ens/resolve-name.ts @@ -31,7 +31,9 @@ export type ResolveNameOptions = { * @extension ENS * @returns A promise that resolves to the Ethereum address. */ -export async function resolveName(options: ResolveNameOptions) { +export async function resolveName( + options: ResolveNameOptions, +): Promise { const { client, address, resolverAddress, resolverChain } = options; return withCache( @@ -46,7 +48,20 @@ export async function resolveName(options: ResolveNameOptions) { contract, reverseName: address as `0x${string}`, coinType: 60n, - }).catch(() => { + }).catch((e) => { + // Re-throw verification errors so callers can detect data integrity issues + if ( + typeof e === "object" && + e !== null && + "data" in e && + typeof e.data === "string" + ) { + // ReverseAddressMismatch(string,bytes) = 0xef9c03ce + if (e.data.startsWith("0xef9c03ce")) { + throw e; + } + } + // Swallow expected "no resolver" / "no name" errors return [null] as const; });