Skip to content

Commit 3a4d98d

Browse files
authored
Has roles (#158)
* created hasRole function in the roylaty module * created tests
1 parent eb26fd0 commit 3a4d98d

File tree

4 files changed

+222
-18
lines changed

4 files changed

+222
-18
lines changed

src/module/token/royalty/RoyaltyERC1155.sol

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
44
import {Module} from "../../../Module.sol";
55

66
import {Role} from "../../../Role.sol";
7+
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";
78

89
import {BeforeBatchTransferCallbackERC1155} from "../../../callback/BeforeBatchTransferCallbackERC1155.sol";
910
import {BeforeTransferCallbackERC1155} from "../../../callback/BeforeTransferCallbackERC1155.sol";
@@ -48,6 +49,12 @@ contract RoyaltyERC1155 is
4849
ICreatorToken
4950
{
5051

52+
/*//////////////////////////////////////////////////////////////
53+
CONSTANTS
54+
//////////////////////////////////////////////////////////////*/
55+
56+
bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;
57+
5158
/*//////////////////////////////////////////////////////////////
5259
STRUCTS
5360
//////////////////////////////////////////////////////////////*/
@@ -80,7 +87,10 @@ contract RoyaltyERC1155 is
8087
error RoyaltyExceedsMaxBps();
8188

8289
/// @notice Revert with an error if the transfer validator is not valid
83-
error InvalidTransferValidatorContract();
90+
error RoyaltyInvalidTransferValidatorContract();
91+
92+
/// @notice Revert with an error if the transfer validator is not valid
93+
error RoyaltyNotTransferValidator();
8494

8595
/*//////////////////////////////////////////////////////////////
8696
MODULE CONFIG
@@ -89,7 +99,7 @@ contract RoyaltyERC1155 is
8999
/// @notice Returns all implemented callback and module functions.
90100
function getModuleConfig() external pure virtual override returns (ModuleConfig memory config) {
91101
config.callbackFunctions = new CallbackFunction[](2);
92-
config.fallbackFunctions = new FallbackFunction[](8);
102+
config.fallbackFunctions = new FallbackFunction[](9);
93103

94104
config.callbackFunctions[0] = CallbackFunction(this.beforeTransferERC1155.selector);
95105
config.callbackFunctions[1] = CallbackFunction(this.beforeBatchTransferERC1155.selector);
@@ -103,11 +113,12 @@ contract RoyaltyERC1155 is
103113
FallbackFunction({selector: this.getTransferValidator.selector, permissionBits: 0});
104114
config.fallbackFunctions[4] =
105115
FallbackFunction({selector: this.getTransferValidationFunction.selector, permissionBits: 0});
106-
config.fallbackFunctions[5] =
107-
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
116+
config.fallbackFunctions[5] = FallbackFunction({selector: this.hasRole.selector, permissionBits: 0});
108117
config.fallbackFunctions[6] =
109-
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
118+
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
110119
config.fallbackFunctions[7] =
120+
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
121+
config.fallbackFunctions[8] =
111122
FallbackFunction({selector: this.setTransferValidator.selector, permissionBits: Role._MANAGER_ROLE});
112123

113124
config.requiredInterfaces = new bytes4[](1);
@@ -250,6 +261,16 @@ contract RoyaltyERC1155 is
250261
_setTransferValidator(validator);
251262
}
252263

264+
function hasRole(bytes32 role, address account) external view returns (bool) {
265+
if (msg.sender != _royaltyStorage().transferValidator) {
266+
revert RoyaltyNotTransferValidator();
267+
}
268+
if (role == DEFAULT_ACCESS_CONTROL_ADMIN_ROLE) {
269+
return OwnableRoles(address(this)).hasAllRoles(account, Role._MANAGER_ROLE);
270+
}
271+
return OwnableRoles(address(this)).hasAllRoles(account, uint256(role));
272+
}
273+
253274
/*//////////////////////////////////////////////////////////////
254275
INTERNAL FUNCTIONS
255276
//////////////////////////////////////////////////////////////*/
@@ -268,7 +289,7 @@ contract RoyaltyERC1155 is
268289
bool isValidTransferValidator = validator.code.length > 0;
269290

270291
if (validator != address(0) && !isValidTransferValidator) {
271-
revert InvalidTransferValidatorContract();
292+
revert RoyaltyInvalidTransferValidatorContract();
272293
}
273294

274295
emit TransferValidatorUpdated(address(getTransferValidator()), validator);

src/module/token/royalty/RoyaltyERC721.sol

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
44
import {Module} from "../../../Module.sol";
55

66
import {Role} from "../../../Role.sol";
7+
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";
78

89
import {BeforeTransferCallbackERC721} from "../../../callback/BeforeTransferCallbackERC721.sol";
910
import {IInstallationCallback} from "../../../interface/IInstallationCallback.sol";
@@ -41,6 +42,12 @@ library RoyaltyStorage {
4142

4243
contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackERC721, ICreatorToken {
4344

45+
/*//////////////////////////////////////////////////////////////
46+
CONSTANTS
47+
//////////////////////////////////////////////////////////////*/
48+
49+
bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;
50+
4451
/*//////////////////////////////////////////////////////////////
4552
STRUCTS
4653
//////////////////////////////////////////////////////////////*/
@@ -73,7 +80,10 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
7380
error RoyaltyExceedsMaxBps();
7481

7582
/// @notice Revert with an error if the transfer validator is not valid
76-
error InvalidTransferValidatorContract();
83+
error RoyaltyInvalidTransferValidatorContract();
84+
85+
/// @notice Revert with an error if the transfer validator is not valid
86+
error RoyaltyNotTransferValidator();
7787

7888
/*//////////////////////////////////////////////////////////////
7989
MODULE CONFIG
@@ -82,7 +92,7 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
8292
/// @notice Returns all implemented callback and module functions.
8393
function getModuleConfig() external pure virtual override returns (ModuleConfig memory config) {
8494
config.callbackFunctions = new CallbackFunction[](1);
85-
config.fallbackFunctions = new FallbackFunction[](8);
95+
config.fallbackFunctions = new FallbackFunction[](9);
8696

8797
config.callbackFunctions[0] = CallbackFunction(this.beforeTransferERC721.selector);
8898

@@ -95,11 +105,12 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
95105
FallbackFunction({selector: this.getTransferValidator.selector, permissionBits: 0});
96106
config.fallbackFunctions[4] =
97107
FallbackFunction({selector: this.getTransferValidationFunction.selector, permissionBits: 0});
98-
config.fallbackFunctions[5] =
99-
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
108+
config.fallbackFunctions[5] = FallbackFunction({selector: this.hasRole.selector, permissionBits: 0});
100109
config.fallbackFunctions[6] =
101-
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
110+
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
102111
config.fallbackFunctions[7] =
112+
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
113+
config.fallbackFunctions[8] =
103114
FallbackFunction({selector: this.setTransferValidator.selector, permissionBits: Role._MANAGER_ROLE});
104115

105116
config.requiredInterfaces = new bytes4[](1);
@@ -227,6 +238,16 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
227238
_setTransferValidator(validator);
228239
}
229240

241+
function hasRole(bytes32 role, address account) external view returns (bool) {
242+
if (msg.sender != _royaltyStorage().transferValidator) {
243+
revert RoyaltyNotTransferValidator();
244+
}
245+
if (role == DEFAULT_ACCESS_CONTROL_ADMIN_ROLE) {
246+
return OwnableRoles(address(this)).hasAllRoles(account, Role._MANAGER_ROLE);
247+
}
248+
return OwnableRoles(address(this)).hasAllRoles(account, uint256(role));
249+
}
250+
230251
/*//////////////////////////////////////////////////////////////
231252
INTERNAL FUNCTIONS
232253
//////////////////////////////////////////////////////////////*/
@@ -245,7 +266,7 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
245266
bool isValidTransferValidator = validator.code.length > 0;
246267

247268
if (validator != address(0) && !isValidTransferValidator) {
248-
revert InvalidTransferValidatorContract();
269+
revert RoyaltyInvalidTransferValidatorContract();
249270
}
250271

251272
emit TransferValidatorUpdated(address(getTransferValidator()), validator);

test/module/royalty/RoyaltyERC1155.t.sol

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,31 @@ contract TransferToken {
4141

4242
}
4343

44+
struct CollectionSecurityPolicyV3 {
45+
bool disableAuthorizationMode;
46+
bool authorizersCannotSetWildcardOperators;
47+
uint8 transferSecurityLevel;
48+
uint120 listId;
49+
bool enableAccountFreezingMode;
50+
uint16 tokenType;
51+
}
52+
53+
interface CreatorTokenTransferValidator is ITransferValidator {
54+
55+
function setTransferSecurityLevelOfCollection(
56+
address collection,
57+
uint8 transferSecurityLevel,
58+
bool isTransferRestricted,
59+
bool isTransferWithRestrictedRecipient,
60+
bool isTransferWithRestrictedToken
61+
) external;
62+
function getCollectionSecurityPolicy(address collection)
63+
external
64+
view
65+
returns (CollectionSecurityPolicyV3 memory);
66+
67+
}
68+
4469
contract RoyaltyERC1155Test is Test {
4570

4671
ERC1155Core public core;
@@ -49,7 +74,8 @@ contract RoyaltyERC1155Test is Test {
4974

5075
MintableERC1155 public mintableModuleImplementation;
5176
TransferToken public transferTokenContract;
52-
ITransferValidator public mockTransferValidator;
77+
CreatorTokenTransferValidator public mockTransferValidator;
78+
uint8 TRANSFER_SECURITY_LEVEL_SEVEN = 7;
5379

5480
uint256 ownerPrivateKey = 1;
5581
address public owner;
@@ -133,7 +159,7 @@ contract RoyaltyERC1155Test is Test {
133159
core.grantRoles(owner, Role._MINTER_ROLE);
134160

135161
// set up transfer validator
136-
mockTransferValidator = ITransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
162+
mockTransferValidator = CreatorTokenTransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
137163
vm.etch(address(mockTransferValidator), TRANSFER_VALIDATOR_DEPLOYED_BYTECODE);
138164
}
139165

@@ -247,7 +273,7 @@ contract RoyaltyERC1155Test is Test {
247273
function test_revert_setTransferValidator_invalidContract() public {
248274
// attempt to set the transfer validator to an invalid contract
249275
vm.prank(owner);
250-
vm.expectRevert(RoyaltyERC1155.InvalidTransferValidatorContract.selector);
276+
vm.expectRevert(RoyaltyERC1155.RoyaltyInvalidTransferValidatorContract.selector);
251277
RoyaltyERC1155(address(core)).setTransferValidator(address(11_111));
252278
}
253279

@@ -323,6 +349,61 @@ contract RoyaltyERC1155Test is Test {
323349
assertEq(0, core.balanceOf(permissionedActor, 1));
324350
}
325351

352+
/*///////////////////////////////////////////////////////////////
353+
Unit tests: `setTransferPolicy`
354+
//////////////////////////////////////////////////////////////*/
355+
356+
function test_setTransferSecurityLevel() public {
357+
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
358+
//skip test if evm version is not cancun
359+
return;
360+
}
361+
362+
// set transfer validator
363+
vm.prank(owner);
364+
RoyaltyERC1155(address(core)).setTransferValidator(address(mockTransferValidator));
365+
366+
vm.prank(owner);
367+
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);
368+
369+
vm.prank(permissionedActor);
370+
mockTransferValidator.setTransferSecurityLevelOfCollection(
371+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
372+
);
373+
374+
assertEq(
375+
mockTransferValidator.getCollectionSecurityPolicy(address(core)).transferSecurityLevel,
376+
TRANSFER_SECURITY_LEVEL_SEVEN
377+
);
378+
}
379+
380+
function test_revert_setTransferSecurityLevel() public {
381+
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
382+
//skip test if evm version is not cancun
383+
return;
384+
}
385+
vm.prank(owner);
386+
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);
387+
388+
// revert due to msg.sender not being the transfer validator
389+
vm.expectRevert();
390+
vm.prank(permissionedActor);
391+
mockTransferValidator.setTransferSecurityLevelOfCollection(
392+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
393+
);
394+
395+
// set transfer validator
396+
vm.prank(owner);
397+
RoyaltyERC1155(address(core)).setTransferValidator(address(mockTransferValidator));
398+
399+
// revert due to incorrect permissions
400+
vm.prank(unpermissionedActor);
401+
vm.expectRevert();
402+
mockTransferValidator.setTransferSecurityLevelOfCollection(
403+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
404+
);
405+
}
406+
326407
/*///////////////////////////////////////////////////////////////
327408
UTILITY FUNCTIONS
328409
//////////////////////////////////////////////////////////////*/

0 commit comments

Comments
 (0)