Skip to content

Commit

Permalink
added hasRole to creatorTokenERC20 module (#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
GWSzeto authored Sep 16, 2024
1 parent 5464318 commit 8f45917
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 4 deletions.
24 changes: 23 additions & 1 deletion src/module/token/transferable/CreatorTokenERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pragma solidity ^0.8.0;

import {Module} from "../../../Module.sol";
import {Role} from "../../../Role.sol";

import {BeforeTransferCallbackERC20} from "../../../callback/BeforeTransferCallbackERC20.sol";
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";

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

Expand Down Expand Up @@ -34,21 +36,30 @@ library CreatorTokenStorage {

contract CreatorTokenERC20 is Module, BeforeTransferCallbackERC20, ICreatorToken {

/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/

bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;

/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/

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

/// @notice Revert with an error if the transfer validator is not valid
error NotTransferValidator();

/*//////////////////////////////////////////////////////////////
EXTENSION CONFIG
//////////////////////////////////////////////////////////////*/

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

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

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

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -99,6 +111,16 @@ contract CreatorTokenERC20 is Module, BeforeTransferCallbackERC20, ICreatorToken
_setTransferValidator(validator);
}

function hasRole(bytes32 role, address account) external view returns (bool) {
if (msg.sender != _creatorTokenStorage().transferValidator) {
revert NotTransferValidator();
}
if (role == DEFAULT_ACCESS_CONTROL_ADMIN_ROLE) {
return OwnableRoles(address(this)).hasAllRoles(account, Role._MANAGER_ROLE);
}
return OwnableRoles(address(this)).hasAllRoles(account, uint256(role));
}

/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
Expand Down
87 changes: 84 additions & 3 deletions test/module/transferable/CreatorTokenERC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ contract TransferToken {

}

struct CollectionSecurityPolicyV3 {
bool disableAuthorizationMode;
bool authorizersCannotSetWildcardOperators;
uint8 transferSecurityLevel;
uint120 listId;
bool enableAccountFreezingMode;
uint16 tokenType;
}

interface CreatorTokenTransferValidator is ITransferValidator {

function setTransferSecurityLevelOfCollection(
address collection,
uint8 transferSecurityLevel,
bool isTransferRestricted,
bool isTransferWithRestrictedRecipient,
bool isTransferWithRestrictedToken
) external;
function getCollectionSecurityPolicy(address collection)
external
view
returns (CollectionSecurityPolicyV3 memory);

}

contract CreatorTokenERC20Test is Test {

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

TransferToken public transferTokenContract;

ITransferValidator public mockTransferValidator;
CreatorTokenTransferValidator public mockTransferValidator;
uint8 TRANSFER_SECURITY_LEVEL_SEVEN = 7;

uint256 ownerPrivateKey = 1;
address public owner;
Expand Down Expand Up @@ -120,7 +146,7 @@ contract CreatorTokenERC20Test is Test {
vm.prank(owner);
core.grantRoles(owner, Role._MINTER_ROLE);

mockTransferValidator = ITransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
mockTransferValidator = CreatorTokenTransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
vm.etch(address(mockTransferValidator), TRANSFER_VALIDATOR_DEPLOYED_BYTECODE);
}

Expand Down Expand Up @@ -176,7 +202,7 @@ contract CreatorTokenERC20Test is Test {
}
_mintToken();

assertEq(1, core.balanceOf(owner));
assertEq(100, core.balanceOf(owner));

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

/*///////////////////////////////////////////////////////////////
Unit tests: `setTransferPolicy`
//////////////////////////////////////////////////////////////*/

function test_setTransferSecurityLevel() public {
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
//skip test if evm version is not cancun
return;
}

// set transfer validator
vm.prank(owner);
CreatorTokenERC20(address(core)).setTransferValidator(address(mockTransferValidator));

vm.prank(owner);
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);

vm.prank(permissionedActor);
mockTransferValidator.setTransferSecurityLevelOfCollection(
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
);

assertEq(
mockTransferValidator.getCollectionSecurityPolicy(address(core)).transferSecurityLevel,
TRANSFER_SECURITY_LEVEL_SEVEN
);
}

function test_revert_setTransferSecurityLevel() public {
if (evmVersionHash != keccak256(abi.encode('evm_version = "cancun"'))) {
//skip test if evm version is not cancun
return;
}
vm.prank(owner);
core.grantRoles(permissionedActor, Role._MANAGER_ROLE);

// revert due to msg.sender not being the transfer validator
vm.expectRevert();
vm.prank(permissionedActor);
mockTransferValidator.setTransferSecurityLevelOfCollection(
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
);

// set transfer validator
vm.prank(owner);
CreatorTokenERC20(address(core)).setTransferValidator(address(mockTransferValidator));

// revert due to incorrect permissions
vm.prank(unpermissionedActor);
vm.expectRevert();
mockTransferValidator.setTransferSecurityLevelOfCollection(
address(core), TRANSFER_SECURITY_LEVEL_SEVEN, true, false, false
);
}

function _mintToken() internal {
address saleRecipient = address(0x987);

Expand Down

0 comments on commit 8f45917

Please sign in to comment.