While developing justaname, we noted a limitation in address resolution that could impact the promises of off-chain names vs their on-chain equivalents. This was also brought forward to us by @lightwalker.eth during a call. The following is a technical step-by-step proposal that aims to tackle this. Any feedback would be highly appreciated!
Problem:
Resolving addresses in off-chain environments presents a current challenge. This procedure involves translating an address into a user-friendly name, enhancing ease and intuitiveness in user interactions. Dealing with off-chain storage can introduce complexities due to the decentralized nature and security measures of blockchain technology, making it challenging to access the required data or resources for resolution efficiently.
Proposal:
Setting the Primary Name:
Setting the resolver to the off-chain resolver:
const nameHash = ethers.namehash(testAddress.substring(2) + ".addr.reverse");
First step is to call the function [âfunction recordExists(bytes32) view returns (bool)â] on the ENS Registry contract, the next steps would depend on its response:
- True: Call ["function setResolver(bytes32 node, address resolver)â] on ENS Registry contract and pass the nameHash and the off-chain resolver address. Costs 31,165 gas units.
- False: Call [âfunction claimWithResolver(address owner, address resolver)â] on Reverse Registrar Contract and pass the address along with the off-chain resolver address. Costs 44,002 gas units and 81,002 gas units for the first time.
Setting the Primary Name:
This is dependent on the off-chain solutions providerâs specific implementation. As an example we can have an entity that looks like this:
PrimaryName: {
name: string,
address: string,
nameHash: string,
chainId: number
}
The provider should also implement a SIWE-like type of message to verify the messageâs authenticity, along with authenticating the ownership of the name.
Reverse Resolution:
const nameHash = ethers.namehash(testAddress.substring(2) + ".addr.reverse");
First Step: Query Registry Contract:
The first step would be to query the registry contract to get the resolver contractâs address associated with a given nameHash. This should return the off-chain providerâs resolver contract address.
Second Step: Query the Resolver Contract:
Supports Interface:
Call the function [âfunction supportsInterface(bytes4 interfaceID) returns boolâ] with interfaceId = â0x9061b923â.
False:
In case it returns false, call the function [âfunction name(bytes32 node) returns (string)â] on the Resolver contract. This should return the associated name.
True:
In case it returns true,
call the function [âresolve(bytes name, bytes data) returns (bytes)â] on the Off-chain Resolver Contract.
The param name should be the DNS-encoded nameHash.
The param data should be [âname(bytes32)â]
Query the contract:
The rest of the flow would be an extension to CCIP-Read and ENSIP-10
The contract should revert with the same error:
error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);
Call the gateway:
Query the gateway on the url returned by the contract in step2, and pass the sender with the calldata. Example:
{url}/resolve/{sender}/{callData}.json
The off-chain gateway handling the request should add its own logic for handling the [âname(bytes32)â] and return the correct data, similar to how it is handling the logic of:
[âaddr(bytes32)â,
âaddr(bytes32,uint256)â,
âtext(bytes32,string)â,
âcontenthash(bytes32)â]
Callback Function:
Call the callbackFunction of the contract (returned in revert error of step 2), and pass the gateway response of step3, along with the extraData returned in step 2.
The response returned from the contract should be decoded and will return the primary name associated with the nameHash.
Introducing a Custom NPM Package for Off-Chain Reverse Resolution Support:
To overcome the limitations related to off-chain address resolution, a dedicated npm package has been crafted specifically for this purpose. This development addresses the challenges uncovered during the exploration and creation of justaname, particularly the necessity for a reliable method to convert Ethereum addresses back to human-readable names without relying solely on on-chain processes. Through this npm package, a novel solution is presented, combining both on-chain and off-chain technologies to enable reverse resolution. This ensures a smooth and user-friendly interaction for users, and this package aims to work as an extension to ethers.jsâ existing ens related functionality. For more information, including installation guidelines and documentation, visit the npm repository under the name @justaname.id/address-resolution. This package is open-source, and community contributions to expand its functionality or improve its features are strongly encouraged.