Skip to content

Commit

Permalink
Add support interface (#21)
Browse files Browse the repository at this point in the history
* Add support interface

* Use ens-contracts IExtendedResolver

* Add support interface to reverse registrar

* Change test name

* Update L1 deployment contract address for base and OP

* Remove offset from getTarget

* Inherit Interfaces

* Inherit interfaces for ReverseResolver

* Add ERC165 signature
  • Loading branch information
makoto committed Nov 30, 2023
1 parent c52f671 commit 9be5192
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 19 deletions.
6 changes: 3 additions & 3 deletions crosschain-resolver/README.md
Expand Up @@ -110,7 +110,7 @@ const l2resolverAddress = await l2Factory.predictAddress(ETH_ADDRESS)
- DelegatableResolverRegistrar = [DelegatableResolverRegistrar](https://goerli-optimism.etherscan.io/address/0x2b07cf3ef421a5ff1cb6f437036bdef132eea37b#writeContract) = Demo contract that allow anyone to register subname under `op.evmgateway.eth` on [L2 resolver on `op.evmgateway.eth`](https://goerli-optimism.etherscan.io/address/0x96753bd0D9bdd98d3a84837B5933078AF49aF12d#writeContract)

#### L1
- L1Resolver = [0x65a0963A2941A13a96FcDCfE36c94c6a341f26E5](https://goerli.etherscan.io/address/0x65a0963A2941A13a96FcDCfE36c94c6a341f26E5) = Currently `op.evmgateway.eth` is set to the resolver
- L1Resolver = [0x7Bf57B0a683CC964B0fEe30633A72F5c05464a0f](https://goerli.etherscan.io/address/0x7Bf57B0a683CC964B0fEe30633A72F5c05464a0f) = Currently `op.evmgateway.eth` is set to the resolver

### Base

Expand All @@ -121,7 +121,7 @@ const l2resolverAddress = await l2Factory.predictAddress(ETH_ADDRESS)
- DelegatableResolverRegistrar = [DelegatableResolverRegistrar](https://goerli.basescan.org/address/0xe0356133c3c43cbb623543488e607e4e349eaa10#code) = Demo contract that allow anyone to register subname under `base.evmgateway.eth` on [L2 resolver on `base.evmgateway.eth`](https://goerli.basescan.org/address/0xE4B18eFbF71d516046514598FD7FcFbad4beC742)

#### L1
- L1Resolver = [0x052D7E10D55Ae12b4F62cdE18dBb7E938efa230D](https://goerli.etherscan.io/address/0x052D7E10D55Ae12b4F62cdE18dBb7E938efa230D) = Currently `base.evmgateway.eth` is set to the resolver
- L1Resolver = [0x3Ac25843A1F696fe2166C5dE127FD4f2832F4d42](https://goerli.etherscan.io/address/0x3Ac25843A1F696fe2166C5dE127FD4f2832F4d42) = Currently `base.evmgateway.eth` is set to the resolver


## Usage
Expand Down Expand Up @@ -214,7 +214,7 @@ Once done, set addrss of the subname from the operator, wait 10~20 min, then que
Go to [Base L1 resolver](https://goerli.etherscan.io/address/0x052D7E10D55Ae12b4F62cdE18dBb7E938efa230D#readContract)

```
[node, target] = l1resolver.getTarget(encodedname, 0)
[node, target] = l1resolver.getTarget(encodedname)
```

#### Step 2: Deploy the registrar contract
Expand Down
8 changes: 8 additions & 0 deletions crosschain-resolver/contracts/ITargetResolver.sol
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface ITargetResolver{
function getTarget(
bytes memory name
) external view returns (bytes32 node, address target);
}
34 changes: 25 additions & 9 deletions crosschain-resolver/contracts/L1Resolver.sol
Expand Up @@ -11,14 +11,16 @@ import {IAddrResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profi
import {IAddressResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol";
import {ITextResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol";
import {IContentHashResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol";
import "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol";
import {ITargetResolver} from './ITargetResolver.sol';
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";


contract L1Resolver is EVMFetchTarget {
contract L1Resolver is EVMFetchTarget, ITargetResolver, IExtendedResolver, ERC165 {
using EVMFetcher for EVMFetcher.EVMFetchRequest;
using BytesUtils for bytes;
IEVMVerifier immutable verifier;
ENS immutable ens;
INameWrapper immutable nameWrapper;
IEVMVerifier public immutable verifier;
ENS public immutable ens;
INameWrapper public immutable nameWrapper;
mapping(bytes32 => address) targets;
uint256 constant COIN_TYPE_ETH = 60;
uint256 constant RECORD_VERSIONS_SLOT = 0;
Expand Down Expand Up @@ -72,19 +74,24 @@ contract L1Resolver is EVMFetchTarget {
/**
* @dev Returns the L2 target address that can answer queries for `name`.
* @param name DNS encoded ENS name to query
* @param offset The offset of the label to query recursively.
* @return node The node of the name
* @return target The L2 resolver address to verify against.
*/
function getTarget(
bytes memory name
) public view returns (bytes32 node, address target) {
return _getTarget(name, 0);
}

function _getTarget(
bytes memory name,
uint256 offset
) public view returns (bytes32 node, address target) {
) private view returns (bytes32 node, address target) {
uint256 len = name.readUint8(offset);
node = bytes32(0);
if (len > 0) {
bytes32 label = name.keccak(offset + 1, len);
(node, target) = getTarget(
(node, target) = _getTarget(
name,
offset + len + 1
);
Expand All @@ -111,7 +118,7 @@ contract L1Resolver is EVMFetchTarget {
* @return result result of the call
*/
function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) {
(, address target) = getTarget(name, 0);
(, address target) = _getTarget(name, 0);
bytes4 selector = bytes4(data);

if (selector == IAddrResolver.addr.selector) {
Expand Down Expand Up @@ -210,4 +217,13 @@ contract L1Resolver is EVMFetchTarget {
) public pure returns (bytes memory) {
return abi.encode(values[1]);
}

function supportsInterface(
bytes4 interfaceId
) public override view returns (bool) {
return
interfaceId == type(IExtendedResolver).interfaceId ||
interfaceId == type(ITargetResolver).interfaceId ||
super.supportsInterface(interfaceId);
}
}
4 changes: 2 additions & 2 deletions crosschain-resolver/scripts/getaddr.ts
@@ -1,7 +1,7 @@
import packet from 'dns-packet';
const encodeName = (name) => '0x' + packet.name.encode(name).toString('hex')
const l1abi = [
"function getTarget(bytes,uint256) view returns (bytes32, address)",
"function getTarget(bytes) view returns (bytes32, address)",
"function addr(bytes32) view returns (address)",
"function resolve(bytes,bytes) view returns (bytes)",
]
Expand Down Expand Up @@ -32,7 +32,7 @@ export const main = async () => {
}
console.log({ENS_NAME, resolver, encodedname, node})
const l1resolver = new ethers.Contract(resolver.address, l1abi, l1provider);
const target = await l1resolver.getTarget(encodedname, 0)
const target = await l1resolver.getTarget(encodedname)
const l2resolverAddress = target[1]
console.log('Target is set to ' + l2resolverAddress);
const l2resolver = new ethers.Contract(l2resolverAddress, l2abi, l2provider);
Expand Down
14 changes: 10 additions & 4 deletions crosschain-resolver/test/testResolver.ts
Expand Up @@ -159,13 +159,13 @@ describe('Crosschain Resolver', () => {
}catch(e){
}

const result = await target.getTarget(incorrectname, 0)
const result = await target.getTarget(incorrectname)
expect(result[1]).to.equal(EMPTY_ADDRESS);
})

it("should allow owner to set target", async() => {
await target.setTarget(node, signerAddress)
const result = await target.getTarget(encodeName(name), 0)
const result = await target.getTarget(encodeName(name))
expect(result[1]).to.equal(signerAddress);
})

Expand All @@ -174,7 +174,7 @@ describe('Crosschain Resolver', () => {
const encodedsubname = encodeName(subname)
const subnode = ethers.namehash(subname)
await target.setTarget(node, signerAddress)
const result = await target.getTarget(encodedsubname, 0)
const result = await target.getTarget(encodedsubname)
expect(result[0]).to.equal(subnode);
expect(result[1]).to.equal(signerAddress);
})
Expand All @@ -193,7 +193,7 @@ describe('Crosschain Resolver', () => {
const wrappedtnode = ethers.namehash(`${label}.eth`)
await target.setTarget(wrappedtnode, resolverAddress)
const encodedname = encodeName(`${label}.eth`)
const result = await target.getTarget(encodedname, 0)
const result = await target.getTarget(encodedname)
expect(result[1]).to.equal(resolverAddress);
})

Expand Down Expand Up @@ -290,4 +290,10 @@ describe('Crosschain Resolver', () => {
const decoded = i.decodeFunctionResult("contenthash", result2)
expect(decoded[0]).to.equal(contenthash);
})

it("should support interface", async() => {
expect(await target.supportsInterface('0x15f64386')).to.equal(true) // ITargetResolver
expect(await target.supportsInterface('0x9061b923')).to.equal(true) // IExtendedResolver
expect(await target.supportsInterface('0x01ffc9a7')).to.equal(true) // ERC-165 support
})
});
14 changes: 13 additions & 1 deletion crosschain-reverse-resolver/contracts/L1ReverseResolver.sol
Expand Up @@ -4,8 +4,11 @@ pragma solidity ^0.8.17;
import {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';
import {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';
import {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';
import "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol";
import "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

contract L1ReverseResolver is EVMFetchTarget {
contract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC165 {
using EVMFetcher for EVMFetcher.EVMFetchRequest;
IEVMVerifier immutable verifier;
address immutable target;
Expand Down Expand Up @@ -67,4 +70,13 @@ contract L1ReverseResolver is EVMFetchTarget {
) public pure returns (string memory) {
return string(values[1]);
}

function supportsInterface(
bytes4 interfaceId
) public override view returns (bool) {
return
interfaceId == type(ITextResolver).interfaceId ||
interfaceId == type(INameResolver).interfaceId ||
super.supportsInterface(interfaceId);
}
}
5 changes: 5 additions & 0 deletions crosschain-reverse-resolver/test/testReverseResolver.ts
Expand Up @@ -114,4 +114,9 @@ describe('Crosschain Reverse Resolver', () => {
expect(result2).to.equal(value);
})

it("should support interface", async() => {
expect(await target.supportsInterface('0x59d1d43c')).to.equal(true) // ITextResolver
expect(await target.supportsInterface('0x691f3431')).to.equal(true) // INameResolver
expect(await target.supportsInterface('0x01ffc9a7')).to.equal(true) // ERC-165 support
})
});

0 comments on commit 9be5192

Please sign in to comment.