Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Has roles #158

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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