Skip to content

Latest commit

 

History

History

crosschain-reverse-resolver

@ensdomains/crosschain-reverse-resolver

A reverse resolver contract that is built on top of evm-verifier.

Deployment

Pior to deploying ENS gateway contracts, deploy your own EVM Gateway verifier and host the gateway, or use the preexising ones(OP, Base, Arbitrum ).

Once EVM verifier contracts are deployed, deploy L2ReverseResolver (You can skip this section if you have already deployed l2 contracts as part of setting up crosschain-resolver).

Once all complete, create .env and set the following variables (use VERIFIER_ADDRESS to specify the chain specific verifier)

  • DEPLOYER_PRIVATE_KEY
  • L1_PROVIDER_URL
  • L2_PROVIDER_URL
  • L1_ETHERSCAN_API_KEY
  • L2_ETHERSCAN_API_KEY
  • VERIFIER_ADDRESS = Address deployed via -verifier repo on evmgateway
  • REVERSE_NAMESPACE = A Reverse resolver contract, following the Evm reverse resolution draft ENSIP (eg: 2158639068.reverse for the OP sepolia namespace)
  • L2_REVERSE_RESOLVER_ADDRESS = l2 Reverse resolver address
  • CHAIN_NAME (Op/Base/Arb)
bun run hardhat deploy --network sepolia

After deployment is complete, set the rersolver of $REVERSE_NAMESPACE to L1ReverseResolver contract address

Deployed addresses

L1

OP

L2

L1

Base

L2

L1

Arbitrum

L2

L1

Usage

Set Default Primary name on L1

const testSigner = new ethers.Wallet(PRIVATE_KEY); 
const testAddress = testSigner.address
const name = 'myname.eth'
const reverseLabel = testAddress.substring(2).toLowerCase()
const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse`
const l2ReverseNode = ethers.namehash(l2ReverseName)
const encodedL2ReverseName = encodeName(l2ReverseName)

const defaultReverseName = `${reverseLabel}.default.reverse`
const defaultReverseNode = ethers.namehash(defaultReverseName)
const encodedDefaultReverseName = encodeName(defaultReverseName)

const funcId = ethers
    .id('setNameForAddrWithSignature(address,string,uint256,bytes)')
    .substring(0, 10)

const block = await provider.getBlock('latest')
const inceptionDate = block?.timestamp
const message =  ethers.solidityPackedKeccak256(
    ['bytes32', 'address', 'uint256', 'uint256'],
    [ethers.solidityPackedKeccak256(['bytes4', 'string'], [funcId, name]), testAddress, inceptionDate, 0],
)
const signature = await testSigner.signMessage(ethers.toBeArray(message))    
await defaultReverseResolver.setNameForAddrWithSignature(
    testAddress,
    name,
    inceptionDate,
    signature,
)

or run the script

DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY REVERSE_NAMESPACE=$REVERSE_NAMESPACE L1_PROVIDER_URL=$L1_PROVIDER_URL DEFAULT_REVERSE_RESOLVER_ADDRESS=$DEFAULT_REVERSE_RESOLVER_ADDRESS DEFAULT_ENS_NAME=$DEFAULT_ENS_NAME yarn setdefaultname

Set Primary name on L2

const name = 'foo.op.evmgateway.eth'
const registrar = registrar.setName(name)

, try it directly from etherscan, or run the script

DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY REVERSE_NAMESPACE=$REVERSE_NAMESPACE L2_PROVIDER_URL=$L2_PROVIDER_URL L2_REVERSE_RESOLVER_ADDRESS=$L2_REVERSE_RESOLVER_ADDRESS ENS_NAME=$ENS_NAME yarn setname --network optimismSepolia

Query Primary name on L1

All primary names are registered under ${ADDRESS}.${cointype}.reverse namespace.

  • 2158639068 is the coin type of Optimism Sepolia (11155420)
  • 2147568180 is the coin type of Base Sepolia (84532)
  • 2147905262 is the coin type of Arbitrum Sepolia (421614)
import packet from 'dns-packet';
import {ethers} from 'ethers';
const abi = ['function name(bytes32) view returns(string)'];
const encodeName = (name) => '0x' + packet.name.encode(name).toString('hex')
const namespace       = '2158639068.reverse' // 2158639068 is the coinType of Optimism Sepolia (11155420)
const name            = ETH_ADDRESS.substring(2).toLowerCase() + "." + namespace
const encodedname     = encodeName(name);
const reversenode     = ethers.namehash(name);
const reverseresolver = await provider.getResolver(namespace);
const provider        = new ethers.JsonRpcProvider(L1_PROVIDER_URL);
const l1resolver = new ethers.Contract(reverseresolver.address, abi, provider);
console.log(await l1resolver.name(reversenode, {enableCcipRead:true}))

Using the script

L1_PROVIDER_URL=$L1_PROVIDER_URL REVERSE_NAMESPACE=$REVERSE_NAMESPACE L2_REVERSE_RESOLVER_ADDRESS=$L2_REVERSE_RESOLVER_ADDRESS ETH_ADDRESS=$ETH_ADDRESS yarn getname