From d6e515f74fb74f8ec55887ee0d9d0cce1a76f10f Mon Sep 17 00:00:00 2001 From: "Serenae.eth" <95138671+serenae-fansubs@users.noreply.github.com> Date: Wed, 25 Sep 2024 15:48:33 -0400 Subject: [PATCH] Adding UR page (#283) --- app/local/config/navigation/protocol.ts | 6 + app/local/data/resolver.tsx | 8 +- app/local/data/universalresolver.tsx | 252 ++++++++++++++++++++++++ docs/resolvers/interfaces.mdx | 5 +- docs/resolvers/universalresolver.mdx | 60 ++++++ docs/wrapper/expiry.mdx | 4 +- 6 files changed, 328 insertions(+), 7 deletions(-) create mode 100644 app/local/data/universalresolver.tsx create mode 100644 docs/resolvers/universalresolver.mdx diff --git a/app/local/config/navigation/protocol.ts b/app/local/config/navigation/protocol.ts index 2cbcb771..175cdfa9 100644 --- a/app/local/config/navigation/protocol.ts +++ b/app/local/config/navigation/protocol.ts @@ -246,6 +246,12 @@ export const navigation: SectionData[] = [ wip: 70, icon: '✍️', }, + { + title: 'Universal Resolver', + href: '/resolvers/universalresolver', + wip: 70, + icon: '✍️', + }, ], }, { diff --git a/app/local/data/resolver.tsx b/app/local/data/resolver.tsx index 0054a1ae..1f91b447 100644 --- a/app/local/data/resolver.tsx +++ b/app/local/data/resolver.tsx @@ -199,8 +199,8 @@ export const resolver_methods: ContractMethod[] = [ }, { name: 'setAddr(bytes32 node, address a)', - interface: '0x3b3b57de', - usage: 'Write Ethereum Adress', + interface: '0xd5fa2b00', + usage: 'Write Ethereum Address', seeMore: 'Implemented by Public Resolver', input: [ { @@ -217,7 +217,7 @@ export const resolver_methods: ContractMethod[] = [ events: ['event AddrChanged(bytes32 indexed node, address a);'], }, { - name: 'setAddr(bytes32 node, uint coinType, bytes calldata a)', + name: 'setAddr(bytes32 node, uint256 coinType, bytes calldata a)', interface: '0x8b95dd71', usage: 'Set Multicoin Address', seeMore: 'Implemented by Public Resolver', @@ -229,7 +229,7 @@ export const resolver_methods: ContractMethod[] = [ }, { name: 'coinType', - type: 'uint', + type: 'uint256', description: 'The ENSIP-9 coin type to update.', }, { diff --git a/app/local/data/universalresolver.tsx b/app/local/data/universalresolver.tsx new file mode 100644 index 00000000..8a4e3354 --- /dev/null +++ b/app/local/data/universalresolver.tsx @@ -0,0 +1,252 @@ +/* eslint-disable sonarjs/no-duplicate-string */ +import { ContractMethod } from './interfaces'; + +export const universalresolver_methods: ContractMethod[] = [ + { + name: 'supportsInterface(bytes4 interfaceID) external pure returns (bool)', + interface: '0x01ffc9a7', + usage: 'Check Interface Support', + seeMore: 'EIP-165', + input: [ + { + name: 'interfaceID', + type: 'bytes4', + description: + 'The interface identifier, as specified in ERC-165', + }, + ], + output: [ + { + type: 'bool', + description: + 'True if the contract supports the specified interface.', + }, + ], + }, + { + name: 'resolve(bytes calldata name, bytes memory data) external view returns (bytes memory, address)', + interface: '0x9061b923', + usage: 'Resolve Name', + seeMore: 'ENSIP-10', + input: [ + { + name: 'name', + type: 'bytes', + description: + 'The name to resolve, in normalised and DNS-encoded form.', + }, + { + name: 'data', + type: 'bytes', + description: 'The resolution data, as specified in ENSIP-10.', + }, + ], + output: [ + { + type: 'bytes', + description: 'The return data of the resolver call.', + }, + { + type: 'address', + description: 'The address of the resolver contract.', + }, + ], + }, + { + name: 'resolve(bytes calldata name, bytes memory data, string[] memory gateways) external view returns (bytes memory, address)', + interface: '0x0667cfea', + usage: 'Resolve Name (with custom gateways)', + seeMore: 'ENSIP-10', + input: [ + { + name: 'name', + type: 'bytes', + description: + 'The name to resolve, in normalised and DNS-encoded form.', + }, + { + name: 'data', + type: 'bytes', + description: 'The resolution data, as specified in ENSIP-10.', + }, + { + name: 'gateways', + type: 'string[]', + description: 'An array of custom CCIP Read gateway URLs.', + }, + ], + output: [ + { + type: 'bytes', + description: 'The return data of the resolver call.', + }, + { + type: 'address', + description: 'The address of the resolver contract.', + }, + ], + }, + { + name: 'resolve(bytes calldata name, bytes[] memory data) external view returns (Result[] memory, address)', + interface: '0x206c74c9', + usage: 'Resolve Name (multiple records)', + seeMore: 'ENSIP-10', + input: [ + { + name: 'name', + type: 'bytes', + description: + 'The name to resolve, in normalised and DNS-encoded form.', + }, + { + name: 'data', + type: 'bytes[]', + description: 'The resolution data, as specified in ENSIP-10.', + }, + ], + output: [ + { + type: 'Result[]', + description: + 'The return data of the resolver call. This is a struct with: [bool success, bytes returnData]', + }, + { + type: 'address', + description: 'The address of the resolver contract.', + }, + ], + }, + { + name: 'resolve(bytes calldata name, bytes[] memory data, string[] memory gateways) public view returns (Result[] memory, address)', + interface: '0x76286c00', + usage: 'Resolve Name (multiple records with custom gateways)', + seeMore: 'ENSIP-10', + input: [ + { + name: 'name', + type: 'bytes', + description: + 'The name to resolve, in normalised and DNS-encoded form.', + }, + { + name: 'data', + type: 'bytes[]', + description: 'The resolution data, as specified in ENSIP-10.', + }, + { + name: 'gateways', + type: 'string[]', + description: 'An array of custom CCIP Read gateway URLs.', + }, + ], + output: [ + { + type: 'Result[]', + description: + 'The return data of the resolver call. This is a struct with: [bool success, bytes returnData]', + }, + { + type: 'address', + description: 'The address of the resolver contract.', + }, + ], + }, + { + name: 'reverse(bytes calldata reverseName) external view returns (string memory, address, address, address)', + interface: '0xec11c823', + usage: 'Resolve Reverse Name', + seeMore: '', + input: [ + { + name: 'reverseName', + type: 'bytes', + description: + 'The reverse name to resolve, in normalised and DNS-encoded form.', + }, + ], + output: [ + { + type: 'string', + description: 'The resolved name.', + }, + { + type: 'address', + description: 'The resolved address.', + }, + { + type: 'address', + description: 'The reverse resolver address.', + }, + { + type: 'address', + description: 'The resolver address.', + }, + ], + }, + { + name: 'reverse(bytes calldata reverseName, string[] memory gateways) public view returns (string memory, address, address, address)', + interface: '0xb241d0d3', + usage: 'Resolve Reverse Name (with custom gateways)', + seeMore: '', + input: [ + { + name: 'reverseName', + type: 'bytes', + description: + 'The reverse name to resolve, in normalised and DNS-encoded form.', + }, + { + name: 'gateways', + type: 'string[]', + description: 'An array of custom CCIP Read gateway URLs.', + }, + ], + output: [ + { + type: 'string', + description: 'The resolved name.', + }, + { + type: 'address', + description: 'The resolved address.', + }, + { + type: 'address', + description: 'The reverse resolver address.', + }, + { + type: 'address', + description: 'The resolver address.', + }, + ], + }, + { + name: 'findResolver(bytes calldata name) public view returns (Resolver, bytes32, uint256)', + interface: '0xa1cbcbaf', + usage: 'Find Resolver', + seeMore: + 'Finds a resolver by recursively querying the registry, starting at the longest name and progressively removing labels until it finds a result.', + input: [ + { + name: 'name', + type: 'bytes', + description: + 'The name to resolve, in DNS-encoded and normalised form.', + }, + ], + output: [ + { + type: 'address', + description: 'The Resolver responsible for this name.', + }, + { + type: 'bytes32', + description: 'The namehash of the full name.', + }, + { + type: 'uint256', + description: 'The offset of the first label with a resolver.', + }, + ], + }, +]; diff --git a/docs/resolvers/interfaces.mdx b/docs/resolvers/interfaces.mdx index a7575a1d..c1511b1c 100644 --- a/docs/resolvers/interfaces.mdx +++ b/docs/resolvers/interfaces.mdx @@ -7,7 +7,10 @@ import { h2, h3, h4 } from '@/components/mdx/heading/h2'; export const meta = { description: '', emoji: '👉', - contributors: [] + contributors: [ + 'luc.eth', + 'serenae.eth' + ] }; # Resolver Interface Standards diff --git a/docs/resolvers/universalresolver.mdx b/docs/resolvers/universalresolver.mdx new file mode 100644 index 00000000..399c835a --- /dev/null +++ b/docs/resolvers/universalresolver.mdx @@ -0,0 +1,60 @@ +import { WIP } from "@/components/wip/WIP"; +import { interfaceDetails } from "#/data/interfaces"; +import { universalresolver_methods } from "#/data/universalresolver"; +import { h2, h3, h4 } from '@/components/mdx/heading/h2'; + +{/* * @type {import('@/lib/mdxPageProps').MdxMetaProps} */} +export const meta = { + description: '', + emoji: '👉', + contributors: [ + 'luc.eth', + 'serenae.eth' + ] +}; + +# Universal Resolver + +## Overview + +The Universal Resolver is a contract that handles the work of resolving a name entirely onchain, making it possible to make a single smart contract call to resolve an ENS name. + +Note that this contract is already built into libraries like Viem and ENSjs, so most developers don't typically need to use it directly. + +### Forward Resolution + +To resolve one or more records for a name, use one of the `resolve` methods, such as `resolve(bytes name, bytes data)`. + +The `name` argument for these methods will be the [DNS-encoded](/resolution/names#dns) version of the name. Make sure to [normalize](/resolution/names#normalize) the name first, as well! For example, given the name `My.Name.eth`: + +1. Normalize: + - `My.Name.eth` -> `my.name.eth` +2. DNS Encode: + - `my.name.eth` -> `0x026d79046e616d650365746800` + +The `data` argument for these methods will be an ABI-encoded call to the resolver for that name. + +For example, if you want to resolve the ETH address for `my.name.eth`, using the `addr(bytes32 node)` method, then the corresponding ABI-encoded call would be: + +``` +0x3b3b57def61adbd8ee36cf930560efc644af752731733dc6421afe47608f8e2cfeaabe2b +``` + +See here for standard resolver methods: [Resolver Interface Standards](/resolvers/interfaces) + +### Reverse Resolution + +To reverse-resolve an address to an ENS name, call one of the `reverse` methods, such as `reverse(bytes reverseName)`. + +The `reverseName` argument for these methods will be the [DNS-encoded](/resolution/names#dns) version of the reverse name. The "reverse name" is `[addr].addr.reverse`, where `[addr]` is the Ethereum public address (without the "0x"). Make sure to [normalize](/resolution/names#normalize) the name as well! For example, given the address `0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63`: + +1. Construct Reverse Name: + - `0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63` -> `231b0Ee14048e9dCcD1d247744d114a4EB5E8E63.addr.reverse` +2. Normalize: + - `231b0Ee14048e9dCcD1d247744d114a4EB5E8E63.addr.reverse` -> `231b0ee14048e9dccd1d247744d114a4eb5e8e63.addr.reverse` +3. DNS Encode: + - `231b0ee14048e9dccd1d247744d114a4eb5e8e63.addr.reverse` -> `0x28323331623065653134303438653964636364316432343737343464313134613465623565386536330461646472077265766572736500` + +## Interface Standards + +{interfaceDetails(universalresolver_methods)} \ No newline at end of file diff --git a/docs/wrapper/expiry.mdx b/docs/wrapper/expiry.mdx index e53bf0f5..b0dbcd11 100644 --- a/docs/wrapper/expiry.mdx +++ b/docs/wrapper/expiry.mdx @@ -57,6 +57,6 @@ The owner will *not* yet lose ownership of the name, but they will also not be a When a name is merely **Wrapped** but not **Emancipated** or **Locked**, parent-controlled fuses can still be burned. This means that the parent can burn a custom fuse for a limited amount of time. -When the expiry is reached, all fuses will be reset, but the name will otherwise be unaffected. +When the expiry (end of grace period for .eth 2LDs) is reached, all fuses will be reset, but the name will otherwise be unaffected. -When a name is **Emancipated** or **Locked**, the expiry has an important additional effect. In this scenario, when the expiry has been reached, **the name itself will expire**, and the owner **loses ownership** of the name. +When a name is **Emancipated** or **Locked**, the expiry has an important additional effect. In this scenario, when the expiry (end of grace period for .eth 2LDs) has been reached, **the name itself will expire**, and the owner **loses ownership** of the name.