Skip to content

Commit 8f45917

Browse files
authored
added hasRole to creatorTokenERC20 module (#167)
1 parent 5464318 commit 8f45917

File tree

2 files changed

+107
-4
lines changed

2 files changed

+107
-4
lines changed

Diff for: src/module/token/transferable/CreatorTokenERC20.sol

+23-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ pragma solidity ^0.8.0;
33

44
import {Module} from "../../../Module.sol";
55
import {Role} from "../../../Role.sol";
6+
67
import {BeforeTransferCallbackERC20} from "../../../callback/BeforeTransferCallbackERC20.sol";
8+
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";
79

810
import {ICreatorToken} from "@limitbreak/creator-token-standards/interfaces/ICreatorToken.sol";
911

@@ -34,21 +36,30 @@ library CreatorTokenStorage {
3436

3537
contract CreatorTokenERC20 is Module, BeforeTransferCallbackERC20, ICreatorToken {
3638

39+
/*//////////////////////////////////////////////////////////////
40+
CONSTANTS
41+
//////////////////////////////////////////////////////////////*/
42+
43+
bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;
44+
3745
/*//////////////////////////////////////////////////////////////
3846
ERRORS
3947
//////////////////////////////////////////////////////////////*/
4048

4149
/// @notice Revert with an error if the transfer validator is not valid
4250
error InvalidTransferValidatorContract();
4351

52+
/// @notice Revert with an error if the transfer validator is not valid
53+
error NotTransferValidator();
54+
4455
/*//////////////////////////////////////////////////////////////
4556
EXTENSION CONFIG
4657
//////////////////////////////////////////////////////////////*/
4758

4859
/// @notice Returns all implemented callback and extension functions.
4960
function getModuleConfig() external pure override returns (ModuleConfig memory config) {
5061
config.callbackFunctions = new CallbackFunction[](1);
51-
config.fallbackFunctions = new FallbackFunction[](3);
62+
config.fallbackFunctions = new FallbackFunction[](4);
5263

5364
config.callbackFunctions[0] = CallbackFunction(this.beforeTransferERC20.selector);
5465

@@ -58,6 +69,7 @@ contract CreatorTokenERC20 is Module, BeforeTransferCallbackERC20, ICreatorToken
5869
FallbackFunction({selector: this.getTransferValidationFunction.selector, permissionBits: 0});
5970
config.fallbackFunctions[2] =
6071
FallbackFunction({selector: this.setTransferValidator.selector, permissionBits: Role._MANAGER_ROLE});
72+
config.fallbackFunctions[3] = FallbackFunction({selector: this.hasRole.selector, permissionBits: 0});
6173
}
6274

6375
/*//////////////////////////////////////////////////////////////
@@ -99,6 +111,16 @@ contract CreatorTokenERC20 is Module, BeforeTransferCallbackERC20, ICreatorToken
99111
_setTransferValidator(validator);
100112
}
101113

114+
function hasRole(bytes32 role, address account) external view returns (bool) {
115+
if (msg.sender != _creatorTokenStorage().transferValidator) {
116+
revert NotTransferValidator();
117+
}
118+
if (role == DEFAULT_ACCESS_CONTROL_ADMIN_ROLE) {
119+
return OwnableRoles(address(this)).hasAllRoles(account, Role._MANAGER_ROLE);
120+
}
121+
return OwnableRoles(address(this)).hasAllRoles(account, uint256(role));
122+
}
123+
102124
/*//////////////////////////////////////////////////////////////
103125
INTERNAL FUNCTIONS
104126
//////////////////////////////////////////////////////////////*/

Diff for: test/module/transferable/CreatorTokenERC20.t.sol

+84-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ contract TransferToken {
3333

3434
}
3535

36+
struct CollectionSecurityPolicyV3 {
37+
bool disableAuthorizationMode;
38+
bool authorizersCannotSetWildcardOperators;
39+
uint8 transferSecurityLevel;
40+
uint120 listId;
41+
bool enableAccountFreezingMode;
42+
uint16 tokenType;
43+
}
44+
45+
interface CreatorTokenTransferValidator is ITransferValidator {
46+
47+
function setTransferSecurityLevelOfCollection(
48+
address collection,
49+
uint8 transferSecurityLevel,
50+
bool isTransferRestricted,
51+
bool isTransferWithRestrictedRecipient,
52+
bool isTransferWithRestrictedToken
53+
) external;
54+
function getCollectionSecurityPolicy(address collection)
55+
external
56+
view
57+
returns (CollectionSecurityPolicyV3 memory);
58+
59+
}
60+
3661
contract CreatorTokenERC20Test is Test {
3762

3863
ERC20Core public core;
@@ -43,7 +68,8 @@ contract CreatorTokenERC20Test is Test {
4368

4469
TransferToken public transferTokenContract;
4570

46-
ITransferValidator public mockTransferValidator;
71+
CreatorTokenTransferValidator public mockTransferValidator;
72+
uint8 TRANSFER_SECURITY_LEVEL_SEVEN = 7;
4773

4874
uint256 ownerPrivateKey = 1;
4975
address public owner;
@@ -120,7 +146,7 @@ contract CreatorTokenERC20Test is Test {
120146
vm.prank(owner);
121147
core.grantRoles(owner, Role._MINTER_ROLE);
122148

123-
mockTransferValidator = ITransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
149+
mockTransferValidator = CreatorTokenTransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
124150
vm.etch(address(mockTransferValidator), TRANSFER_VALIDATOR_DEPLOYED_BYTECODE);
125151
}
126152

@@ -176,7 +202,7 @@ contract CreatorTokenERC20Test is Test {
176202
}
177203
_mintToken();
178204

179-
assertEq(1, core.balanceOf(owner));
205+
assertEq(100, core.balanceOf(owner));
180206

181207
// set transfer validator
182208
vm.prank(owner);
@@ -192,6 +218,61 @@ contract CreatorTokenERC20Test is Test {
192218
assertEq(0, core.balanceOf(permissionedActor));
193219
}
194220

221+
/*///////////////////////////////////////////////////////////////
222+
Unit tests: `setTransferPolicy`
223+
//////////////////////////////////////////////////////////////*/
224+
225+
function test_setTransferSecurityLevel() public {
226+
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
227+
//skip test if evm version is not cancun
228+
return;
229+
}
230+
231+
// set transfer validator
232+
vm.prank(owner);
233+
CreatorTokenERC20(address(core)).setTransferValidator(address(mockTransferValidator));
234+
235+
vm.prank(owner);
236+
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);
237+
238+
vm.prank(permissionedActor);
239+
mockTransferValidator.setTransferSecurityLevelOfCollection(
240+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
241+
);
242+
243+
assertEq(
244+
mockTransferValidator.getCollectionSecurityPolicy(address(core)).transferSecurityLevel,
245+
TRANSFER_SECURITY_LEVEL_SEVEN
246+
);
247+
}
248+
249+
function test_revert_setTransferSecurityLevel() public {
250+
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
251+
//skip test if evm version is not cancun
252+
return;
253+
}
254+
vm.prank(owner);
255+
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);
256+
257+
// revert due to msg.sender not being the transfer validator
258+
vm.expectRevert();
259+
vm.prank(permissionedActor);
260+
mockTransferValidator.setTransferSecurityLevelOfCollection(
261+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
262+
);
263+
264+
// set transfer validator
265+
vm.prank(owner);
266+
CreatorTokenERC20(address(core)).setTransferValidator(address(mockTransferValidator));
267+
268+
// revert due to incorrect permissions
269+
vm.prank(unpermissionedActor);
270+
vm.expectRevert();
271+
mockTransferValidator.setTransferSecurityLevelOfCollection(
272+
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
273+
);
274+
}
275+
195276
function _mintToken() internal {
196277
address saleRecipient = address(0x987);
197278

0 commit comments

Comments
 (0)