diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index 954f1457..df9cb475 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -52,8 +52,8 @@ library Errors { error HookRegistry_RegisteringDuplicatedHook(); /// @notice This error is thrown when trying to register a hook with the address 0. error HookRegistry_RegisteringZeroAddressHook(); - /// @notice This error is thrown when the caller is not an admin of the HookRegistry. - error HookRegistry_CallerNotAdmin(); + /// @notice This error is thrown when the caller is not IP Org owner. + error HookRegistry_CallerNotIPOrgOwner(); /// @notice This error is thrown when trying to register more than the maximum allowed number of hooks. error HookRegistry_MaxHooksExceeded(); /// @notice This error is thrown when the length of the hooks configuration array does not match the length of the hooks array. diff --git a/contracts/modules/base/BaseModule.sol b/contracts/modules/base/BaseModule.sol index df403434..53987797 100644 --- a/contracts/modules/base/BaseModule.sol +++ b/contracts/modules/base/BaseModule.sol @@ -125,7 +125,6 @@ abstract contract BaseModule is IModule, HookRegistry { return result == HookResult.Completed; } - function _hookRegistryAdmin() virtual override internal view returns (address); function _configure(IIPOrg ipOrg_, address caller_, bytes calldata params_) virtual internal returns (bytes memory); function _verifyExecution(IIPOrg ipOrg_, address caller_, bytes calldata params_) virtual internal {} function _performAction(IIPOrg ipOrg_, address caller_, bytes calldata params_) virtual internal returns (bytes memory result) {} diff --git a/contracts/modules/base/HookRegistry.sol b/contracts/modules/base/HookRegistry.sol index 3a424e8a..706106ab 100644 --- a/contracts/modules/base/HookRegistry.sol +++ b/contracts/modules/base/HookRegistry.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.13; import { Errors } from "contracts/lib/Errors.sol"; import { IHook } from "contracts/interfaces/hooks/base/IHook.sol"; +import { IIPOrg } from "contracts/interfaces/ip-org/IIPOrg.sol"; /// @title HookRegistry /// @notice This contract is an abstract contract that manages the registration of hooks. @@ -29,29 +30,34 @@ abstract contract HookRegistry { event HooksRegistered(HookType indexed hType, bytes32 indexed registryKey, address[] indexed hook); event HooksCleared(HookType indexed hType, bytes32 indexed registryKey); - /// @dev Modifier to check if the caller is the hook registry admin. - /// Reverts if the caller is not the admin. - modifier onlyHookRegistryAdmin() { - if (msg.sender != _hookRegistryAdmin()) - revert Errors.HookRegistry_CallerNotAdmin(); + /// @dev Modifier to check if the caller is the IPOrg owner. + /// Reverts if the caller is not the IP Org owner. + modifier onlyIpOrgOwner(IIPOrg ipOrg_) { + if (address(ipOrg_) == address(0)) { + revert Errors.ZeroAddress(); + } + + if (msg.sender != ipOrg_.owner()) + revert Errors.HookRegistry_CallerNotIPOrgOwner(); _; } /// @dev Registers hooks for a specific type and registry key. /// Clears any existing hooks for the same type and registry key. /// Emits a HooksRegistered event. - /// Can only be called by the hook registry admin. + /// Can only be called by the IP Org owner. /// @param hookType_ The type of the hooks to register. /// @param registryKey_ The registry key for the hooks. /// @param hooks_ The addresses of the hooks to register. /// @param hooksConfig_ The configurations for the hooks. function registerHooks( HookType hookType_, + IIPOrg ipOrg_, bytes32 registryKey_, address[] calldata hooks_, bytes[] calldata hooksConfig_ - ) public onlyHookRegistryAdmin { - clearHooks(hookType_, registryKey_); + ) public onlyIpOrgOwner(ipOrg_) { + clearHooks(hookType_, ipOrg_, registryKey_); _registerHooks( _hooksForType(hookType_, registryKey_), _hooksConfigForType(hookType_, registryKey_), @@ -134,13 +140,14 @@ abstract contract HookRegistry { /// @dev Clears all hooks for a specific type and registry key. /// Emits a HooksCleared event. - /// Can only be called by the hook registry admin. + /// Can only be called by the IP Org owner. /// @param hookType_ The type of the hooks to clear. /// @param registryKey_ The registry key for the hooks. function clearHooks( HookType hookType_, + IIPOrg ipOrg_, bytes32 registryKey_ - ) public onlyHookRegistryAdmin { + ) public onlyIpOrgOwner(ipOrg_) { if (hookType_ == HookType.PreAction && _preActionHooks[registryKey_].length > 0) { delete _preActionHooks[registryKey_]; delete _preActionHooksConfig[registryKey_]; @@ -164,11 +171,6 @@ abstract contract HookRegistry { return _hookIndex(_hooksForType(hookType_, registryKey_), hook_); } - /// @dev Returns the address of the hook registry admin. - /// This function should be overridden in derived contracts to provide the actual admin address. - /// @return The address of the hook registry admin. - function _hookRegistryAdmin() internal view virtual returns (address); - /// @dev Returns the hooks for a specific type and registry key. /// @param hookType_ The type of the hooks. /// @param registryKey_ The registry key for the hooks. diff --git a/contracts/modules/licensing/LicenseCreatorModule.sol b/contracts/modules/licensing/LicenseCreatorModule.sol index f7638a6a..d5da5ab7 100644 --- a/contracts/modules/licensing/LicenseCreatorModule.sol +++ b/contracts/modules/licensing/LicenseCreatorModule.sol @@ -122,16 +122,6 @@ contract LicenseCreatorModule is BaseModule, TermsRepository { } } - function _hookRegistryAdmin() - internal - view - virtual - override - returns (address) - { - return address(0); - } - //////////////////////////////////////////////////////////////////////////// // Create License // //////////////////////////////////////////////////////////////////////////// diff --git a/contracts/modules/registration/RegistrationModule.sol b/contracts/modules/registration/RegistrationModule.sol index 9e62697b..c6487134 100644 --- a/contracts/modules/registration/RegistrationModule.sol +++ b/contracts/modules/registration/RegistrationModule.sol @@ -42,6 +42,23 @@ contract RegistrationModule is BaseModule, IRegistrationModule, AccessControlled address accessControl_ ) BaseModule(params_) AccessControlled(accessControl_) {} + + /// @notice Registers hooks for a specific type and IP Org. + /// @dev This function can only be called by the IP Org owner. + /// @param hType_ The type of the hooks to register. + /// @param ipOrg_ The IP Org for which the hooks are being registered. + /// @param hooks_ The addresses of the hooks to register. + /// @param hooksConfig_ The configurations for the hooks. + function registerHooks( + HookType hType_, + IIPOrg ipOrg_, + address[] calldata hooks_, + bytes[] calldata hooksConfig_ + ) external onlyIpOrgOwner(ipOrg_) { + bytes32 registryKey = _generateRegistryKey(ipOrg_); + registerHooks(hType_, ipOrg_, registryKey, hooks_, hooksConfig_); + } + /// @notice Gets the contract URI for an IP Org. /// @param ipOrg_ The address of the IP Org. function contractURI(address ipOrg_) public view returns (string memory) { @@ -278,24 +295,15 @@ contract RegistrationModule is BaseModule, IRegistrationModule, AccessControlled } } - /// @dev Returns the administrator for the registration module hooks. - /// TODO(kingter) Define the administrator for this call. - function _hookRegistryAdmin() - internal - view - virtual - override - returns (address) - { - return address(0); - } - function _hookRegistryKey( IIPOrg ipOrg_, address, - bytes calldata params_ + bytes calldata ) internal view virtual override returns(bytes32) { - return keccak256(abi.encode(address(ipOrg_), "REGISTRATION")); + return _generateRegistryKey(ipOrg_); } + function _generateRegistryKey(IIPOrg ipOrg_) private pure returns(bytes32) { + return keccak256(abi.encode(address(ipOrg_), "REGISTRATION")); + } } diff --git a/contracts/modules/relationships/RelationshipModule.sol b/contracts/modules/relationships/RelationshipModule.sol index de24d0de..e7893572 100644 --- a/contracts/modules/relationships/RelationshipModule.sol +++ b/contracts/modules/relationships/RelationshipModule.sol @@ -40,7 +40,25 @@ contract RelationshipModule is BaseModule, IRelationshipModule, AccessControlled address accessControl_ ) BaseModule(params_) AccessControlled(accessControl_) {} - + + /// @notice Registers hooks for a specific hook type, based on IP Org and relationship type. + /// @dev This function can only be called by the IP Org owner. + /// @param hType_ The type of the hooks to register. + /// @param ipOrg_ The IP Org for which the hooks are being registered. + /// @param relType_ The relationship type for which the hooks are being registered. + /// @param hooks_ The addresses of the hooks to register. + /// @param hooksConfig_ The configurations for the hooks. + function registerHooks( + HookType hType_, + IIPOrg ipOrg_, + string calldata relType_, + address[] calldata hooks_, + bytes[] calldata hooksConfig_ + ) external onlyIpOrgOwner(ipOrg_) { + bytes32 registryKey = _generateRegistryKey(ipOrg_, relType_); + registerHooks(hType_, ipOrg_, registryKey, hooks_, hooksConfig_); + } + /// Gets relationship type definition for a given relationship type name /// Will revert if no relationship type is found /// @param ipOrg_ IP Org address or zero address for protocol level relationships @@ -76,16 +94,6 @@ contract RelationshipModule is BaseModule, IRelationshipModule, AccessControlled return _relHashes[keccak256(abi.encode(rel_))] != 0; } - function _hookRegistryAdmin() - internal - view - virtual - override - returns (address) - { - return address(0); // TODO - } - /// Relationship module supports configuration to add or remove relationship types function _configure( IIPOrg ipOrg_, @@ -252,6 +260,10 @@ contract RelationshipModule is BaseModule, IRelationshipModule, AccessControlled bytes calldata params_ ) internal view virtual override returns(bytes32) { LibRelationship.CreateRelationshipParams memory createParams = abi.decode(params_, (LibRelationship.CreateRelationshipParams)); - return keccak256(abi.encode(address(ipOrg_), createParams.relType)); + return _generateRegistryKey(ipOrg_, createParams.relType); + } + + function _generateRegistryKey(IIPOrg ipOrg_, string memory relType_) private pure returns(bytes32) { + return keccak256(abi.encode(address(ipOrg_), relType_)); } } diff --git a/test/foundry/mocks/MockBaseModule.sol b/test/foundry/mocks/MockBaseModule.sol index 80b4fe1b..b87ac399 100644 --- a/test/foundry/mocks/MockBaseModule.sol +++ b/test/foundry/mocks/MockBaseModule.sol @@ -36,16 +36,6 @@ contract MockBaseModule is BaseModule { return _callStack[index_]; } - function _hookRegistryAdmin() - internal - view - virtual - override - returns (address) - { - return _admin; - } - function _configure( IIPOrg ipOrg_, address caller_, @@ -77,9 +67,9 @@ contract MockBaseModule is BaseModule { string memory hookRegistrationInfo_, address[] calldata hooks_, bytes[] calldata hooksConfig_ - ) external onlyHookRegistryAdmin { + ) external onlyIpOrgOwner(ipOrg_) { bytes32 registryKey = _generateRegistryKey(address(ipOrg_), hookRegistrationInfo_); - registerHooks(hType_, registryKey, hooks_, hooksConfig_); + registerHooks(hType_, ipOrg_, registryKey, hooks_, hooksConfig_); } function hookRegistryKey( diff --git a/test/foundry/mocks/MockHookRegistry.sol b/test/foundry/mocks/MockHookRegistry.sol index 2c9ecb36..9fd83beb 100644 --- a/test/foundry/mocks/MockHookRegistry.sol +++ b/test/foundry/mocks/MockHookRegistry.sol @@ -7,22 +7,6 @@ import { IIPOrg } from "contracts/interfaces/ip-org/IIPOrg.sol"; /// @title Mock Hook Registry /// @notice This mock contract is used for testing the base hook registry. contract MockHookRegistry is HookRegistry { - address public immutable ADMIN; - - - constructor() { - ADMIN = msg.sender; - } - - function _hookRegistryAdmin() - internal - view - virtual - override - returns (address) - { - return ADMIN; - } function hookRegistryKey( address ipOrg_, diff --git a/test/foundry/modules/base/HookRegistryTest.t.sol b/test/foundry/modules/base/HookRegistryTest.t.sol index 78f395be..d6a938e7 100644 --- a/test/foundry/modules/base/HookRegistryTest.t.sol +++ b/test/foundry/modules/base/HookRegistryTest.t.sol @@ -9,6 +9,8 @@ import { MockHookRegistry } from "test/foundry/mocks/MockHookRegistry.sol"; import { Errors } from "contracts/lib/Errors.sol"; import { MockBaseHook } from "test/foundry/mocks/MockBaseHook.sol"; import { IHook } from "contracts/interfaces/hooks/base/IHook.sol"; +import { IIPOrg } from "contracts/interfaces/ip-org/IIPOrg.sol"; +import { MockIPOrg } from "test/foundry/mocks/MockIPOrg.sol"; contract HookRegistryTest is BaseTest { MockHookRegistry hookRegistry; @@ -30,12 +32,13 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKey, hooks); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 1), hooks[1]); @@ -52,13 +55,14 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); vm.expectEmit(true, false, false, true); emit HooksCleared(HookRegistry.HookType.PreAction, registryKey); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 1), hooks[1]); @@ -75,12 +79,13 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PostAction, registryKey, hooks); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 1), hooks[1]); @@ -97,13 +102,14 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.expectEmit(true, false, false, true); emit HooksCleared(HookRegistry.HookType.PostAction, registryKey); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 1), hooks[1]); @@ -113,33 +119,35 @@ contract HookRegistryTest is BaseTest { assertEq(hookRegistry.totalHooksConfig(HookRegistry.HookType.PostAction, registryKey), hooksConfig.length); } - function test_hookRegistry_revertRegisterHooksCallerNotAdmin() public { + function test_hookRegistry_revertRegisterHooksCallerNotIpOrgOwner() public { address[] memory hooks = new address[](2); hooks[0] = address(new MockBaseHook(address(accessControl))); hooks[1] = address(new MockBaseHook(address(accessControl))); bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.expectRevert(Errors.HookRegistry_CallerNotAdmin.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.expectRevert(Errors.HookRegistry_CallerNotIPOrgOwner.selector); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); } function test_hookRegistry_revertRegisterMaxHooksExceeded() public { address[] memory hooks = new address[](hookRegistry.MAX_HOOKS() + 1); bytes[] memory hooksConfig = new bytes[](hookRegistry.MAX_HOOKS() + 1); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); for(uint256 i = 0; i <= hookRegistry.MAX_HOOKS(); i++) { hooks[i] = address(new MockBaseHook(address(accessControl))); hooksConfig[i] = abi.encode("HookConfig", i + 1); } vm.expectRevert(Errors.HookRegistry_MaxHooksExceeded.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.expectRevert(Errors.HookRegistry_MaxHooksExceeded.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); } @@ -151,11 +159,12 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); vm.expectRevert(Errors.HookRegistry_RegisteringDuplicatedHook.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.stopPrank(); } @@ -166,11 +175,12 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKey, 1), hooks[1]); assertEq(hookRegistry.hookConfigAt(HookRegistry.HookType.PreAction, registryKey, 0), hooksConfig[0]); @@ -182,7 +192,7 @@ contract HookRegistryTest is BaseTest { assertEq(hookRegistry.isRegistered(HookRegistry.HookType.PreAction, registryKey, hooks[0]), true); assertEq(hookRegistry.isRegistered(HookRegistry.HookType.PreAction, registryKey, hooks[1]), true); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 0), hooks[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PostAction, registryKey, 1), hooks[1]); assertEq(hookRegistry.hookConfigAt(HookRegistry.HookType.PostAction, registryKey, 0), hooksConfig[0]); @@ -204,13 +214,14 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey, hooks, hooksConfig); vm.expectEmit(true, true, false, true); - emit HooksCleared(HookRegistry.HookType.PreAction, registryKey); - hookRegistry.clearHooks(HookRegistry.HookType.PreAction, registryKey); + emit HooksCleared(HookRegistry.HookType.PreAction, registryKey); + hookRegistry.clearHooks(HookRegistry.HookType.PreAction, ipOrg, registryKey); vm.stopPrank(); assertEq(hookRegistry.hookIndex(HookRegistry.HookType.PreAction, registryKey, hooks[0]), hookRegistry.INDEX_NOT_FOUND()); assertEq(hookRegistry.hookIndex(HookRegistry.HookType.PreAction, registryKey, hooks[1]), hookRegistry.INDEX_NOT_FOUND()); @@ -226,13 +237,14 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); vm.expectEmit(true, true, false, true); emit HooksCleared(HookRegistry.HookType.PostAction, registryKey); - hookRegistry.clearHooks(HookRegistry.HookType.PostAction, registryKey); + hookRegistry.clearHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey); vm.stopPrank(); assertEq(hookRegistry.hookIndex(HookRegistry.HookType.PostAction, registryKey, hooks[0]), hookRegistry.INDEX_NOT_FOUND()); assertEq(hookRegistry.hookIndex(HookRegistry.HookType.PostAction, registryKey, hooks[1]), hookRegistry.INDEX_NOT_FOUND()); @@ -248,10 +260,14 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfig = new bytes[](2); hooksConfig[0] = abi.encode("Hook1Config"); hooksConfig[1] = abi.encode("Hook2Config"); - address ipOrg = address(0x789); - bytes32 registryKey = hookRegistry.hookRegistryKey(ipOrg, "RelationshipType_A"); - vm.expectRevert(Errors.HookRegistry_CallerNotAdmin.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PostAction, registryKey, hooks, hooksConfig); + address ipOrgOwner = address(0x789); + IIPOrg ipOrg = new MockIPOrg(ipOrgOwner); + bytes32 registryKey = hookRegistry.hookRegistryKey(address(ipOrg), "RelationshipType_A"); + vm.startPrank(ipOrgOwner); + hookRegistry.registerHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey, hooks, hooksConfig); + vm.stopPrank(); + vm.expectRevert(Errors.HookRegistry_CallerNotIPOrgOwner.selector); + hookRegistry.clearHooks(HookRegistry.HookType.PostAction, ipOrg, registryKey); } function test_hookRegistry_registerHooksWithMultipleRegistryKeys() public { @@ -266,8 +282,8 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigA = new bytes[](2); hooksConfigA[0] = abi.encode("Hook1Config"); hooksConfigA[1] = abi.encode("Hook2Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); + IIPOrg ipOrg1 = new MockIPOrg(address(0x789)); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); // hooks B shares same ipOrg with hooks A address[] memory hooksB = new address[](2); @@ -276,7 +292,7 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigB = new bytes[](2); hooksConfigB[0] = abi.encode("Hook3Config"); hooksConfigB[1] = abi.encode("Hook5Config"); - bytes32 registryKeyB = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_B"); + bytes32 registryKeyB = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_B"); address[] memory hooksC = new address[](2); hooksC[0] = hook2; @@ -284,22 +300,21 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigC = new bytes[](2); hooksConfigC[0] = abi.encode("Hook2Config"); hooksConfigC[1] = abi.encode("Hook3Config"); - address ipOrg2 = address(0x999); - bytes32 registryKeyC = hookRegistry.hookRegistryKey(ipOrg2, "RelationshipType_C"); - - vm.startPrank(admin); + IIPOrg ipOrg2 = new MockIPOrg(address(0x999)); + bytes32 registryKeyC = hookRegistry.hookRegistryKey(address(ipOrg2), "RelationshipType_C"); + vm.startPrank(address(0x789)); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyA, hooksA); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyB, hooksB); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyB, hooksB, hooksConfigB); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyB, hooksB, hooksConfigB); + vm.stopPrank(); + vm.startPrank(address(0x999)); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyC, hooksC); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyC, hooksC, hooksConfigC); - + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg2, registryKeyC, hooksC, hooksConfigC); vm.stopPrank(); - assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKeyA, 0), hooksA[0]); assertEq(hookRegistry.hookAt(HookRegistry.HookType.PreAction, registryKeyA, 1), hooksA[1]); assertEq(hookRegistry.hookConfigAt(HookRegistry.HookType.PreAction, registryKeyA, 0), hooksConfigA[0]); @@ -337,8 +352,9 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigA = new bytes[](2); hooksConfigA[0] = abi.encode("Hook1Config"); hooksConfigA[1] = abi.encode("Hook2Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); + address ipOrgOwner1 = address(0x789); + IIPOrg ipOrg1 = new MockIPOrg(ipOrgOwner1); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); // hooks B shares same ipOrg with hooks A address[] memory hooksB = new address[](2); @@ -347,7 +363,7 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigB = new bytes[](2); hooksConfigB[0] = abi.encode("Hook3Config"); hooksConfigB[1] = abi.encode("Hook5Config"); - bytes32 registryKeyB = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_B"); + bytes32 registryKeyB = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_B"); address[] memory hooksC = new address[](3); hooksC[0] = hook6; @@ -358,13 +374,13 @@ contract HookRegistryTest is BaseTest { hooksConfigC[1] = abi.encode("Hook7Config"); hooksConfigC[2] = abi.encode("Hook8Config"); - vm.startPrank(admin); + vm.startPrank(ipOrgOwner1); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyA, hooksA); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyB, hooksB); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyB, hooksB, hooksConfigB); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyB, hooksB, hooksConfigB); // Expecting both clear and register events should be emitted vm.expectEmit(true, false, false, true); @@ -372,7 +388,7 @@ contract HookRegistryTest is BaseTest { vm.expectEmit(true, false, false, true); emit HooksRegistered(HookRegistry.HookType.PreAction, registryKeyA, hooksC); // register new hooks with the same registryKeyA, expecting the existing hooks should be replaced - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksC, hooksConfigC); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksC, hooksConfigC); vm.stopPrank(); @@ -405,10 +421,11 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigA = new bytes[](2); hooksConfigA[0] = abi.encode("Hook1Config"); hooksConfigA[1] = abi.encode("Hook2Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + address ipOrgOwner1 = address(0x789); + IIPOrg ipOrg1 = new MockIPOrg(ipOrgOwner1); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); + vm.startPrank(ipOrgOwner1); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.stopPrank(); vm.expectRevert( abi.encodeWithSelector( @@ -429,10 +446,11 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigA = new bytes[](2); hooksConfigA[0] = abi.encode("Hook1Config"); hooksConfigA[1] = abi.encode("Hook2Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); - vm.startPrank(admin); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + address ipOrgOwner1 = address(0x789); + IIPOrg ipOrg1 = new MockIPOrg(ipOrgOwner1); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); + vm.startPrank(ipOrgOwner1); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.stopPrank(); vm.expectRevert( abi.encodeWithSelector( @@ -452,11 +470,12 @@ contract HookRegistryTest is BaseTest { hooksA[1] = hook2; bytes[] memory hooksConfigA = new bytes[](1); hooksConfigA[0] = abi.encode("Hook1Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner1 = address(0x789); + IIPOrg ipOrg1 = new MockIPOrg(ipOrgOwner1); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); + vm.startPrank(ipOrgOwner1); vm.expectRevert(Errors.HookRegistry_HooksConfigLengthMismatch.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.stopPrank(); } @@ -470,11 +489,12 @@ contract HookRegistryTest is BaseTest { bytes[] memory hooksConfigA = new bytes[](2); hooksConfigA[0] = abi.encode("Hook1Config"); hooksConfigA[1] = abi.encode("Hook2Config"); - address ipOrg1 = address(0x789); - bytes32 registryKeyA = hookRegistry.hookRegistryKey(ipOrg1, "RelationshipType_A"); - vm.startPrank(admin); + address ipOrgOwner1 = address(0x789); + IIPOrg ipOrg1 = new MockIPOrg(ipOrgOwner1); + bytes32 registryKeyA = hookRegistry.hookRegistryKey(address(ipOrg1), "RelationshipType_A"); + vm.startPrank(ipOrgOwner1); vm.expectRevert(Errors.HookRegistry_RegisteringZeroAddressHook.selector); - hookRegistry.registerHooks(HookRegistry.HookType.PreAction, registryKeyA, hooksA, hooksConfigA); + hookRegistry.registerHooks(HookRegistry.HookType.PreAction, ipOrg1, registryKeyA, hooksA, hooksConfigA); vm.stopPrank(); } }