diff --git a/contracts/instance/IInstance.sol b/contracts/instance/IInstance.sol index 6604ae41d..0a1b7c58f 100644 --- a/contracts/instance/IInstance.sol +++ b/contracts/instance/IInstance.sol @@ -8,6 +8,7 @@ import {StateId} from "../types/StateId.sol"; import {RiskId} from "../types/RiskId.sol"; import {VersionPart} from "../types/Version.sol"; import {Key32} from "../types/Key32.sol"; +import {RoleId} from "../types/RoleId.sol"; import {IRegisterable} from "../shared/IRegisterable.sol"; @@ -16,83 +17,44 @@ import {ITransferInterceptor} from "../registry/ITransferInterceptor.sol"; import {InstanceAccessManager} from "./InstanceAccessManager.sol"; import {BundleManager} from "./BundleManager.sol"; import {InstanceReader} from "./InstanceReader.sol"; +import {InstanceStore} from "./InstanceStore.sol"; + +import {IKeyValueStore} from "./base/IKeyValueStore.sol"; + +import {IAccess} from "./module/IAccess.sol"; -import {IBundle} from "./module/IBundle.sol"; import {IBundleService} from "./service/IBundleService.sol"; -import {IComponents} from "./module/IComponents.sol"; import {IDistributionService} from "./service/IDistributionService.sol"; -import {InstanceAccessManager} from "./InstanceAccessManager.sol"; -import {IKeyValueStore} from "./base/IKeyValueStore.sol"; -import {IPolicy} from "./module/IPolicy.sol"; -import {IDistribution} from "./module/IDistribution.sol"; import {IPolicyService} from "./service/IPolicyService.sol"; import {IPoolService} from "./service/IPoolService.sol"; import {IProductService} from "./service/IProductService.sol"; import {IPolicyService} from "./service/IPolicyService.sol"; import {IBundleService} from "./service/IBundleService.sol"; -import {IRisk} from "./module/IRisk.sol"; -import {ISetup} from "./module/ISetup.sol"; interface IInstance is IRegisterable, ITransferInterceptor, - IAccessManaged, - IKeyValueStore + IAccessManaged { + function createRole(string memory roleName, string memory adminName) external returns (RoleId roleId, RoleId admin); + function grantRole(RoleId roleId, address account) external; + function revokeRole(RoleId roleId, address account) external; + + function createTarget(address target, string memory name) external; + function setTargetFunctionRole(string memory targetName, bytes4[] calldata selectors, RoleId roleId) external; + function setTargetLocked(address target, bool locked) external; + function getDistributionService() external view returns (IDistributionService); function getProductService() external view returns (IProductService); function getPoolService() external view returns (IPoolService); function getPolicyService() external view returns (IPolicyService); function getBundleService() external view returns (IBundleService); - function createDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup) external; - function updateDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup, StateId newState) external; - function updateDistributionSetupState(NftId distributionNftId, StateId newState) external; - - function createPoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info) external; - function updatePoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info, StateId newState) external; - function updatePoolSetupState(NftId poolNftId, StateId newState) external; - - function createBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle) external; - function updateBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle, StateId newState) external; - function updateBundleState(NftId bundleNftId, StateId newState) external; - - function createProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup) external; - function updateProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup, StateId newState) external; - function updateProductSetupState(NftId productNftId, StateId newState) external; - - function createDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info) external; - function updateDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info, StateId newState) external; - function updateDistributorTypeState(Key32 distributorKey, StateId newState) external; - - function createDistributor(NftId nftId, IDistribution.DistributorInfo memory info) external; - function updateDistributor(NftId nftId, IDistribution.DistributorInfo memory info, StateId newState) external; - function updateDistributorState(NftId nftId, StateId newState) external; - - function createReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo) external; - function updateReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo, StateId newState) external; - function updateReferralState(Key32 referralKey, StateId newState) external; - - function createRisk(RiskId riskId, IRisk.RiskInfo memory risk) external; - function updateRisk(RiskId riskId, IRisk.RiskInfo memory risk, StateId newState) external; - function updateRiskState(RiskId riskId, StateId newState) external; - - function createApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy) external; - function updateApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy, StateId newState) external; - function updateApplicationState(NftId applicationNftId, StateId newState) external; - - function updatePolicy(NftId policyNftId, IPolicy.PolicyInfo memory policy, StateId newState) external; - function updatePolicyState(NftId policyNftId, StateId newState) external; - - // TODO add claims/payouts function to instance - // function updateClaims(NftId policyNftId, IPolicy.PolicyInfo memory policy, StateId newState) external; - function getMajorVersion() external pure returns (VersionPart majorVersion); function getInstanceReader() external view returns (InstanceReader); function getBundleManager() external view returns (BundleManager); - - function setInstanceAccessManager(InstanceAccessManager accessManager) external; function getInstanceAccessManager() external view returns (InstanceAccessManager); + function getInstanceStore() external view returns (InstanceStore); } \ No newline at end of file diff --git a/contracts/instance/IInstanceService.sol b/contracts/instance/IInstanceService.sol index 5a25c2310..b440d4b61 100644 --- a/contracts/instance/IInstanceService.sol +++ b/contracts/instance/IInstanceService.sol @@ -15,6 +15,7 @@ import {InstanceAccessManager} from "./InstanceAccessManager.sol"; import {Instance} from "./Instance.sol"; import {InstanceReader} from "./InstanceReader.sol"; import {BundleManager} from "./BundleManager.sol"; +import {InstanceStore} from "./InstanceStore.sol"; interface IInstanceService is IService { @@ -33,11 +34,13 @@ interface IInstanceService is IService { error ErrorInstanceServiceInstanceAccessManagerZero(); error ErrorInstanceServiceInstanceReaderZero(); error ErrorInstanceServiceBundleManagerZero(); + error ErrorInstanceServiceInstanceStoreZero(); error ErrorInstanceServiceInstanceAuthorityMismatch(); error ErrorInstanceServiceBundleManagerAuthorityMismatch(); error ErrorInstanceServiceInstanceReaderInstanceMismatch2(); error ErrorInstanceServiceBundleMangerInstanceMismatch(); + error ErrorInstanceServiceInstanceStoreAuthorityMismatch(); error ErrorInstanceServiceRequestUnauhorized(address caller); error ErrorInstanceServiceNotInstanceOwner(address caller, NftId instanceNftId); @@ -46,7 +49,15 @@ interface IInstanceService is IService { error ErrorInstanceServiceInstanceComponentMismatch(NftId instanceNftId, NftId componentNftId); error ErrorInstanceServiceInvalidComponentType(address componentAddress, ObjectType expectedType, ObjectType componentType); - event LogInstanceCloned(address clonedOzAccessManager, address clonedInstanceAccessManager, address clonedInstance, address clonedBundleManager, address clonedInstanceReader, NftId clonedInstanceNftId); + event LogInstanceCloned( + address clonedOzAccessManager, + address clonedInstanceAccessManager, + address clonedInstance, + address clonedInstanceStore, + address clonedBundleManager, + address clonedInstanceReader, + NftId clonedInstanceNftId + ); function createInstanceClone() external @@ -56,7 +67,8 @@ interface IInstanceService is IService { Instance clonedInstance, NftId instanceNftId, InstanceReader clonedInstanceReader, - BundleManager clonedBundleManager + BundleManager clonedBundleManager, + InstanceStore clonedInstanceStore ); function createGifTarget( diff --git a/contracts/instance/Instance.sol b/contracts/instance/Instance.sol index 5b1cc88b4..1c79b37c4 100644 --- a/contracts/instance/Instance.sol +++ b/contracts/instance/Instance.sol @@ -3,19 +3,14 @@ pragma solidity ^0.8.20; import {AccessManagedUpgradeable} from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; -import {Key32, KeyId, Key32Lib} from "../types/Key32.sol"; import {NftId} from "../types/NftId.sol"; -import {ClaimId} from "../types/ClaimId.sol"; -import {NumberId} from "../types/NumberId.sol"; import {ObjectType, BUNDLE, DISTRIBUTION, INSTANCE, POLICY, POOL, ROLE, PRODUCT, TARGET, COMPONENT, DISTRIBUTOR, DISTRIBUTOR_TYPE} from "../types/ObjectType.sol"; -import {RiskId, RiskIdLib} from "../types/RiskId.sol"; -import {RoleId, RoleIdLib, INSTANCE_ROLE, INSTANCE_OWNER_ROLE} from "../types/RoleId.sol"; -import {StateId, ACTIVE} from "../types/StateId.sol"; -import {TimestampLib} from "../types/Timestamp.sol"; +import {RoleId, RoleIdLib, eqRoleId, ADMIN_ROLE, INSTANCE_ROLE, INSTANCE_OWNER_ROLE} from "../types/RoleId.sol"; import {VersionPart, VersionPartLib} from "../types/Version.sol"; import {ERC165} from "../shared/ERC165.sol"; import {Registerable} from "../shared/Registerable.sol"; +import {TokenHandler} from "../shared/TokenHandler.sol"; import {IRegistry} from "../registry/IRegistry.sol"; @@ -23,6 +18,7 @@ import {IInstance} from "./IInstance.sol"; import {InstanceReader} from "./InstanceReader.sol"; import {InstanceAccessManager} from "./InstanceAccessManager.sol"; import {BundleManager} from "./BundleManager.sol"; +import {InstanceStore} from "./InstanceStore.sol"; import {KeyValueStore} from "./base/KeyValueStore.sol"; @@ -39,29 +35,20 @@ import {IPoolService} from "./service/IPoolService.sol"; import {IProductService} from "./service/IProductService.sol"; import {IPolicyService} from "./service/IPolicyService.sol"; import {IBundleService} from "./service/IBundleService.sol"; -import {TokenHandler} from "../shared/TokenHandler.sol"; -import {VersionPart, VersionPartLib} from "../types/Version.sol"; contract Instance is IInstance, AccessManagedUpgradeable, - Registerable, - KeyValueStore + Registerable { - uint256 public constant GIF_MAJOR_VERSION = 3; - uint64 public constant ADMIN_ROLE = type(uint64).min; - uint64 public constant PUBLIC_ROLE = type(uint64).max; - uint64 public constant CUSTOM_ROLE_ID_MIN = 10000; - - uint32 public constant EXECUTION_DELAY = 0; - bool private _initialized; InstanceAccessManager internal _accessManager; InstanceReader internal _instanceReader; BundleManager internal _bundleManager; + InstanceStore internal _instanceStore; modifier onlyChainNft() { if(msg.sender != getRegistry().getChainNftAddress()) { @@ -71,168 +58,66 @@ contract Instance is } function initialize(address authority, address registryAddress, address initialOwner) - public + external initializer() { __AccessManaged_init(authority); IRegistry registry = IRegistry(registryAddress); initializeRegisterable(registryAddress, registry.getNftId(), INSTANCE(), true, initialOwner, ""); - initializeLifecycle(); registerInterface(type(IInstance).interfaceId); } - //--- ProductSetup ------------------------------------------------------// - function createProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup) external restricted() { - create(_toNftKey32(productNftId, PRODUCT()), abi.encode(setup)); - } - - function updateProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup, StateId newState) external restricted() { - update(_toNftKey32(productNftId, PRODUCT()), abi.encode(setup), newState); - } - - function updateProductSetupState(NftId productNftId, StateId newState) external restricted() { - updateState(_toNftKey32(productNftId, PRODUCT()), newState); - } - - //--- DistributionSetup ------------------------------------------------------// - function createDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup) external restricted() { - create(_toNftKey32(distributionNftId, DISTRIBUTION()), abi.encode(setup)); - } - - function updateDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup, StateId newState) external restricted() { - update(_toNftKey32(distributionNftId, DISTRIBUTION()), abi.encode(setup), newState); - } - - function updateDistributionSetupState(NftId distributionNftId, StateId newState) external restricted() { - updateState(_toNftKey32(distributionNftId, DISTRIBUTION()), newState); - } - - //--- PoolSetup ------------------------------------------------------// - function createPoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info) external restricted() { - create(_toNftKey32(poolNftId, POOL()), abi.encode(info)); - } - - function updatePoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info, StateId newState) external restricted() { - update(_toNftKey32(poolNftId, POOL()), abi.encode(info), newState); - } - - function updatePoolSetupState(NftId poolNftId, StateId newState) external restricted() { - updateState(_toNftKey32(poolNftId, POOL()), newState); - } - - //--- DistributorType -------------------------------------------------------// - function createDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info) external restricted() { - create(distributorKey, abi.encode(info)); - } - - function updateDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info, StateId newState) external restricted() { - update(distributorKey, abi.encode(info), newState); - } - - function updateDistributorTypeState(Key32 distributorKey, StateId newState) external restricted() { - updateState(distributorKey, newState); - } - - //--- Distributor -------------------------------------------------------// - function createDistributor(NftId nftId, IDistribution.DistributorInfo memory info) external restricted() { - create(toDistributorKey32(nftId), abi.encode(info)); - } - - function updateDistributor(NftId nftId, IDistribution.DistributorInfo memory info, StateId newState) external restricted() { - update(toDistributorKey32(nftId), abi.encode(info), newState); - } + //--- Roles ------------------------------------------------------------// - function updateDistributorState(NftId nftId, StateId newState) external restricted() { - updateState(toDistributorKey32(nftId), newState); - } - - //--- Referral ----------------------------------------------------------// - function createReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo) external restricted() { - create(referralKey, abi.encode(referralInfo)); - } - - function updateReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo, StateId newState) external restricted() { - update(referralKey, abi.encode(referralInfo), newState); - } - - function updateReferralState(Key32 referralKey, StateId newState) external restricted() { - updateState(referralKey, newState); - } - - //--- Bundle ------------------------------------------------------------// - function createBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle) external restricted() { - create(toBundleKey32(bundleNftId), abi.encode(bundle)); - } - - function updateBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle, StateId newState) external restricted() { - update(toBundleKey32(bundleNftId), abi.encode(bundle), newState); - } - - function updateBundleState(NftId bundleNftId, StateId newState) external restricted() { - updateState(toBundleKey32(bundleNftId), newState); - } - - //--- Risk --------------------------------------------------------------// - function createRisk(RiskId riskId, IRisk.RiskInfo memory risk) external restricted() { - create(riskId.toKey32(), abi.encode(risk)); - } - - function updateRisk(RiskId riskId, IRisk.RiskInfo memory risk, StateId newState) external restricted() { - update(riskId.toKey32(), abi.encode(risk), newState); - } - - function updateRiskState(RiskId riskId, StateId newState) external restricted() { - updateState(riskId.toKey32(), newState); - } - - //--- Application (Policy) ----------------------------------------------// - function createApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy) external restricted() { - create(toPolicyKey32(applicationNftId), abi.encode(policy)); - } - - function updateApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy, StateId newState) external restricted() { - update(toPolicyKey32(applicationNftId), abi.encode(policy), newState); - } - - function updateApplicationState(NftId applicationNftId, StateId newState) external restricted() { - updateState(toPolicyKey32(applicationNftId), newState); - } - - //--- Policy ------------------------------------------------------------// - function updatePolicy(NftId policyNftId, IPolicy.PolicyInfo memory policy, StateId newState) external restricted() { - update(toPolicyKey32(policyNftId), abi.encode(policy), newState); - } - - function updatePolicyState(NftId policyNftId, StateId newState) external restricted() { - updateState(toPolicyKey32(policyNftId), newState); + function createRole(string memory roleName, string memory adminName) + external + restricted // INSTANCE_OWNER_ROLE + returns (RoleId roleId, RoleId admin) + { + (roleId, admin) = _accessManager.createRole(roleName, adminName); } - //--- Claim -------------------------------------------------------------// - function createClaim(NftId policyNftId, ClaimId claimId, IPolicy.ClaimInfo memory claim) external restricted() { - create(toPolicyKey32(policyNftId), abi.encode(claim)); + function grantRole(RoleId roleId, address account) + external + restricted // INSTANCE_OWNER_ROLE + { + _accessManager.grantRole(roleId, account); } - function updateClaim(NftId policyNftId, ClaimId claimId, IPolicy.ClaimInfo memory claim, StateId newState) external restricted() { - update(toPolicyKey32(policyNftId), abi.encode(claim), newState); + function revokeRole(RoleId roleId, address account) + external + restricted // INSTANCE_OWNER_ROLE + { + _accessManager.revokeRole(roleId, account); } - function updateClaimState(NftId policyNftId, ClaimId claimId, StateId newState) external restricted() { - updateState(toPolicyKey32(policyNftId), newState); - } + //--- Targets ------------------------------------------------------------// - //--- Payout ------------------------------------------------------------// - function createPayout(NftId policyNftId, NumberId payoutId, IPolicy.PayoutInfo memory payout) external restricted() { - create(toPolicyKey32(policyNftId), abi.encode(payout)); + function createTarget(address target, string memory name) + external + restricted // INSTANCE_OWNER_ROLE + { + _accessManager.createTarget(target, name); } - function updatePayout(NftId policyNftId, NumberId payoutId, IPolicy.PayoutInfo memory payout, StateId newState) external restricted() { - update(toPolicyKey32(policyNftId), abi.encode(payout), newState); + function setTargetFunctionRole( + string memory targetName, + bytes4[] calldata selectors, + RoleId roleId + ) + external + restricted // INSTANCE_OWNER_ROLE + { + _accessManager.setTargetFunctionRole(targetName, selectors, roleId); } - function updatePayoutState(NftId policyNftId, StateId newState) external restricted() { - updateState(toPolicyKey32(policyNftId), newState); + function setTargetLocked(address target, bool locked) + external + restricted // INSTANCE_OWNER_ROLE + { + _accessManager.setTargetLockedByInstance(target, locked); } //--- ITransferInterceptor ------------------------------------------------------------// @@ -246,31 +131,6 @@ contract Instance is assert(_accessManager.grantRole(INSTANCE_OWNER_ROLE(), to) == true); } - //--- internal view/pure functions --------------------------------------// - function _toNftKey32(NftId nftId, ObjectType objectType) internal pure returns (Key32) { - return nftId.toKey32(objectType); - } - - function toBundleKey32(NftId bundleNftId) public pure returns (Key32) { - return bundleNftId.toKey32(BUNDLE()); - } - - function toPolicyKey32(NftId policyNftId) public pure returns (Key32) { - return policyNftId.toKey32(POLICY()); - } - - function toDistributionKey32(NftId distNftId) public pure returns (Key32) { - return distNftId.toKey32(DISTRIBUTION()); - } - - function toDistributorTypeKey32(NftId distNftId) public pure returns (Key32) { - return distNftId.toKey32(DISTRIBUTOR_TYPE()); - } - - function toDistributorKey32(NftId distNftId) public pure returns (Key32) { - return distNftId.toKey32(DISTRIBUTOR()); - } - function getDistributionService() external view returns (IDistributionService) { return IDistributionService(getRegistry().getServiceAddress(DISTRIBUTION(), VersionPart.wrap(3))); } @@ -324,4 +184,16 @@ contract Instance is function getInstanceAccessManager() external view returns (InstanceAccessManager) { return _accessManager; } -} + + function setInstanceStore(InstanceStore instanceStore) external restricted { + require(address(_instanceStore) == address(0), "InstanceStore is set"); + require(instanceStore.authority() == authority(), "InstanceStore authority mismatch"); + _instanceStore = instanceStore; + } + + function getInstanceStore() external view returns (InstanceStore) { + return _instanceStore; + } + + //--- internal view/pure functions --------------------------------------// +} \ No newline at end of file diff --git a/contracts/instance/InstanceAccessManager.sol b/contracts/instance/InstanceAccessManager.sol index 08f01d620..85acb8825 100644 --- a/contracts/instance/InstanceAccessManager.sol +++ b/contracts/instance/InstanceAccessManager.sol @@ -73,7 +73,7 @@ contract InstanceAccessManager is _createRole(ADMIN_ROLE(), ADMIN_ROLE_NAME, IAccess.Type.Core); _createRole(PUBLIC_ROLE(), PUBLIC_ROLE_NAME, IAccess.Type.Core); _createRole(INSTANCE_ROLE(), INSTANCE_ROLE_NAME, IAccess.Type.Core); - _createRole(INSTANCE_OWNER_ROLE(), INSTANCE_OWNER_ROLE_NAME, IAccess.Type.Gif); + _createRole(INSTANCE_OWNER_ROLE(), INSTANCE_OWNER_ROLE_NAME, IAccess.Type.Gif);// TODO should be of core type // assume `this` is already a member of ADMIN_ROLE EnumerableSet.add(_roleMembers[ADMIN_ROLE()], address(this)); @@ -142,6 +142,7 @@ contract InstanceAccessManager is _roleInfo[roleId].admin = admin; } + // TODO core role can be granted only to 1 member function grantRole(RoleId roleId, address member) public restrictedToRoleAdmin(roleId) @@ -226,7 +227,7 @@ contract InstanceAccessManager is return _roleIds[idx]; } - // TODO now: for non existent name returns ADMIN_ROLE id + // TODO returns ADMIN_ROLE id for non existent name function getRoleIdForName(string memory name) external view returns (RoleId roleId) { return _roleIdForName[ShortStrings.toShortString(name)]; } @@ -250,7 +251,7 @@ contract InstanceAccessManager is _createTarget(target, name, IAccess.Type.Core); } // INSTANCE_SERVICE_ROLE - // assume gif target is registered and belongs to the same instance as instance access manager + // TODO check for instance mismatch? function createGifTarget(address target, string memory name) external restricted() { if(!_registry.isRegistered(target)) { @@ -269,26 +270,22 @@ contract InstanceAccessManager is _createTarget(target, name, IAccess.Type.Custom); } - // INSTANCE_SERVICE_ROLE - // IMPORTANT: instance access manager MUST be of Core type -> otherwise will be locked forever - function setTargetLocked(address target, bool locked) + // TODO instance owner locks component instead of revoking it access to the instance... + function setTargetLockedByService(address target, bool locked) external - restricted() + restricted // INSTANCE_SERVICE_ROLE { - IAccess.Type targetType = _targetInfo[target].ttype; - if(target == address(0) || targetType == IAccess.Type.NotInitialized) { - revert IAccess.ErrorIAccessTargetDoesNotExist(target); - } - - if(targetType == IAccess.Type.Core) { - revert IAccess.ErrorIAccessTargetTypeInvalid(target, targetType); - } + _setTargetLocked(target, locked); + } - // TODO isLocked is redundant but makes getTargetInfo() faster - _targetInfo[target].isLocked = locked; - _accessManager.setTargetClosed(target, locked); + function setTargetLockedByInstance(address target, bool locked) + external + restricted // INSTANCE_ROLE + { + _setTargetLocked(target, locked); } + // allowed combinations of roles and targets: //1) set core role for core target //2) set gif role for gif target @@ -362,7 +359,7 @@ contract InstanceAccessManager is } function isTargetLocked(address target) public view returns (bool locked) { - return _accessManager.isTargetClosed(target); + return _targetInfo[target].isLocked; } function targetExists(address target) public view returns (bool exists) { @@ -497,6 +494,22 @@ contract InstanceAccessManager is } } + // IMPORTANT: instance access manager MUST be of Core type -> otherwise can be locked forever + function _setTargetLocked(address target, bool locked) internal + { + IAccess.Type targetType = _targetInfo[target].ttype; + if(target == address(0) || targetType == IAccess.Type.NotInitialized) { + revert IAccess.ErrorIAccessTargetDoesNotExist(target); + } + + if(targetType == IAccess.Type.Core) { + revert IAccess.ErrorIAccessTargetTypeInvalid(target, targetType); + } + + _targetInfo[target].isLocked = locked; + _accessManager.setTargetClosed(target, locked); + } + function _setTargetFunctionRole( address target, ShortString name, diff --git a/contracts/instance/InstanceReader.sol b/contracts/instance/InstanceReader.sol index c455bc38a..60550d3b5 100644 --- a/contracts/instance/InstanceReader.sol +++ b/contracts/instance/InstanceReader.sol @@ -27,6 +27,8 @@ import {ISetup} from "../instance/module/ISetup.sol"; import {ITreasury} from "../instance/module/ITreasury.sol"; import {TimestampLib} from "../types/Timestamp.sol"; +import {InstanceStore} from "./InstanceStore.sol"; + contract InstanceReader { bool private _initialized; @@ -42,7 +44,7 @@ contract InstanceReader { "ERROR:CRD-001:INSTANCE_ZERO"); _instance = IInstance(instance); - _store = IKeyValueStore(instance); + _store = _instance.getInstanceStore(); _initialized = true; } @@ -66,7 +68,7 @@ contract InstanceReader { view returns (StateId state) { - return _instance.getState(toPolicyKey(policyNftId)); + return _store.getState(toPolicyKey(policyNftId)); } function getRiskInfo(RiskId riskId) diff --git a/contracts/instance/InstanceService.sol b/contracts/instance/InstanceService.sol index 8681e88a3..e1e3add9a 100644 --- a/contracts/instance/InstanceService.sol +++ b/contracts/instance/InstanceService.sol @@ -4,26 +4,32 @@ pragma solidity ^0.8.20; import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; import {ShortString, ShortStrings} from "@openzeppelin/contracts/utils/ShortStrings.sol"; -import {Instance} from "./Instance.sol"; -import {IInstance} from "./IInstance.sol"; -import {InstanceAccessManager} from "./InstanceAccessManager.sol"; -import {IInstanceService} from "./IInstanceService.sol"; -import {InstanceReader} from "./InstanceReader.sol"; -import {BundleManager} from "./BundleManager.sol"; -import {AccessManagerUpgradeableInitializeable} from "./AccessManagerUpgradeableInitializeable.sol"; -import {IRegistry} from "../registry/IRegistry.sol"; -import {IRegistryService} from "../registry/IRegistryService.sol"; -import {ChainNft} from "../registry/ChainNft.sol"; -import {Service} from "../../contracts/shared/Service.sol"; -import {IService} from "../shared/IService.sol"; import {NftId} from "../../contracts/types/NftId.sol"; import {RoleId} from "../types/RoleId.sol"; import {ADMIN_ROLE, INSTANCE_OWNER_ROLE, DISTRIBUTION_OWNER_ROLE, POOL_OWNER_ROLE, PRODUCT_OWNER_ROLE, INSTANCE_SERVICE_ROLE, DISTRIBUTION_SERVICE_ROLE, POOL_SERVICE_ROLE, PRODUCT_SERVICE_ROLE, APPLICATION_SERVICE_ROLE, POLICY_SERVICE_ROLE, CLAIM_SERVICE_ROLE, BUNDLE_SERVICE_ROLE, INSTANCE_ROLE} from "../types/RoleId.sol"; import {ObjectType, INSTANCE, BUNDLE, APPLICATION, POLICY, CLAIM, PRODUCT, DISTRIBUTION, REGISTRY, POOL} from "../types/ObjectType.sol"; + +import {Service} from "../shared/Service.sol"; +import {IService} from "../shared/IService.sol"; + import {IDistributionComponent} from "../components/IDistributionComponent.sol"; import {IPoolComponent} from "../components/IPoolComponent.sol"; import {IProductComponent} from "../components/IProductComponent.sol"; +import {IRegistry} from "../registry/IRegistry.sol"; +import {IRegistryService} from "../registry/IRegistryService.sol"; +import {ChainNft} from "../registry/ChainNft.sol"; + +import {Instance} from "./Instance.sol"; +import {IInstance} from "./IInstance.sol"; +import {InstanceAccessManager} from "./InstanceAccessManager.sol"; +import {IInstanceService} from "./IInstanceService.sol"; +import {InstanceReader} from "./InstanceReader.sol"; +import {BundleManager} from "./BundleManager.sol"; +import {AccessManagerUpgradeableInitializeable} from "./AccessManagerUpgradeableInitializeable.sol"; +import {InstanceStore} from "./InstanceStore.sol"; + + contract InstanceService is Service, IInstanceService @@ -33,6 +39,7 @@ contract InstanceService is address internal _masterInstance; address internal _masterInstanceReader; address internal _masterInstanceBundleManager; + address internal _masterInstanceStore; // TODO update to real hash when instance is stable bytes32 public constant INSTANCE_CREATION_CODE_HASH = bytes32(0); @@ -67,18 +74,18 @@ contract InstanceService is Instance clonedInstance, NftId clonedInstanceNftId, InstanceReader clonedInstanceReader, - BundleManager clonedBundleManager + BundleManager clonedBundleManager, + InstanceStore clonedInstanceStore ) { address instanceOwner = msg.sender; IRegistry registry = getRegistry(); - address registryAddress = address(registry); - NftId registryNftId = registry.getNftId(registryAddress); - address registryServiceAddress = registry.getServiceAddress(REGISTRY(), getVersion().toMajorPart()); - IRegistryService registryService = IRegistryService(registryServiceAddress); + NftId registryNftId = registry.getNftId(address(registry)); + IRegistryService registryService = IRegistryService( + registry.getServiceAddress(REGISTRY(), getVersion().toMajorPart()) + ); - clonedOzAccessManager = AccessManagerUpgradeableInitializeable( - Clones.clone(_masterOzAccessManager)); + clonedOzAccessManager = AccessManagerUpgradeableInitializeable(Clones.clone(_masterOzAccessManager)); // initially grants ADMIN_ROLE to this (being the instance service). // This will allow the instance service to bootstrap the authorizations of the instance. @@ -89,8 +96,12 @@ contract InstanceService is clonedInstance = Instance(Clones.clone(_masterInstance)); clonedInstance.initialize( address(clonedOzAccessManager), - registryAddress, + address(registry), instanceOwner); + // initialize and set before instance reader + clonedInstanceStore = InstanceStore(Clones.clone(address(_masterInstanceStore))); + clonedInstanceStore.initialize(address(clonedInstance)); + clonedInstance.setInstanceStore(clonedInstanceStore); clonedInstanceReader = InstanceReader(Clones.clone(address(_masterInstanceReader))); clonedInstanceReader.initialize(address(clonedInstance)); @@ -107,18 +118,18 @@ contract InstanceService is // TODO amend setters with instance specific , policy manager ... - _grantInitialAuthorizations(clonedInstanceAccessManager, clonedInstance, clonedBundleManager, instanceOwner); + _grantInitialAuthorizations(clonedInstanceAccessManager, clonedInstance, clonedBundleManager, clonedInstanceStore, instanceOwner); clonedOzAccessManager.renounceRole(ADMIN_ROLE().toInt(), address(this)); IRegistry.ObjectInfo memory info = registryService.registerInstance(clonedInstance, instanceOwner); clonedInstanceNftId = info.nftId; - // clonedInstance.linkToRegisteredNftId(); emit LogInstanceCloned( address(clonedOzAccessManager), address(clonedInstanceAccessManager), - address(clonedInstance), + address(clonedInstance), + address(clonedInstanceStore), address(clonedBundleManager), address(clonedInstanceReader), clonedInstanceNftId); @@ -128,20 +139,22 @@ contract InstanceService is InstanceAccessManager clonedAccessManager, Instance clonedInstance, BundleManager clonedBundleManager, + InstanceStore clonedInstanceStore, address instanceOwner) internal { _createCoreAndGifRoles(clonedAccessManager); - _createCoreTargets(clonedAccessManager, clonedInstance, clonedBundleManager); - _grantDistributionServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantPoolServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantProductServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantApplicationServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantPolicyServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantClaimServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantBundleServiceAuthorizations(clonedAccessManager, clonedInstance, clonedBundleManager); + _createCoreTargets(clonedAccessManager, clonedInstance, clonedBundleManager, clonedInstanceStore); + _grantDistributionServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantPoolServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantProductServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantApplicationServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantPolicyServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantClaimServiceAuthorizations(clonedAccessManager, clonedInstanceStore); + _grantBundleServiceAuthorizations(clonedAccessManager, clonedInstanceStore, clonedBundleManager); _grantInstanceServiceAuthorizations(clonedAccessManager, clonedInstance); - _grantInstanceOwnerAuthorizations(clonedAccessManager, instanceOwner); + _grantInstanceAuthorizations(clonedAccessManager); + _grantInstanceOwnerAuthorizations(clonedAccessManager, clonedInstance); } function _createCoreAndGifRoles(InstanceAccessManager clonedAccessManager) internal { @@ -161,114 +174,121 @@ contract InstanceService is clonedAccessManager.createGifRole(PRODUCT_OWNER_ROLE(), "ProductOwnerRole", INSTANCE_OWNER_ROLE()); } - function _createCoreTargets(InstanceAccessManager clonedAccessManager, Instance clonedInstance, BundleManager clonedBundleManager) internal { - clonedAccessManager.createCoreTarget(address(clonedAccessManager), "InstanceAccessManager"); - clonedAccessManager.createCoreTarget(address(clonedInstance), "Instance"); + function _createCoreTargets( + InstanceAccessManager clonedAccessManager, + Instance clonedInstance, + BundleManager clonedBundleManager, + InstanceStore clonedInstanceStore) + internal + { + clonedAccessManager.createCoreTarget(address(clonedAccessManager), "InstanceAccessManager");// TODO create in instance access manager initializer? + clonedAccessManager.createCoreTarget(address(clonedInstance), "Instance");// TODO create in instance access manager initializer? clonedAccessManager.createCoreTarget(address(clonedBundleManager), "BundleManager"); - } + clonedAccessManager.createCoreTarget(address(clonedInstanceStore), "InstanceStore"); + } - function _grantDistributionServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantDistributionServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for distribution service on instance address distributionServiceAddress = getRegistry().getServiceAddress(DISTRIBUTION(), getVersion().toMajorPart()); clonedAccessManager.grantRole(DISTRIBUTION_SERVICE_ROLE(), distributionServiceAddress); bytes4[] memory instanceDistributionServiceSelectors = new bytes4[](11); - instanceDistributionServiceSelectors[0] = clonedInstance.createDistributionSetup.selector; - instanceDistributionServiceSelectors[1] = clonedInstance.updateDistributionSetup.selector; - instanceDistributionServiceSelectors[2] = clonedInstance.createDistributorType.selector; - instanceDistributionServiceSelectors[3] = clonedInstance.updateDistributorType.selector; - instanceDistributionServiceSelectors[4] = clonedInstance.updateDistributorTypeState.selector; - instanceDistributionServiceSelectors[5] = clonedInstance.createDistributor.selector; - instanceDistributionServiceSelectors[6] = clonedInstance.updateDistributor.selector; - instanceDistributionServiceSelectors[7] = clonedInstance.updateDistributorState.selector; - instanceDistributionServiceSelectors[8] = clonedInstance.createReferral.selector; - instanceDistributionServiceSelectors[9] = clonedInstance.updateReferral.selector; - instanceDistributionServiceSelectors[10] = clonedInstance.updateReferralState.selector; + instanceDistributionServiceSelectors[0] = clonedInstanceStore.createDistributionSetup.selector; + instanceDistributionServiceSelectors[1] = clonedInstanceStore.updateDistributionSetup.selector; + instanceDistributionServiceSelectors[2] = clonedInstanceStore.createDistributorType.selector; + instanceDistributionServiceSelectors[3] = clonedInstanceStore.updateDistributorType.selector; + instanceDistributionServiceSelectors[4] = clonedInstanceStore.updateDistributorTypeState.selector; + instanceDistributionServiceSelectors[5] = clonedInstanceStore.createDistributor.selector; + instanceDistributionServiceSelectors[6] = clonedInstanceStore.updateDistributor.selector; + instanceDistributionServiceSelectors[7] = clonedInstanceStore.updateDistributorState.selector; + instanceDistributionServiceSelectors[8] = clonedInstanceStore.createReferral.selector; + instanceDistributionServiceSelectors[9] = clonedInstanceStore.updateReferral.selector; + instanceDistributionServiceSelectors[10] = clonedInstanceStore.updateReferralState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instanceDistributionServiceSelectors, DISTRIBUTION_SERVICE_ROLE()); } - function _grantPoolServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantPoolServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for pool service on instance address poolServiceAddress = getRegistry().getServiceAddress(POOL(), getVersion().toMajorPart()); clonedAccessManager.grantRole(POOL_SERVICE_ROLE(), address(poolServiceAddress)); bytes4[] memory instancePoolServiceSelectors = new bytes4[](4); - instancePoolServiceSelectors[0] = clonedInstance.createPoolSetup.selector; - instancePoolServiceSelectors[1] = clonedInstance.updatePoolSetup.selector; + instancePoolServiceSelectors[0] = clonedInstanceStore.createPoolSetup.selector; + instancePoolServiceSelectors[1] = clonedInstanceStore.updatePoolSetup.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instancePoolServiceSelectors, POOL_SERVICE_ROLE()); } - function _grantProductServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantProductServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for product service on instance address productServiceAddress = getRegistry().getServiceAddress(PRODUCT(), getVersion().toMajorPart()); clonedAccessManager.grantRole(PRODUCT_SERVICE_ROLE(), address(productServiceAddress)); bytes4[] memory instanceProductServiceSelectors = new bytes4[](5); - instanceProductServiceSelectors[0] = clonedInstance.createProductSetup.selector; - instanceProductServiceSelectors[1] = clonedInstance.updateProductSetup.selector; - instanceProductServiceSelectors[2] = clonedInstance.createRisk.selector; - instanceProductServiceSelectors[3] = clonedInstance.updateRisk.selector; - instanceProductServiceSelectors[4] = clonedInstance.updateRiskState.selector; + instanceProductServiceSelectors[0] = clonedInstanceStore.createProductSetup.selector; + instanceProductServiceSelectors[1] = clonedInstanceStore.updateProductSetup.selector; + instanceProductServiceSelectors[2] = clonedInstanceStore.createRisk.selector; + instanceProductServiceSelectors[3] = clonedInstanceStore.updateRisk.selector; + instanceProductServiceSelectors[4] = clonedInstanceStore.updateRiskState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instanceProductServiceSelectors, PRODUCT_SERVICE_ROLE()); } - function _grantApplicationServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantApplicationServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for application services on instance address applicationServiceAddress = getRegistry().getServiceAddress(APPLICATION(), getVersion().toMajorPart()); clonedAccessManager.grantRole(APPLICATION_SERVICE_ROLE(), applicationServiceAddress); bytes4[] memory instanceApplicationServiceSelectors = new bytes4[](3); - instanceApplicationServiceSelectors[0] = clonedInstance.createApplication.selector; - instanceApplicationServiceSelectors[1] = clonedInstance.updateApplication.selector; - instanceApplicationServiceSelectors[2] = clonedInstance.updateApplicationState.selector; + instanceApplicationServiceSelectors[0] = clonedInstanceStore.createApplication.selector; + instanceApplicationServiceSelectors[1] = clonedInstanceStore.updateApplication.selector; + instanceApplicationServiceSelectors[2] = clonedInstanceStore.updateApplicationState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instanceApplicationServiceSelectors, APPLICATION_SERVICE_ROLE()); } - function _grantPolicyServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantPolicyServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for policy services on instance address policyServiceAddress = getRegistry().getServiceAddress(POLICY(), getVersion().toMajorPart()); clonedAccessManager.grantRole(POLICY_SERVICE_ROLE(), policyServiceAddress); bytes4[] memory instancePolicyServiceSelectors = new bytes4[](2); - instancePolicyServiceSelectors[0] = clonedInstance.updatePolicy.selector; - instancePolicyServiceSelectors[1] = clonedInstance.updatePolicyState.selector; + instancePolicyServiceSelectors[0] = clonedInstanceStore.updatePolicy.selector; + instancePolicyServiceSelectors[1] = clonedInstanceStore.updatePolicyState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instancePolicyServiceSelectors, POLICY_SERVICE_ROLE()); } - function _grantClaimServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { + function _grantClaimServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore) internal { // configure authorization for claim/payout services on instance address claimServiceAddress = getRegistry().getServiceAddress(CLAIM(), getVersion().toMajorPart()); clonedAccessManager.grantRole(POLICY_SERVICE_ROLE(), claimServiceAddress); // TODO add claims function authz bytes4[] memory instanceClaimServiceSelectors = new bytes4[](0); - // instanceClaimServiceSelectors[0] = clonedInstance.updatePolicy.selector; - // instanceClaimServiceSelectors[1] = clonedInstance.updatePolicyState.selector; + // instanceClaimServiceSelectors[0] = clonedInstanceStore.updatePolicy.selector; + // instanceClaimServiceSelectors[1] = clonedInstanceStore.updatePolicyState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instanceClaimServiceSelectors, CLAIM_SERVICE_ROLE()); } - function _grantBundleServiceAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance, BundleManager clonedBundleManager) internal { + function _grantBundleServiceAuthorizations(InstanceAccessManager clonedAccessManager, InstanceStore clonedInstanceStore, BundleManager clonedBundleManager) internal { // configure authorization for bundle service on instance address bundleServiceAddress = getRegistry().getServiceAddress(BUNDLE(), getVersion().toMajorPart()); clonedAccessManager.grantRole(BUNDLE_SERVICE_ROLE(), address(bundleServiceAddress)); bytes4[] memory instanceBundleServiceSelectors = new bytes4[](3); - instanceBundleServiceSelectors[0] = clonedInstance.createBundle.selector; - instanceBundleServiceSelectors[1] = clonedInstance.updateBundle.selector; - instanceBundleServiceSelectors[2] = clonedInstance.updateBundleState.selector; + instanceBundleServiceSelectors[0] = clonedInstanceStore.createBundle.selector; + instanceBundleServiceSelectors[1] = clonedInstanceStore.updateBundle.selector; + instanceBundleServiceSelectors[2] = clonedInstanceStore.updateBundleState.selector; clonedAccessManager.setCoreTargetFunctionRole( - "Instance", + "InstanceStore", instanceBundleServiceSelectors, BUNDLE_SERVICE_ROLE()); @@ -299,7 +319,7 @@ contract InstanceService is // configure authorizations for instance service on instance access manager bytes4[] memory accessManagerInstanceServiceSelectors = new bytes4[](3); accessManagerInstanceServiceSelectors[0] = clonedAccessManager.createGifTarget.selector; - accessManagerInstanceServiceSelectors[1] = clonedAccessManager.setTargetLocked.selector; + accessManagerInstanceServiceSelectors[1] = clonedAccessManager.setTargetLockedByService.selector; accessManagerInstanceServiceSelectors[2] = clonedAccessManager.setCoreTargetFunctionRole.selector; clonedAccessManager.setCoreTargetFunctionRole( "InstanceAccessManager", @@ -307,21 +327,33 @@ contract InstanceService is INSTANCE_SERVICE_ROLE()); } - function _grantInstanceOwnerAuthorizations(InstanceAccessManager clonedAccessManager, address instanceOwner) internal { + function _grantInstanceAuthorizations(InstanceAccessManager clonedAccessManager) internal { + bytes4[] memory accessManagerInstanceSelectors = new bytes4[](4); + accessManagerInstanceSelectors[0] = clonedAccessManager.createRole.selector; + accessManagerInstanceSelectors[1] = clonedAccessManager.createTarget.selector; + accessManagerInstanceSelectors[2] = clonedAccessManager.setTargetFunctionRole.selector; + accessManagerInstanceSelectors[3] = clonedAccessManager.setTargetLockedByInstance.selector; + clonedAccessManager.setCoreTargetFunctionRole( + "InstanceAccessManager", + accessManagerInstanceSelectors, + INSTANCE_ROLE()); + } + + function _grantInstanceOwnerAuthorizations(InstanceAccessManager clonedAccessManager, Instance clonedInstance) internal { // configure authorization for instance owner on instance access manager // instance owner role is granted/revoked ONLY by INSTANCE_ROLE - bytes4[] memory accessManagerInstanceOwnerSelectors = new bytes4[](3); - accessManagerInstanceOwnerSelectors[0] = clonedAccessManager.createRole.selector; - accessManagerInstanceOwnerSelectors[1] = clonedAccessManager.createTarget.selector; - accessManagerInstanceOwnerSelectors[2] = clonedAccessManager.setTargetFunctionRole.selector; + bytes4[] memory instanceInstanceOwnerSelectors = new bytes4[](4); + instanceInstanceOwnerSelectors[0] = clonedInstance.createRole.selector; + instanceInstanceOwnerSelectors[1] = clonedInstance.createTarget.selector; + instanceInstanceOwnerSelectors[2] = clonedInstance.setTargetFunctionRole.selector; + instanceInstanceOwnerSelectors[3] = clonedInstance.setTargetLocked.selector; clonedAccessManager.setCoreTargetFunctionRole( - "InstanceAccessManager", - accessManagerInstanceOwnerSelectors, + "Instance", + instanceInstanceOwnerSelectors, INSTANCE_OWNER_ROLE()); } - - function setAndRegisterMasterInstance(address instanceAddress) + function setAndRegisterMasterInstance(address instanceAddress) external onlyOwner returns(NftId masterInstanceNftId) @@ -342,14 +374,18 @@ contract InstanceService is address instanceReaderAddress = address(instanceReader); BundleManager bundleManager = instance.getBundleManager(); address bundleManagerAddress = address(bundleManager); + InstanceStore instanceStore = instance.getInstanceStore(); + address instanceStoreAddress = address(instanceStore); if(ozAccessManagerAddress == address(0)) { revert ErrorInstanceServiceOzAccessManagerZero();} if(instanceAccessManagerAddress == address(0)) { revert ErrorInstanceServiceInstanceAccessManagerZero(); } if(instanceReaderAddress == address(0)) { revert ErrorInstanceServiceInstanceReaderZero(); } if(bundleManagerAddress == address(0)) { revert ErrorInstanceServiceBundleManagerZero(); } + if(instanceStoreAddress == address(0)) { revert ErrorInstanceServiceInstanceStoreZero(); } if(instance.authority() != instanceAccessManager.authority()) { revert ErrorInstanceServiceInstanceAuthorityMismatch(); } if(bundleManager.authority() != instanceAccessManager.authority()) { revert ErrorInstanceServiceBundleManagerAuthorityMismatch(); } + if(instanceStore.authority() != instanceAccessManager.authority()) { revert ErrorInstanceServiceInstanceStoreAuthorityMismatch(); } if(instanceReader.getInstance() != instance) { revert ErrorInstanceServiceInstanceReaderInstanceMismatch2(); } if(bundleManager.getInstance() != instance) { revert ErrorInstanceServiceBundleMangerInstanceMismatch(); } @@ -358,13 +394,12 @@ contract InstanceService is _masterInstance = instanceAddress; _masterInstanceReader = instanceReaderAddress; _masterInstanceBundleManager = bundleManagerAddress; + _masterInstanceStore = instanceStoreAddress; IRegistryService registryService = IRegistryService(getRegistry().getServiceAddress(REGISTRY(), getVersion().toMajorPart())); IInstance masterInstance = IInstance(_masterInstance); IRegistry.ObjectInfo memory info = registryService.registerInstance(masterInstance, getOwner()); masterInstanceNftId = info.nftId; - - // masterInstance.linkToRegisteredNftId(); } function setMasterInstanceReader(address instanceReaderAddress) external onlyOwner { @@ -449,7 +484,7 @@ contract InstanceService is InstanceAccessManager accessManager = instance.getInstanceAccessManager(); accessManager.createGifTarget(targetAddress, targetName); // set proposed target config - // TODO restriction: for gif targets can set only once and only here? + // TODO restriction: gif targets are set only once and only here? // assume config is a mix of gif and custom roles and no further configuration by INSTANCE_OWNER_ROLE is ever needed? for(uint roleIdx = 0; roleIdx < roles.length; roleIdx++) { @@ -468,7 +503,7 @@ contract InstanceService is registry.getObjectInfo( instanceNftId).objectAddress); - instance.getInstanceAccessManager().setTargetLocked( + instance.getInstanceAccessManager().setTargetLockedByService( componentAddress, locked); } diff --git a/contracts/instance/InstanceStore.sol b/contracts/instance/InstanceStore.sol new file mode 100644 index 000000000..639224b95 --- /dev/null +++ b/contracts/instance/InstanceStore.sol @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {AccessManagedUpgradeable} from "@openzeppelin/contracts-upgradeable/access/manager/AccessManagedUpgradeable.sol"; + +import {Key32, KeyId, Key32Lib} from "../types/Key32.sol"; +import {NftId} from "../types/NftId.sol"; +import {ClaimId} from "../types/ClaimId.sol"; +import {NumberId} from "../types/NumberId.sol"; +import {ObjectType, BUNDLE, DISTRIBUTION, INSTANCE, POLICY, POOL, ROLE, PRODUCT, TARGET, COMPONENT, DISTRIBUTOR, DISTRIBUTOR_TYPE} from "../types/ObjectType.sol"; +import {RiskId, RiskIdLib} from "../types/RiskId.sol"; +import {RoleId, RoleIdLib, INSTANCE_ROLE, INSTANCE_OWNER_ROLE} from "../types/RoleId.sol"; +import {StateId, ACTIVE} from "../types/StateId.sol"; +import {TimestampLib} from "../types/Timestamp.sol"; +import {VersionPart, VersionPartLib} from "../types/Version.sol"; + +//import {IRegistry} from "../registry/IRegistry.sol"; + +import {IInstance} from "./IInstance.sol"; +import {KeyValueStore} from "./base/KeyValueStore.sol"; +import {IKeyValueStore} from "./base/KeyValueStore.sol"; + +import {IBundle} from "./module/IBundle.sol"; +import {IComponents} from "./module/IComponents.sol"; +import {IDistribution} from "./module/IDistribution.sol"; +import {IPolicy} from "./module/IPolicy.sol"; +import {IRisk} from "./module/IRisk.sol"; +import {ISetup} from "./module/ISetup.sol"; + + +// TODO combine with instance reader? +contract InstanceStore is AccessManagedUpgradeable, KeyValueStore +{ + function initialize(address instance) + public + initializer() + { + address authority = IInstance(instance).authority(); + __AccessManaged_init(authority); + initializeLifecycle(); + } + + //--- ProductSetup ------------------------------------------------------// + function createProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup) external restricted() { + create(_toNftKey32(productNftId, PRODUCT()), abi.encode(setup)); + } + + function updateProductSetup(NftId productNftId, ISetup.ProductSetupInfo memory setup, StateId newState) external restricted() { + update(_toNftKey32(productNftId, PRODUCT()), abi.encode(setup), newState); + } + + function updateProductSetupState(NftId productNftId, StateId newState) external restricted() { + updateState(_toNftKey32(productNftId, PRODUCT()), newState); + } + + //--- DistributionSetup ------------------------------------------------------// + function createDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup) external restricted() { + create(_toNftKey32(distributionNftId, DISTRIBUTION()), abi.encode(setup)); + } + + function updateDistributionSetup(NftId distributionNftId, ISetup.DistributionSetupInfo memory setup, StateId newState) external restricted() { + update(_toNftKey32(distributionNftId, DISTRIBUTION()), abi.encode(setup), newState); + } + + function updateDistributionSetupState(NftId distributionNftId, StateId newState) external restricted() { + updateState(_toNftKey32(distributionNftId, DISTRIBUTION()), newState); + } + + //--- PoolSetup ------------------------------------------------------// + function createPoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info) external restricted() { + create(_toNftKey32(poolNftId, POOL()), abi.encode(info)); + } + + function updatePoolSetup(NftId poolNftId, IComponents.ComponentInfo memory info, StateId newState) external restricted() { + update(_toNftKey32(poolNftId, POOL()), abi.encode(info), newState); + } + + function updatePoolSetupState(NftId poolNftId, StateId newState) external restricted() { + updateState(_toNftKey32(poolNftId, POOL()), newState); + } + + //--- DistributorType -------------------------------------------------------// + function createDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info) external restricted() { + create(distributorKey, abi.encode(info)); + } + + function updateDistributorType(Key32 distributorKey, IDistribution.DistributorTypeInfo memory info, StateId newState) external restricted() { + update(distributorKey, abi.encode(info), newState); + } + + function updateDistributorTypeState(Key32 distributorKey, StateId newState) external restricted() { + updateState(distributorKey, newState); + } + + //--- Distributor -------------------------------------------------------// + function createDistributor(NftId nftId, IDistribution.DistributorInfo memory info) external restricted() { + create(toDistributorKey32(nftId), abi.encode(info)); + } + + function updateDistributor(NftId nftId, IDistribution.DistributorInfo memory info, StateId newState) external restricted() { + update(toDistributorKey32(nftId), abi.encode(info), newState); + } + + function updateDistributorState(NftId nftId, StateId newState) external restricted() { + updateState(toDistributorKey32(nftId), newState); + } + + //--- Referral ----------------------------------------------------------// + function createReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo) external restricted() { + create(referralKey, abi.encode(referralInfo)); + } + + function updateReferral(Key32 referralKey, IDistribution.ReferralInfo memory referralInfo, StateId newState) external restricted() { + update(referralKey, abi.encode(referralInfo), newState); + } + + function updateReferralState(Key32 referralKey, StateId newState) external restricted() { + updateState(referralKey, newState); + } + + //--- Bundle ------------------------------------------------------------// + function createBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle) external restricted() { + create(toBundleKey32(bundleNftId), abi.encode(bundle)); + } + + function updateBundle(NftId bundleNftId, IBundle.BundleInfo memory bundle, StateId newState) external restricted() { + update(toBundleKey32(bundleNftId), abi.encode(bundle), newState); + } + + function updateBundleState(NftId bundleNftId, StateId newState) external restricted() { + updateState(toBundleKey32(bundleNftId), newState); + } + + //--- Risk --------------------------------------------------------------// + function createRisk(RiskId riskId, IRisk.RiskInfo memory risk) external restricted() { + create(riskId.toKey32(), abi.encode(risk)); + } + + function updateRisk(RiskId riskId, IRisk.RiskInfo memory risk, StateId newState) external restricted() { + update(riskId.toKey32(), abi.encode(risk), newState); + } + + function updateRiskState(RiskId riskId, StateId newState) external restricted() { + updateState(riskId.toKey32(), newState); + } + + //--- Application (Policy) ----------------------------------------------// + function createApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy) external restricted() { + create(toPolicyKey32(applicationNftId), abi.encode(policy)); + } + + function updateApplication(NftId applicationNftId, IPolicy.PolicyInfo memory policy, StateId newState) external restricted() { + update(toPolicyKey32(applicationNftId), abi.encode(policy), newState); + } + + function updateApplicationState(NftId applicationNftId, StateId newState) external restricted() { + updateState(toPolicyKey32(applicationNftId), newState); + } + + //--- Policy ------------------------------------------------------------// + function updatePolicy(NftId policyNftId, IPolicy.PolicyInfo memory policy, StateId newState) external restricted() { + update(toPolicyKey32(policyNftId), abi.encode(policy), newState); + } + + function updatePolicyState(NftId policyNftId, StateId newState) external restricted() { + updateState(toPolicyKey32(policyNftId), newState); + } + + //--- Claim -------------------------------------------------------------// + function createClaim(NftId policyNftId, ClaimId claimId, IPolicy.ClaimInfo memory claim) external restricted() { + create(toPolicyKey32(policyNftId), abi.encode(claim)); + } + + function updateClaim(NftId policyNftId, ClaimId claimId, IPolicy.ClaimInfo memory claim, StateId newState) external restricted() { + update(toPolicyKey32(policyNftId), abi.encode(claim), newState); + } + + function updateClaimState(NftId policyNftId, ClaimId claimId, StateId newState) external restricted() { + updateState(toPolicyKey32(policyNftId), newState); + } + + //--- Payout ------------------------------------------------------------// + function createPayout(NftId policyNftId, NumberId payoutId, IPolicy.PayoutInfo memory payout) external restricted() { + create(toPolicyKey32(policyNftId), abi.encode(payout)); + } + + function updatePayout(NftId policyNftId, NumberId payoutId, IPolicy.PayoutInfo memory payout, StateId newState) external restricted() { + update(toPolicyKey32(policyNftId), abi.encode(payout), newState); + } + + function updatePayoutState(NftId policyNftId, StateId newState) external restricted() { + updateState(toPolicyKey32(policyNftId), newState); + } + + //--- internal view/pure functions --------------------------------------// + function _toNftKey32(NftId nftId, ObjectType objectType) internal pure returns (Key32) { + return nftId.toKey32(objectType); + } + + function toBundleKey32(NftId bundleNftId) public pure returns (Key32) { + return bundleNftId.toKey32(BUNDLE()); + } + + function toPolicyKey32(NftId policyNftId) public pure returns (Key32) { + return policyNftId.toKey32(POLICY()); + } + + function toDistributionKey32(NftId distNftId) public pure returns (Key32) { + return distNftId.toKey32(DISTRIBUTION()); + } + + function toDistributorTypeKey32(NftId distNftId) public pure returns (Key32) { + return distNftId.toKey32(DISTRIBUTOR_TYPE()); + } + + function toDistributorKey32(NftId distNftId) public pure returns (Key32) { + return distNftId.toKey32(DISTRIBUTOR()); + } +} diff --git a/contracts/instance/service/ApplicationService.sol b/contracts/instance/service/ApplicationService.sol index 5d625ef2c..384af5552 100644 --- a/contracts/instance/service/ApplicationService.sol +++ b/contracts/instance/service/ApplicationService.sol @@ -44,6 +44,7 @@ import {IDistributionService} from "./IDistributionService.sol"; import {IPoolService} from "./IPoolService.sol"; import {IService} from "../../shared/IService.sol"; import {Service} from "../../shared/Service.sol"; +import {InstanceStore} from "../InstanceStore.sol"; contract ApplicationService is @@ -135,7 +136,7 @@ contract ApplicationService is zeroTimestamp() ); - instance.createApplication(applicationNftId, policyInfo); + instance.getInstanceStore().createApplication(applicationNftId, policyInfo); // TODO: add logging } @@ -173,7 +174,7 @@ contract ApplicationService is virtual override { (,, IInstance instance) = _getAndVerifyComponentInfoAndInstance(PRODUCT()); - instance.updateApplicationState(applicationNftId, REVOKED()); + instance.getInstanceStore().updateApplicationState(applicationNftId, REVOKED()); } // TODO: maybe move this to a pricing service later diff --git a/contracts/instance/service/BundleService.sol b/contracts/instance/service/BundleService.sol index fa8b605b0..fcb3f7f38 100644 --- a/contracts/instance/service/BundleService.sol +++ b/contracts/instance/service/BundleService.sol @@ -106,7 +106,7 @@ contract BundleService is // save updated pool info componentInfo.data = abi.encode(poolInfo); - instance.updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); + instance.getInstanceStore().updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); } } @@ -154,7 +154,7 @@ contract BundleService is ); // create bundle info in instance - instance.createBundle(bundleNftId, bundleInfo); + instance.getInstanceStore().createBundle(bundleNftId, bundleInfo); // put bundle under bundle managemet BundleManager bundleManager = instance.getBundleManager(); @@ -187,7 +187,7 @@ contract BundleService is bundleInfo.fee = fee; - instance.updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); + instance.getInstanceStore().updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); } @@ -256,7 +256,7 @@ contract BundleService is } // save updated bundle info - instance.updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); + instance.getInstanceStore().updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); } @@ -267,7 +267,7 @@ contract BundleService is (,, IInstance instance) = _getAndVerifyComponentInfoAndInstance(POOL()); // udpate bundle state - instance.updateBundleState(bundleNftId, PAUSED()); + instance.getInstanceStore().updateBundleState(bundleNftId, PAUSED()); // update set of active bundles BundleManager bundleManager = instance.getBundleManager(); @@ -284,7 +284,7 @@ contract BundleService is (,, IInstance instance) = _getAndVerifyComponentInfoAndInstance(POOL()); // udpate bundle state - instance.updateBundleState(bundleNftId, ACTIVE()); + instance.getInstanceStore().updateBundleState(bundleNftId, ACTIVE()); // update set of active bundles BundleManager bundleManager = instance.getBundleManager(); @@ -303,7 +303,7 @@ contract BundleService is // TODO add restricted and autz for pool service { // udpate bundle state - instance.updateBundleState(bundleNftId, CLOSED()); + instance.getInstanceStore().updateBundleState(bundleNftId, CLOSED()); // ensure no open policies attached to bundle BundleManager bundleManager = instance.getBundleManager(); @@ -348,7 +348,7 @@ contract BundleService is // reduce locked amount by released collateral amount bundleInfo.lockedAmount = AmountLib.toAmount(bundleInfo.lockedAmount.toInt() - collateralAmount); - instance.updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); + instance.getInstanceStore().updateBundle(bundleNftId, bundleInfo, KEEP_STATE()); _unlinkPolicy(instance, policyNftId); } @@ -364,7 +364,7 @@ contract BundleService is if (policyInfo.activatedAt.gtz() && policyInfo.activatedAt < TimestampLib.blockTimestamp()) { revert BundleManager.ErrorBundleManagerPolicyAlreadyActivated(policyNftId); } - + BundleManager bundleManager = instance.getBundleManager(); bundleManager.linkPolicy(policyNftId); } diff --git a/contracts/instance/service/DistributionService.sol b/contracts/instance/service/DistributionService.sol index 432b05f25..472ac9851 100644 --- a/contracts/instance/service/DistributionService.sol +++ b/contracts/instance/service/DistributionService.sol @@ -33,6 +33,7 @@ import {ReferralId, ReferralStatus, ReferralLib} from "../../types/Referral.sol" import {Timestamp, TimestampLib, zeroTimestamp} from "../../types/Timestamp.sol"; import {Key32} from "../../types/Key32.sol"; import {IDistribution} from "../module/IDistribution.sol"; +import {InstanceStore} from "../InstanceStore.sol"; contract DistributionService is @@ -87,7 +88,7 @@ contract DistributionService is distribution.linkToRegisteredNftId(); distributionNftId = distributionInfo.nftId; - instance.createDistributionSetup(distributionNftId, distribution.getSetupInfo()); + instance.getInstanceStore().createDistributionSetup(distributionNftId, distribution.getSetupInfo()); // TODO move to distribution? bytes4[][] memory selectors = new bytes4[][](2); selectors[0] = new bytes4[](1); @@ -126,7 +127,7 @@ contract DistributionService is distSetupInfo.minDistributionOwnerFee = minDistributionOwnerFee; distSetupInfo.distributionFee = distributionFee; - instance.updateDistributionSetup(distributionNftId, distSetupInfo, KEEP_STATE()); + instance.getInstanceStore().updateDistributionSetup(distributionNftId, distSetupInfo, KEEP_STATE()); } function createDistributorType( @@ -157,7 +158,7 @@ contract DistributionService is distributorType = DistributorTypeLib.toDistributorType(distributionNftId, name); Key32 key32 = distributorType.toKey32(); - if(!instance.exists(key32)) { + if(!instance.getInstanceStore().exists(key32)) { IDistribution.DistributorTypeInfo memory info = IDistribution.DistributorTypeInfo( name, minDiscountPercentage, @@ -169,7 +170,7 @@ contract DistributionService is allowRenewals, data); - instance.createDistributorType(key32, info); + instance.getInstanceStore().createDistributorType(key32, info); } } @@ -199,7 +200,7 @@ contract DistributionService is 0, 0); - instance.createDistributor(distributorNftId, info); + instance.getInstanceStore().createDistributor(distributorNftId, info); } function updateDistributorType( @@ -213,7 +214,7 @@ contract DistributionService is IDistribution.DistributorInfo memory distributorInfo = instanceReader.getDistributorInfo(distributorNftId); distributorInfo.distributorType = distributorType; distributorInfo.data = data; - instance.updateDistributor(distributorNftId, distributorInfo, KEEP_STATE()); + instance.getInstanceStore().updateDistributor(distributorNftId, distributorInfo, KEEP_STATE()); } @@ -267,7 +268,7 @@ contract DistributionService is data ); - instance.createReferral(referralId.toKey32(), info); + instance.getInstanceStore().createReferral(referralId.toKey32(), info); return referralId; } @@ -289,6 +290,7 @@ contract DistributionService is IInstance instance = _getInstanceForDistribution(distributionNftId); InstanceReader reader = instance.getInstanceReader(); + InstanceStore store = instance.getInstanceStore(); IDistribution.ReferralInfo memory referralInfo = reader.getReferralInfo(referralId); IDistribution.DistributorInfo memory distributorInfo = reader.getDistributorInfo(referralInfo.distributorNftId); ISetup.DistributionSetupInfo memory setupInfo = reader.getDistributionSetupInfo(distributionNftId); @@ -303,17 +305,17 @@ contract DistributionService is if (distributionOwnerFee > 0) { setupInfo.sumDistributionOwnerFees += distributionOwnerFee; - instance.updateDistributionSetup(distributionNftId, setupInfo, KEEP_STATE()); + store.updateDistributionSetup(distributionNftId, setupInfo, KEEP_STATE()); } if (isReferral) { referralInfo.usedReferrals += 1; - instance.updateReferral(referralId.toKey32(), referralInfo, KEEP_STATE()); + store.updateReferral(referralId.toKey32(), referralInfo, KEEP_STATE()); if (commissionAmount > 0) { distributorInfo.sumCommisions += commissionAmount; distributorInfo.numPoliciesSold += 1; - instance.updateDistributor(referralInfo.distributorNftId, distributorInfo, KEEP_STATE()); + store.updateDistributor(referralInfo.distributorNftId, distributorInfo, KEEP_STATE()); } } } @@ -432,4 +434,4 @@ contract DistributionService is address instanceAddress = getRegistry().getObjectInfo(instanceNftId).objectAddress; return IInstance(instanceAddress); } -} +} \ No newline at end of file diff --git a/contracts/instance/service/PolicyService.sol b/contracts/instance/service/PolicyService.sol index 543e9f59b..db2a20748 100644 --- a/contracts/instance/service/PolicyService.sol +++ b/contracts/instance/service/PolicyService.sol @@ -162,7 +162,7 @@ contract PolicyService is } // store updated policy info - instance.updatePolicy(applicationNftId, applicationInfo, newPolicyState); + instance.getInstanceStore().updatePolicy(applicationNftId, applicationInfo, newPolicyState); // lock collateral and update pool and bundle book keeping // pool retention level: fraction of sum insured that product will cover from pool funds directly @@ -206,7 +206,7 @@ contract PolicyService is policyInfo.premiumPaidAmount += unpaidPremiumAmount; _bundleService.increaseBalance(instance, policyInfo.bundleNftId, netPremiumAmount); - instance.updatePolicy(policyNftId, policyInfo, KEEP_STATE()); + instance.getInstanceStore().updatePolicy(policyNftId, policyInfo, KEEP_STATE()); if(activateAt.gtz() && policyInfo.activatedAt.eqz()) { activate(policyNftId, activateAt); @@ -229,7 +229,7 @@ contract PolicyService is policyInfo.activatedAt = activateAt; policyInfo.expiredAt = activateAt.addSeconds(policyInfo.lifetime); - instance.updatePolicy(policyNftId, policyInfo, ACTIVE()); + instance.getInstanceStore().updatePolicy(policyNftId, policyInfo, ACTIVE()); // TODO: add logging } @@ -288,7 +288,7 @@ contract PolicyService is policyNftId, policyInfo); - instance.updatePolicy(policyNftId, policyInfo, CLOSED()); + instance.getInstanceStore().updatePolicy(policyNftId, policyInfo, CLOSED()); } function _getPoolNftId( diff --git a/contracts/instance/service/PoolService.sol b/contracts/instance/service/PoolService.sol index 5e7e360e3..3f7c875bd 100644 --- a/contracts/instance/service/PoolService.sol +++ b/contracts/instance/service/PoolService.sol @@ -95,7 +95,7 @@ contract PoolService is componentInfo.tokenHandler = new TokenHandler(address(componentInfo.token)); // save amended component info with instance - instance.createPoolSetup(poolNftId, componentInfo); + instance.getInstanceStore().createPoolSetup(poolNftId, componentInfo); bytes4[][] memory selectors = new bytes4[][](2); selectors[0] = new bytes4[](1); @@ -130,7 +130,7 @@ contract PoolService is poolInfo.maxCapitalAmount = maxCapitalAmount; componentInfo.data = abi.encode(poolInfo); - instance.updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); + instance.getInstanceStore().updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); emit LogPoolServiceMaxCapitalAmountUpdated(poolNftId, previousMaxCapitalAmount, maxCapitalAmount); } @@ -152,7 +152,7 @@ contract PoolService is poolInfo.bundleOwnerRole = bundleOwnerRole; componentInfo.data = abi.encode(poolInfo); - instance.updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); + instance.getInstanceStore().updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); emit LogPoolServiceBundleOwnerRoleSet(poolNftId, bundleOwnerRole); } @@ -176,7 +176,7 @@ contract PoolService is poolInfo.stakingFee = stakingFee; poolInfo.performanceFee = performanceFee; componentInfo.data = abi.encode(poolInfo); - instance.updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); + instance.getInstanceStore().updatePoolSetup(poolNftId, componentInfo, KEEP_STATE()); // TODO add logging } diff --git a/contracts/instance/service/ProductService.sol b/contracts/instance/service/ProductService.sol index 32bdce281..4b8944d08 100644 --- a/contracts/instance/service/ProductService.sol +++ b/contracts/instance/service/ProductService.sol @@ -111,7 +111,7 @@ contract ProductService is ComponentService, IProductService { product.linkToRegisteredNftId(); // create product setup in instance - instance.createProductSetup(productNftId, product.getSetupInfo()); + instance.getInstanceStore().createProductSetup(productNftId, product.getSetupInfo()); bytes4[][] memory selectors = new bytes4[][](1); selectors[0] = new bytes4[](1); @@ -165,7 +165,7 @@ contract ProductService is ComponentService, IProductService { productSetupInfo.productFee = productFee; productSetupInfo.processingFee = processingFee; - instance.updateProductSetup(productNftId, productSetupInfo, KEEP_STATE()); + instance.getInstanceStore().updateProductSetup(productNftId, productSetupInfo, KEEP_STATE()); } function createRisk( @@ -177,8 +177,7 @@ contract ProductService is ComponentService, IProductService { { (NftId productNftId, IRegistry.ObjectInfo memory productInfo, IInstance instance) = _getAndVerifyComponentInfoAndInstance(PRODUCT()); IRisk.RiskInfo memory riskInfo = IRisk.RiskInfo(productNftId, data); - - instance.createRisk( + instance.getInstanceStore().createRisk( riskId, riskInfo ); @@ -195,16 +194,16 @@ contract ProductService is ComponentService, IProductService { IRisk.RiskInfo memory riskInfo = instanceReader.getRiskInfo(riskId); riskInfo.data = data; - instance.updateRisk(riskId, riskInfo, KEEP_STATE()); + instance.getInstanceStore().updateRisk(riskId, riskInfo, KEEP_STATE()); } function updateRiskState( RiskId riskId, StateId state - ) - external + ) + external { (,, IInstance instance) = _getAndVerifyComponentInfoAndInstance(PRODUCT()); - instance.updateRiskState(riskId, state); + instance.getInstanceStore().updateRiskState(riskId, state); } } diff --git a/contracts/registry/ReleaseConfigV3.solx b/contracts/registry/ReleaseConfigV3.solx new file mode 100644 index 000000000..a9b0cf497 --- /dev/null +++ b/contracts/registry/ReleaseConfigV3.solx @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol"; + +import {NftId} from "../types/NftId.sol"; +import {RoleId} from "../types/RoleId.sol"; +import {ObjectType, ObjectTypeLib, zeroObjectType, REGISTRY, SERVICE} from "../types/ObjectType.sol"; +import {VersionPart, VersionPartLib} from "../types/Version.sol"; +import {Timestamp, TimestampLib} from "../types/Timestamp.sol"; + +import {IService} from "../shared/IService.sol"; + +import {IRegistry} from "./IRegistry.sol"; +import {Registry} from "./Registry.sol"; +import {IRegistryService} from "./IRegistryService.sol"; +import {RegistryAccessManager} from "./RegistryAccessManager.sol"; + + +contract ReleaseConfigV3 is IReleaseConfig +{ + // USED BY REGISTRY ACCESS MANAGER + + // domain-function set to connect services to registry service + function getFunctionConfigs() + external + pure + returns( + FunctionConfig[] memory config + ) + { + config = new FunctionConfig[](8); + + // order of service registrations MUST be reverse to this array + /*config[-1].serviceDomain = STAKE(); + config[-1].selector = RegistryService.registerStake.selector;*/ + + config[0].serviceDomain = POLICY(); + config[0].selectors = new bytes4[](0); + + config[1].serviceDomain = APPLICATION(); + config[1].selectors = new bytes4[](1); + config[1].selectors[0] = RegistryService.registerPolicy.selector; + + config[2].serviceDomain = CLAIM(); + config[2].selectors = new bytes4[](0); + + config[3].serviceDomain = BUNDLE(); + config[3].selectors = new bytes4[](1); + config[3].selectors[0] = RegistryService.registerBundle.selector; + + config[4].serviceDomain = PRODUCT(); + config[4].selectors = new bytes4[](1); + config[4].selectors[0] = RegistryService.registerProduct.selector; + + config[5].serviceDomain = POOL(); + config[5].selectors = new bytes4[](1); + config[5].selectors[0] = RegistryService.registerPool.selector; + + config[6].serviceDomain = DISTRIBUTION(); + config[6].selectors = new bytes4[](2); + config[6].selectors[0] = RegistryService.registerDistribution.selector; + config[6].selectors[1] = RegistryService.registerDistributor.selector; + + // registerInstance() have no restriction + config[7].serviceDomain = INSTANCE(); + config[7].selectors = new bytes4[](1); + config[7].selectors[0] = RegistryService.registerInstance.selector; + } + + // USED BY RELESASE ACCESS MANAGER + + // set of all roles in release + + // role-function set for each service in release + + // precalculated address of each service in release + // 1. upon service registration its authority is checked + // service must know release access manager at initialization time + // release access manager is created during createNextRelease() where precalculated addresses of all services also must be known + // 1. precalculate next release access manager address + // 2. precalculate addresses of all service with 1). + // 3. call createNextRelease() giving all addresses 2) + // release access manager get deployed to address 1). + // 4. each service get deployed and registered + +} diff --git a/scripts/deploy_all.ts b/scripts/deploy_all.ts index a94dccb30..d8e8eddd6 100644 --- a/scripts/deploy_all.ts +++ b/scripts/deploy_all.ts @@ -184,6 +184,7 @@ function printAddresses( addresses += `masterInstanceAccessManagerAddress: ${masterInstance.instanceAccessManagerAddress}\n`; addresses += `masterBundleManagerAddress: ${masterInstance.instanceBundleManagerAddress}\n`; addresses += `masterInstanceReaderAddress: ${masterInstance.instanceReaderAddress}\n`; + addresses += `masterInstanceStoreAddress: ${masterInstance.instanceStoreAddress}\n`; addresses += `--------\n`; addresses += `clonedInstanceAddress: ${clonedInstance.instanceAddress}\n`; addresses += `clonedInstanceNftId: ${clonedInstance.instanceNftId}\n`; diff --git a/scripts/libs/instance.ts b/scripts/libs/instance.ts index b57f2dcfc..4fe72c461 100644 --- a/scripts/libs/instance.ts +++ b/scripts/libs/instance.ts @@ -1,5 +1,5 @@ import { AddressLike, Signer, ethers, resolveAddress } from "ethers"; -import { BundleManager, IRegistry__factory, Instance, InstanceAccessManager, InstanceService__factory, InstanceReader, AccessManagerUpgradeableInitializeable } from "../../typechain-types"; +import { BundleManager, IRegistry__factory, Instance, InstanceAccessManager, InstanceService__factory, InstanceReader, AccessManagerUpgradeableInitializeable, InstanceStore } from "../../typechain-types"; import { logger } from "../logger"; import { deployContract } from "./deployment"; import { LibraryAddresses } from "./libraries"; @@ -12,6 +12,7 @@ export type InstanceAddresses = { instanceAccessManagerAddress: AddressLike, instanceReaderAddress: AddressLike, instanceBundleManagerAddress: AddressLike, + instanceStoreAddress: AddressLike, instanceAddress: AddressLike, instanceNftId: string, } @@ -45,11 +46,7 @@ export async function deployAndRegisterMasterInstance( undefined, { libraries: { - Key32Lib: libraries.key32LibAddress, NftIdLib: libraries.nftIdLibAddress, - ObjectTypeLib: libraries.objectTypeLibAddress, - RiskIdLib: libraries.riskIdLibAddress, - StateIdLib: libraries.stateIdLibAddress, VersionPartLib: libraries.versionPartLibAddress, RoleIdLib: libraries.roleIdLibAddress, } @@ -75,6 +72,24 @@ export async function deployAndRegisterMasterInstance( await executeTx(() => instanceAccessManager.initialize(instanceAddress)); await executeTx(() => instance.setInstanceAccessManager(instanceAccessManager)); + const { address: instanceStoreAddress, contract: masterInstanceStoreContract } = await deployContract( + "InstanceStore", + owner, + [], + { + libraries: { + Key32Lib: libraries.key32LibAddress, + NftIdLib: libraries.nftIdLibAddress, + ObjectTypeLib: libraries.objectTypeLibAddress, + RiskIdLib: libraries.riskIdLibAddress, + StateIdLib: libraries.stateIdLibAddress + } + } + ); + const instanceStore = masterInstanceStoreContract as InstanceStore; + await executeTx(() => instanceStore.initialize(instanceAddress)); + await executeTx(() => instance.setInstanceStore(instanceStore)); + const { address: instanceReaderAddress, contract: masterReaderBaseContract } = await deployContract( "InstanceReader", owner, @@ -133,6 +148,7 @@ export async function deployAndRegisterMasterInstance( instanceAccessManagerAddress: instanceAccessManagerAddress, instanceReaderAddress: instanceReaderAddress, instanceBundleManagerAddress: bundleManagerAddress, + instanceStoreAddress: instanceStoreAddress, instanceAddress: instanceAddress, instanceNftId: masterInstanceNfdId, } as InstanceAddresses; diff --git a/test_forge/TestDeployAll.t.sol b/test_forge/TestDeployAll.t.sol index 7922a290c..281f756ae 100644 --- a/test_forge/TestDeployAll.t.sol +++ b/test_forge/TestDeployAll.t.sol @@ -51,10 +51,10 @@ contract TestDeployAll is TestGifBase { function testDeployAllInstanceLifecycles() public { - assertTrue(instance.hasLifecycle(BUNDLE()), "instance misses bundle lifecycle"); - assertTrue(instance.hasLifecycle(COMPONENT()), "instance misses component lifecycle"); - assertTrue(instance.hasLifecycle(POLICY()), "instance misses policy lifecycle"); - assertTrue(instance.hasLifecycle(RISK()), "instance misses risk lifecycle"); + assertTrue(instance.getInstanceStore().hasLifecycle(BUNDLE()), "instance misses bundle lifecycle"); + assertTrue(instance.getInstanceStore().hasLifecycle(COMPONENT()), "instance misses component lifecycle"); + assertTrue(instance.getInstanceStore().hasLifecycle(POLICY()), "instance misses policy lifecycle"); + assertTrue(instance.getInstanceStore().hasLifecycle(RISK()), "instance misses risk lifecycle"); } diff --git a/test_forge/TestProduct.t.sol b/test_forge/TestProduct.t.sol index 40f93e0cc..2d703bbf6 100644 --- a/test_forge/TestProduct.t.sol +++ b/test_forge/TestProduct.t.sol @@ -140,7 +140,7 @@ contract TestProduct is TestGifBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); IPolicy.PolicyInfo memory policyInfo = instanceReader.getPolicyInfo(policyNftId); assertTrue(eqRiskId(policyInfo.riskId, riskId), "riskId not set"); @@ -176,7 +176,7 @@ contract TestProduct is TestGifBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); // WHEN bool requirePremiumPayment = false; @@ -240,7 +240,7 @@ contract TestProduct is TestGifBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); vm.stopPrank(); @@ -348,7 +348,7 @@ contract TestProduct is TestGifBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); // WHEN dproduct.underwrite(policyNftId, false, zeroTimestamp()); @@ -416,7 +416,7 @@ contract TestProduct is TestGifBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == UNDERWRITTEN(), "state not UNDERWRITTEN"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == UNDERWRITTEN(), "state not UNDERWRITTEN"); IBundle.BundleInfo memory bundleInfoBefore = instanceReader.getBundleInfo(bundleNftId); assertEq(bundleInfoBefore.lockedAmount.toInt(), 1000, "lockedAmount not 1000 (before)"); diff --git a/test_forge/base/TestGifBase.sol b/test_forge/base/TestGifBase.sol index ea089774d..ad8f0d5f6 100644 --- a/test_forge/base/TestGifBase.sol +++ b/test_forge/base/TestGifBase.sol @@ -6,9 +6,27 @@ import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IER import {Test, console} from "../../lib/forge-std/src/Test.sol"; import {VersionPartLib} from "../../contracts/types/Version.sol"; +import {NftId, NftIdLib, zeroNftId} from "../../contracts/types/NftId.sol"; +import {REGISTRY, TOKEN, SERVICE, INSTANCE, POOL, ORACLE, PRODUCT, DISTRIBUTION, BUNDLE, POLICY} from "../../contracts/types/ObjectType.sol"; +import {Fee, FeeLib} from "../../contracts/types/Fee.sol"; +import { + ADMIN_ROLE, + INSTANCE_OWNER_ROLE, + PRODUCT_OWNER_ROLE, + POOL_OWNER_ROLE, + DISTRIBUTION_OWNER_ROLE} from "../../contracts/types/RoleId.sol"; +import {UFixed, UFixedLib} from "../../contracts/types/UFixed.sol"; +import {Version} from "../../contracts/types/Version.sol"; +import {IVersionable} from "../../contracts/shared/IVersionable.sol"; +import {ProxyManager} from "../../contracts/shared/ProxyManager.sol"; import {TokenHandler} from "../../contracts/shared/TokenHandler.sol"; +import {RegistryService} from "../../contracts/registry/RegistryService.sol"; +import {IRegistryService} from "../../contracts/registry/RegistryService.sol"; +import {RegistryServiceManager} from "../../contracts/registry/RegistryServiceManager.sol"; +import {RegistryAccessManager} from "../../contracts/registry/RegistryAccessManager.sol"; +import {ReleaseManager} from "../../contracts/registry/ReleaseManager.sol"; import {ChainNft} from "../../contracts/registry/ChainNft.sol"; import {Registry} from "../../contracts/registry/Registry.sol"; import {IRegistry} from "../../contracts/registry/IRegistry.sol"; @@ -27,46 +45,29 @@ import {PolicyService} from "../../contracts/instance/service/PolicyService.sol" import {PolicyServiceManager} from "../../contracts/instance/service/PolicyServiceManager.sol"; import {ClaimService} from "../../contracts/instance/service/ClaimService.sol"; import {ClaimServiceManager} from "../../contracts/instance/service/ClaimServiceManager.sol"; - import {BundleService} from "../../contracts/instance/service/BundleService.sol"; import {BundleServiceManager} from "../../contracts/instance/service/BundleServiceManager.sol"; import {InstanceService} from "../../contracts/instance/InstanceService.sol"; import {InstanceServiceManager} from "../../contracts/instance/InstanceServiceManager.sol"; + import {AccessManagerUpgradeableInitializeable} from "../../contracts/instance/AccessManagerUpgradeableInitializeable.sol"; import {InstanceAccessManager} from "../../contracts/instance/InstanceAccessManager.sol"; import {Instance} from "../../contracts/instance/Instance.sol"; import {InstanceReader} from "../../contracts/instance/InstanceReader.sol"; import {BundleManager} from "../../contracts/instance/BundleManager.sol"; import {IKeyValueStore} from "../../contracts/instance/base/IKeyValueStore.sol"; -import {TokenHandler} from "../../contracts/shared/TokenHandler.sol"; +import {InstanceStore} from "../../contracts/instance/InstanceStore.sol"; + import {Distribution} from "../../contracts/components/Distribution.sol"; import {Product} from "../../contracts/components/Product.sol"; + import {USDC} from "../../contracts/test/Usdc.sol"; import {SimpleDistribution} from "../mock/SimpleDistribution.sol"; import {SimplePool} from "../mock/SimplePool.sol"; // import {IPolicy} from "../../contracts/instance/module/policy/IPolicy.sol"; // import {IPool} from "../../contracts/instance/module/pool/IPoolModule.sol"; -import {NftId, NftIdLib, zeroNftId} from "../../contracts/types/NftId.sol"; -import {REGISTRY, TOKEN, SERVICE, INSTANCE, POOL, ORACLE, PRODUCT, DISTRIBUTION, BUNDLE, POLICY} from "../../contracts/types/ObjectType.sol"; -import {Fee, FeeLib} from "../../contracts/types/Fee.sol"; -import { - ADMIN_ROLE, - INSTANCE_OWNER_ROLE, - PRODUCT_OWNER_ROLE, - POOL_OWNER_ROLE, - DISTRIBUTION_OWNER_ROLE} from "../../contracts/types/RoleId.sol"; -import {UFixed, UFixedLib} from "../../contracts/types/UFixed.sol"; -import {Version} from "../../contracts/types/Version.sol"; - -import {ProxyManager} from "../../contracts/shared/ProxyManager.sol"; -import {IVersionable} from "../../contracts/shared/IVersionable.sol"; -import {RegistryService} from "../../contracts/registry/RegistryService.sol"; -import {IRegistryService} from "../../contracts/registry/RegistryService.sol"; -import {RegistryServiceManager} from "../../contracts/registry/RegistryServiceManager.sol"; -import {RegistryAccessManager} from "../../contracts/registry/RegistryAccessManager.sol"; -import {ReleaseManager} from "../../contracts/registry/ReleaseManager.sol"; // solhint-disable-next-line max-states-count @@ -115,16 +116,18 @@ contract TestGifBase is Test { BundleService public bundleService; NftId public bundleServiceNftId; - AccessManagerUpgradeableInitializeable masterOzAccessManager; - InstanceAccessManager masterInstanceAccessManager; - BundleManager masterBundleManager; - Instance masterInstance; - NftId masterInstanceNftId; - InstanceReader masterInstanceReader; - - AccessManagerUpgradeableInitializeable ozAccessManager; - InstanceAccessManager instanceAccessManager; - BundleManager instanceBundleManager; + AccessManagerUpgradeableInitializeable public masterOzAccessManager; + InstanceAccessManager public masterInstanceAccessManager; + BundleManager public masterBundleManager; + InstanceStore public masterInstanceStore; + Instance public masterInstance; + NftId public masterInstanceNftId; + InstanceReader public masterInstanceReader; + + AccessManagerUpgradeableInitializeable public ozAccessManager; + InstanceAccessManager public instanceAccessManager; + BundleManager public instanceBundleManager; + InstanceStore public instanceStore; Instance public instance; NftId public instanceNftId; InstanceReader public instanceReader; @@ -465,15 +468,18 @@ contract TestGifBase is Test { masterOzAccessManager = new AccessManagerUpgradeableInitializeable(); // grants registryOwner ADMIN_ROLE masterOzAccessManager.initialize(registryOwner); - - masterInstanceAccessManager = new InstanceAccessManager(); masterInstance = new Instance(); masterInstance.initialize( address(masterOzAccessManager), address(registry), registryOwner); - + // MUST be initialized and set before instance reader + masterInstanceStore = new InstanceStore(); + masterInstanceStore.initialize(address(masterInstance)); + masterInstance.setInstanceStore(masterInstanceStore); + assert(masterInstance.getInstanceStore() == masterInstanceStore); + masterInstanceReader = new InstanceReader(); masterInstanceReader.initialize(address(masterInstance)); masterInstance.setInstanceReader(masterInstanceReader); @@ -502,6 +508,7 @@ contract TestGifBase is Test { console.log("master instance access manager deployed at", address(masterInstanceAccessManager)); console.log("master instance reader deployed at", address(masterInstanceReader)); console.log("master bundle manager deployed at", address(masterBundleManager)); + console.log("master instance store deployed at", address(masterInstanceStore)); // solhint-enable } @@ -513,7 +520,8 @@ contract TestGifBase is Test { instance, instanceNftId, instanceReader, - instanceBundleManager + instanceBundleManager, + instanceStore ) = instanceService.createInstanceClone(); diff --git a/test_forge/components/distribution/Referral.t.sol b/test_forge/components/distribution/Referral.t.sol index 88df7250b..31e17b51a 100644 --- a/test_forge/components/distribution/Referral.t.sol +++ b/test_forge/components/distribution/Referral.t.sol @@ -106,7 +106,7 @@ contract ReferralTest is ReferralTestBase { assertTrue(policyNftId.gtz(), "policyNftId was zero"); assertEq(chainNft.ownerOf(policyNftId.toInt()), customer, "customer not owner of policyNftId"); - assertTrue(instance.getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); + assertTrue(instance.getInstanceStore().getState(policyNftId.toKey32(POLICY())) == APPLIED(), "state not APPLIED"); vm.stopPrank(); diff --git a/test_forge/instance/TestInstanceAccessManager.t.sol b/test_forge/instance/TestInstanceAccessManager.t.sol index 4c7b374e5..c232beaca 100644 --- a/test_forge/instance/TestInstanceAccessManager.t.sol +++ b/test_forge/instance/TestInstanceAccessManager.t.sol @@ -14,7 +14,7 @@ import {zeroNftId} from "../../contracts/types/NftId.sol"; import {FeeLib} from "../../contracts/types/Fee.sol"; import {RoleId} from "../../contracts/types/RoleId.sol"; import {TimestampLib} from "../../contracts/types/Timestamp.sol"; -import {ADMIN_ROLE, PRODUCT_SERVICE_ROLE, PRODUCT_OWNER_ROLE, POOL_OWNER_ROLE, INSTANCE_OWNER_ROLE, RoleId, RoleIdLib} from "../../contracts/types/RoleId.sol"; +import {ADMIN_ROLE, PRODUCT_SERVICE_ROLE, PRODUCT_OWNER_ROLE, POOL_OWNER_ROLE, INSTANCE_OWNER_ROLE, INSTANCE_ROLE, RoleId, RoleIdLib} from "../../contracts/types/RoleId.sol"; import {IRegisterable} from "../../contracts/shared/IRegisterable.sol"; @@ -120,11 +120,11 @@ contract TestInstanceAccessManager is TestGifBase { vm.startPrank(instanceOwner); // create special role and special role admin - (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("SpecialRole", "SpecialRoleAdmin"); + (customRoleId, customRoleAdmin) = instance.createRole("SpecialRole", "SpecialRoleAdmin"); // set special role for product custom product function bytes4[] memory fcts = new bytes4[](1); fcts[0] = SimpleProduct.doSomethingSpecial.selector; - instanceAccessManager.setTargetFunctionRole(product.getName(), fcts, customRoleId); + instance.setTargetFunctionRole(product.getName(), fcts, customRoleId); // assign special role to outsider instanceAccessManager.grantRole(customRoleAdmin, instanceOwner); //instanceAccessManager.grantRole("SpecialRole", outsider); @@ -166,7 +166,7 @@ contract TestInstanceAccessManager is TestGifBase { vm.startPrank(instanceOwner); bytes4[] memory fctSelectors = new bytes4[](1); fctSelectors[0] = SimpleProduct.doWhenNotLocked.selector; - instanceAccessManager.setTargetFunctionRole(product.getName(), fctSelectors, PRODUCT_OWNER_ROLE()); + instance.setTargetFunctionRole(product.getName(), fctSelectors, PRODUCT_OWNER_ROLE()); vm.stopPrank(); vm.startPrank(productOwner); @@ -395,7 +395,7 @@ contract TestInstanceAccessManager is TestGifBase { updatedAt: TimestampLib.blockTimestamp(), createdAt: TimestampLib.blockTimestamp() }); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("Role1234", "RoleAdmin1234"); @@ -463,7 +463,7 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_createRole_withExistingCustomRoleName() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("Role1234", "RoleAdmin1234"); @@ -479,7 +479,7 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_createRole_withExistingCustomRoleAdminName() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("Role1234", "RoleAdmin1234"); @@ -495,7 +495,7 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_createRole_withEmptyRoleName() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessRoleNameEmpty.selector, @@ -507,7 +507,9 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_createRole_withEmptyRoleAdminName() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); + + require(instanceAccessManager.hasRole(INSTANCE_ROLE(), address(instance))); vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessRoleNameEmpty.selector, @@ -604,9 +606,11 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_renounceCustomRole_HappyCase() public { - vm.startPrank(instanceOwner); - + vm.startPrank(address(instance)); (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("Role1234", "RoleAdmin1234"); + vm.stopPrank(); + + vm.startPrank(instanceOwner); assertTrue(instanceAccessManager.grantRole(customRoleAdmin, instanceOwner), "grantRole() by role admin failed #1"); assertTrue(instanceAccessManager.grantRole(customRoleId, outsider), "grantRole() by role admin failed #2"); assertTrue(instanceAccessManager.grantRole(customRoleAdmin, productOwner), "grantRole() by role admin failed #3"); @@ -631,9 +635,11 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_renounceCustomRole_byNotMember() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); (customRoleId, customRoleAdmin) = instanceAccessManager.createRole("Role1234", "RoleAdmin1234"); - + vm.stopPrank(); + + vm.startPrank(instanceOwner); assertFalse(instanceAccessManager.renounceRole(customRoleId), "renounce custom role by not member succeeded"); assertFalse(instanceAccessManager.renounceRole(customRoleAdmin), "renounce custom role admin by not member succeeded"); vm.stopPrank(); @@ -1030,7 +1036,7 @@ contract TestInstanceAccessManager is TestGifBase { updatedAt: TimestampLib.blockTimestamp() }); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); instanceAccessManager.createTarget(targetAddress, "CustomTarget1234"); vm.stopPrank(); @@ -1057,7 +1063,7 @@ contract TestInstanceAccessManager is TestGifBase { IAccessManaged target = new AccessManagedMock(address(ozAccessManager)); address targetAddress = address(target); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); instanceAccessManager.createTarget(targetAddress, "CustomTarget1234"); @@ -1072,7 +1078,7 @@ contract TestInstanceAccessManager is TestGifBase { function test_InstanceAccessManager_createTarget_withZeroTargetAddress() public { - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); vm.expectRevert(); instanceAccessManager.createTarget(address(0), "CustomTarget1234"); vm.stopPrank(); @@ -1086,7 +1092,7 @@ contract TestInstanceAccessManager is TestGifBase { IAccessManaged target2 = new AccessManagedMock(address(ozAccessManager)); address targetAddress2 = address(target2); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); instanceAccessManager.createTarget(targetAddress1, "CustomTarget1234"); @@ -1105,7 +1111,7 @@ contract TestInstanceAccessManager is TestGifBase { IAccessManaged target = new AccessManagedMock(address(ozAccessManager)); address targetAddress = address(target); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessTargetNameEmpty.selector, @@ -1121,7 +1127,7 @@ contract TestInstanceAccessManager is TestGifBase { IAccessManaged target = new AccessManagedMock(address(accessManager)); address targetAddress = address(target); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessTargetAuthorityInvalid.selector, @@ -1134,7 +1140,7 @@ contract TestInstanceAccessManager is TestGifBase { //--- Set target locked -----------------------------------------------------// - function test_InstanceAccessManager_setTargetLocked_ToggleCoreTarget() public + function test_InstanceAccessManager_setTargetLockedByService_ToggleCoreTarget() public { vm.startPrank(address(instanceService)); address targetAddress = instanceAccessManager.getTargetAddress("Instance"); @@ -1143,18 +1149,18 @@ contract TestInstanceAccessManager is TestGifBase { IAccess.ErrorIAccessTargetTypeInvalid.selector, targetAddress, IAccess.Type.Core)); - instanceAccessManager.setTargetLocked(targetAddress, true); + instanceAccessManager.setTargetLockedByService(targetAddress, true); vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessTargetTypeInvalid.selector, targetAddress, IAccess.Type.Core)); - instanceAccessManager.setTargetLocked(targetAddress, false); + instanceAccessManager.setTargetLockedByService(targetAddress, false); vm.stopPrank(); } - function test_InstanceAccessManager_setTargetLocked_ToggleGifTarget() public + function test_InstanceAccessManager_setTargetLockedByService_ToggleGifTarget() public { vm.startPrank(instanceOwner); IRegisterable gifTarget = new SimpleAccessManagedRegisterableMock(instanceNftId, PRODUCT(), address(ozAccessManager)); @@ -1170,39 +1176,39 @@ contract TestInstanceAccessManager is TestGifBase { assertEq(instanceAccessManager.getTargetAddress("GifTarget1234"), gifTargetAddress, "unexpected target address"); - instanceAccessManager.setTargetLocked(gifTargetAddress, true); + instanceAccessManager.setTargetLockedByService(gifTargetAddress, true); assertTrue(instanceAccessManager.isTargetLocked(gifTargetAddress), "gif target is not locked"); - instanceAccessManager.setTargetLocked(gifTargetAddress, false); + instanceAccessManager.setTargetLockedByService(gifTargetAddress, false); vm.stopPrank(); assertFalse(instanceAccessManager.isTargetLocked(gifTargetAddress), "gif target is locked"); } - function test_InstanceAccessManager_setTargetLocked_ToggleCustomTargetHappyCase() public + function test_InstanceAccessManager_setTargetLockedByService_ToggleCustomTargetHappyCase() public { IAccessManaged customTarget = new AccessManagedMock(address(ozAccessManager)); address customTargetAddress = address(customTarget); - vm.startPrank(instanceOwner); + vm.startPrank(address(instance)); instanceAccessManager.createTarget(customTargetAddress, "CustomTarget1234"); vm.stopPrank(); assertEq(instanceAccessManager.getTargetAddress("CustomTarget1234"), customTargetAddress, "unexpected target address"); vm.startPrank(address(instanceService)); - instanceAccessManager.setTargetLocked(customTargetAddress, true); + instanceAccessManager.setTargetLockedByService(customTargetAddress, true); assertTrue(instanceAccessManager.isTargetLocked(customTargetAddress), "custom target is not locked"); - instanceAccessManager.setTargetLocked(customTargetAddress, false); + instanceAccessManager.setTargetLockedByService(customTargetAddress, false); vm.stopPrank(); assertFalse(instanceAccessManager.isTargetLocked(customTargetAddress), "custom target is locked"); } - function test_InstanceAccessManager_setTargetLocked_withNonExitingTarget() public + function test_InstanceAccessManager_setTargetLockedByService_withNonExitingTarget() public { address nonExistingTargetAddress = address(1234567890); @@ -1210,7 +1216,7 @@ contract TestInstanceAccessManager is TestGifBase { vm.expectRevert(abi.encodeWithSelector( IAccess.ErrorIAccessTargetDoesNotExist.selector, nonExistingTargetAddress)); - instanceAccessManager.setTargetLocked(nonExistingTargetAddress, true); + instanceAccessManager.setTargetLockedByService(nonExistingTargetAddress, true); vm.stopPrank(); }