Skip to content

Commit

Permalink
Has roles (#158)
Browse files Browse the repository at this point in the history
* created hasRole function in the roylaty module

* created tests
  • Loading branch information
GWSzeto authored Sep 11, 2024
1 parent eb26fd0 commit 3a4d98d
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 18 deletions.
33 changes: 27 additions & 6 deletions src/module/token/royalty/RoyaltyERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
import {Module} from "../../../Module.sol";

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

import {BeforeBatchTransferCallbackERC1155} from "../../../callback/BeforeBatchTransferCallbackERC1155.sol";
import {BeforeTransferCallbackERC1155} from "../../../callback/BeforeTransferCallbackERC1155.sol";
Expand Down Expand Up @@ -48,6 +49,12 @@ contract RoyaltyERC1155 is
ICreatorToken
{

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

bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;

/*//////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -80,7 +87,10 @@ contract RoyaltyERC1155 is
error RoyaltyExceedsMaxBps();

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

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

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

config.callbackFunctions[0] = CallbackFunction(this.beforeTransferERC1155.selector);
config.callbackFunctions[1] = CallbackFunction(this.beforeBatchTransferERC1155.selector);
Expand All @@ -103,11 +113,12 @@ contract RoyaltyERC1155 is
FallbackFunction({selector: this.getTransferValidator.selector, permissionBits: 0});
config.fallbackFunctions[4] =
FallbackFunction({selector: this.getTransferValidationFunction.selector, permissionBits: 0});
config.fallbackFunctions[5] =
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[5] = FallbackFunction({selector: this.hasRole.selector, permissionBits: 0});
config.fallbackFunctions[6] =
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[7] =
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[8] =
FallbackFunction({selector: this.setTransferValidator.selector, permissionBits: Role._MANAGER_ROLE});

config.requiredInterfaces = new bytes4[](1);
Expand Down Expand Up @@ -250,6 +261,16 @@ contract RoyaltyERC1155 is
_setTransferValidator(validator);
}

function hasRole(bytes32 role, address account) external view returns (bool) {
if (msg.sender != _royaltyStorage().transferValidator) {
revert RoyaltyNotTransferValidator();
}
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 All @@ -268,7 +289,7 @@ contract RoyaltyERC1155 is
bool isValidTransferValidator = validator.code.length > 0;

if (validator != address(0) && !isValidTransferValidator) {
revert InvalidTransferValidatorContract();
revert RoyaltyInvalidTransferValidatorContract();
}

emit TransferValidatorUpdated(address(getTransferValidator()), validator);
Expand Down
33 changes: 27 additions & 6 deletions src/module/token/royalty/RoyaltyERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.20;
import {Module} from "../../../Module.sol";

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

import {BeforeTransferCallbackERC721} from "../../../callback/BeforeTransferCallbackERC721.sol";
import {IInstallationCallback} from "../../../interface/IInstallationCallback.sol";
Expand Down Expand Up @@ -41,6 +42,12 @@ library RoyaltyStorage {

contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackERC721, ICreatorToken {

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

bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00;

/*//////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -73,7 +80,10 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
error RoyaltyExceedsMaxBps();

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

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

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

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

Expand All @@ -95,11 +105,12 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
FallbackFunction({selector: this.getTransferValidator.selector, permissionBits: 0});
config.fallbackFunctions[4] =
FallbackFunction({selector: this.getTransferValidationFunction.selector, permissionBits: 0});
config.fallbackFunctions[5] =
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[5] = FallbackFunction({selector: this.hasRole.selector, permissionBits: 0});
config.fallbackFunctions[6] =
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
FallbackFunction({selector: this.setDefaultRoyaltyInfo.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[7] =
FallbackFunction({selector: this.setRoyaltyInfoForToken.selector, permissionBits: Role._MANAGER_ROLE});
config.fallbackFunctions[8] =
FallbackFunction({selector: this.setTransferValidator.selector, permissionBits: Role._MANAGER_ROLE});

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

function hasRole(bytes32 role, address account) external view returns (bool) {
if (msg.sender != _royaltyStorage().transferValidator) {
revert RoyaltyNotTransferValidator();
}
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 All @@ -245,7 +266,7 @@ contract RoyaltyERC721 is Module, IInstallationCallback, BeforeTransferCallbackE
bool isValidTransferValidator = validator.code.length > 0;

if (validator != address(0) && !isValidTransferValidator) {
revert InvalidTransferValidatorContract();
revert RoyaltyInvalidTransferValidatorContract();
}

emit TransferValidatorUpdated(address(getTransferValidator()), validator);
Expand Down
87 changes: 84 additions & 3 deletions test/module/royalty/RoyaltyERC1155.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,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 RoyaltyERC1155Test is Test {

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

MintableERC1155 public mintableModuleImplementation;
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 @@ -133,7 +159,7 @@ contract RoyaltyERC1155Test is Test {
core.grantRoles(owner, Role._MINTER_ROLE);

// set up transfer validator
mockTransferValidator = ITransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
mockTransferValidator = CreatorTokenTransferValidator(0x721C0078c2328597Ca70F5451ffF5A7B38D4E947);
vm.etch(address(mockTransferValidator), TRANSFER_VALIDATOR_DEPLOYED_BYTECODE);
}

Expand Down Expand Up @@ -247,7 +273,7 @@ contract RoyaltyERC1155Test is Test {
function test_revert_setTransferValidator_invalidContract() public {
// attempt to set the transfer validator to an invalid contract
vm.prank(owner);
vm.expectRevert(RoyaltyERC1155.InvalidTransferValidatorContract.selector);
vm.expectRevert(RoyaltyERC1155.RoyaltyInvalidTransferValidatorContract.selector);
RoyaltyERC1155(address(core)).setTransferValidator(address(11_111));
}

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

/*///////////////////////////////////////////////////////////////
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);
RoyaltyERC1155(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);
RoyaltyERC1155(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
);
}

/*///////////////////////////////////////////////////////////////
UTILITY FUNCTIONS
//////////////////////////////////////////////////////////////*/
Expand Down
Loading

0 comments on commit 3a4d98d

Please sign in to comment.