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

Feature/expose process policy in ayii product #73

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"solidity.remappingsUnix": [
"@openzeppelin/=/home/vscode/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.7.3",
"@chainlink/=/home/vscode/.brownie/packages/smartcontractkit/chainlink@1.6.0",
"@etherisc/gif-interface/=/home/vscode/.brownie/packages/etherisc/gif-interface@3f16cfe",
"@etherisc/gif-interface/=/home/vscode/.brownie/packages/etherisc/gif-interface@3b0002a",
],
"solidity.compileUsingRemoteVersion": "v0.8.2+commit.661d1103",
"peacock.remoteColor": "1D3C43",
Expand Down
4 changes: 2 additions & 2 deletions brownie-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ compiler:
remappings:
- "@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.7.3"
- "@chainlink=smartcontractkit/chainlink@1.6.0"
- "@etherisc/gif-interface=etherisc/gif-interface@3f16cfe"
- "@etherisc/gif-interface=etherisc/gif-interface@3b0002a"

# packages below will be added to brownie
# you may use 'brownie pm list' after 'brownie compile'
Expand All @@ -32,7 +32,7 @@ dependencies:
# github dependency format: <owner>/<repository>@<release>
- OpenZeppelin/openzeppelin-contracts@4.7.3
- smartcontractkit/chainlink@1.6.0
- etherisc/gif-interface@3f16cfe
- etherisc/gif-interface@3b0002a

# exclude open zeppeling contracts when calculating test coverage
# https://eth-brownie.readthedocs.io/en/v1.10.3/config.html#exclude_paths
Expand Down
65 changes: 53 additions & 12 deletions contracts/examples/AyiiProduct.sol
Original file line number Diff line number Diff line change
Expand Up @@ -395,35 +395,76 @@ contract AyiiProduct is

function processPoliciesForRisk(bytes32 riskId, uint256 batchSize)
external
onlyRole(INSURER_ROLE)
matthiaszimmermann marked this conversation as resolved.
Show resolved Hide resolved
returns(bytes32 [] memory processedPolicies)
{
Risk memory risk = _risks[riskId];
require(risk.responseAt > 0, "ERROR:AYI-030:ORACLE_RESPONSE_MISSING");

EnumerableSet.Bytes32Set storage policyIds = _policies[riskId];
uint256 elements = EnumerableSet.length(policyIds);
uint256 elements = EnumerableSet.length(_policies[riskId]);
if (elements == 0) {
emit LogAyiiRiskProcessed(riskId, 0);
return new bytes32[](0);
}

if (batchSize == 0) { batchSize = elements; }
else { batchSize = min(batchSize, elements); }
else { batchSize = min(batchSize, elements); }

processedPolicies = new bytes32[](batchSize);
uint256 elementIdx = elements - 1;

for (uint256 i = 0; i < batchSize; i++) {
// grab and process the last policy
bytes32 policyId = EnumerableSet.at(policyIds, EnumerableSet.length(policyIds) - 1);
_processPolicy(policyId, risk);

_expire(policyId);
_close(policyId);

bytes32 policyId = EnumerableSet.at(_policies[riskId], elementIdx - i);
processPolicy(policyId);
processedPolicies[i] = policyId;

// remove the last (processed) policy from the list
EnumerableSet.remove(policyIds, policyId);
}

emit LogAyiiRiskProcessed(riskId, batchSize);
}

function processPolicy(bytes32 policyId)
public
onlyRole(INSURER_ROLE)
{
IPolicy.Application memory application = _getApplication(policyId);
bytes32 riskId = abi.decode(application.data, (bytes32));
Risk memory risk = _risks[riskId];

require(risk.id == riskId, "ERROR:AYI-031:RISK_ID_INVALID");
require(risk.responseAt > 0, "ERROR:AYI-032:ORACLE_RESPONSE_MISSING");
require(EnumerableSet.contains(_policies[riskId], policyId), "ERROR:AYI-033:POLICY_FOR_RISK_UNKNOWN");

EnumerableSet.remove(_policies[riskId], policyId);


uint256 claimAmount = calculatePayout(
risk.payoutPercentage,
application.sumInsuredAmount);

uint256 claimId = _newClaim(policyId, claimAmount, "");
emit LogAyiiClaimCreated(policyId, claimId, claimAmount);

if (claimAmount > 0) {
uint256 payoutAmount = claimAmount;
_confirmClaim(policyId, claimId, payoutAmount);

uint256 payoutId = _newPayout(policyId, claimId, payoutAmount, "");
_processPayout(policyId, payoutId);

emit LogAyiiPayoutCreated(policyId, payoutAmount);
}
else {
_declineClaim(policyId, claimId);
_closeClaim(policyId, claimId);
}

_expire(policyId);
_close(policyId);

emit LogAyiiPolicyProcessed(policyId);
}

function calculatePayout(uint256 payoutPercentage, uint256 sumInsuredAmount)
public
pure
Expand Down
4 changes: 2 additions & 2 deletions contracts/flows/PolicyDefaultFlow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ contract PolicyDefaultFlow is
policy.collectPremium(processId, netPremiumAmount + feeAmount);

PoolController pool = getPoolContract();
pool.increaseBalance(processId, netPremiumAmount);
pool.processPremium(processId, netPremiumAmount);
}
}

Expand Down Expand Up @@ -272,7 +272,7 @@ contract PolicyDefaultFlow is
policy.processPayout(processId, payoutId);

PoolController pool = getPoolContract();
pool.decreaseBalance(processId, netPayoutAmount + feeAmount);
pool.processPayout(processId, netPayoutAmount + feeAmount);
}

function request(
Expand Down
118 changes: 75 additions & 43 deletions contracts/modules/BundleController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ contract BundleController is

modifier onlyFundableBundle(uint256 bundleId) {
Bundle storage bundle = _bundles[bundleId];
require(bundle.createdAt > 0, "ERROR:BUC-031:BUNDLE_DOES_NOT_EXIST");
require(bundle.createdAt > 0, "ERROR:BUC-002:BUNDLE_DOES_NOT_EXIST");
require(
bundle.state != IBundle.BundleState.Burned
&& bundle.state != IBundle.BundleState.Closed, "ERROR:BUC-032:BUNDLE_BURNED_OR_CLOSED"
&& bundle.state != IBundle.BundleState.Closed, "ERROR:BUC-003:BUNDLE_BURNED_OR_CLOSED"
);
_;
}
Expand Down Expand Up @@ -182,60 +182,93 @@ contract BundleController is
}


function releasePolicy(uint256 bundleId, bytes32 processId)
external override
function processPremium(uint256 bundleId, bytes32 processId, uint256 amount)
external override
onlyRiskpoolService
returns(uint256 collateralAmount)
onlyFundableBundle(bundleId)
{
// make sure bundle exists and is not yet closed
IPolicy.Policy memory policy = _policy.getPolicy(processId);
require(
policy.state != IPolicy.PolicyState.Closed,
"ERROR:POL-030:POLICY_STATE_INVALID"
);

Bundle storage bundle = _bundles[bundleId];
require(bundle.createdAt > 0, "ERROR:BUC-024:BUNDLE_DOES_NOT_EXIST");
require(_activePolicies[bundleId] > 0, "ERROR:BUC-025:NO_ACTIVE_POLICIES_FOR_BUNDLE");
require(bundle.createdAt > 0, "ERROR:BUC-031:BUNDLE_DOES_NOT_EXIST");

bundle.balance += amount;
bundle.updatedAt = block.timestamp; // solhint-disable-line
}

collateralAmount = _valueLockedPerPolicy[bundleId][processId];
require(collateralAmount > 0, "ERROR:BUC-026:NOT_COLLATERALIZED_BY_BUNDLE");

// this should never ever fail ...
function processPayout(uint256 bundleId, bytes32 processId, uint256 amount)
external override
onlyRiskpoolService
{
IPolicy.Policy memory policy = _policy.getPolicy(processId);
require(
bundle.lockedCapital >= collateralAmount,
"PANIC:BUC-027:UNLOCK_CAPITAL_TOO_BIG"
policy.state != IPolicy.PolicyState.Closed,
"ERROR:POL-040:POLICY_STATE_INVALID"
);

// policy no longer relevant for bundle
_activePolicies[bundleId] -= 1;
delete _valueLockedPerPolicy[bundleId][processId];
// check there are policies and there is sufficient locked capital for policy
require(_activePolicies[bundleId] > 0, "ERROR:BUC-041:NO_ACTIVE_POLICIES_FOR_BUNDLE");
require(_valueLockedPerPolicy[bundleId][processId] >= amount, "ERROR:BUC-042:COLLATERAL_INSUFFICIENT_FOR_POLICY");

// update bundle capital
bundle.lockedCapital -= collateralAmount;
bundle.updatedAt = block.timestamp;
// make sure bundle exists and is not yet closed
Bundle storage bundle = _bundles[bundleId];
require(bundle.createdAt > 0, "ERROR:BUC-043:BUNDLE_DOES_NOT_EXIST");
require(
bundle.state == IBundle.BundleState.Active
|| bundle.state == IBundle.BundleState.Locked,
"ERROR:BUC-044:BUNDLE_STATE_INVALID");
require(bundle.capital >= amount, "ERROR:BUC-045:CAPITAL_TOO_LOW");
require(bundle.lockedCapital >= amount, "ERROR:BUC-046:LOCKED_CAPITAL_TOO_LOW");
require(bundle.balance >= amount, "ERROR:BUC-047:BALANCE_TOO_LOW");

_valueLockedPerPolicy[bundleId][processId] -= amount;
bundle.capital -= amount;
bundle.lockedCapital -= amount;
bundle.balance -= amount;
bundle.updatedAt = block.timestamp; // solhint-disable-line

uint256 capacityAmount = bundle.capital - bundle.lockedCapital;
emit LogBundlePolicyExpired(bundleId, processId, collateralAmount, capacityAmount);
emit LogBundlePayoutProcessed(bundleId, processId, amount);
}


function increaseBalance(uint256 bundleId, uint256 amount)
external override
function releasePolicy(uint256 bundleId, bytes32 processId)
external override
onlyRiskpoolService
onlyFundableBundle(bundleId)
returns(uint256 remainingCollateralAmount)
{
IPolicy.Policy memory policy = _policy.getPolicy(processId);
require(
policy.state == IPolicy.PolicyState.Closed,
"ERROR:POL-050:POLICY_STATE_INVALID"
);

// make sure bundle exists and is not yet closed
Bundle storage bundle = _bundles[bundleId];
bundle.balance += amount;
bundle.updatedAt = block.timestamp;
}
require(bundle.createdAt > 0, "ERROR:BUC-051:BUNDLE_DOES_NOT_EXIST");
require(_activePolicies[bundleId] > 0, "ERROR:BUC-052:NO_ACTIVE_POLICIES_FOR_BUNDLE");

uint256 lockedForPolicyAmount = _valueLockedPerPolicy[bundleId][processId];
// this should never ever fail ...
require(
bundle.lockedCapital >= lockedForPolicyAmount,
"PANIC:BUC-053:UNLOCK_CAPITAL_TOO_BIG"
);

function decreaseBalance(uint256 bundleId, uint256 amount)
external override
onlyRiskpoolService
onlyFundableBundle(bundleId)
{
Bundle storage bundle = _bundles[bundleId];
// policy no longer relevant for bundle
_activePolicies[bundleId] -= 1;
delete _valueLockedPerPolicy[bundleId][processId];

require(bundle.balance >= amount, "ERROR:BUC-035:BUNDLE_BALANCE_TOO_SMALL");
// update bundle capital
bundle.lockedCapital -= lockedForPolicyAmount;
bundle.updatedAt = block.timestamp; // solhint-disable-line

bundle.balance -= amount;
bundle.updatedAt = block.timestamp;
uint256 capacityAmount = bundle.capital - bundle.lockedCapital;
emit LogBundlePolicyReleased(bundleId, processId, lockedForPolicyAmount, capacityAmount);
}

function getOwner(uint256 bundleId) public view returns(address) {
Expand Down Expand Up @@ -270,7 +303,7 @@ contract BundleController is

function getBundle(uint256 bundleId) public view returns(Bundle memory) {
Bundle memory bundle = _bundles[bundleId];
require(bundle.createdAt > 0, "ERROR:BUC-040:BUNDLE_DOES_NOT_EXIST");
require(bundle.createdAt > 0, "ERROR:BUC-060:BUNDLE_DOES_NOT_EXIST");
return bundle;
}

Expand Down Expand Up @@ -308,23 +341,22 @@ contract BundleController is
if (oldState == BundleState.Active) {
require(
newState == BundleState.Locked || newState == BundleState.Closed,
"ERROR:BUC-050:ACTIVE_INVALID_TRANSITION"
"ERROR:BUC-070:ACTIVE_INVALID_TRANSITION"
);
} else if (oldState == BundleState.Locked) {
require(
newState == BundleState.Active || newState == BundleState.Closed,
"ERROR:BUC-051:LOCKED_INVALID_TRANSITION"
"ERROR:BUC-071:LOCKED_INVALID_TRANSITION"
);
} else if (oldState == BundleState.Closed) {
require(
newState == BundleState.Burned,
"ERROR:BUC-052:CLOSED_INVALID_TRANSITION"
"ERROR:BUC-072:CLOSED_INVALID_TRANSITION"
);
} else if (oldState == BundleState.Burned) {
revert("ERROR:BUC-053:BURNED_IS_FINAL_STATE");
revert("ERROR:BUC-073:BURNED_IS_FINAL_STATE");
} else {
revert("ERROR:BOC-054:INITIAL_STATE_NOT_HANDLED");
revert("ERROR:BOC-074:INITIAL_STATE_NOT_HANDLED");
}
}

}