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..de376f58a 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 accessManaged The address of the governance contract + function initialize(address accessManaged) external initializer { + __AccessManaged_init(accessManaged); } /// @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. @@ -248,5 +245,5 @@ contract AccessController is IAccessController, GovernableUpgradeable, UUPSUpgra /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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 0c670497f..a47036183 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/ProtocolAdminRoles.sol b/contracts/lib/ProtocolAdminRoles.sol new file mode 100644 index 000000000..96c55a050 --- /dev/null +++ b/contracts/lib/ProtocolAdminRoles.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.23; + +/// @title ProtocolAdminRoles +/// @dev This library provides roles and utils to configure the protocol AccessManager +library ProtocolAdminRoles { + uint64 public constant PROTOCOL_ADMIN = type(uint64).min; // 0 + uint64 public constant PUBLIC_ROLE = type(uint64).max; // 2**64-1 + uint64 public constant UPGRADER_ROLE = 1; +} diff --git a/contracts/modules/dispute/DisputeModule.sol b/contracts/modules/dispute/DisputeModule.sol index e99c40805..6abca21f0 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 governance 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(); @@ -345,7 +346,7 @@ contract DisputeModule is /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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..a63b17b6d 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 governance contract + function initialize(address accessManager) public initializer { + __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); } @@ -83,7 +84,7 @@ 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); @@ -92,5 +93,5 @@ contract ArbitrationPolicySP is IArbitrationPolicy, GovernableUpgradeable, UUPSU /// @notice Hook that is called before any upgrade /// @param newImplementation Address of the new implementation - function _authorizeUpgrade(address newImplementation) internal override onlyProtocolAdmin {} + function _authorizeUpgrade(address newImplementation) internal override restricted {} } diff --git a/contracts/modules/licensing/LicensingModule.sol b/contracts/modules/licensing/LicensingModule.sol index c3f58906d..351eb4eae 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 governance contract + function initialize(address accessManager) public initializer { __ReentrancyGuard_init(); __UUPSUpgradeable_init(); - __GovernableUpgradeable_init(governance); + __AccessManaged_init(accessManager); } /// @notice Attaches license terms to an IP. @@ -450,5 +451,5 @@ contract LicensingModule is /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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..49bd291a3 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 governance 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(); @@ -265,7 +266,7 @@ contract RoyaltyModule is /// @notice Hook that is called before any upgrade for authorization /// @param newImplementation 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 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..8d051a8d6 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; @@ -351,5 +352,5 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, GovernableUpgradeable, Reentranc /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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..c5147ddc2 100644 --- a/contracts/registries/IPAssetRegistry.sol +++ b/contracts/registries/IPAssetRegistry.sol @@ -5,12 +5,12 @@ import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; 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 +22,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, AccessManager { using ERC165Checker for address; using Strings for *; using IPAccountStorageOps for IIPAccount; @@ -33,8 +33,8 @@ contract IPAssetRegistry is IIPAssetRegistry, IPAccountRegistry, Governable { constructor( address erc6551Registry, address ipAccountImpl, - address governance - ) IPAccountRegistry(erc6551Registry, ipAccountImpl) Governable(governance) {} + address accessManager + ) IPAccountRegistry(erc6551Registry, ipAccountImpl) AccessManager(accessManager) {} /// @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..541c6afe6 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 governance 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); } @@ -507,5 +508,5 @@ contract LicenseRegistry is ILicenseRegistry, GovernableUpgradeable, UUPSUpgrade /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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..683e5d074 100644 --- a/contracts/registries/ModuleRegistry.sol +++ b/contracts/registries/ModuleRegistry.sol @@ -4,17 +4,18 @@ 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 +40,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 +53,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 +70,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 +85,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 +93,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(); } @@ -195,5 +192,5 @@ contract ModuleRegistry is IModuleRegistry, GovernableUpgradeable, UUPSUpgradeab /// @dev Hook to authorize the upgrade according to UUPSUgradeable /// @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/test/foundry/governance/Governance.t.sol b/test/foundry/governance/Governance.t.sol deleted file mode 100644 index 5e03632bf..000000000 --- a/test/foundry/governance/Governance.t.sol +++ /dev/null @@ -1,350 +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(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ moduleRegistry: true, licenseRegistry: false })); - deployConditionally(); - postDeploymentSetup(); - - 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); - } -}