@@ -35,12 +35,36 @@ contract Core is ERC721Core {
35
35
36
36
}
37
37
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 {
39
61
40
62
Core public core;
41
63
42
64
ImmutableAllowlistERC721 public immutableAllowlistModule;
43
65
OperatorAllowlist public operatorAllowlist;
66
+ DummyContract public dummyContract1;
67
+ DummyContract public dummyContract2;
44
68
45
69
address public owner = address (0x1 );
46
70
address public actorOne = address (0x2 );
@@ -55,6 +79,8 @@ contract TransferableERC721Test is Test {
55
79
56
80
core = new Core ("test " , "TEST " , "" , owner, modules, moduleData);
57
81
immutableAllowlistModule = new ImmutableAllowlistERC721 ();
82
+
83
+ vm.prank (owner);
58
84
operatorAllowlist = new OperatorAllowlist (owner);
59
85
60
86
// install module
@@ -64,6 +90,14 @@ contract TransferableERC721Test is Test {
64
90
core.installModule (address (immutableAllowlistModule), encodedOperatorAllowlist);
65
91
vm.stopPrank ();
66
92
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
+
67
101
// mint tokens
68
102
core.mint (actorOne, 1 , string ("" ), "" ); // tokenId 0
69
103
core.mint (actorTwo, 1 , string ("" ), "" ); // tokenId 1
@@ -73,6 +107,13 @@ contract TransferableERC721Test is Test {
73
107
core.grantRoles (owner, Role._MANAGER_ROLE);
74
108
}
75
109
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
+
76
117
/*///////////////////////////////////////////////////////////////
77
118
Unit tests: `setOperatorAllowlistRegistry`
78
119
//////////////////////////////////////////////////////////////*/
@@ -97,14 +138,126 @@ contract TransferableERC721Test is Test {
97
138
}
98
139
99
140
/*///////////////////////////////////////////////////////////////
100
- Unit tests: `setTransferable `
141
+ Unit tests: `beforeApproveERC721 `
101
142
//////////////////////////////////////////////////////////////*/
102
143
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
+ }
108
261
109
262
/// @notice Callback function for ERC721.setApprovalForAll
110
263
function beforeApproveForAll (address _from , address _to , bool _approved ) external returns (bytes memory ) {}
0 commit comments