@@ -35,12 +35,36 @@ contract Core is ERC721Core {
3535
3636}
3737
38- contract TransferableERC721Test is Test {
38+ contract DummyContract {
39+
40+ ERC721Core public immutable erc721Core;
41+
42+ constructor (address payable _erc721Core ) {
43+ erc721Core = ERC721Core (_erc721Core);
44+ }
45+
46+ function approve (address _to , uint256 _tokenId ) external {
47+ erc721Core.approve (_to, _tokenId);
48+ }
49+
50+ function setApprovalForAll (address _operator ) external {
51+ erc721Core.setApprovalForAll (_operator, true );
52+ }
53+
54+ function transfer (address _to , uint256 _tokenId ) external {
55+ erc721Core.transferFrom (address (this ), _to, _tokenId);
56+ }
57+
58+ }
59+
60+ contract ImmutableAllowlistERC721Test is Test {
3961
4062 Core public core;
4163
4264 ImmutableAllowlistERC721 public immutableAllowlistModule;
4365 OperatorAllowlist public operatorAllowlist;
66+ DummyContract public dummyContract1;
67+ DummyContract public dummyContract2;
4468
4569 address public owner = address (0x1 );
4670 address public actorOne = address (0x2 );
@@ -55,6 +79,8 @@ contract TransferableERC721Test is Test {
5579
5680 core = new Core ("test " , "TEST " , "" , owner, modules, moduleData);
5781 immutableAllowlistModule = new ImmutableAllowlistERC721 ();
82+
83+ vm.prank (owner);
5884 operatorAllowlist = new OperatorAllowlist (owner);
5985
6086 // install module
@@ -64,6 +90,14 @@ contract TransferableERC721Test is Test {
6490 core.installModule (address (immutableAllowlistModule), encodedOperatorAllowlist);
6591 vm.stopPrank ();
6692
93+ // set registrar role for owner
94+ vm.prank (owner);
95+ operatorAllowlist.grantRegistrarRole (owner);
96+
97+ // deploy dummy contract
98+ dummyContract1 = new DummyContract (payable (address (core)));
99+ dummyContract2 = new DummyContract (payable (address (core)));
100+
67101 // mint tokens
68102 core.mint (actorOne, 1 , string ("" ), "" ); // tokenId 0
69103 core.mint (actorTwo, 1 , string ("" ), "" ); // tokenId 1
@@ -73,6 +107,13 @@ contract TransferableERC721Test is Test {
73107 core.grantRoles (owner, Role._MANAGER_ROLE);
74108 }
75109
110+ function allowlist (address _target ) internal {
111+ address [] memory allowlist = new address [](1 );
112+ allowlist[0 ] = _target;
113+ vm.prank (owner);
114+ operatorAllowlist.addAddressToAllowlist (allowlist);
115+ }
116+
76117 /*///////////////////////////////////////////////////////////////
77118 Unit tests: `setOperatorAllowlistRegistry`
78119 //////////////////////////////////////////////////////////////*/
@@ -97,14 +138,126 @@ contract TransferableERC721Test is Test {
97138 }
98139
99140 /*///////////////////////////////////////////////////////////////
100- Unit tests: `setTransferable `
141+ Unit tests: `beforeApproveERC721 `
101142 //////////////////////////////////////////////////////////////*/
102143
103- /// @notice Callback function for ERC721.approve
104- function beforeApproveERC721 (address _from , address _to , uint256 _tokenId , bool _approve )
105- external
106- returns (bytes memory )
107- {}
144+ function test_state_beforeApproveERC721 () public {
145+ // passes when msg.sender is an EOA and targetApproval is an EOA
146+ vm.prank (actorOne);
147+ core.approve (actorTwo, 0 );
148+
149+ // set allowlist for dummy contract
150+ address [] memory allowlist = new address [](3 );
151+ allowlist[0 ] = address (dummyContract1);
152+ allowlist[1 ] = address (dummyContract2);
153+ allowlist[2 ] = address (actorThree);
154+ vm.prank (owner);
155+ operatorAllowlist.addAddressToAllowlist (allowlist);
156+
157+ vm.startPrank (actorThree);
158+ core.mint (actorThree, 2 , string ("" ), "" ); // tokenId 3
159+ core.transferFrom (actorThree, address (dummyContract1), 3 );
160+ vm.stopPrank ();
161+
162+ // passes when msg.sender is a contract and is allowlisted
163+ // and when targetApproval is a contract and is allowlisted
164+ dummyContract1.approve (address (dummyContract2), 3 );
165+ }
166+
167+ function test_revert_beforeApproveERC721 () public {
168+ vm.prank (actorOne);
169+ vm.expectRevert (
170+ abi.encodeWithSelector (
171+ OperatorAllowlistEnforcementErrors.ApproveTargetNotInAllowlist.selector , address (dummyContract1)
172+ )
173+ );
174+ core.approve (address (dummyContract1), 0 );
175+ }
176+
177+ /*///////////////////////////////////////////////////////////////
178+ Unit tests: `beforeApproveForAll`
179+ //////////////////////////////////////////////////////////////*/
180+
181+ function test_state_beforeApproveForAllERC721 () public {
182+ // passes when msg.sender is an EOA and targetApproval is an EOA
183+ vm.prank (actorOne);
184+ core.setApprovalForAll (actorTwo, true );
185+
186+ // set allowlist for dummy contract
187+ address [] memory allowlist = new address [](3 );
188+ allowlist[0 ] = address (dummyContract1);
189+ allowlist[1 ] = address (dummyContract2);
190+ allowlist[2 ] = address (actorThree);
191+ vm.prank (owner);
192+ operatorAllowlist.addAddressToAllowlist (allowlist);
193+
194+ vm.startPrank (actorThree);
195+ core.mint (actorThree, 1 , string ("" ), "" ); // tokenId 3
196+ core.transferFrom (actorThree, address (dummyContract1), 3 );
197+ vm.stopPrank ();
198+
199+ // passes when msg.sender is a contract and is allowlisted
200+ // and when targetApproval is a contract and is allowlisted
201+ dummyContract1.setApprovalForAll (address (dummyContract2));
202+ }
203+
204+ function test_revert_beforeApproveForAllERC721 () public {
205+ vm.prank (actorOne);
206+ vm.expectRevert (
207+ abi.encodeWithSelector (
208+ OperatorAllowlistEnforcementErrors.ApproveTargetNotInAllowlist.selector , address (dummyContract1)
209+ )
210+ );
211+ core.setApprovalForAll (address (dummyContract1), true );
212+ }
213+
214+ /*///////////////////////////////////////////////////////////////
215+ Unit tests: `beforeTransferERC721`
216+ //////////////////////////////////////////////////////////////*/
217+
218+ function test_state_beforeTransferERC721 () public {
219+ // set allowlist
220+ address [] memory allowlist = new address [](5 );
221+ allowlist[0 ] = address (dummyContract1);
222+ allowlist[1 ] = address (dummyContract2);
223+ allowlist[2 ] = address (actorOne);
224+ allowlist[3 ] = address (actorTwo);
225+ allowlist[4 ] = address (actorThree);
226+ vm.prank (owner);
227+ operatorAllowlist.addAddressToAllowlist (allowlist);
228+
229+ vm.prank (actorOne);
230+ core.transferFrom (actorOne, actorTwo, 0 );
231+
232+ // passes when msg.sender is an EOA and targetApproval is a contract and is allowlisted
233+ core.mint (actorThree, 1 , string ("" ), "" ); // tokenId 3
234+ vm.startPrank (actorThree);
235+ core.transferFrom (actorThree, address (dummyContract1), 3 );
236+ vm.stopPrank ();
237+
238+ // passes when msg.sender is a contract and is allowlisted
239+ // and when targetApproval is a contract and is allowlisted
240+ dummyContract1.transfer (address (dummyContract2), 3 );
241+ }
242+
243+ function test_revert_beforeTransferERC721 () public {
244+ // fails when msg.sender is not allowlisted
245+ vm.prank (actorOne);
246+ vm.expectRevert (
247+ abi.encodeWithSelector (OperatorAllowlistEnforcementErrors.CallerNotInAllowlist.selector , actorOne)
248+ );
249+ core.transferFrom (actorOne, actorTwo, 0 );
250+
251+ // fails when target is not allowlisted
252+ allowlist (actorOne);
253+ vm.prank (actorOne);
254+ vm.expectRevert (
255+ abi.encodeWithSelector (
256+ OperatorAllowlistEnforcementErrors.TransferToNotInAllowlist.selector , address (dummyContract1)
257+ )
258+ );
259+ core.transferFrom (actorOne, address (dummyContract1), 0 );
260+ }
108261
109262 /// @notice Callback function for ERC721.setApprovalForAll
110263 function beforeApproveForAll (address _from , address _to , bool _approved ) external returns (bytes memory ) {}
0 commit comments