diff --git a/contracts/LicenseToken.sol b/contracts/LicenseToken.sol index 10eeae051..034176e70 100644 --- a/contracts/LicenseToken.sol +++ b/contracts/LicenseToken.sol @@ -6,16 +6,17 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ERC721EnumerableUpgradeable, ERC721Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { ILicenseToken } from "./interfaces/ILicenseToken.sol"; import { ILicensingModule } from "./interfaces/modules/licensing/ILicensingModule.sol"; import { IDisputeModule } from "./interfaces/modules/dispute/IDisputeModule.sol"; import { Errors } from "./lib/Errors.sol"; -import { GovernableUpgradeable } from "./governance/GovernableUpgradeable.sol"; import { ILicenseTemplate } from "./interfaces/modules/licensing/ILicenseTemplate.sol"; /// @title LicenseToken aka LNFT -contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableUpgradeable, UUPSUpgradeable { +contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, AccessManagedUpgradeable, UUPSUpgradeable { using Strings for *; /// @notice Emitted for metadata updates, per EIP-4906 @@ -49,9 +50,9 @@ contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableU } /// @dev Initializes the LicenseToken contract - function initialize(address governance, string memory imageUrl) public initializer { + function initialize(address accessManager, string memory imageUrl) public initializer { __ERC721_init("Programmable IP License Token", "PILicenseToken"); - __GovernableUpgradeable_init(governance); + __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); _getLicenseTokenStorage().imageUrl = imageUrl; } @@ -59,7 +60,7 @@ contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableU /// @notice Sets the LicensingModule address. /// @dev Enforced to be only callable by the protocol admin /// @param newLicensingModule The address of the LicensingModule - function setLicensingModule(address newLicensingModule) external onlyProtocolAdmin { + function setLicensingModule(address newLicensingModule) external restricted { if (newLicensingModule == address(0)) { revert Errors.LicenseToken__ZeroLicensingModule(); } @@ -70,7 +71,7 @@ contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableU /// @notice Sets the DisputeModule address. /// @dev Enforced to be only callable by the protocol admin /// @param newDisputeModule The address of the DisputeModule - function setDisputeModule(address newDisputeModule) external onlyProtocolAdmin { + function setDisputeModule(address newDisputeModule) external restricted { if (newDisputeModule == address(0)) { revert Errors.LicenseToken__ZeroDisputeModule(); } @@ -81,7 +82,7 @@ contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableU /// @dev Sets the Licensing Image URL. /// @dev Enforced to be only callable by the protocol admin /// @param url The URL of the Licensing Image - function setLicensingImageUrl(string calldata url) external onlyProtocolAdmin { + function setLicensingImageUrl(string calldata url) external restricted { LicenseTokenStorage storage $ = _getLicenseTokenStorage(); $.imageUrl = url; emit BatchMetadataUpdate(1, $.totalMintedTokens); @@ -326,5 +327,5 @@ contract LicenseToken is ILicenseToken, ERC721EnumerableUpgradeable, GovernableU /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/access/AccessController.sol b/contracts/access/AccessController.sol index 237a418b1..dbcaa14d1 100644 --- a/contracts/access/AccessController.sol +++ b/contracts/access/AccessController.sol @@ -2,6 +2,8 @@ pragma solidity 0.8.23; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { IAccessController } from "../interfaces/access/IAccessController.sol"; import { IModuleRegistry } from "../interfaces/registries/IModuleRegistry.sol"; @@ -9,7 +11,6 @@ import { IIPAccountRegistry } from "../interfaces/registries/IIPAccountRegistry. import { IModuleRegistry } from "../interfaces/registries/IModuleRegistry.sol"; import { IPAccountChecker } from "../lib/registries/IPAccountChecker.sol"; import { IIPAccount } from "../interfaces/IIPAccount.sol"; -import { GovernableUpgradeable } from "../governance/GovernableUpgradeable.sol"; import { AccessPermission } from "../lib/AccessPermission.sol"; import { Errors } from "../lib/Errors.sol"; @@ -28,7 +29,7 @@ import { Errors } from "../lib/Errors.sol"; /// - setPermission: Sets the permission for a specific function call. /// - getPermission: Returns the permission level for a specific function call. /// - checkPermission: Checks if a specific function call is allowed. -contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgradeable { +contract AccessController is IAccessController, AccessManagedUpgradeable, UUPSUpgradeable { using IPAccountChecker for IIPAccountRegistry; /// @dev The storage struct of AccessController. @@ -54,16 +55,16 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra } /// @notice initializer for this implementation contract - /// @param governance The address of the governance contract - function initialize(address governance) external initializer { - __GovernableUpgradeable_init(governance); + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) external initializer { + __AccessManaged_init(accessManager); } /// @notice Sets the addresses of the IP account registry and the module registry /// @dev TODO: figure out how to set these addresses in the constructor to make them immutable /// @param ipAccountRegistry address of the IP account registry /// @param moduleRegistry address of the module registry - function setAddresses(address ipAccountRegistry, address moduleRegistry) external onlyProtocolAdmin { + function setAddresses(address ipAccountRegistry, address moduleRegistry) external restricted { AccessControllerStorage storage $ = _getAccessControllerStorage(); $.ipAccountRegistry = ipAccountRegistry; $.moduleRegistry = moduleRegistry; @@ -72,7 +73,8 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra /// @notice Sets a batch of permissions in a single transaction. /// @dev This function allows setting multiple permissions at once. Pausable. /// @param permissions An array of `Permission` structs, each representing the permission to be set. - function setBatchPermissions(AccessPermission.Permission[] memory permissions) external whenNotPaused { + function setBatchPermissions(AccessPermission.Permission[] memory permissions) external { + // TODO: removed pause. for (uint256 i = 0; i < permissions.length; ) { setPermission( permissions[i].ipAccount, @@ -93,7 +95,7 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra /// @param to The address that can be called by the `signer` (currently only modules can be `to`) /// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount` /// @param permission The new permission level - function setGlobalPermission(address signer, address to, bytes4 func, uint8 permission) external onlyProtocolAdmin { + function setGlobalPermission(address signer, address to, bytes4 func, uint8 permission) external restricted { if (signer == address(0)) { revert Errors.AccessController__SignerIsZeroAddress(); } @@ -119,13 +121,8 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra /// @param to The address that can be called by the `signer` (currently only modules can be `to`) /// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount` /// @param permission The new permission level - function setPermission( - address ipAccount, - address signer, - address to, - bytes4 func, - uint8 permission - ) public whenNotPaused { + function setPermission(address ipAccount, address signer, address to, bytes4 func, uint8 permission) public { + // TODO: Reintroduce pause // IPAccount and signer does not support wildcard permission if (ipAccount == address(0)) { revert Errors.AccessController__IPAccountIsZeroAddress(); @@ -159,7 +156,7 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra /// @param to The address that can be called by the `signer` (currently only modules can be `to`) /// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount` // solhint-disable code-complexity - function checkPermission(address ipAccount, address signer, address to, bytes4 func) external view whenNotPaused { + function checkPermission(address ipAccount, address signer, address to, bytes4 func) external view { // The ipAccount is restricted to interact exclusively with registered modules. // This includes initiating calls to these modules and receiving calls from them. // Additionally, it can modify Permissions settings. @@ -246,7 +243,7 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra } } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/governance/Governable.sol b/contracts/governance/Governable.sol deleted file mode 100644 index ab6649dd5..000000000 --- a/contracts/governance/Governable.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; - -import { Errors } from "../lib/Errors.sol"; -import { IGovernance } from "../interfaces/governance/IGovernance.sol"; -import { IGovernable } from "../interfaces/governance/IGovernable.sol"; -import { GovernanceLib } from "../lib/GovernanceLib.sol"; - -/// @title Governable -/// @dev All contracts managed by governance should inherit from this contract. -abstract contract Governable is IGovernable { - /// @notice The address of the governance. - address public governance; - - /// @dev Ensures that the function is called by the protocol admin. - modifier onlyProtocolAdmin() { - if (!IGovernance(governance).hasRole(GovernanceLib.PROTOCOL_ADMIN, msg.sender)) { - revert Errors.Governance__OnlyProtocolAdmin(); - } - _; - } - - modifier whenNotPaused() { - if (IGovernance(governance).getState() == GovernanceLib.ProtocolState.Paused) { - revert Errors.Governance__ProtocolPaused(); - } - _; - } - - /// @notice Constructs a new Governable contract. - /// @param governance_ The address of the governance. - constructor(address governance_) { - if (governance_ == address(0)) revert Errors.Governance__ZeroAddress(); - governance = governance_; - emit GovernanceUpdated(governance); - } - - /// @notice Sets a new governance address. - /// @param newGovernance The address of the new governance. - function setGovernance(address newGovernance) external onlyProtocolAdmin { - if (newGovernance == address(0)) revert Errors.Governance__ZeroAddress(); - if (!ERC165Checker.supportsInterface(newGovernance, type(IGovernance).interfaceId)) - revert Errors.Governance__UnsupportedInterface("IGovernance"); - if (IGovernance(newGovernance).getState() != IGovernance(governance).getState()) - revert Errors.Governance__InconsistentState(); - governance = newGovernance; - emit GovernanceUpdated(newGovernance); - } - - /// @notice Returns the current governance address. - /// @return governance The address of the current governance. - function getGovernance() external view returns (address) { - return governance; - } -} diff --git a/contracts/governance/GovernableUpgradeable.sol b/contracts/governance/GovernableUpgradeable.sol deleted file mode 100644 index 74900340c..000000000 --- a/contracts/governance/GovernableUpgradeable.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - -import { Errors } from "../lib/Errors.sol"; -import { IGovernance } from "../interfaces/governance/IGovernance.sol"; -import { IGovernable } from "../interfaces/governance/IGovernable.sol"; -import { GovernanceLib } from "../lib/GovernanceLib.sol"; - -/// @title Governable -/// @dev All contracts managed by governance should inherit from this contract. -abstract contract GovernableUpgradeable is IGovernable, Initializable { - /// @dev Storage for GovernableUpgradeable - /// @param governance The address of the governance. - /// @custom:storage-location erc7201:story-protocol.GovernableUpgradeable - struct GovernableUpgradeableStorage { - address governance; - } - - // keccak256(abi.encode(uint256(keccak256("story-protocol.GovernableUpgradeable")) - 1)) & ~bytes32(uint256(0xff)); - bytes32 private constant GovernableUpgradeableStorageLocation = - 0xaed547d8331715caab0800583ca79170ef3186de64f009413517d98c5b905c00; - - /// @dev Ensures that the function is called by the protocol admin. - modifier onlyProtocolAdmin() { - GovernableUpgradeableStorage storage $ = _getGovernableUpgradeableStorage(); - if (!IGovernance($.governance).hasRole(GovernanceLib.PROTOCOL_ADMIN, msg.sender)) { - revert Errors.Governance__OnlyProtocolAdmin(); - } - _; - } - - modifier whenNotPaused() { - GovernableUpgradeableStorage storage $ = _getGovernableUpgradeableStorage(); - if (IGovernance($.governance).getState() == GovernanceLib.ProtocolState.Paused) { - revert Errors.Governance__ProtocolPaused(); - } - _; - } - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - /// @notice initializer for this implementation contract - /// @param governance_ The address of the governance. - function __GovernableUpgradeable_init(address governance_) internal onlyInitializing { - if (governance_ == address(0)) revert Errors.Governance__ZeroAddress(); - _getGovernableUpgradeableStorage().governance = governance_; - emit GovernanceUpdated(governance_); - } - - /// @notice Sets a new governance address. - /// @param newGovernance The address of the new governance. - function setGovernance(address newGovernance) external onlyProtocolAdmin { - GovernableUpgradeableStorage storage $ = _getGovernableUpgradeableStorage(); - - if (newGovernance == address(0)) revert Errors.Governance__ZeroAddress(); - if (!ERC165Checker.supportsInterface(newGovernance, type(IGovernance).interfaceId)) - revert Errors.Governance__UnsupportedInterface("IGovernance"); - if (IGovernance(newGovernance).getState() != IGovernance($.governance).getState()) - revert Errors.Governance__InconsistentState(); - $.governance = newGovernance; - emit GovernanceUpdated(newGovernance); - } - - /// @notice Returns the current governance address. - /// @return governance The address of the current governance. - function getGovernance() external view returns (address) { - return _getGovernableUpgradeableStorage().governance; - } - - function _getGovernableUpgradeableStorage() private pure returns (GovernableUpgradeableStorage storage $) { - assembly { - $.slot := GovernableUpgradeableStorageLocation - } - } -} diff --git a/contracts/governance/Governance.sol b/contracts/governance/Governance.sol deleted file mode 100644 index 3eede8d03..000000000 --- a/contracts/governance/Governance.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol"; - -import { Errors } from "../lib/Errors.sol"; -import { IGovernance } from "../interfaces/governance/IGovernance.sol"; -import { GovernanceLib } from "../lib/GovernanceLib.sol"; - -/// @title Governance -/// @dev This contract is used for governance of the protocol. -/// TODO: Replace with OZ's 2StepOwnable -contract Governance is AccessControl, IGovernance { - /// @dev The current governance state. - GovernanceLib.ProtocolState internal state; - - /// @notice Creates a new Governance contract. - /// @param admin The address of the initial admin. - constructor(address admin) { - if (admin == address(0)) revert Errors.Governance__ZeroAddress(); - _grantRole(GovernanceLib.PROTOCOL_ADMIN, admin); - } - - /// @notice Sets the state of the protocol - /// @dev This function can only be called by an account with the appropriate role - /// @param newState The new state to set for the protocol - function setState(GovernanceLib.ProtocolState newState) external override { - if (!hasRole(GovernanceLib.PROTOCOL_ADMIN, msg.sender)) revert Errors.Governance__OnlyProtocolAdmin(); - if (newState == state) revert Errors.Governance__NewStateIsTheSameWithOldState(); - emit StateSet(msg.sender, state, newState, block.timestamp); - state = newState; - } - - /// @notice Returns the current state of the protocol - /// @return state The current state of the protocol - function getState() external view override returns (GovernanceLib.ProtocolState) { - return state; - } - - /// @notice IERC165 interface support. - function supportsInterface(bytes4 interfaceId) public view override returns (bool) { - return (interfaceId == type(IGovernance).interfaceId || super.supportsInterface(interfaceId)); - } -} diff --git a/contracts/interfaces/governance/IGovernable.sol b/contracts/interfaces/governance/IGovernable.sol deleted file mode 100644 index 14e060696..000000000 --- a/contracts/interfaces/governance/IGovernable.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -/// @title IGovernable -/// @notice This is the interface for the Lens Protocol main governance functions. -interface IGovernable { - /// @notice Emitted when the governance is updated - /// @param newGovernance The address of the new governance - event GovernanceUpdated(address indexed newGovernance); - - /// @notice Sets the governance address - /// @param newGovernance The address of the new governance - function setGovernance(address newGovernance) external; - - /// @notice Returns the current governance address - /// @return The address of the current governance - function getGovernance() external view returns (address); -} diff --git a/contracts/interfaces/governance/IGovernance.sol b/contracts/interfaces/governance/IGovernance.sol deleted file mode 100644 index e7519f53d..000000000 --- a/contracts/interfaces/governance/IGovernance.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol"; - -import { GovernanceLib } from "../../lib/GovernanceLib.sol"; - -/// @title IGovernance -/// @dev This interface defines the governance functionality for the protocol. -interface IGovernance is IAccessControl { - /// @notice Emitted when the protocol state is set - /// @param account The address that triggered the state change - /// @param prevState The previous state of the protocol - /// @param newState The new state of the protocol - /// @param timestamp The time when the state change occurred - event StateSet( - address indexed account, - GovernanceLib.ProtocolState prevState, - GovernanceLib.ProtocolState newState, - uint256 timestamp - ); - - /// @notice Sets the state of the protocol - /// @dev This function can only be called by an account with the appropriate role - /// @param newState The new state to set for the protocol - function setState(GovernanceLib.ProtocolState newState) external; - - /// @notice Returns the current state of the protocol - /// @return state The current state of the protocol - function getState() external view returns (GovernanceLib.ProtocolState); -} diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index d72f2516a..e4cb47906 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -4,16 +4,6 @@ pragma solidity 0.8.23; /// @title Errors Library /// @notice Library for all Story Protocol contract errors. library Errors { - //////////////////////////////////////////////////////////////////////////// - // Governance // - //////////////////////////////////////////////////////////////////////////// - error Governance__OnlyProtocolAdmin(); - error Governance__ZeroAddress(); - error Governance__ProtocolPaused(); - error Governance__InconsistentState(); - error Governance__NewStateIsTheSameWithOldState(); - error Governance__UnsupportedInterface(string interfaceName); - //////////////////////////////////////////////////////////////////////////// // IPAccount // //////////////////////////////////////////////////////////////////////////// diff --git a/contracts/lib/GovernanceLib.sol b/contracts/lib/GovernanceLib.sol deleted file mode 100644 index c1faba949..000000000 --- a/contracts/lib/GovernanceLib.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -/// @title Governance -/// @dev This library provides types for Story Protocol Governance. -library GovernanceLib { - bytes32 public constant PROTOCOL_ADMIN = bytes32(0); - - /// @notice An enum containing the different states the protocol can be in. - /// @param Unpaused The unpaused state. - /// @param Paused The paused state. - enum ProtocolState { - Unpaused, - Paused - } -} diff --git a/contracts/lib/ProtocolAdmin.sol b/contracts/lib/ProtocolAdmin.sol new file mode 100644 index 000000000..020a21245 --- /dev/null +++ b/contracts/lib/ProtocolAdmin.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.23; + +/// @title ProtocolAdmin +/// @dev This library provides roles and utils to configure protocol AccessManager +library ProtocolAdmin { + /// @notice Protocol admin role, as it is used in AccessManager. + /// Root admin role, grants all roles. + uint64 public constant PROTOCOL_ADMIN_ROLE = type(uint64).min; // 0 + string public constant PROTOCOL_ADMIN_ROLE_LABEL = "PROTOCOL_ADMIN_ROLE"; + /// @notice Public role, as it is used in AccessManager + uint64 public constant PUBLIC_ROLE = type(uint64).max; // 2**64-1 + /// @notice Upgrader role, as it is used in AccessManager + uint64 public constant UPGRADER_ROLE = 1; + string public constant UPGRADER_ROLE_LABEL = "UPGRADER_ROLE"; +} diff --git a/contracts/modules/dispute/DisputeModule.sol b/contracts/modules/dispute/DisputeModule.sol index e99c40805..feb22ae1d 100644 --- a/contracts/modules/dispute/DisputeModule.sol +++ b/contracts/modules/dispute/DisputeModule.sol @@ -4,10 +4,11 @@ pragma solidity 0.8.23; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { DISPUTE_MODULE_KEY } from "../../lib/modules/Module.sol"; import { BaseModule } from "../../modules/BaseModule.sol"; -import { GovernableUpgradeable } from "../../governance/GovernableUpgradeable.sol"; import { AccessControlled } from "../../access/AccessControlled.sol"; import { IIPAssetRegistry } from "../../interfaces/registries/IIPAssetRegistry.sol"; import { IDisputeModule } from "../../interfaces/modules/dispute/IDisputeModule.sol"; @@ -21,7 +22,7 @@ import { ShortStringOps } from "../../utils/ShortStringOps.sol"; contract DisputeModule is IDisputeModule, BaseModule, - GovernableUpgradeable, + AccessManagedUpgradeable, ReentrancyGuardUpgradeable, AccessControlled, UUPSUpgradeable @@ -73,9 +74,9 @@ contract DisputeModule is } /// @notice initializer for this implementation contract - /// @param _governance The address of the governance contract - function initialize(address _governance) external initializer { - __GovernableUpgradeable_init(_governance); + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) external initializer { + __AccessManaged_init(accessManager); __ReentrancyGuard_init(); __UUPSUpgradeable_init(); } @@ -83,7 +84,7 @@ contract DisputeModule is /// @notice Whitelists a dispute tag /// @param tag The dispute tag /// @param allowed Indicates if the dispute tag is whitelisted or not - function whitelistDisputeTag(bytes32 tag, bool allowed) external onlyProtocolAdmin { + function whitelistDisputeTag(bytes32 tag, bool allowed) external restricted { if (tag == bytes32(0)) revert Errors.DisputeModule__ZeroDisputeTag(); DisputeModuleStorage storage $ = _getDisputeModuleStorage(); @@ -95,7 +96,7 @@ contract DisputeModule is /// @notice Whitelists an arbitration policy /// @param arbitrationPolicy The address of the arbitration policy /// @param allowed Indicates if the arbitration policy is whitelisted or not - function whitelistArbitrationPolicy(address arbitrationPolicy, bool allowed) external onlyProtocolAdmin { + function whitelistArbitrationPolicy(address arbitrationPolicy, bool allowed) external restricted { if (arbitrationPolicy == address(0)) revert Errors.DisputeModule__ZeroArbitrationPolicy(); DisputeModuleStorage storage $ = _getDisputeModuleStorage(); @@ -112,7 +113,7 @@ contract DisputeModule is address arbitrationPolicy, address arbPolicyRelayer, bool allowed - ) external onlyProtocolAdmin { + ) external restricted { if (arbitrationPolicy == address(0)) revert Errors.DisputeModule__ZeroArbitrationPolicy(); if (arbPolicyRelayer == address(0)) revert Errors.DisputeModule__ZeroArbitrationRelayer(); @@ -124,7 +125,7 @@ contract DisputeModule is /// @notice Sets the base arbitration policy /// @param arbitrationPolicy The address of the arbitration policy - function setBaseArbitrationPolicy(address arbitrationPolicy) external onlyProtocolAdmin { + function setBaseArbitrationPolicy(address arbitrationPolicy) external restricted { DisputeModuleStorage storage $ = _getDisputeModuleStorage(); if (!$.isWhitelistedArbitrationPolicy[arbitrationPolicy]) revert Errors.DisputeModule__NotWhitelistedArbitrationPolicy(); @@ -343,9 +344,9 @@ contract DisputeModule is return $.arbitrationPolicies[ipId]; } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} /// @dev Returns the storage struct of DisputeModule. function _getDisputeModuleStorage() private pure returns (DisputeModuleStorage storage $) { diff --git a/contracts/modules/dispute/policies/ArbitrationPolicySP.sol b/contracts/modules/dispute/policies/ArbitrationPolicySP.sol index 91b5db419..e4db914c3 100644 --- a/contracts/modules/dispute/policies/ArbitrationPolicySP.sol +++ b/contracts/modules/dispute/policies/ArbitrationPolicySP.sol @@ -4,8 +4,9 @@ pragma solidity 0.8.23; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; -import { GovernableUpgradeable } from "../../../governance/GovernableUpgradeable.sol"; import { IDisputeModule } from "../../../interfaces/modules/dispute/IDisputeModule.sol"; import { IArbitrationPolicy } from "../../../interfaces/modules/dispute/policies/IArbitrationPolicy.sol"; import { Errors } from "../../../lib/Errors.sol"; @@ -13,7 +14,7 @@ import { Errors } from "../../../lib/Errors.sol"; /// @title Story Protocol Arbitration Policy /// @notice The Story Protocol arbitration policy is a simple policy that requires the dispute initiator to pay a fixed /// amount of tokens to raise a dispute and refunds that amount if the dispute initiator wins the dispute. -contract ArbitrationPolicySP is IArbitrationPolicy, GovernableUpgradeable, UUPSUpgradeable { +contract ArbitrationPolicySP is IArbitrationPolicy, AccessManagedUpgradeable, UUPSUpgradeable { using SafeERC20 for IERC20; /// @notice Returns the dispute module address @@ -47,9 +48,9 @@ contract ArbitrationPolicySP is IArbitrationPolicy, GovernableUpgradeable, UUPSU } /// @notice initializer for this implementation contract - /// @param governance The address of the governance contract - function initialize(address governance) public initializer { - __GovernableUpgradeable_init(governance); + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) public initializer { + __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); } @@ -83,14 +84,14 @@ contract ArbitrationPolicySP is IArbitrationPolicy, GovernableUpgradeable, UUPSU /// @notice Allows governance address to withdraw /// @dev Enforced to be only callable by the governance protocol admin. - function governanceWithdraw() external onlyProtocolAdmin { + function governanceWithdraw() external restricted { uint256 balance = IERC20(PAYMENT_TOKEN).balanceOf(address(this)); IERC20(PAYMENT_TOKEN).safeTransfer(msg.sender, balance); emit GovernanceWithdrew(balance); } - /// @notice Hook that is called before any upgrade - /// @param newImplementation Address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable + /// @param newImplementation The address of the new implementation + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/modules/licensing/LicensingModule.sol b/contracts/modules/licensing/LicensingModule.sol index c3f58906d..5e25ac574 100644 --- a/contracts/modules/licensing/LicensingModule.sol +++ b/contracts/modules/licensing/LicensingModule.sol @@ -7,6 +7,8 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { IIPAccount } from "../../interfaces/IIPAccount.sol"; import { IModule } from "../../interfaces/modules/base/IModule.sol"; @@ -21,7 +23,6 @@ import { RoyaltyModule } from "../../modules/royalty/RoyaltyModule.sol"; import { AccessControlled } from "../../access/AccessControlled.sol"; import { LICENSING_MODULE_KEY } from "../../lib/modules/Module.sol"; import { BaseModule } from "../BaseModule.sol"; -import { GovernableUpgradeable } from "../../governance/GovernableUpgradeable.sol"; import { ILicenseTemplate } from "contracts/interfaces/modules/licensing/ILicenseTemplate.sol"; import { IMintingFeeModule } from "contracts/interfaces/modules/licensing/IMintingFeeModule.sol"; import { IPAccountStorageOps } from "../../lib/IPAccountStorageOps.sol"; @@ -38,7 +39,7 @@ contract LicensingModule is ILicensingModule, BaseModule, ReentrancyGuardUpgradeable, - GovernableUpgradeable, + AccessManagedUpgradeable, UUPSUpgradeable { using ERC165Checker for address; @@ -94,11 +95,11 @@ contract LicensingModule is } /// @notice initializer for this implementation contract - /// @param governance The address of the governance contract - function initialize(address governance) public initializer { + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) public initializer { __ReentrancyGuard_init(); __UUPSUpgradeable_init(); - __GovernableUpgradeable_init(governance); + __AccessManaged_init(accessManager); } /// @notice Attaches license terms to an IP. @@ -448,7 +449,7 @@ contract LicensingModule is } } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/modules/royalty/RoyaltyModule.sol b/contracts/modules/royalty/RoyaltyModule.sol index 257c73d34..cd5f9416e 100644 --- a/contracts/modules/royalty/RoyaltyModule.sol +++ b/contracts/modules/royalty/RoyaltyModule.sol @@ -5,9 +5,10 @@ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { BaseModule } from "../BaseModule.sol"; -import { GovernableUpgradeable } from "../../governance/GovernableUpgradeable.sol"; import { IRoyaltyModule } from "../../interfaces/modules/royalty/IRoyaltyModule.sol"; import { IRoyaltyPolicy } from "../../interfaces/modules/royalty/policies/IRoyaltyPolicy.sol"; import { IDisputeModule } from "../../interfaces/modules/dispute/IDisputeModule.sol"; @@ -20,7 +21,7 @@ import { BaseModule } from "../BaseModule.sol"; /// derivative IP. contract RoyaltyModule is IRoyaltyModule, - GovernableUpgradeable, + AccessManagedUpgradeable, ReentrancyGuardUpgradeable, BaseModule, UUPSUpgradeable @@ -55,9 +56,9 @@ contract RoyaltyModule is } /// @notice initializer for this implementation contract - /// @param _governance The address of the governance contract - function initialize(address _governance) external initializer { - __GovernableUpgradeable_init(_governance); + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) external initializer { + __AccessManaged_init(accessManager); __ReentrancyGuard_init(); __UUPSUpgradeable_init(); } @@ -72,7 +73,7 @@ contract RoyaltyModule is /// @notice Sets the licensing module /// @dev Enforced to be only callable by the protocol admin /// @param licensing The address of the license module - function setLicensingModule(address licensing) external onlyProtocolAdmin { + function setLicensingModule(address licensing) external restricted { if (licensing == address(0)) revert Errors.RoyaltyModule__ZeroLicensingModule(); _getRoyaltyModuleStorage().licensingModule = licensing; } @@ -80,7 +81,7 @@ contract RoyaltyModule is /// @notice Sets the dispute module /// @dev Enforced to be only callable by the protocol admin /// @param dispute The address of the dispute module - function setDisputeModule(address dispute) external onlyProtocolAdmin { + function setDisputeModule(address dispute) external restricted { if (dispute == address(0)) revert Errors.RoyaltyModule__ZeroDisputeModule(); _getRoyaltyModuleStorage().disputeModule = dispute; } @@ -89,7 +90,7 @@ contract RoyaltyModule is /// @dev Enforced to be only callable by the protocol admin /// @param royaltyPolicy The address of the royalty policy /// @param allowed Indicates if the royalty policy is whitelisted or not - function whitelistRoyaltyPolicy(address royaltyPolicy, bool allowed) external onlyProtocolAdmin { + function whitelistRoyaltyPolicy(address royaltyPolicy, bool allowed) external restricted { if (royaltyPolicy == address(0)) revert Errors.RoyaltyModule__ZeroRoyaltyPolicy(); RoyaltyModuleStorage storage $ = _getRoyaltyModuleStorage(); @@ -102,7 +103,7 @@ contract RoyaltyModule is /// @dev Enforced to be only callable by the protocol admin /// @param token The token address /// @param allowed Indicates if the token is whitelisted or not - function whitelistRoyaltyToken(address token, bool allowed) external onlyProtocolAdmin { + function whitelistRoyaltyToken(address token, bool allowed) external restricted { if (token == address(0)) revert Errors.RoyaltyModule__ZeroRoyaltyToken(); RoyaltyModuleStorage storage $ = _getRoyaltyModuleStorage(); @@ -263,9 +264,9 @@ contract RoyaltyModule is return interfaceId == type(IRoyaltyModule).interfaceId || super.supportsInterface(interfaceId); } - /// @notice Hook that is called before any upgrade for authorization - /// @param newImplementation Address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable + /// @param newImplementation The address of the new implementation + function _authorizeUpgrade(address newImplementation) internal override restricted {} /// @dev Returns the storage struct of RoyaltyModule. function _getRoyaltyModuleStorage() private pure returns (RoyaltyModuleStorage storage $) { diff --git a/contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol b/contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol index 32240c1fb..55cf17c3d 100644 --- a/contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol +++ b/contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol @@ -6,16 +6,17 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { BeaconProxy } from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { IIpRoyaltyVault } from "../../../interfaces/modules/royalty/policies/IIpRoyaltyVault.sol"; -import { GovernableUpgradeable } from "../../../../contracts/governance/GovernableUpgradeable.sol"; import { IRoyaltyPolicyLAP } from "../../../interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; import { ArrayUtils } from "../../../lib/ArrayUtils.sol"; import { Errors } from "../../../lib/Errors.sol"; /// @title Liquid Absolute Percentage Royalty Policy /// @notice Defines the logic for splitting royalties for a given ipId using a liquid absolute percentage mechanism -contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { +contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, AccessManagedUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { using SafeERC20 for IERC20; /// @dev Storage structure for the RoyaltyPolicyLAP @@ -73,7 +74,7 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, Reentranc /// @notice Initializer for this implementation contract /// @param governance The governance address function initialize(address governance) external initializer { - __GovernableUpgradeable_init(governance); + __AccessManaged_init(governance); __ReentrancyGuard_init(); __UUPSUpgradeable_init(); } @@ -81,7 +82,7 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, Reentranc /// @dev Set the snapshot interval /// @dev Enforced to be only callable by the protocol admin in governance /// @param timestampInterval The minimum timestamp interval between snapshots - function setSnapshotInterval(uint256 timestampInterval) public onlyProtocolAdmin { + function setSnapshotInterval(uint256 timestampInterval) public restricted { RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); $.snapshotInterval = timestampInterval; } @@ -89,7 +90,7 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, Reentranc /// @dev Set the ip royalty vault beacon /// @dev Enforced to be only callable by the protocol admin in governance /// @param beacon The ip royalty vault beacon address - function setIpRoyaltyVaultBeacon(address beacon) public onlyProtocolAdmin { + function setIpRoyaltyVaultBeacon(address beacon) public restricted { if (beacon == address(0)) revert Errors.RoyaltyPolicyLAP__ZeroIpRoyaltyVaultBeacon(); RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); $.ipRoyaltyVaultBeacon = beacon; @@ -349,7 +350,7 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, Reentranc } } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/registries/IPAssetRegistry.sol b/contracts/registries/IPAssetRegistry.sol index 4e6ee69e6..807dca896 100644 --- a/contracts/registries/IPAssetRegistry.sol +++ b/contracts/registries/IPAssetRegistry.sol @@ -10,7 +10,6 @@ import { IIPAccount } from "../interfaces/IIPAccount.sol"; import { IIPAssetRegistry } from "../interfaces/registries/IIPAssetRegistry.sol"; import { IPAccountRegistry } from "../registries/IPAccountRegistry.sol"; import { Errors } from "../lib/Errors.sol"; -import { Governable } from "../governance/Governable.sol"; import { IPAccountStorageOps } from "../lib/IPAccountStorageOps.sol"; /// @title IP Asset Registry @@ -22,7 +21,7 @@ import { IPAccountStorageOps } from "../lib/IPAccountStorageOps.sol"; /// attribution and an IP account for protocol authorization. /// IMPORTANT: The IP account address, besides being used for protocol /// auth, is also the canonical IP identifier for the IP NFT. -contract IPAssetRegistry is IIPAssetRegistry, IPAccountRegistry, Governable { +contract IPAssetRegistry is IIPAssetRegistry, IPAccountRegistry { using ERC165Checker for address; using Strings for *; using IPAccountStorageOps for IIPAccount; @@ -30,11 +29,7 @@ contract IPAssetRegistry is IIPAssetRegistry, IPAccountRegistry, Governable { /// @notice Tracks the total number of IP assets in existence. uint256 public totalSupply = 0; - constructor( - address erc6551Registry, - address ipAccountImpl, - address governance - ) IPAccountRegistry(erc6551Registry, ipAccountImpl) Governable(governance) {} + constructor(address erc6551Registry, address ipAccountImpl) IPAccountRegistry(erc6551Registry, ipAccountImpl) {} /// @notice Registers an NFT as an IP asset. /// @dev The IP required metadata name and URI are derived from the NFT's metadata. diff --git a/contracts/registries/LicenseRegistry.sol b/contracts/registries/LicenseRegistry.sol index 2bde58efa..611fc0ffc 100644 --- a/contracts/registries/LicenseRegistry.sol +++ b/contracts/registries/LicenseRegistry.sol @@ -6,20 +6,21 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { ILicenseRegistry } from "../interfaces/registries/ILicenseRegistry.sol"; import { ILicensingModule } from "../interfaces/modules/licensing/ILicensingModule.sol"; import { IDisputeModule } from "../interfaces/modules/dispute/IDisputeModule.sol"; import { Errors } from "../lib/Errors.sol"; import { Licensing } from "../lib/Licensing.sol"; -import { GovernableUpgradeable } from "../governance/GovernableUpgradeable.sol"; import { ILicenseTemplate } from "../interfaces/modules/licensing/ILicenseTemplate.sol"; import { IPAccountStorageOps } from "../lib/IPAccountStorageOps.sol"; import { IIPAccount } from "../interfaces/IIPAccount.sol"; /// @title LicenseRegistry aka LNFT /// @notice Registry of License NFTs, which represent licenses granted by IP ID licensors to create derivative IPs. -contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgradeable { +contract LicenseRegistry is ILicenseRegistry, AccessManagedUpgradeable, UUPSUpgradeable { using Strings for *; using ERC165Checker for address; using EnumerableSet for EnumerableSet.UintSet; @@ -77,16 +78,16 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade } /// @notice initializer for this implementation contract - /// @param governance The address of the governance contract - function initialize(address governance) public initializer { - __GovernableUpgradeable_init(governance); + /// @param accessManager The address of the protocol admin roles contract + function initialize(address accessManager) public initializer { + __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); } /// @dev Sets the DisputeModule address. /// @dev Enforced to be only callable by the protocol admin /// @param newDisputeModule The address of the DisputeModule - function setDisputeModule(address newDisputeModule) external onlyProtocolAdmin { + function setDisputeModule(address newDisputeModule) external restricted { if (newDisputeModule == address(0)) { revert Errors.LicenseRegistry__ZeroDisputeModule(); } @@ -97,7 +98,7 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade /// @dev Sets the LicensingModule address. /// @dev Enforced to be only callable by the protocol admin /// @param newLicensingModule The address of the LicensingModule - function setLicensingModule(address newLicensingModule) external onlyProtocolAdmin { + function setLicensingModule(address newLicensingModule) external restricted { if (newLicensingModule == address(0)) { revert Errors.LicenseRegistry__ZeroLicensingModule(); } @@ -108,7 +109,7 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade /// @notice Sets the default license terms that are attached to all IPs by default. /// @param newLicenseTemplate The address of the new default license template. /// @param newLicenseTermsId The ID of the new default license terms. - function setDefaultLicenseTerms(address newLicenseTemplate, uint256 newLicenseTermsId) external onlyProtocolAdmin { + function setDefaultLicenseTerms(address newLicenseTemplate, uint256 newLicenseTermsId) external restricted { LicenseRegistryStorage storage $ = _getLicenseRegistryStorage(); $.defaultLicenseTemplate = newLicenseTemplate; $.defaultLicenseTermsId = newLicenseTermsId; @@ -116,7 +117,7 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade /// @notice Registers a new license template in the Story Protocol. /// @param licenseTemplate The address of the license template to register. - function registerLicenseTemplate(address licenseTemplate) external onlyProtocolAdmin { + function registerLicenseTemplate(address licenseTemplate) external restricted { if (!licenseTemplate.supportsInterface(type(ILicenseTemplate).interfaceId)) { revert Errors.LicenseRegistry__NotLicenseTemplate(licenseTemplate); } @@ -505,7 +506,7 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade } } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/registries/ModuleRegistry.sol b/contracts/registries/ModuleRegistry.sol index 9e02adb44..ecdb67cfa 100644 --- a/contracts/registries/ModuleRegistry.sol +++ b/contracts/registries/ModuleRegistry.sol @@ -4,17 +4,17 @@ pragma solidity 0.8.23; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +// solhint-disable-next-line max-line-length +import { AccessManagedUpgradeable } from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; import { IModuleRegistry } from "../interfaces/registries/IModuleRegistry.sol"; import { Errors } from "../lib/Errors.sol"; import { IModule } from "../interfaces/modules/base/IModule.sol"; -import { GovernableUpgradeable } from "../governance/GovernableUpgradeable.sol"; - import { MODULE_TYPE_DEFAULT } from "../lib/modules/Module.sol"; /// @title ModuleRegistry /// @notice This contract is used to register and track modules in the protocol. -contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeable { +contract ModuleRegistry is IModuleRegistry, AccessManagedUpgradeable, UUPSUpgradeable { using Strings for *; using ERC165Checker for address; @@ -39,9 +39,9 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab } /// @notice initializer for this implementation contract - /// @param governance_ The address of the governance. - function initialize(address governance_) public initializer { - __GovernableUpgradeable_init(governance_); + /// @param accessManager The address of the governance. + function initialize(address accessManager) public initializer { + __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); // Register the default module types @@ -52,7 +52,7 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab /// @dev Enforced to be only callable by the protocol admin in governance. /// @param name The name of the module type to be registered. /// @param interfaceId The interface ID associated with the module type. - function registerModuleType(string memory name, bytes4 interfaceId) external override onlyProtocolAdmin { + function registerModuleType(string memory name, bytes4 interfaceId) external override restricted { ModuleRegistryStorage storage $ = _getModuleRegistryStorage(); if (interfaceId == 0) { revert Errors.ModuleRegistry__InterfaceIdZero(); @@ -69,7 +69,7 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab /// @notice Removes a module type from the registry. /// @dev Enforced to be only callable by the protocol admin in governance. /// @param name The name of the module type to be removed. - function removeModuleType(string memory name) external override onlyProtocolAdmin { + function removeModuleType(string memory name) external override restricted { if (bytes(name).length == 0) { revert Errors.ModuleRegistry__NameEmptyString(); } @@ -84,7 +84,7 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab /// @dev Enforced to be only callable by the protocol admin in governance. /// @param name The name of the module. /// @param moduleAddress The address of the module. - function registerModule(string memory name, address moduleAddress) external onlyProtocolAdmin { + function registerModule(string memory name, address moduleAddress) external restricted { _registerModule(name, moduleAddress, MODULE_TYPE_DEFAULT); } @@ -92,18 +92,14 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab /// @param name The name of the module to be registered. /// @param moduleAddress The address of the module. /// @param moduleType The type of the module being registered. - function registerModule( - string memory name, - address moduleAddress, - string memory moduleType - ) external onlyProtocolAdmin { + function registerModule(string memory name, address moduleAddress, string memory moduleType) external restricted { _registerModule(name, moduleAddress, moduleType); } /// @notice Removes a module from the registry. /// @dev Enforced to be only callable by the protocol admin in governance. /// @param name The name of the module. - function removeModule(string memory name) external onlyProtocolAdmin { + function removeModule(string memory name) external restricted { if (bytes(name).length == 0) { revert Errors.ModuleRegistry__NameEmptyString(); } @@ -193,7 +189,7 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab } } - /// @dev Hook to authorize the upgrade according to UUPSUgradeable + /// @dev Hook to authorize the upgrade according to UUPSUpgradeable /// @param newImplementation The address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/script/foundry/deployment/Main.s.sol b/script/foundry/deployment/Main.s.sol index 317730d98..8c8f6a880 100644 --- a/script/foundry/deployment/Main.s.sol +++ b/script/foundry/deployment/Main.s.sol @@ -27,20 +27,10 @@ contract Main is DeployHelper { /// forge script script/foundry/deployment/Main.s.sol:Main --rpc-url $RPC_URL --broadcast --verify -vvvv function run() public virtual override { - bool configByMultisig; - try vm.envBool("DEPLOYMENT_CONFIG_BY_MULTISIG") returns (bool mult) { - configByMultisig = mult; - } catch { - configByMultisig = false; - } - console2.log("configByMultisig:", configByMultisig); - // deploy all contracts via DeployHelper super.run( - configByMultisig ? multisig : deployer, // deployer - configByMultisig, true, // runStorageLayoutCheck - true // writeDeploys + true // writeDeployments ); _writeDeployment(); // write deployment json to deployments/deployment-{chainId}.json _endBroadcast(); // BroadcastManager.s.sol diff --git a/script/foundry/utils/BroadcastManager.s.sol b/script/foundry/utils/BroadcastManager.s.sol index 08e814cf1..802159aa1 100644 --- a/script/foundry/utils/BroadcastManager.s.sol +++ b/script/foundry/utils/BroadcastManager.s.sol @@ -5,10 +5,13 @@ import { Script } from "forge-std/Script.sol"; import { StringUtil } from "./StringUtil.sol"; import { MockERC20 } from "../../../test/foundry/mocks/token/MockERC20.sol"; +import { Users, UsersLib } from "../../../test/foundry/utils/Users.t.sol"; contract BroadcastManager is Script { address public multisig; address public deployer; + address public relayer; + uint32 public upgraderExecDelay; function _beginBroadcast() internal { uint256 deployerPrivateKey; @@ -16,15 +19,24 @@ contract BroadcastManager is Script { deployerPrivateKey = vm.envUint("MAINNET_PRIVATEKEY"); deployer = vm.addr(deployerPrivateKey); multisig = vm.envAddress("MAINNET_MULTISIG_ADDRESS"); + upgraderExecDelay = uint32(vm.envUint("MAINNET_UPGRADER_EXEC_DELAY")); + relayer = vm.envAddress("MAINNET_RELAYER_ADDRESS"); vm.startBroadcast(deployerPrivateKey); } else if (block.chainid == 11155111) { deployerPrivateKey = vm.envUint("SEPOLIA_PRIVATEKEY"); deployer = vm.addr(deployerPrivateKey); multisig = vm.envAddress("SEPOLIA_MULTISIG_ADDRESS"); + relayer = vm.envAddress("SEPOLIA_RELAYER_ADDRESS"); + upgraderExecDelay = 10 minutes; vm.startBroadcast(deployerPrivateKey); } else if (block.chainid == 31337) { - require(deployer != address(0), "Deployer not set"); - multisig = vm.addr(0x987321); + Users memory u = UsersLib.createMockUsers(vm); + // DeployHelper.sol will set the final admin as the multisig, so we do this for coherence + // with the tests (DeployHelper.sol is used both in tests and in the deployment scripts) + multisig = u.admin; + deployer = u.alice; + relayer = u.relayer; + upgraderExecDelay = 10 minutes; vm.startPrank(deployer); } else { revert("Unsupported chain"); diff --git a/script/foundry/utils/DeployHelper.sol b/script/foundry/utils/DeployHelper.sol index 32d37439e..476e276b9 100644 --- a/script/foundry/utils/DeployHelper.sol +++ b/script/foundry/utils/DeployHelper.sol @@ -9,14 +9,16 @@ import { console2 } from "forge-std/console2.sol"; import { Script } from "forge-std/Script.sol"; import { stdJson } from "forge-std/StdJson.sol"; import { ERC6551Registry } from "erc6551/ERC6551Registry.sol"; +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; // contracts import { AccessController } from "contracts/access/AccessController.sol"; import { IPAccountImpl } from "contracts/IPAccountImpl.sol"; import { IIPAccount } from "contracts/interfaces/IIPAccount.sol"; import { IRoyaltyPolicyLAP } from "contracts/interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; -import { Governance } from "contracts/governance/Governance.sol"; import { AccessPermission } from "contracts/lib/AccessPermission.sol"; +import { ProtocolAdmin } from "contracts/lib/ProtocolAdmin.sol"; import { Errors } from "contracts/lib/Errors.sol"; import { PILFlavors } from "contracts/lib/PILFlavors.sol"; // solhint-disable-next-line max-line-length @@ -53,6 +55,8 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag using StringUtil for uint256; using stdJson for string; + error RoleConfigError(string message); + ERC6551Registry internal immutable erc6551Registry; IPAccountImpl internal ipAccountImpl; @@ -78,8 +82,8 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag IpRoyaltyVault internal ipRoyaltyVaultImpl; // Access Control - Governance internal governance; - AccessController internal accessController; + AccessManager internal protocolAccessManager; // protocol roles + AccessController internal accessController; // per IPA roles // License system LicenseToken internal licenseToken; @@ -117,8 +121,6 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag /// forge script script/foundry/deployment/Main.s.sol:Main --rpc-url $RPC_URL --broadcast --verify -vvvv function run( - address runDeployer, - bool configByMultisig, bool runStorageLayoutCheck, bool writeDeploys_ ) public virtual { @@ -126,37 +128,50 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag // This will run OZ storage layout check for all contracts. Requires --ffi flag. if (runStorageLayoutCheck) super.run(); - - if (block.chainid == 31337) deployer = runDeployer; // set for local before _beginBroadcast + _beginBroadcast(); // BroadcastManager.s.sol - _deployProtocolContracts(deployer); - if (!configByMultisig) { - _configureDeployment(); + _deployProtocolContracts(); + _configureDeployment(); + _configureRoles(); + + // Check role assignment. + (bool deployerIsAdmin, ) = protocolAccessManager.hasRole(ProtocolAdmin.PROTOCOL_ADMIN_ROLE, deployer); + if (deployerIsAdmin) { + revert RoleConfigError("Deployer did not renounce admin role"); + } + (bool multisigAdmin, ) = protocolAccessManager.hasRole(ProtocolAdmin.PROTOCOL_ADMIN_ROLE, multisig); + (bool multisigUpgrader, ) = protocolAccessManager.hasRole(ProtocolAdmin.UPGRADER_ROLE, multisig); + + if (!multisigAdmin || !multisigUpgrader) { + revert RoleConfigError("Multisig roles not granted"); } if (writeDeploys) _writeDeployment(); _endBroadcast(); // BroadcastManager.s.sol } - function _deployProtocolContracts(address runDeployer) private { + function _deployProtocolContracts() private { require(address(erc20) != address(0), "Deploy: Asset Not Set"); string memory contractKey; // Core Protocol Contracts - contractKey = "Governance"; + contractKey = "ProtocolAccessManager"; _predeploy(contractKey); - governance = new Governance(runDeployer); - _postdeploy(contractKey, address(governance)); + protocolAccessManager = new AccessManager(deployer); + _postdeploy(contractKey, address(protocolAccessManager)); contractKey = "AccessController"; _predeploy(contractKey); address impl = address(new AccessController()); accessController = AccessController( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(AccessController.initialize, address(protocolAccessManager)) + ) ); impl = address(0); // Make sure we don't deploy wrong impl _postdeploy(contractKey, address(accessController)); @@ -170,14 +185,20 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _predeploy(contractKey); impl = address(new ModuleRegistry()); moduleRegistry = ModuleRegistry( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ModuleRegistry.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(ModuleRegistry.initialize, address(protocolAccessManager)) + ) ); impl = address(0); // Make sure we don't deploy wrong impl _postdeploy(contractKey, address(moduleRegistry)); contractKey = "IPAssetRegistry"; _predeploy(contractKey); - ipAssetRegistry = new IPAssetRegistry(address(erc6551Registry), address(ipAccountImpl), address(governance)); + ipAssetRegistry = new IPAssetRegistry( + address(erc6551Registry), + address(ipAccountImpl) + ); _postdeploy(contractKey, address(ipAssetRegistry)); IPAccountRegistry ipAccountRegistry = IPAccountRegistry(address(ipAssetRegistry)); @@ -186,7 +207,10 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _predeploy(contractKey); impl = address(new RoyaltyModule()); royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) + ) ); impl = address(0); _postdeploy(contractKey, address(royaltyModule)); @@ -195,7 +219,10 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _predeploy(contractKey); impl = address(new DisputeModule(address(accessController), address(ipAssetRegistry))); disputeModule = DisputeModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(DisputeModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(DisputeModule.initialize, address(protocolAccessManager)) + ) ); impl = address(0); _postdeploy(contractKey, address(disputeModule)); @@ -206,12 +233,7 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag licenseRegistry = LicenseRegistry( TestProxyHelper.deployUUPSProxy( impl, - abi.encodeCall( - LicenseRegistry.initialize, - ( - address(governance) - ) - ) + abi.encodeCall(LicenseRegistry.initialize, (address(protocolAccessManager))) ) ); impl = address(0); // Make sure we don't deploy wrong impl @@ -226,7 +248,7 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag abi.encodeCall( LicenseToken.initialize, ( - address(governance), + address(protocolAccessManager), "https://github.com/storyprotocol/protocol-core/blob/main/assets/license-image.gif" ) ) @@ -248,7 +270,10 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag ) ); licensingModule = LicensingModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicensingModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(LicensingModule.initialize, address(protocolAccessManager)) + ) ); impl = address(0); // Make sure we don't deploy wrong impl _postdeploy(contractKey, address(licensingModule)); @@ -260,7 +285,10 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _predeploy("ArbitrationPolicySP"); impl = address(new ArbitrationPolicySP(address(disputeModule), address(erc20), ARBITRATION_PRICE)); arbitrationPolicySP = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(ArbitrationPolicySP.initialize, address(protocolAccessManager)) + ) ); impl = address(0); _postdeploy("ArbitrationPolicySP", address(arbitrationPolicySP)); @@ -268,7 +296,10 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _predeploy("RoyaltyPolicyLAP"); impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); royaltyPolicyLAP = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyPolicyLAP.initialize, address(protocolAccessManager)) + ) ); impl = address(0); _postdeploy("RoyaltyPolicyLAP", address(royaltyPolicyLAP)); @@ -300,7 +331,7 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag _postdeploy("IpRoyaltyVaultImpl", address(ipRoyaltyVaultImpl)); _predeploy("IpRoyaltyVaultBeacon"); - ipRoyaltyVaultBeacon = new UpgradeableBeacon(address(ipRoyaltyVaultImpl), address(governance)); + ipRoyaltyVaultBeacon = new UpgradeableBeacon(address(ipRoyaltyVaultImpl), address(protocolAccessManager)); _postdeploy("IpRoyaltyVaultBeacon", address(ipRoyaltyVaultBeacon)); _predeploy("CoreMetadataModule"); @@ -358,7 +389,7 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag royaltyPolicyLAP.setIpRoyaltyVaultBeacon(address(ipRoyaltyVaultBeacon)); // Dispute Module and SP Dispute Policy - address arbitrationRelayer = deployer; + address arbitrationRelayer = relayer; disputeModule.whitelistDisputeTag("PLAGIARISM", true); disputeModule.whitelistArbitrationPolicy(address(arbitrationPolicySP), true); disputeModule.whitelistArbitrationRelayer(address(arbitrationPolicySP), arbitrationRelayer, true); @@ -370,4 +401,31 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag // License Template licenseRegistry.registerLicenseTemplate(address(pilTemplate)); } + + function _configureRoles() private { + + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = UUPSUpgradeable.upgradeToAndCall.selector; + + ///////// Role Configuration ///////// + // Upgrades + protocolAccessManager.labelRole(ProtocolAdmin.UPGRADER_ROLE, ProtocolAdmin.UPGRADER_ROLE_LABEL); + // Note: upgraderExecDelay is set in BroadcastManager.sol + protocolAccessManager.setTargetFunctionRole(address(licenseToken), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(accessController), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(disputeModule), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(arbitrationPolicySP), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(licensingModule), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(royaltyModule), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(royaltyPolicyLAP), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(licenseRegistry), selectors, ProtocolAdmin.UPGRADER_ROLE); + protocolAccessManager.setTargetFunctionRole(address(moduleRegistry), selectors, ProtocolAdmin.UPGRADER_ROLE); + + ///////// Role Granting ///////// + protocolAccessManager.grantRole(ProtocolAdmin.UPGRADER_ROLE, multisig, upgraderExecDelay); + protocolAccessManager.grantRole(ProtocolAdmin.PROTOCOL_ADMIN_ROLE, multisig, 0); + + ///////// Renounce admin role ///////// + protocolAccessManager.renounceRole(ProtocolAdmin.PROTOCOL_ADMIN_ROLE, deployer); + } } diff --git a/test/foundry/governance/Governance.t.sol b/test/foundry/governance/Governance.t.sol deleted file mode 100644 index 956a877c1..000000000 --- a/test/foundry/governance/Governance.t.sol +++ /dev/null @@ -1,346 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { IIPAccount } from "../../../contracts/interfaces/IIPAccount.sol"; -import { AccessPermission } from "../../../contracts/lib/AccessPermission.sol"; -import { Errors } from "../../../contracts/lib/Errors.sol"; -import { IGovernable } from "../../../contracts/interfaces/governance/IGovernable.sol"; -import { GovernanceLib } from "../../../contracts/lib/GovernanceLib.sol"; -import { Governance } from "../../../contracts/governance/Governance.sol"; - -import { MockModule } from "../mocks/module/MockModule.sol"; -import { BaseTest } from "../utils/BaseTest.t.sol"; - -contract GovernanceTest is BaseTest { - MockModule public mockModule; - MockModule public moduleWithoutPermission; - IIPAccount public ipAccount; - - address public owner = vm.addr(1); - uint256 public tokenId = 100; - - function setUp() public override { - super.setUp(); - - mockNFT.mintId(owner, tokenId); - - address deployedAccount = ipAccountRegistry.registerIpAccount(block.chainid, address(mockNFT), tokenId); - ipAccount = IIPAccount(payable(deployedAccount)); - - mockModule = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule"); - } - - function test_Governance_registerModuleSuccess() public { - vm.prank(u.admin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - assertEq(moduleRegistry.getModule("MockModule"), address(mockModule)); - assertTrue(moduleRegistry.isRegistered(address(mockModule))); - } - - function test_Governance_removeModuleSuccess() public { - vm.prank(u.admin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - assertEq(moduleRegistry.getModule("MockModule"), address(mockModule)); - assertTrue(moduleRegistry.isRegistered(address(mockModule))); - - vm.prank(u.admin); - moduleRegistry.removeModule("MockModule"); - assertEq(moduleRegistry.getModule("MockModule"), address(0)); - assertFalse(moduleRegistry.isRegistered(address(mockModule))); - } - - function test_Governance_setGlobalPermissionSuccess() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - assertEq( - accessController.getPermission(address(0), address(mockModule), address(mockModule2), bytes4(0)), - AccessPermission.ALLOW - ); - } - - function test_Governance_revert_registerModuleWithNonAdmin() public { - vm.prank(address(0x777)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.registerModule("MockModule", address(mockModule)); - } - - function test_Governance_revert_removeModuleWithNonAdmin() public { - vm.prank(u.admin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - assertEq(moduleRegistry.getModule("MockModule"), address(mockModule)); - assertTrue(moduleRegistry.isRegistered(address(mockModule))); - - vm.prank(address(0x777)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.removeModule("MockModule"); - } - - function test_Governance_revert_setGlobalPermissionNonAdmin() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - vm.prank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - - vm.prank(address(0x777)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_registerModuleWithNewAdmin() public { - address newAdmin = vm.addr(3); - vm.prank(u.admin); - governance.grantRole(GovernanceLib.PROTOCOL_ADMIN, newAdmin); - - vm.prank(newAdmin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - } - - function test_Governance_setGlobalPermissionWithNewAdmin() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - address newAdmin = vm.addr(3); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - governance.grantRole(GovernanceLib.PROTOCOL_ADMIN, newAdmin); - - vm.startPrank(newAdmin); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_revert_registerModuleWithOldAdmin() public { - address newAdmin = vm.addr(3); - - vm.startPrank(u.admin); - governance.grantRole(GovernanceLib.PROTOCOL_ADMIN, newAdmin); - governance.revokeRole(GovernanceLib.PROTOCOL_ADMIN, u.admin); - - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.registerModule("MockModule", address(mockModule)); - } - - function test_Governance_revert_removeModuleWithOldAdmin() public { - address newAdmin = vm.addr(3); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - assertEq(moduleRegistry.getModule("MockModule"), address(mockModule)); - assertTrue(moduleRegistry.isRegistered(address(mockModule))); - - governance.grantRole(GovernanceLib.PROTOCOL_ADMIN, newAdmin); - governance.revokeRole(GovernanceLib.PROTOCOL_ADMIN, u.admin); - - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.removeModule("MockModule"); - } - - function test_Governance_revert_setGlobalPermissionWithOldAdmin() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - address newAdmin = vm.addr(3); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - - governance.grantRole(GovernanceLib.PROTOCOL_ADMIN, newAdmin); - governance.revokeRole(GovernanceLib.PROTOCOL_ADMIN, u.admin); - vm.stopPrank(); - - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_setNewGovernance() public { - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - vm.prank(u.admin); - IGovernable(address(moduleRegistry)).setGovernance(address(newGovernance)); - assertEq(IGovernable(address(moduleRegistry)).getGovernance(), address(newGovernance)); - } - - function test_Governance_registerModuleWithNewGov() public { - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - vm.prank(u.admin); - IGovernable(address(moduleRegistry)).setGovernance(address(newGovernance)); - vm.prank(newAdmin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - } - - function test_Governance_setGlobalPermissionWithNewGov() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - IGovernable(address(accessController)).setGovernance(address(newGovernance)); - - vm.startPrank(newAdmin); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_revert_registerModuleWithOldGov() public { - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - - vm.startPrank(u.admin); - IGovernable(address(moduleRegistry)).setGovernance(address(newGovernance)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.registerModule("MockModule", address(mockModule)); - } - - function test_Governance_revert_removeModuleWithOldGov() public { - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule", address(mockModule)); - assertEq(moduleRegistry.getModule("MockModule"), address(mockModule)); - assertTrue(moduleRegistry.isRegistered(address(mockModule))); - - IGovernable(address(moduleRegistry)).setGovernance(address(newGovernance)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - moduleRegistry.removeModule("MockModule"); - } - - function test_Governance_revert_setGlobalPermissionWithOldGov() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - IGovernable(address(accessController)).setGovernance(address(newGovernance)); - - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - accessController.setGlobalPermission( - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_revert_setNewGovernanceZeroAddr() public { - vm.prank(u.admin); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__ZeroAddress.selector)); - IGovernable(address(moduleRegistry)).setGovernance(address(0)); - } - - function test_Governance_revert_setNewGovernanceNotContract() public { - vm.prank(u.admin); - vm.expectRevert(); - IGovernable(address(moduleRegistry)).setGovernance(address(0xbeefbeef)); - } - - function test_Governance_revert_setNewGovernanceNotSupportInterface() public { - vm.prank(u.admin); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__UnsupportedInterface.selector, "IGovernance")); - IGovernable(address(moduleRegistry)).setGovernance(address(mockModule)); - } - - function test_Governance_revert_setNewGovernanceInconsistentState() public { - address newAdmin = vm.addr(3); - Governance newGovernance = new Governance(newAdmin); - vm.prank(newAdmin); - newGovernance.setState(GovernanceLib.ProtocolState.Paused); - - vm.prank(u.admin); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__InconsistentState.selector)); - IGovernable(address(moduleRegistry)).setGovernance(address(newGovernance)); - } - - function test_Governance_revert_setPermissionWhenPaused() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - governance.setState(GovernanceLib.ProtocolState.Paused); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__ProtocolPaused.selector)); - accessController.setPermission( - address(ipAccount), - address(mockModule), - address(mockModule2), - bytes4(0), - AccessPermission.ALLOW - ); - } - - function test_Governance_revert_checkPermissionWhenPaused() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - governance.setState(GovernanceLib.ProtocolState.Paused); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__ProtocolPaused.selector)); - accessController.checkPermission(address(ipAccount), address(mockModule), address(mockModule2), bytes4(0)); - } - - function test_Governance_revert_checkPermissionUnPausedThenPauseThenUnPause() public { - MockModule mockModule2 = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule2"); - vm.startPrank(u.admin); - moduleRegistry.registerModule("MockModule2", address(mockModule2)); - vm.expectRevert( - abi.encodeWithSelector( - Errors.AccessController__PermissionDenied.selector, - address(ipAccount), - address(mockModule), - address(mockModule2), - bytes4(0) - ) - ); - accessController.checkPermission(address(ipAccount), address(mockModule), address(mockModule2), bytes4(0)); - - governance.setState(GovernanceLib.ProtocolState.Paused); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__ProtocolPaused.selector)); - accessController.checkPermission(address(ipAccount), address(mockModule), address(mockModule2), bytes4(0)); - - governance.setState(GovernanceLib.ProtocolState.Unpaused); - vm.expectRevert( - abi.encodeWithSelector( - Errors.AccessController__PermissionDenied.selector, - address(ipAccount), - address(mockModule), - address(mockModule2), - bytes4(0) - ) - ); - accessController.checkPermission(address(ipAccount), address(mockModule), address(mockModule2), bytes4(0)); - } - - function test_Governance_revert_setStateWithNonAdmin() public { - vm.prank(address(0x777)); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__OnlyProtocolAdmin.selector)); - governance.setState(GovernanceLib.ProtocolState.Paused); - } - - function test_Governance_revert_setSameState() public { - vm.startPrank(u.admin); - vm.expectRevert(abi.encodeWithSelector(Errors.Governance__NewStateIsTheSameWithOldState.selector)); - governance.setState(GovernanceLib.ProtocolState.Unpaused); - } -} diff --git a/test/foundry/integration/e2e/e2e.t.sol b/test/foundry/integration/e2e/e2e.t.sol index 8e29883ea..a83f99b2e 100644 --- a/test/foundry/integration/e2e/e2e.t.sol +++ b/test/foundry/integration/e2e/e2e.t.sol @@ -5,10 +5,10 @@ pragma solidity 0.8.23; import { Test } from "forge-std/Test.sol"; import { ERC6551Registry } from "erc6551/ERC6551Registry.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; // contracts import { AccessController } from "../../../../contracts/access/AccessController.sol"; -import { Governance } from "../../../../contracts/governance/Governance.sol"; import { IPAccountImpl } from "../../../../contracts/IPAccountImpl.sol"; import { IPAssetRegistry } from "../../../../contracts/registries/IPAssetRegistry.sol"; import { ModuleRegistry } from "../../../../contracts/registries/ModuleRegistry.sol"; @@ -39,7 +39,7 @@ contract e2e is Test { address dave; address eve; - Governance governance; + AccessManager protocolAccessManager; AccessController accessController; ModuleRegistry moduleRegistry; ERC6551Registry erc6551Registry; @@ -71,45 +71,60 @@ contract e2e is Test { erc20 = new MockERC20(); mockNft = new MockERC721("ape"); - governance = new Governance(admin); + protocolAccessManager = new AccessManager(admin); // Deploy contracts address impl = address(new AccessController()); accessController = AccessController( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(AccessController.initialize, address(protocolAccessManager)) + ) ); impl = address(new ModuleRegistry()); moduleRegistry = ModuleRegistry( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(AccessController.initialize, address(protocolAccessManager)) + ) ); erc6551Registry = new ERC6551Registry(); ipAccountImpl = new IPAccountImpl(address(accessController)); - ipAssetRegistry = new IPAssetRegistry(address(erc6551Registry), address(ipAccountImpl), address(governance)); + ipAssetRegistry = new IPAssetRegistry(address(erc6551Registry), address(ipAccountImpl)); impl = address(new LicenseRegistry()); licenseRegistry = LicenseRegistry( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicenseRegistry.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(LicenseRegistry.initialize, (address(protocolAccessManager))) + ) ); impl = address(new LicenseToken()); licenseToken = LicenseToken( TestProxyHelper.deployUUPSProxy( impl, - abi.encodeCall(LicenseToken.initialize, (address(governance), "image_url")) + abi.encodeCall(LicenseToken.initialize, (address(protocolAccessManager), "image_url")) ) ); impl = address(new RoyaltyModule()); royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, (address(protocolAccessManager))) + ) ); vm.label(address(royaltyModule), "RoyaltyModule"); impl = address(new DisputeModule(address(accessController), address(ipAssetRegistry))); disputeModule = DisputeModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(DisputeModule.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(DisputeModule.initialize, (address(protocolAccessManager))) + ) ); impl = address( @@ -124,7 +139,10 @@ contract e2e is Test { ); licensingModule = LicensingModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicensingModule.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(LicensingModule.initialize, (address(protocolAccessManager))) + ) ); erc20 = new MockERC20(); @@ -132,12 +150,18 @@ contract e2e is Test { impl = address(new ArbitrationPolicySP(address(disputeModule), address(erc20), ARBITRATION_PRICE)); ArbitrationPolicySP arbitrationPolicySP = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(ArbitrationPolicySP.initialize, (address(protocolAccessManager))) + ) ); impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); royaltyPolicyLAP = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, (address(governance)))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyPolicyLAP.initialize, (address(protocolAccessManager))) + ) ); impl = address( @@ -163,7 +187,7 @@ contract e2e is Test { new IpRoyaltyVault(address(royaltyPolicyLAP), address(disputeModule)) ); address ipRoyaltyVaultBeacon = address( - new UpgradeableBeacon(ipRoyaltyVaultImplementation, address(governance)) + new UpgradeableBeacon(ipRoyaltyVaultImplementation, address(protocolAccessManager)) ); royaltyPolicyLAP.setIpRoyaltyVaultBeacon(ipRoyaltyVaultBeacon); diff --git a/test/foundry/integration/flows/disputes/Disputes.t.sol b/test/foundry/integration/flows/disputes/Disputes.t.sol index b472839b9..271844752 100644 --- a/test/foundry/integration/flows/disputes/Disputes.t.sol +++ b/test/foundry/integration/flows/disputes/Disputes.t.sol @@ -138,7 +138,7 @@ contract Flows_Integration_Disputes is BaseIntegration { disputeId = disputeModule.raiseDispute(ipAddrToDispute, string("urlExample"), "PLAGIARISM", ""); vm.stopPrank(); - vm.prank(u.admin); // admin is a judge + vm.prank(u.relayer); // admin is a judge disputeModule.setDisputeJudgement(disputeId, true, ""); } } diff --git a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol index a4a2a3a7f..596cd980d 100644 --- a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol +++ b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol @@ -21,7 +21,7 @@ contract TestArbitrationPolicySP is BaseTest { function setUp() public override { super.setUp(); - arbitrationRelayer = u.admin; + arbitrationRelayer = u.relayer; USDC.mint(ipAccount1, 10000 * 10 ** 6); diff --git a/test/foundry/modules/dispute/DisputeModule.t.sol b/test/foundry/modules/dispute/DisputeModule.t.sol index 4768aac9e..b1df27c79 100644 --- a/test/foundry/modules/dispute/DisputeModule.t.sol +++ b/test/foundry/modules/dispute/DisputeModule.t.sol @@ -42,14 +42,17 @@ contract DisputeModuleTest is BaseTest { function setUp() public override { super.setUp(); - arbitrationRelayer = u.admin; + arbitrationRelayer = u.relayer; USDC.mint(ipAccount1, 1000 * 10 ** 6); // second arbitration policy address impl = address(new ArbitrationPolicySP(address(disputeModule), address(USDC), ARBITRATION_PRICE)); arbitrationPolicySP2 = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(ArbitrationPolicySP.initialize, address(protocolAccessManager)) + ) ); vm.startPrank(u.admin); diff --git a/test/foundry/modules/royalty/RoyaltyModule.t.sol b/test/foundry/modules/royalty/RoyaltyModule.t.sol index 85f335191..187bf9f54 100644 --- a/test/foundry/modules/royalty/RoyaltyModule.t.sol +++ b/test/foundry/modules/royalty/RoyaltyModule.t.sol @@ -48,10 +48,13 @@ contract TestRoyaltyModule is BaseTest { address impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); royaltyPolicyLAP2 = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyPolicyLAP.initialize, address(protocolAccessManager)) + ) ); - arbitrationRelayer = u.admin; + arbitrationRelayer = u.relayer; vm.startPrank(u.admin); // whitelist royalty policy @@ -156,7 +159,10 @@ contract TestRoyaltyModule is BaseTest { function test_RoyaltyModule_setDisputeModule_revert_ZeroDisputeModule() public { address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) + ) ); vm.expectRevert(Errors.RoyaltyModule__ZeroDisputeModule.selector); vm.prank(u.admin); @@ -167,7 +173,10 @@ contract TestRoyaltyModule is BaseTest { vm.startPrank(u.admin); address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) + ) ); testRoyaltyModule.setDisputeModule(address(disputeModule)); assertEq(testRoyaltyModule.disputeModule(), address(disputeModule)); @@ -183,7 +192,10 @@ contract TestRoyaltyModule is BaseTest { vm.startPrank(u.admin); address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) + ) ); testRoyaltyModule.setLicensingModule(address(licensingModule)); assertEq(testRoyaltyModule.licensingModule(), address(licensingModule)); diff --git a/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol b/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol index 4085e93aa..b3154b69c 100644 --- a/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol +++ b/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol @@ -5,6 +5,7 @@ import { RoyaltyPolicyLAP } from "../../../../contracts/modules/royalty/policies import { Errors } from "../../../../contracts/lib/Errors.sol"; import { BaseTest } from "../../utils/BaseTest.t.sol"; +import { IAccessManaged } from "@openzeppelin/contracts/access/manager/IAccessManaged.sol"; contract TestRoyaltyPolicyLAP is BaseTest { RoyaltyPolicyLAP internal testRoyaltyPolicyLAP; @@ -23,6 +24,7 @@ contract TestRoyaltyPolicyLAP is BaseTest { vm.startPrank(address(royaltyModule)); _setupMaxUniqueTree(); + vm.stopPrank(); } function _setupMaxUniqueTree() internal { @@ -146,7 +148,12 @@ contract TestRoyaltyPolicyLAP is BaseTest { } function test_RoyaltyPolicyLAP_setSnapshotInterval_revert_NotOwner() public { - vm.expectRevert(Errors.Governance__OnlyProtocolAdmin.selector); + vm.expectRevert( + abi.encodeWithSelector( + IAccessManaged.AccessManagedUnauthorized.selector, + address(this) + ) + ); royaltyPolicyLAP.setSnapshotInterval(100); } @@ -157,7 +164,12 @@ contract TestRoyaltyPolicyLAP is BaseTest { } function test_RoyaltyPolicyLAP_setIpRoyaltyVaultBeacon_revert_NotOwner() public { - vm.expectRevert(Errors.Governance__OnlyProtocolAdmin.selector); + vm.expectRevert( + abi.encodeWithSelector( + IAccessManaged.AccessManagedUnauthorized.selector, + address(this) + ) + ); royaltyPolicyLAP.setIpRoyaltyVaultBeacon(address(1)); } @@ -174,13 +186,13 @@ contract TestRoyaltyPolicyLAP is BaseTest { } function test_RoyaltyPolicyLAP_onLicenseMinting_revert_NotRoyaltyModule() public { - vm.stopPrank(); vm.expectRevert(Errors.RoyaltyPolicyLAP__NotRoyaltyModule.selector); royaltyPolicyLAP.onLicenseMinting(address(1), abi.encode(uint32(0)), abi.encode(uint32(0))); } function test_RoyaltyPolicyLAP_onLicenseMinting_revert_AboveRoyaltyStackLimit() public { uint256 excessPercent = royaltyPolicyLAP.TOTAL_RT_SUPPLY() + 1; + vm.prank(address(royaltyModule)); vm.expectRevert(Errors.RoyaltyPolicyLAP__AboveRoyaltyStackLimit.selector); royaltyPolicyLAP.onLicenseMinting(address(100), abi.encode(excessPercent), ""); } @@ -190,14 +202,16 @@ contract TestRoyaltyPolicyLAP is BaseTest { for (uint32 i = 0; i < parentsIpIds100.length; i++) { encodedLicenseData[i] = abi.encode(parentsIpIds100[i]); } - + vm.startPrank(address(royaltyModule)); royaltyPolicyLAP.onLinkToParents(address(100), parentsIpIds100, encodedLicenseData, ""); vm.expectRevert(Errors.RoyaltyPolicyLAP__LastPositionNotAbleToMintLicense.selector); royaltyPolicyLAP.onLicenseMinting(address(100), abi.encode(uint32(0)), ""); + vm.stopPrank(); } function test_RoyaltyPolicyLAP_onLicenseMinting() public { + vm.prank(address(royaltyModule)); royaltyPolicyLAP.onLicenseMinting(address(100), abi.encode(uint32(0)), ""); ( @@ -220,7 +234,6 @@ contract TestRoyaltyPolicyLAP is BaseTest { encodedLicenseData[i] = abi.encode(parentsIpIds100[i]); } - vm.stopPrank(); vm.expectRevert(Errors.RoyaltyPolicyLAP__NotRoyaltyModule.selector); royaltyPolicyLAP.onLinkToParents(address(100), parentsIpIds100, encodedLicenseData, ""); } @@ -236,6 +249,7 @@ contract TestRoyaltyPolicyLAP is BaseTest { excessParents[1] = address(2); excessParents[2] = address(3); + vm.prank(address(royaltyModule)); vm.expectRevert(Errors.RoyaltyPolicyLAP__AboveParentLimit.selector); royaltyPolicyLAP.onLinkToParents(address(100), excessParents, encodedLicenseData, ""); } @@ -245,7 +259,7 @@ contract TestRoyaltyPolicyLAP is BaseTest { for (uint32 i = 0; i < parentsIpIds100.length; i++) { encodedLicenseData[i] = abi.encode(parentsIpIds100[i]); } - + vm.prank(address(royaltyModule)); royaltyPolicyLAP.onLinkToParents(address(100), parentsIpIds100, encodedLicenseData, ""); ( diff --git a/test/foundry/utils/BaseTest.t.sol b/test/foundry/utils/BaseTest.t.sol index c8ad4ee07..e78bffd25 100644 --- a/test/foundry/utils/BaseTest.t.sol +++ b/test/foundry/utils/BaseTest.t.sol @@ -60,8 +60,6 @@ contract BaseTest is Test, DeployHelper, LicensingHelper { // deploy all contracts via DeployHelper super.run( - address(u.admin), - false, // configByMultisig false, // runStorageLayoutCheck false // writeDeploys ); diff --git a/test/foundry/utils/Users.t.sol b/test/foundry/utils/Users.t.sol index 8645f9d64..f43cec497 100644 --- a/test/foundry/utils/Users.t.sol +++ b/test/foundry/utils/Users.t.sol @@ -13,6 +13,8 @@ struct Users { address payable dan; // Malicious user address payable eve; + // Relayer + address payable relayer; } library UsersLib { @@ -32,7 +34,8 @@ library UsersLib { bob: createUser("Bob", vm), carl: createUser("Carl", vm), dan: createUser("Dan", vm), - eve: createUser("Eve", vm) + eve: createUser("Eve", vm), + relayer: createUser("Relayer", vm) }); } }