Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new modifier to check if productId belongs to component #21

Merged
merged 7 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions contracts/examples/AyiiProduct.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";

import "@etherisc/gif-interface/contracts/components/Product.sol";
import "../modules/PolicyController.sol";

import "../modules/AccessController.sol";

contract AyiiProduct is
Product,
AccessControl
AccessControl,
Initializable
{
bytes32 public constant NAME = "AreaYieldIndexProduct";
bytes32 public constant VERSION = "0.1";
Expand Down Expand Up @@ -40,9 +44,10 @@ contract AyiiProduct is
}

uint256 private _oracleId;
PolicyController private _policy;

mapping(bytes32 /* riskId */ => Risk) private _risks;
mapping(bytes32 /* riskId */ => bytes32 [] /*policyIds*/) private _policies;
mapping(bytes32 /* riskId */ => bytes32 [] /* processIds */) private _policies;
bytes32 [] private _applications; // useful for debugging, might need to get rid of this

event LogAyiiPolicyCreated(bytes32 policyId, address policyHolder, uint256 premiumAmount, uint256 sumInsuredAmount);
Expand Down Expand Up @@ -70,6 +75,10 @@ contract AyiiProduct is
_setupRole(INSURER_ROLE, insurer);
}

function initialize(address registry) public initializer {
_policy = PolicyController(_getContractAddress("Policy"));
}

function createRisk(
bytes32 projectId,
bytes32 uaiId,
Expand Down Expand Up @@ -158,12 +167,12 @@ contract AyiiProduct is
}
}

function triggerOracle(bytes32 riskId)
function triggerOracle(bytes32 processId)
external
onlyRole(INSURER_ROLE)
returns(uint256 requestId)
{
Risk storage risk = _risks[riskId];
Risk storage risk = _risks[_getRiskId(processId)];
require(risk.createdAt > 0, "ERROR:AYI-010:RISK_UNDEFINED");
require(risk.requestId == 0, "ERROR:AYI-011:ORACLE_ALREADY_TRIGGERED");

Expand All @@ -174,7 +183,7 @@ contract AyiiProduct is
);

requestId = _request(
riskId,
processId,
queryData,
"oracleCallback",
_oracleId
Expand All @@ -193,7 +202,7 @@ contract AyiiProduct is

function oracleCallback(
uint256 requestId,
bytes32 riskId,
bytes32 processId,
bytes calldata responseData
)
external
Expand All @@ -206,6 +215,7 @@ contract AyiiProduct is
uint256 aaay
) = abi.decode(responseData, (bytes32, bytes32, bytes32, uint256));

bytes32 riskId = _getRiskId(processId);
require(riskId == getRiskId(projectId, uaiId, cropId), "ERROR:AYI-020:RISK_ID_MISMATCH");

Risk storage risk = _risks[riskId];
Expand Down Expand Up @@ -354,4 +364,9 @@ contract AyiiProduct is
function getApplicationDataStructure() external override view returns(string memory dataStructure) {
return "(bytes32 riskId)";
}

function _getRiskId(bytes32 processId) private view returns(bytes32 riskId) {
IPolicy.Application memory application = _getApplication(processId);
(riskId) = abi.decode(application.data, (bytes32));
}
}
42 changes: 36 additions & 6 deletions contracts/flows/PolicyDefaultFlow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,26 @@ contract PolicyDefaultFlow is
PolicyController policy = getPolicyContract();
require(
policy.getPolicy(processId).state == IPolicy.PolicyState.Expired,
"ERROR:PFD-001:POLICY_NOT_EXPIRED"
"ERROR:PFD-002:POLICY_NOT_EXPIRED"
);
_;
}

modifier onlyResponsibleProduct(bytes32 processId) {
PolicyController policy = getPolicyContract();
IPolicy.Metadata memory metadata = policy.getMetadata(processId);
ComponentController component = ComponentController(getContractFromRegistry("Component"));
require(metadata.productId == component.getComponentId(address(msg.sender)), "ERROR:PFD-003:PROCESSID_PRODUCT_MISMATCH");
_;
}

// ComponentController private _component;

// solhint-disable-next-line no-empty-blocks
constructor(address _registry)
WithRegistry(_registry)
{ }
{
}

function newApplication(
address owner,
Expand All @@ -73,6 +84,7 @@ contract PolicyDefaultFlow is

function revoke(bytes32 processId)
external
onlyResponsibleProduct(processId)
{
IPolicy policy = getPolicyContract();
policy.revokeApplication(processId);
Expand All @@ -81,6 +93,7 @@ contract PolicyDefaultFlow is
/* success implies the successful creation of a policy */
function underwrite(bytes32 processId)
external
onlyResponsibleProduct(processId)
returns(bool success)
{
// attempt to get the collateral to secure the policy
Expand All @@ -103,6 +116,7 @@ contract PolicyDefaultFlow is
*/
function collectPremium(bytes32 processId, uint256 amount)
public
onlyResponsibleProduct(processId)
returns(
bool success,
uint256 feeAmount,
Expand All @@ -122,14 +136,18 @@ contract PolicyDefaultFlow is
}
}

function decline(bytes32 processId) external {
function decline(bytes32 processId)
onlyResponsibleProduct(processId)
external
{
IPolicy policy = getPolicyContract();
policy.declineApplication(processId);
}

function expire(bytes32 processId)
external
onlyActivePolicy(processId)
onlyResponsibleProduct(processId)
{
IPolicy policy = getPolicyContract();
policy.expirePolicy(processId);
Expand All @@ -138,6 +156,7 @@ contract PolicyDefaultFlow is
function close(bytes32 processId)
external
onlyExpiredPolicy(processId)
onlyResponsibleProduct(processId)
{
IPolicy policy = getPolicyContract();
policy.closePolicy(processId);
Expand All @@ -153,6 +172,7 @@ contract PolicyDefaultFlow is
)
external
onlyActivePolicy(processId)
onlyResponsibleProduct(processId)
returns (uint256 claimId)
{
claimId = getPolicyContract().createClaim(
Expand All @@ -166,18 +186,25 @@ contract PolicyDefaultFlow is
uint256 claimId,
uint256 confirmedAmount
)
external
external
onlyResponsibleProduct(processId)
{
PolicyController policy = getPolicyContract();
policy.confirmClaim(processId, claimId, confirmedAmount);
}

function declineClaim(bytes32 processId, uint256 claimId) external {
function declineClaim(bytes32 processId, uint256 claimId)
external
onlyResponsibleProduct(processId)
{
PolicyController policy = getPolicyContract();
policy.declineClaim(processId, claimId);
}

function closeClaim(bytes32 processId, uint256 claimId) external {
function closeClaim(bytes32 processId, uint256 claimId)
external
onlyResponsibleProduct(processId)
{
PolicyController policy = getPolicyContract();
policy.closeClaim(processId, claimId);
}
Expand All @@ -189,6 +216,7 @@ contract PolicyDefaultFlow is
bytes calldata data
)
external
onlyResponsibleProduct(processId)
returns(uint256 payoutId)
{
payoutId = getPolicyContract()
Expand All @@ -200,6 +228,7 @@ contract PolicyDefaultFlow is
uint256 payoutId
)
external
onlyResponsibleProduct(processId)
returns(
bool success,
uint256 feeAmount,
Expand All @@ -225,6 +254,7 @@ contract PolicyDefaultFlow is
uint256 _responsibleOracleId
)
external
onlyResponsibleProduct(processId)
returns (uint256 _requestId)
{
_requestId = getQueryContract().request(
Expand Down
12 changes: 6 additions & 6 deletions contracts/modules/PolicyController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ contract PolicyController is
// bytes32 public constant NAME = "PolicyController";

// Metadata
mapping(bytes32 => Metadata) public metadata;
mapping(bytes32 /* processId */ => Metadata) public metadata;

// Applications
mapping(bytes32 => Application) public applications;
mapping(bytes32 /* processId */ => Application) public applications;

// Policies
mapping(bytes32 => Policy) public policies;
mapping(bytes32 /* processId */ => Policy) public policies;

// TODO decide for current data structure or alternative
// alternative mapping(bytes32 => Claim [])
// Claims
mapping(bytes32 => mapping(uint256 => Claim)) public claims;
mapping(bytes32 /* processId */ => mapping(uint256 /* claimId */ => Claim)) public claims;

// TODO decide for current data structure or alternative
// alternative mapping(bytes32 => Payout [])
// Payouts
mapping(bytes32 => mapping(uint256 => Payout)) public payouts;
mapping(bytes32 => uint256) public payoutCount;
mapping(bytes32 /* processId */ => mapping(uint256 /* payoutId */ => Payout)) public payouts;
mapping(bytes32 /* processId */ => uint256) public payoutCount;

// counter for assigned processIds, used to ensure unique processIds
uint256 private _assigendProcessIds;
Expand Down
4 changes: 2 additions & 2 deletions tests/test_ayii_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ def test_happy_path(

print('--- step trigger oracle (call chainlin node) -------------')

tx[0] = product.triggerOracle(riskId[0])
tx[1] = product.triggerOracle(riskId[1])
tx[0] = product.triggerOracle(policyId[0])
tx[1] = product.triggerOracle(policyId[1])
requestId = [tx[0].return_value, tx[1].return_value]

# ensure event emitted as chainlink client
Expand Down
2 changes: 1 addition & 1 deletion tests/test_process_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def test_process_apply_underwrite_expire_close(
with brownie.reverts('ERROR:POC-019:APPLICATION_STATE_INVALID'):
product.decline(processId, {'from': productOwner})

with brownie.reverts('ERROR:PFD-001:POLICY_NOT_EXPIRED'):
with brownie.reverts('ERROR:PFD-002:POLICY_NOT_EXPIRED'):
product.close(processId, {'from': productOwner})

product.expire(processId, {'from': productOwner})
Expand Down