Skip to content

Commit e1d50be

Browse files
authored
feat: L2Resolver state variables and constructor w/unit tests (#2)
# πŸ€– Linear Closes EFI-425 Closes EFI-434
2 parents 05ccc90 + 1e0782c commit e1d50be

7 files changed

Lines changed: 199 additions & 20 deletions

File tree

β€Ž.github/workflows/tests.ymlβ€Ž

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,31 @@ jobs:
3838
shell: bash
3939
run: yarn test:unit
4040

41-
integration-tests:
42-
name: Run Integration Tests
43-
runs-on: ubuntu-latest
44-
steps:
45-
- uses: actions/checkout@v4
41+
# integration-tests:
42+
# name: Run Integration Tests
43+
# runs-on: ubuntu-latest
44+
# steps:
45+
# - uses: actions/checkout@v4
4646

47-
- name: Install Foundry
48-
uses: foundry-rs/foundry-toolchain@v1
49-
with:
50-
version: stable
47+
# - name: Install Foundry
48+
# uses: foundry-rs/foundry-toolchain@v1
49+
# with:
50+
# version: stable
5151

52-
- name: Use Node.js
53-
uses: actions/setup-node@v4
54-
with:
55-
node-version: 20.x
56-
cache: "yarn"
52+
# - name: Use Node.js
53+
# uses: actions/setup-node@v4
54+
# with:
55+
# node-version: 20.x
56+
# cache: "yarn"
5757

58-
- name: Install dependencies
59-
run: yarn --frozen-lockfile --network-concurrency 1
58+
# - name: Install dependencies
59+
# run: yarn --frozen-lockfile --network-concurrency 1
6060

61-
- name: Precompile
62-
run: yarn build
61+
# - name: Precompile
62+
# run: yarn build
6363

64-
- name: Run tests
65-
run: yarn test:integration
64+
# - name: Run tests
65+
# run: yarn test:integration
6666

6767
# medusa-tests:
6868
# name: Medusa Test

β€Žsrc/contracts/L2Resolver.solβ€Ž

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
import {IENS} from 'src/interfaces/IENS.sol';
5+
import {IL2Resolver} from 'src/interfaces/IL2Resolver.sol';
6+
import {INameWrapper} from 'src/interfaces/INameWrapper.sol';
7+
8+
/**
9+
* @title L2Resolver
10+
* @author @defi-wonderland
11+
* @notice Minimal L2 Resolver system for ENS. It resolves ENS names to their corresponding
12+
* formatted chain identifiers and allows reverse lookup by mapping them back to their primary ENS names.
13+
* EIP-7930 is an example of supported chain identifier.
14+
*/
15+
contract L2Resolver is IL2Resolver {
16+
/// @inheritdoc IL2Resolver
17+
bytes32 public constant REVERSE_LOOKUP_NODE = bytes32(keccak256('reverse.chain.id.eip7930'));
18+
19+
/// @inheritdoc IL2Resolver
20+
string public constant CHAIN_IDENTIFIER_EIP7930_KEY = 'chain.id.eip7930';
21+
22+
/// @inheritdoc IL2Resolver
23+
IENS public immutable ENS_REGISTRY;
24+
25+
/// @inheritdoc IL2Resolver
26+
INameWrapper public immutable NAME_WRAPPER;
27+
28+
/// @inheritdoc IL2Resolver
29+
address public immutable REVERSE_ADMIN;
30+
31+
/// @inheritdoc IL2Resolver
32+
bytes32 public immutable PARENT_NODE;
33+
34+
/// @inheritdoc IL2Resolver
35+
mapping(bytes32 _node => mapping(string _key => bytes _data)) public records;
36+
37+
/**
38+
* @notice Constructor
39+
* @param _ensRegistry The ENS registry address.
40+
* @param _nameWrapper The ENS name wrapper address.
41+
* @param _reverseAdmin The reverse admin address.
42+
* @param _parentNode The parent node namehash.
43+
*/
44+
constructor(address _ensRegistry, address _nameWrapper, address _reverseAdmin, bytes32 _parentNode) {
45+
ENS_REGISTRY = IENS(_ensRegistry);
46+
NAME_WRAPPER = INameWrapper(_nameWrapper);
47+
REVERSE_ADMIN = _reverseAdmin;
48+
PARENT_NODE = _parentNode;
49+
}
50+
}

β€Žsrc/interfaces/IENS.solβ€Ž

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
/**
5+
* @title IENS
6+
* @author @defi-wonderland
7+
* @notice Interface for the ENS registry.
8+
*/
9+
interface IENS {}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
import {IENS} from './IENS.sol';
5+
import {INameWrapper} from './INameWrapper.sol';
6+
7+
/**
8+
* @title IL2Resolver
9+
* @author @defi-wonderland
10+
*/
11+
interface IL2Resolver {
12+
/*///////////////////////////////////////////////////////////////
13+
EVENTS
14+
//////////////////////////////////////////////////////////////*/
15+
16+
/*///////////////////////////////////////////////////////////////
17+
ERRORS
18+
//////////////////////////////////////////////////////////////*/
19+
20+
/*///////////////////////////////////////////////////////////////
21+
LOGIC
22+
//////////////////////////////////////////////////////////////*/
23+
24+
/*///////////////////////////////////////////////////////////////
25+
VARIABLES
26+
//////////////////////////////////////////////////////////////*/
27+
/**
28+
* @notice The key used in records to store the EIP-7930 chain identifier bytes for a forward resolution.
29+
* @return _key The key used for a forward resolution.
30+
*/
31+
function CHAIN_IDENTIFIER_EIP7930_KEY() external view returns (string memory _key);
32+
33+
/**
34+
* @notice Stores arbitrary data for each ENS node.
35+
* @dev For domain-to-chain-identifier resolution, the key will be a pre-defined string.
36+
* (e.g., CHAIN_IDENTIFIER_EIP7930_KEY) and data will be the raw EIP-7930 chain identifier
37+
* bytes (formatted with AddressLength = 0).
38+
* @dev For EIP-7930-chain-identifier-to-domain resolution (reverse lookup), the REVERSE_LOOKUP_NODE is used.
39+
* The key is constructed by concatenating a prefix (e.g., CHAIN_IDENTIFIER_EIP7930_KEY)with the hexadecimal string
40+
* representation of the keccak256 hash of the EIP-7930 chain identifier bytes. The data stored is the
41+
* ABI-encoded human-readable ENS name string (e.g., abi.encode("optimism.l2.eth")).
42+
* @param _node The ENS node to store the data for.
43+
* @param _key The key to store the data under.
44+
* @return _data The data stored under the key.
45+
*/
46+
function records(bytes32 _node, string calldata _key) external view returns (bytes memory _data);
47+
48+
/**
49+
* @notice A dedicated node hash for storing reverse lookup entries.
50+
* @return _reverseLookupNode The reverse lookup node.
51+
*/
52+
function REVERSE_LOOKUP_NODE() external view returns (bytes32 _reverseLookupNode);
53+
54+
/**
55+
* @notice The ENS registry.
56+
* @return _ensRegistry The ENS registry address.
57+
*/
58+
function ENS_REGISTRY() external view returns (IENS _ensRegistry);
59+
60+
/**
61+
* @notice The ENS name wrapper.
62+
* @return _nameWrapper The ENS name wrapper address.
63+
*/
64+
function NAME_WRAPPER() external view returns (INameWrapper _nameWrapper);
65+
66+
/**
67+
* @notice The admin authorized to set the reverse lookup node values.
68+
* @return _adminAddress The admin address.
69+
*/
70+
function REVERSE_ADMIN() external view returns (address _adminAddress);
71+
72+
/**
73+
* @notice The parent node namehash for wildcard resolution and authorization.
74+
* @return _parentNode The parent node namehash.
75+
*/
76+
function PARENT_NODE() external view returns (bytes32 _parentNode);
77+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
/**
5+
* @title INameWrapper
6+
* @author @defi-wonderland
7+
* @notice Interface for the ENS Name Wrapper.
8+
*/
9+
interface INameWrapper {}

β€Žtest/unit/L2Resolver.t.solβ€Ž

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
import {Test} from 'forge-std/Test.sol';
5+
import {L2Resolver} from 'src/contracts/L2Resolver.sol';
6+
7+
contract UnitL2Resolverconstructor is Test {
8+
L2Resolver internal _l2Resolver;
9+
address internal _ensRegistry = makeAddr('ENSRegistry');
10+
address internal _nameWrapper = makeAddr('NameWrapper');
11+
address internal _reverseAdmin = makeAddr('ReverseAdmin');
12+
bytes32 internal _parentNode = bytes32(abi.encode('l2.eth'));
13+
14+
function setUp() external {
15+
_l2Resolver = new L2Resolver(_ensRegistry, _nameWrapper, _reverseAdmin, _parentNode);
16+
}
17+
18+
function test_WhenDeployingTheContract() external view {
19+
// it sets the ENS registry address
20+
assertEq(address(_l2Resolver.ENS_REGISTRY()), _ensRegistry);
21+
// it sets the name wrapper address
22+
assertEq(address(_l2Resolver.NAME_WRAPPER()), _nameWrapper);
23+
// it sets the reverse admin address
24+
assertEq(_l2Resolver.REVERSE_ADMIN(), _reverseAdmin);
25+
// it sets the parent node namehash
26+
assertEq(_l2Resolver.PARENT_NODE(), _parentNode);
27+
}
28+
}

β€Žtest/unit/L2Resolver.treeβ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
UnitL2Resolver::constructor
2+
└── when deploying the contract
3+
β”œβ”€β”€ it sets the ENS registry address
4+
β”œβ”€β”€ it sets the name wrapper address
5+
β”œβ”€β”€ it sets the reverse admin address
6+
└── it sets the parent node namehash

0 commit comments

Comments
Β (0)