From 370e731dc6109dd2f6644ea01a2f1cbd9c75f959 Mon Sep 17 00:00:00 2001 From: matthias zimmermann Date: Thu, 30 Jun 2022 18:50:29 +0200 Subject: [PATCH] adapt to gif-interface v1.5.0-staging-j, fix solc to 0.8.2 and oz to 4.7 --- brownie-config.yaml | 10 +-- contracts/flows/PolicyFlowDefault.sol | 6 ++ contracts/modules/AccessController.sol | 64 +++++++++---------- contracts/modules/ComponentController.sol | 9 ++- contracts/modules/PolicyController.sol | 2 +- contracts/services/ComponentOwnerService.sol | 22 +++++-- .../services/InstanceOperatorService.sol | 3 +- contracts/services/InstanceService.sol | 49 +++++++++----- contracts/services/ProductService.sol | 30 +-------- scripts/instance.py | 10 +-- tests/conftest.py | 1 + tests/test_test_product.py | 31 ++++++++- 12 files changed, 138 insertions(+), 99 deletions(-) diff --git a/brownie-config.yaml b/brownie-config.yaml index 054df58..b8d3059 100644 --- a/brownie-config.yaml +++ b/brownie-config.yaml @@ -5,14 +5,14 @@ dotenv: .env compiler: evm_version: null solc: - version: null + version: 0.8.2 optimizer: enabled: true runs: 200 # https://eth-brownie.readthedocs.io/en/stable/compile.html#compiler-settings remappings: - - "@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.6.0" - - "@gif-interface=etherisc/gif-interface@1.5.0-staging-i" + - "@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.7.0" + - "@gif-interface=etherisc/gif-interface@1.5.0-staging-j" vyper: version: null @@ -21,8 +21,8 @@ compiler: # to list the packages installed via the dependency list below dependencies: # github dependency format: /@ - - OpenZeppelin/openzeppelin-contracts@4.6.0 - - etherisc/gif-interface@1.5.0-staging-i + - OpenZeppelin/openzeppelin-contracts@4.7.0 + - etherisc/gif-interface@1.5.0-staging-j # exclude Ownable when calculating test coverage # https://eth-brownie.readthedocs.io/en/v1.10.3/config.html#exclude_paths diff --git a/contracts/flows/PolicyFlowDefault.sol b/contracts/flows/PolicyFlowDefault.sol index a92d434..096f089 100644 --- a/contracts/flows/PolicyFlowDefault.sol +++ b/contracts/flows/PolicyFlowDefault.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "../shared/WithRegistry.sol"; +// import "../shared/CoreController.sol"; import "@gif-interface/contracts/modules/ILicense.sol"; import "@gif-interface/contracts/modules/IPolicy.sol"; import "@gif-interface/contracts/modules/IQuery.sol"; @@ -17,6 +18,7 @@ import "@gif-interface/contracts/modules/IQuery.sol"; contract PolicyFlowDefault is WithRegistry + // CoreController { bytes32 public constant NAME = "PolicyFlowDefault"; @@ -183,4 +185,8 @@ contract PolicyFlowDefault is function getQueryContract() internal view returns (IQuery) { return IQuery(getContractFromRegistry("Query")); } + + // function getContractFromRegistry(bytes32 moduleName) internal view returns(address) { + // return _getContractAddress(moduleName); + // } } diff --git a/contracts/modules/AccessController.sol b/contracts/modules/AccessController.sol index aa5fc35..9842cdf 100644 --- a/contracts/modules/AccessController.sol +++ b/contracts/modules/AccessController.sol @@ -42,37 +42,37 @@ contract AccessController is } //--- enforce role ownership --------------------------------------------// - function enforceProductOwnerRole(address principal) public view { - enforceRole(PRODUCT_OWNER_ROLE, principal); - } - - function enforceOracleProviderRole(address principal) public view { - enforceRole(ORACLE_PROVIDER_ROLE, principal); - } - - function enforceRiskpoolKeeperRole(address principal) public view { - enforceRole(RISKPOOL_KEEPER_ROLE, principal); - } - - // adapted from oz AccessControl._checkRole - function enforceRole(bytes32 role, address principal) public view { - require( - hasRole(role, principal), - string( - abi.encodePacked( - "AccessController.enforceRole: account ", - Strings.toHexString(uint160(principal), 20), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } + // function enforceProductOwnerRole(address principal) public view { + // enforceRole(PRODUCT_OWNER_ROLE, principal); + // } + + // function enforceOracleProviderRole(address principal) public view { + // enforceRole(ORACLE_PROVIDER_ROLE, principal); + // } + + // function enforceRiskpoolKeeperRole(address principal) public view { + // enforceRole(RISKPOOL_KEEPER_ROLE, principal); + // } + + // // adapted from oz AccessControl._checkRole + // function enforceRole(bytes32 role, address principal) public view { + // require( + // hasRole(role, principal), + // string( + // abi.encodePacked( + // "AccessController.enforceRole: account ", + // Strings.toHexString(uint160(principal), 20), + // " is missing role ", + // Strings.toHexString(uint256(role), 32) + // ) + // ) + // ); + // } //--- manage role ownership ---------------------------------------------// function grantRole(bytes32 role, address principal) public - override(AccessControl, IAccessControl, IAccess) + override(IAccessControl, IAccess) onlyInstanceOperator { require(validRole[role], "ERROR:ACL-002:ROLE_UNKNOWN_OR_INVALID"); @@ -81,7 +81,7 @@ contract AccessController is function revokeRole(bytes32 role, address principal) public - override(AccessControl, IAccessControl, IAccess) + override(IAccessControl, IAccess) onlyInstanceOperator { AccessControl.revokeRole(role, principal); @@ -89,14 +89,14 @@ contract AccessController is function renounceRole(bytes32 role, address principal) public - override(AccessControl, IAccessControl, IAccess) + override(IAccessControl, IAccess) { AccessControl.renounceRole(role, principal); } //--- manage roles ------------------------------------------------------// function addRole(bytes32 role) - public + public override onlyInstanceOperator { require(validRole[role], "ERROR:ACL-003:ROLE_EXISTING_AND_VALID"); @@ -104,7 +104,7 @@ contract AccessController is } function invalidateRole(bytes32 role) - public + public override onlyInstanceOperator { require(validRole[role], "ERROR:ACL-004:ROLE_UNKNOWN_OR_INVALID"); @@ -113,7 +113,7 @@ contract AccessController is function hasRole(bytes32 role, address principal) public view - override(AccessControl, IAccessControl, IAccess) + override(IAccessControl, IAccess) returns(bool) { return super.hasRole(role, principal); diff --git a/contracts/modules/ComponentController.sol b/contracts/modules/ComponentController.sol index c48b756..fc029e5 100644 --- a/contracts/modules/ComponentController.sol +++ b/contracts/modules/ComponentController.sol @@ -32,7 +32,10 @@ contract ComponentController is _; } - function propose(IComponent component) external onlyComponentOwnerService { + function propose(IComponent component) + external + onlyComponentOwnerService + { // input validation require(_componentIdByAddress[address(component)] == 0, "ERROR:CCR-002:COMPONENT_ALREADY_EXISTS"); require(_componentIdByName[component.getName()] == 0, "ERROR:CCR-003:COMPONENT_NAME_ALREADY_EXISTS"); @@ -75,7 +78,7 @@ contract ComponentController is } function approve(uint256 id) - external + external onlyInstanceOperatorService { IComponent component = getComponent(id); @@ -87,7 +90,7 @@ contract ComponentController is } function decline(uint256 id) - external + external onlyInstanceOperatorService { IComponent component = getComponent(id); diff --git a/contracts/modules/PolicyController.sol b/contracts/modules/PolicyController.sol index 0f35d6b..ac09d4e 100644 --- a/contracts/modules/PolicyController.sol +++ b/contracts/modules/PolicyController.sol @@ -252,7 +252,7 @@ contract PolicyController is } function getMetadata(bytes32 _bpKey) - public + public override view returns (IPolicy.Metadata memory _metadata) { diff --git a/contracts/services/ComponentOwnerService.sol b/contracts/services/ComponentOwnerService.sol index b25b3f3..6f54114 100644 --- a/contracts/services/ComponentOwnerService.sol +++ b/contracts/services/ComponentOwnerService.sol @@ -37,26 +37,38 @@ contract ComponentOwnerService is } function propose(IComponent component) - external + external override onlyOwnerWithRoleFromComponent(component) { _component.propose(component); } - function stake(uint256 id) external onlyOwnerWithRole(id) { + function stake(uint256 id) + external override + onlyOwnerWithRole(id) + { revert("ERROR:COS-006:IMPLEMENATION_MISSING"); } - function withdraw(uint256 id) external onlyOwnerWithRole(id) { + function withdraw(uint256 id) + external override + onlyOwnerWithRole(id) + { revert("ERROR:COS-007:IMPLEMENATION_MISSING"); } - function pause(uint256 id) external onlyOwnerWithRole(id) { + function pause(uint256 id) + external override + onlyOwnerWithRole(id) + { _component.pause(id); } - function unpause(uint256 id) external onlyOwnerWithRole(id) { + function unpause(uint256 id) + external override + onlyOwnerWithRole(id) + { _component.unpause(id); } diff --git a/contracts/services/InstanceOperatorService.sol b/contracts/services/InstanceOperatorService.sol index b4b5810..d1ca8f8 100644 --- a/contracts/services/InstanceOperatorService.sol +++ b/contracts/services/InstanceOperatorService.sol @@ -74,7 +74,6 @@ contract InstanceOperatorService is _access.grantRole(role, principal); } - // TODO add implementation in accesscontroller function revokeRole(bytes32 role, address principal) external override onlyOwner @@ -112,6 +111,7 @@ contract InstanceOperatorService is } // service staking + // TODO implement setDefaultStaking staking function setDefaultStaking( uint16 componentType, bytes calldata data @@ -122,6 +122,7 @@ contract InstanceOperatorService is revert("ERROR:IOS-001:IMPLEMENATION_MISSING"); } + // TODO implement adjustStakingRequirements staking function adjustStakingRequirements( uint256 id, bytes calldata data diff --git a/contracts/services/InstanceService.sol b/contracts/services/InstanceService.sol index 528c2b7..381ad3b 100644 --- a/contracts/services/InstanceService.sol +++ b/contracts/services/InstanceService.sol @@ -43,7 +43,7 @@ contract InstanceService is return IProductService(_getContractAddress(PRODUCT_SERVICE_NAME)); } - function getOwner() external view returns(address) { + function getOwner() external override view returns(address) { InstanceOperatorService ios = InstanceOperatorService(_getContractAddress(INSTANCE_OPERATOR_SERVICE_NAME)); return ios.owner(); } @@ -73,19 +73,6 @@ contract InstanceService is return _access.hasRole(role, principal); } - /* policy */ - function getMetadata(bytes32 bpKey) external view returns(IPolicy.Metadata memory metadata) { - metadata = _policy().getMetadata(bpKey); - } - - function getApplication(bytes32 bpKey) external view returns(IPolicy.Application memory application) { - application = _policy().getApplication(bpKey); - } - - function getPolicy(bytes32 bpKey) external view returns(IPolicy.Policy memory policy) { - policy = _policy().getPolicy(bpKey); - } - /* component */ function products() external override view returns(uint256) { return _component().products(); @@ -95,7 +82,7 @@ contract InstanceService is return _component().oracles(); } - function riskPools() external override view returns(uint256) { + function riskpools() external override view returns(uint256) { return _component().riskpools(); } @@ -103,7 +90,7 @@ contract InstanceService is return _component().getComponent(id); } - // service staking + /* service staking */ function getStakingRequirements(uint256 id) external override view @@ -120,6 +107,36 @@ contract InstanceService is revert("ERROR:IS-002:IMPLEMENATION_MISSING"); } + /* policy */ + function getMetadata(bytes32 bpKey) external view returns(IPolicy.Metadata memory metadata) { + metadata = _policy().getMetadata(bpKey); + } + + function getApplication(bytes32 processId) external override view returns(IPolicy.Application memory application) { + application = _policy().getApplication(processId); + } + + function getPolicy(bytes32 processId) external override view returns(IPolicy.Policy memory policy) { + policy = _policy().getPolicy(processId); + } + + function claims(bytes32 processId) external override view returns(uint256 numberOfClaims) { + numberOfClaims = _policy().getMetadata(processId).claimsCount; + } + + function payouts(bytes32 processId) external override view returns(uint256 numberOfPayouts) { + numberOfPayouts = _policy().getMetadata(processId).payoutsCount; + } + + function getClaim(bytes32 processId, uint256 claimId) external override view returns (IPolicy.Claim memory claim) { + claim = _policy().getClaim(processId, claimId); + } + + function getPayout(bytes32 processId, uint256 payoutId) external override view returns (IPolicy.Payout memory payout) { + payout = _policy().getPayout(processId, payoutId); + } + + /* internal functions */ function _policy() internal view returns(PolicyController) { return PolicyController(_getContractAddress(POLICY_NAME)); } diff --git a/contracts/services/ProductService.sol b/contracts/services/ProductService.sol index 24b5dfb..be70645 100644 --- a/contracts/services/ProductService.sol +++ b/contracts/services/ProductService.sol @@ -22,35 +22,7 @@ contract ProductService is require(isAuthorized, "ERROR:PRS-001:NOT_AUTHORIZED"); require(policyFlow != address(0),"ERROR:PRS-002:POLICY_FLOW_NOT_RESOLVED"); - _delegateGif(policyFlow); - } - - // delegate from GIF.Delegator - function _delegateGif(address _implementation) internal { - bytes memory data = msg.data; - - /* solhint-disable no-inline-assembly */ - assembly { - let result := delegatecall( - gas(), - _implementation, - add(data, 0x20), - mload(data), - 0, - 0 - ) - let size := returndatasize() - let ptr := mload(0x40) - returndatacopy(ptr, 0, size) - switch result - case 0 { - revert(ptr, size) - } - default { - return(ptr, size) - } - } - /* solhint-enable no-inline-assembly */ + _delegate(policyFlow); } diff --git a/scripts/instance.py b/scripts/instance.py index 74b4480..82e116c 100644 --- a/scripts/instance.py +++ b/scripts/instance.py @@ -120,13 +120,14 @@ def deployWithRegistry( self.query = deployGifModuleV2("Query", QueryController, registry, owner, publishSource) self.licence = deployGifModuleV2("License", LicenseController, registry, owner, publishSource) self.policy = deployGifModuleV2("Policy", PolicyController, registry, owner, publishSource) - self.componentOwnerService = deployGifModuleV2("ComponentOwnerService", ComponentOwnerService, registry, owner, publishSource) # services + self.componentOwnerService = deployGifModuleV2("ComponentOwnerService", ComponentOwnerService, registry, owner, publishSource) self.instanceService = deployGifModuleV2("InstanceService", InstanceService, registry, owner, publishSource) self.oracleService = deployGifModuleV2("OracleService", OracleService, registry, owner, publishSource) - # self.productService = deployGifModuleV2("ProductService", ProductService, registry, owner, publishSource) + # self.productService = deployGifModuleV2("ProductService", ProductService, registry, owner, publishSource) + # self.policyFlow = deployGifModuleV2("PolicyFlowDefault", PolicyFlowDefault, registry, owner, publishSource) # TODO these contracts do not work with proxy pattern self.policyFlow = deployGifService(PolicyFlowDefault, registry, owner, publishSource) self.productService = deployGifService(ProductService, registry, owner, publishSource) @@ -150,12 +151,11 @@ def fromRegistryAddress(self, registry_address): self.oracleService = self.contractFromGifRegistry(OracleService, "OracleService") self.productService = self.contractFromGifRegistry(ProductService, "ProductService") - # self.oracleService = self.contractFromGifRegistry(OracleService) - # self.productService = self.contractFromGifRegistry(ProductService) - self.policyFlow = self.contractFromGifRegistry(PolicyFlowDefault) + self.policyFlow = self.contractFromGifRegistry(PolicyFlowDefault, "PolicyFlowDefault") self.componentOwnerService = self.contractFromGifRegistry(ComponentOwnerService) self.instanceOperatorService = self.contractFromGifRegistry(InstanceOperatorService) + def contractFromGifRegistry(self, contractClass, name=None): if not name: nameB32 = s2b32(contractClass._name) diff --git a/tests/conftest.py b/tests/conftest.py index f612007..2f7eeb7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -166,6 +166,7 @@ def componentOwnerService(ComponentOwnerService, registry, owner) -> ComponentOw @pytest.fixture(scope="module") def policyFlowDefault(PolicyFlowDefault, registry, owner) -> PolicyFlowDefault: return deployGifService(PolicyFlowDefault, registry, owner, PUBLISH_SOURCE) + # return deployGifModuleV2("PolicyFlowDefault", PolicyFlowDefault, registry, owner, PUBLISH_SOURCE) @pytest.fixture(scope="module") def instanceOperatorService(InstanceOperatorService, registry, owner) -> InstanceOperatorService: diff --git a/tests/test_test_product.py b/tests/test_test_product.py index a15f8fb..7027a66 100644 --- a/tests/test_test_product.py +++ b/tests/test_test_product.py @@ -119,7 +119,7 @@ def test_claim_submission_for_expired_policy(testProduct: TestProduct, customer: testProduct.submitClaim(policy_id, Wei('0.1 ether'), {'from': customer}) -def multiple_claim_submission(testProduct: TestProduct, customer: Account): +def test_multiple_claim_submission(instance:GifInstance, testProduct: TestProduct, customer: Account): customer_initial_balance = customer.balance() premium = Wei('0.5 ether'); @@ -140,18 +140,45 @@ def multiple_claim_submission(testProduct: TestProduct, customer: Account): assert customer.balance() + 2 * premium == customer_initial_balance assert testProduct.balance() == 2 * premium + instanceService = instance.getInstanceService() + # ensure successful policy creation assert testProduct.policies() == 2 assert testProduct.claims() == 0 + + assert instanceService.claims(policy1_id) == 0 + assert instanceService.payouts(policy1_id) == 0 + assert instanceService.claims(policy2_id) == 0 + assert instanceService.payouts(policy2_id) == 0 # submit claim for 1st policy testProduct.submitClaim(policy1_id, Wei('0.1 ether'), {'from': customer}) assert testProduct.claims() == 1 assert testProduct.getClaimId(policy1_id) == 0 + + assert instanceService.claims(policy1_id) == 1 + assert instanceService.payouts(policy1_id) == 1 + assert instanceService.claims(policy2_id) == 0 + assert instanceService.payouts(policy2_id) == 0 - # submit claim for 1st policy + # submit claim for 1st policy (every 2nd claim does not have any payout) testProduct.submitClaim(policy2_id, Wei('0.1 ether'), {'from': customer}) assert testProduct.claims() == 2 assert testProduct.getClaimId(policy2_id) == 0 + assert instanceService.claims(policy1_id) == 1 + assert instanceService.payouts(policy1_id) == 1 + assert instanceService.claims(policy2_id) == 1 + assert instanceService.payouts(policy2_id) == 0 + + # submit 2nd claim for 1st policy + testProduct.submitClaim(policy1_id, Wei('0.1 ether'), {'from': customer}) + assert testProduct.claims() == 3 + assert testProduct.getClaimId(policy1_id) == 1 + + assert instanceService.claims(policy1_id) == 2 + assert instanceService.payouts(policy1_id) == 2 + assert instanceService.claims(policy2_id) == 1 + assert instanceService.payouts(policy2_id) == 0 +