@@ -4,25 +4,342 @@ pragma solidity 0.8.30;
44import {Test} from 'forge-std/Test.sol ' ;
55import {L2Resolver} from 'src/contracts/L2Resolver.sol ' ;
66
7- contract UnitL2Resolverconstructor is Test {
7+ import {IENS} from 'src/interfaces/IENS.sol ' ;
8+ import {IL2Resolver} from 'src/interfaces/IL2Resolver.sol ' ;
9+ import {INameWrapper} from 'src/interfaces/INameWrapper.sol ' ;
10+
11+ contract UnitL2Resolver is Test {
812 L2Resolver internal _l2Resolver;
913 address internal _ensRegistry = makeAddr ('ENSRegistry ' );
1014 address internal _nameWrapper = makeAddr ('NameWrapper ' );
1115 address internal _reverseAdmin = makeAddr ('ReverseAdmin ' );
12- bytes32 internal _parentNode = bytes32 (abi.encode ('l2.eth ' ));
16+ bytes32 internal _parentNodeNameHash = keccak256 ('l2.eth ' );
17+ bytes32 internal _reverseLookupNode;
18+ bytes32 internal _nodeNameHash = keccak256 ('optimism.l2.eth ' );
19+ string internal _key;
20+ bytes internal _chainIdBytes = hex '00010001010A00 ' ;
21+ string internal _reverseLookupKey;
22+ bytes internal _reverseLookupValue = abi.encode ('optimism.l2.eth ' );
1323
1424 function setUp () external {
15- _l2Resolver = new L2Resolver (_ensRegistry, _nameWrapper, _reverseAdmin, _parentNode);
25+ _l2Resolver = new L2Resolver (_ensRegistry, _nameWrapper, _reverseAdmin, _parentNodeNameHash);
26+ _reverseLookupNode = _l2Resolver.REVERSE_LOOKUP_NODE ();
27+ _key = _l2Resolver.CHAIN_IDENTIFIER_EIP7930_KEY ();
28+ _reverseLookupKey = string .concat (_key, 'chainIdBytes ' );
29+
30+ vm.etch (address (_ensRegistry), new bytes (0x1 ));
31+ vm.etch (address (_nameWrapper), new bytes (0x1 ));
1632 }
1733
18- function test_WhenDeployingTheContract () external view {
34+ function test_ConstructorWhenDeployingTheContract () external view {
1935 // it sets the ENS registry address
2036 assertEq (address (_l2Resolver.ENS_REGISTRY ()), _ensRegistry);
2137 // it sets the name wrapper address
2238 assertEq (address (_l2Resolver.NAME_WRAPPER ()), _nameWrapper);
2339 // it sets the reverse admin address
2440 assertEq (_l2Resolver.REVERSE_ADMIN (), _reverseAdmin);
2541 // it sets the parent node namehash
26- assertEq (_l2Resolver.PARENT_NODE (), _parentNode);
42+ assertEq (_l2Resolver.PARENT_NODE (), _parentNodeNameHash);
43+ }
44+
45+ modifier whenTheNodeIsTheReverseLookupNode () {
46+ _;
47+ }
48+
49+ function test_SetRecordWhenTheCallerIsTheReverseAdmin () external {
50+ // it emits the RecordSet event
51+ vm.prank (_reverseAdmin);
52+ vm.expectEmit (true , true , false , true );
53+ emit IL2Resolver.RecordSet (_reverseLookupNode, _reverseLookupKey, _reverseLookupValue);
54+ _l2Resolver.setRecord (_reverseLookupNode, _reverseLookupKey, _reverseLookupValue);
55+
56+ // it sets the record
57+ assertEq (_l2Resolver.records (_reverseLookupNode, _reverseLookupKey), _reverseLookupValue);
58+ }
59+
60+ function test_SetRecordWhenTheCallerIsNotTheReverseAdmin (address _caller ) external {
61+ vm.assume (_caller != _reverseAdmin);
62+ // it reverts
63+ vm.prank (_caller);
64+ vm.expectRevert (abi.encodeWithSelector (IL2Resolver.NotAuthorized.selector ));
65+ _l2Resolver.setRecord (_reverseLookupNode, _reverseLookupKey, _reverseLookupValue);
66+ }
67+
68+ modifier whenTheNodeHasAnENSRegistryOwner (address _owner ) {
69+ vm.mockCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _nodeNameHash), abi.encode (_owner));
70+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _nodeNameHash));
71+ _;
72+ }
73+
74+ function test_SetRecordWhenTheCallerIsTheBeneficialOwner (address _caller )
75+ external
76+ whenTheNodeHasAnENSRegistryOwner (_caller)
77+ {
78+ vm.assume (_caller != _nameWrapper);
79+ vm.assume (_caller != address (0 ));
80+
81+ // it emits the RecordSet event
82+ vm.prank (_caller);
83+ vm.expectEmit (true , true , false , true );
84+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
85+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
86+
87+ // it sets the record
88+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
89+ }
90+
91+ function test_SetRecordWhenTheCallerIsAnENSRegistryApprovedOperator (
92+ address _owner ,
93+ address _caller
94+ ) external whenTheNodeHasAnENSRegistryOwner (_owner) {
95+ vm.assume (_owner != _nameWrapper);
96+ vm.assume (_owner != address (0 ));
97+ vm.assume (_caller != _owner);
98+
99+ vm.mockCall (
100+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller), abi.encode (true )
101+ );
102+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller));
103+
104+ // it emits the RecordSet event
105+ vm.prank (_caller);
106+ vm.expectEmit (true , true , false , true );
107+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
108+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
109+
110+ // it sets the record
111+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
112+ }
113+
114+ function test_SetRecordWhenTheCallerIsANameWrapperApprovedOperator (
115+ address _owner ,
116+ address _caller
117+ ) external whenTheNodeHasAnENSRegistryOwner (_nameWrapper) {
118+ vm.assume (_owner != address (0 ));
119+ vm.assume (_caller != _owner);
120+
121+ vm.mockCall (
122+ address (_nameWrapper), abi.encodeWithSelector (INameWrapper.ownerOf.selector , _nodeNameHash), abi.encode (_owner)
123+ );
124+ vm.expectCall (address (_nameWrapper), abi.encodeWithSelector (INameWrapper.ownerOf.selector , _nodeNameHash));
125+ vm.mockCall (
126+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller), abi.encode (false )
127+ );
128+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller));
129+ vm.mockCall (
130+ address (_nameWrapper),
131+ abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _owner, _caller),
132+ abi.encode (true )
133+ );
134+ vm.expectCall (
135+ address (_nameWrapper), abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _owner, _caller)
136+ );
137+
138+ // it emits the RecordSet event
139+ vm.prank (_caller);
140+ vm.expectEmit (true , true , false , true );
141+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
142+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
143+
144+ // it sets the record
145+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
146+ }
147+
148+ function test_SetRecordWhenTheCallerIsNeitherOwnerNorApproved (
149+ address _owner ,
150+ address _caller
151+ ) external whenTheNodeHasAnENSRegistryOwner (_owner) {
152+ vm.assume (_owner != _caller);
153+ vm.assume (_owner != address (0 ));
154+ vm.assume (_owner != _nameWrapper);
155+
156+ vm.mockCall (
157+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller), abi.encode (false )
158+ );
159+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _owner, _caller));
160+ vm.mockCall (
161+ address (_nameWrapper),
162+ abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _owner, _caller),
163+ abi.encode (false )
164+ );
165+ vm.expectCall (
166+ address (_nameWrapper), abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _owner, _caller)
167+ );
168+
169+ // it reverts
170+ vm.prank (_caller);
171+ vm.expectRevert (abi.encodeWithSelector (IL2Resolver.NotAuthorized.selector ));
172+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
173+ }
174+
175+ modifier whenTheNodeHasNoENSRegistryOwner () {
176+ vm.mockCall (
177+ address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _nodeNameHash), abi.encode (address (0 ))
178+ );
179+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _nodeNameHash));
180+ _;
181+ }
182+
183+ function test_SetRecordWhenTheCallerIsTheParentOwner (address _parentNodeOwner )
184+ external
185+ whenTheNodeHasNoENSRegistryOwner
186+ {
187+ vm.assume (_parentNodeOwner != address (0 ));
188+ vm.assume (_parentNodeOwner != _nameWrapper);
189+
190+ vm.mockCall (
191+ address (_ensRegistry),
192+ abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash),
193+ abi.encode (_parentNodeOwner)
194+ );
195+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash));
196+
197+ // it emits the RecordSet event
198+ vm.prank (_parentNodeOwner);
199+ vm.expectEmit (true , true , false , true );
200+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
201+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
202+
203+ // it sets the record
204+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
205+ }
206+
207+ function test_SetRecordWhenTheCallerIsAnENSregistryApprovedOperatorOfTheParent (
208+ address _parentNodeOwner ,
209+ address _caller
210+ ) external whenTheNodeHasNoENSRegistryOwner {
211+ vm.assume (_parentNodeOwner != address (0 ));
212+ vm.assume (_parentNodeOwner != _nameWrapper);
213+ vm.assume (_caller != _parentNodeOwner);
214+
215+ vm.mockCall (
216+ address (_ensRegistry),
217+ abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash),
218+ abi.encode (_parentNodeOwner)
219+ );
220+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash));
221+
222+ vm.mockCall (
223+ address (_ensRegistry),
224+ abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller),
225+ abi.encode (true )
226+ );
227+ vm.expectCall (
228+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller)
229+ );
230+
231+ // it emits the RecordSet event
232+ vm.prank (_caller);
233+ vm.expectEmit (true , true , false , true );
234+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
235+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
236+
237+ // it sets the record
238+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
239+ }
240+
241+ function test_SetRecordWhenTheCallerIsANameWrapperApprovedOperatorOfTheParent (
242+ address _parentNodeOwner ,
243+ address _caller
244+ ) external whenTheNodeHasNoENSRegistryOwner {
245+ vm.assume (_parentNodeOwner != address (0 ));
246+ vm.assume (_parentNodeOwner != _nameWrapper);
247+ vm.assume (_caller != _parentNodeOwner);
248+
249+ vm.mockCall (
250+ address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash), abi.encode (_nameWrapper)
251+ );
252+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash));
253+ vm.mockCall (
254+ address (_nameWrapper),
255+ abi.encodeWithSelector (INameWrapper.ownerOf.selector , _parentNodeNameHash),
256+ abi.encode (_parentNodeOwner)
257+ );
258+ vm.expectCall (address (_nameWrapper), abi.encodeWithSelector (INameWrapper.ownerOf.selector , _parentNodeNameHash));
259+
260+ vm.mockCall (
261+ address (_ensRegistry),
262+ abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller),
263+ abi.encode (false )
264+ );
265+ vm.expectCall (
266+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller)
267+ );
268+
269+ vm.mockCall (
270+ address (_nameWrapper),
271+ abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _parentNodeOwner, _caller),
272+ abi.encode (true )
273+ );
274+ vm.expectCall (
275+ address (_nameWrapper), abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _parentNodeOwner, _caller)
276+ );
277+
278+ // it emits the RecordSet event
279+ vm.prank (_caller);
280+ vm.expectEmit (true , true , false , true );
281+ emit IL2Resolver.RecordSet (_nodeNameHash, _key, _chainIdBytes);
282+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
283+
284+ // it sets the record
285+ assertEq (_l2Resolver.records (_nodeNameHash, _key), _chainIdBytes);
286+ }
287+
288+ function test_SetRecordWhenTheCallerIsNotAnApprovedOperatorOfTheParent (
289+ address _parentNodeOwner ,
290+ address _caller
291+ ) external whenTheNodeHasNoENSRegistryOwner {
292+ vm.assume (_parentNodeOwner != address (0 ));
293+ vm.assume (_parentNodeOwner != _nameWrapper);
294+ vm.assume (_caller != _parentNodeOwner);
295+
296+ vm.mockCall (
297+ address (_ensRegistry),
298+ abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash),
299+ abi.encode (_parentNodeOwner)
300+ );
301+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash));
302+
303+ vm.mockCall (
304+ address (_ensRegistry),
305+ abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller),
306+ abi.encode (false )
307+ );
308+ vm.expectCall (
309+ address (_ensRegistry), abi.encodeWithSelector (IENS.isApprovedForAll.selector , _parentNodeOwner, _caller)
310+ );
311+
312+ vm.mockCall (
313+ address (_nameWrapper),
314+ abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _parentNodeOwner, _caller),
315+ abi.encode (false )
316+ );
317+ vm.expectCall (
318+ address (_nameWrapper), abi.encodeWithSelector (INameWrapper.isApprovedForAll.selector , _parentNodeOwner, _caller)
319+ );
320+
321+ // it reverts
322+ vm.prank (_caller);
323+ vm.expectRevert (abi.encodeWithSelector (IL2Resolver.NotAuthorized.selector ));
324+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
325+ }
326+
327+ function test_SetRecordWhenTheCallerIsNotAuthorizedOnTheParent (
328+ address _parentNodeOwner ,
329+ address _caller
330+ ) external whenTheNodeHasNoENSRegistryOwner {
331+ vm.assume (_parentNodeOwner != address (0 ));
332+ vm.assume (_parentNodeOwner != _nameWrapper);
333+ vm.assume (_caller != _parentNodeOwner);
334+
335+ vm.mockCall (
336+ address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash), abi.encode (address (0 ))
337+ );
338+ vm.expectCall (address (_ensRegistry), abi.encodeWithSelector (IENS.owner.selector , _parentNodeNameHash));
339+
340+ // it reverts
341+ vm.prank (_caller);
342+ vm.expectRevert (abi.encodeWithSelector (IL2Resolver.NotAuthorized.selector ));
343+ _l2Resolver.setRecord (_nodeNameHash, _key, _chainIdBytes);
27344 }
28345}
0 commit comments