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/simplify interaction with deployed artefacts #37

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 115 additions & 112 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Example session inside the Brownie console
* Deployment of a GIF instance
* Deployment and usage of Test oracle and product

```bash
```python
# --- imports ---
import uuid
from scripts.product import GifInstance, GifTestOracle, GifTestProduct, GifTestRiskpool
Expand Down Expand Up @@ -133,7 +133,7 @@ txPolicy2 = product.applyForPolicy(premium, sumInsured, metaData, applicationDat

Brownie console commands to deploy/use the example product

```shell
```python
from scripts.area_yield_index import GifAreaYieldIndexOracle, GifAreaYieldIndexProduct

from scripts.setup import fund_riskpool, fund_customer
Expand Down Expand Up @@ -235,7 +235,7 @@ owner.address
```

Use Polygon test [faucet](https://faucet.polygon.technology/) to fund the owner address
```bash
```python
from scripts.instance import GifInstance

# publishes source code to the network
Expand All @@ -255,21 +255,85 @@ brownie run scripts/instance.py dump_sources 0x2852593b21796b549555d09873155B252

## Full Deployment with Example Product

```bash
# --- ganache accounts setup -------------
instanceOperator=accounts[0]
instanceWallet=accounts[1]
oracleProvider=accounts[2]
chainlinkNodeOperator=accounts[3]
riskpoolKeeper=accounts[4]
riskpoolWallet=accounts[5]
investor=accounts[6]
productOwner=accounts[7]
insurer=accounts[8]
customer=accounts[9]
customer2=accounts[10]
Before attempting to deploy the setup on a life chain ensure that the
`instanceOperator` has sufficient funds to cover the setup.

For testnets faucet funds may be used

* [avax-test (Fuji (C-Chain))](https://faucet.avax.network/)
* [polygon-test](https://faucet.polygon.technology/)

Using the ganache scenario shown below ensures that all addresses used are sufficiently funded.

```python
from scripts.deploy_ayii import (
stakeholders_accounts_ganache,
check_funds,
amend_funds,
deploy,
from_registry,
from_component,
)

from scripts.instance import (
GifInstance,
dump_sources
)

from scripts.util import (
s2b,
b2s,
contract_from_address,
)

# for ganche the command below may be used
# for other chains, use accounts.add() and record the mnemonics
a = stakeholders_accounts_ganache()

# check_funds checks which stakeholder accounts need funding for the deploy
# also, it checks if the instanceOperator has a balance that allows to provided
# the missing funds for the other accounts
check_funds(a)

# amend_funds transfers missing funds to stakeholder addresses using the
# avaulable balance of the instanceOperator
amend_funds(a)

publishSource=False
d = deploy(a, publishSource)

(
componentOwnerService,customer1,customer2,erc20Token,instance,instanceOperator,instanceOperatorService,instanceService,
instanceWallet,insurer,investor,oracle,oracleProvider,processId1,processId2,product,productOwner,riskId1,riskId2,
riskpool,riskpoolKeeper,riskpoolWallet
)=(
d['componentOwnerService'],d['customer1'],d['customer2'],d['erc20Token'],d['instance'],d['instanceOperator'],d['instanceOperatorService'],d['instanceService'],
d['instanceWallet'],d['insurer'],d['investor'],d['oracle'],d['oracleProvider'],d['processId1'],d['processId2'],d['product'],d['productOwner'],d['riskId1'],d['riskId2'],
d['riskpool'],d['riskpoolKeeper'],d['riskpoolWallet']
)

# the deployed setup can now be used
# example usage
instanceOperator
instance.getRegistry()
instanceService.getInstanceId()

product.getId()
b2s(product.getName())

customer1
instanceService.getMetadata(processId1)
instanceService.getApplication(processId1)
instanceService.getPolicy(processId1)
```

For a first time setup on a live chain the setup below can be used.

# --- test net accounts setup -------------
IMPORTANT: Make sure to write down the generated mnemonics for the
stakeholder accounts. To reuse the same accounts replace `accounts.add`
with `accounts.from_mnemonic` using the recorded mnemonics.

```python
instanceOperator=accounts.add()
instanceWallet=accounts.add()
oracleProvider=accounts.add()
Expand All @@ -279,108 +343,47 @@ riskpoolWallet=accounts.add()
investor=accounts.add()
productOwner=accounts.add()
insurer=accounts.add()
customer=accounts.add()
customer1=accounts.add()
customer2=accounts.add()

# --- optional erc20 token deploy -------------
# skip this if the value token for the product and
# riskpool is already deployed

erc20Token = TestCoin.deploy({'from': instanceOperator})

# --- gif instance deploy deploy -------------
# if the gif instance is already deployed replace
# the command below with the following line
# instance = GifInstance(registryAddress='0x...')
from scripts.instance import GifInstance

instance = GifInstance(instanceOperator, instanceWallet=instanceWallet)
instanceService = instance.getInstanceService()

instance.getRegistry()

# --- example product deploy deploy -------------
from scripts.ayii_product import GifAyiiProductComplete

ayiiDeploy = GifAyiiProductComplete(instance, productOwner, insurer, oracleProvider, chainlinkNodeOperator, riskpoolKeeper, investor, erc20Token, riskpoolWallet)

ayiiProduct = ayiiDeploy.getProduct()
ayiiOracle = ayiiProduct.getOracle()
ayiiRiskpool = ayiiProduct.getRiskpool()

product = ayiiProduct.getContract()
oracle = ayiiOracle.getContract()
riskpool = ayiiRiskpool.getContract()
a = {
'instanceOperator': instanceOperator,
'instanceWallet': instanceWallet,
'oracleProvider': oracleProvider,
'chainlinkNodeOperator': chainlinkNodeOperator,
'riskpoolKeeper': riskpoolKeeper,
'riskpoolWallet': riskpoolWallet,
'investor': investor,
'productOwner': productOwner,
'insurer': insurer,
'customer1': customer1,
'customer2': customer2,
}
```

## Interact with Example Product

```bash
from scripts.util import s2b32

#--- setup risk (group policy) definition -----------------
projectId = s2b32('test-project')
uaiId = s2b32('some-region-id')
cropId = s2b32('maize')
To interact with an existing setup use the following helper methods as shown below.

multiplier = product.getPercentageMultiplier()
trigger = 0.75 * multiplier
exit_ = 0.1 * multiplier # exit is needed to exit the console
tsi = 0.9 * multiplier
aph = 2.0 * multiplier
```python
from scripts.deploy_ayii import (
from_registry,
from_component,
)

tx = product.createRisk(projectId, uaiId, cropId, trigger, exit_, tsi, aph,
{'from': insurer})
riskId = tx.return_value
from scripts.instance import (
GifInstance,
)

#--- fund investor which in turn creates a risk bundle ---
bundleInitialFunding=1000000
erc20Token.transfer(investor, bundleInitialFunding, {'from': instanceOperator})
erc20Token.approve(instance.getTreasury(), bundleInitialFunding, {'from': investor})
from scripts.util import (
s2b,
b2s,
contract_from_address,
)

applicationFilter = bytes(0)
riskpool.createBundle(applicationFilter, bundleInitialFunding, {'from': investor})
# for the case of a known registry address,
# eg '0xE7eD6747FaC5360f88a2EFC03E00d25789F69291'
(instance, product, oracle, riskpool) = from_registry('0xE7eD6747FaC5360f88a2EFC03E00d25789F69291')

instanceService.getBundle(1)
erc20Token.balanceOf(riskpoolWallet.address)
erc20Token.balanceOf(instanceWallet.address)

# approvel for payouts/defunding
maxUint256 = 2**256-1
erc20Token.approve(instance.getTreasury(), maxUint256, {'from': riskpoolWallet})

#--- fund customer which in turn applies for a policy ---
customerFunding=1000
erc20Token.transfer(customer, customerFunding, {'from': instanceOperator})

premium = 100
sumInsured = 20000

tx = product.applyForPolicy(customer, premium, sumInsured, riskId,
{'from': insurer})
policyId = tx.return_value

# print data for bundle and newly created policy
riskpool.getTotalValueLocked() # shows the 20000 of locked capital to cover the sum insurance
instanceService.getBundle(1) # bundle state, locked capital (20000 to cover sum insured)
instanceService.getMetadata(policyId) # policy owner and product id
instanceService.getApplication(policyId) # premium, sum insurec, risk id
instanceService.getPolicy(policyId) # policy state, premium payed (=0 for now)

# premium payment in bits, allowance set for full premium
erc20Token.approve(instance.getTreasury(), 100, {'from': customer})

# first installment
product.collectPremium(policyId, 40, {'from':insurer})
instanceService.getPolicy(policyId)

# second installment
product.collectPremium(policyId, 60, {'from':insurer})
instanceService.getPolicy(policyId)

# TODO add:
# - oracle call
# - policy processing
# - payout to customer
# - definding back to inverster
# or for a known address of a component, eg
# eg product address '0xF039D8acecbB47763c67937D66A254DB48c87757'
(instance, product, oracle, riskpool) = from_component('0xF039D8acecbB47763c67937D66A254DB48c87757')
```
15 changes: 15 additions & 0 deletions contracts/modules/ComponentController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pragma solidity ^0.8.0;
import "../shared/CoreController.sol";

import "@etherisc/gif-interface/contracts/components/IComponent.sol";
import "@etherisc/gif-interface/contracts/components/IOracle.sol";
import "@etherisc/gif-interface/contracts/components/IProduct.sol";
import "@etherisc/gif-interface/contracts/components/IRiskpool.sol";
import "@etherisc/gif-interface/contracts/modules/IComponentEvents.sol";

contract ComponentController is
Expand Down Expand Up @@ -202,6 +205,18 @@ contract ComponentController is
return _componentState[id];
}

function getOracleId(uint256 idx) public view returns (uint256 oracleId) {
return _oracles[idx];
}

function getRiskpoolId(uint256 idx) public view returns (uint256 riskpoolId) {
return _riskpools[idx];
}

function getProductId(uint256 idx) public view returns (uint256 productId) {
return _products[idx];
}

function getRequiredRole(IComponent.ComponentType componentType) external returns (bytes32) {
if (componentType == IComponent.ComponentType.Product) { return _access.getProductOwnerRole(); }
else if (componentType == IComponent.ComponentType.Oracle) { return _access.getOracleProviderRole(); }
Expand Down
23 changes: 19 additions & 4 deletions contracts/services/InstanceService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import "../shared/CoreController.sol";
import "../services/InstanceOperatorService.sol";

import "@etherisc/gif-interface/contracts/components/IComponent.sol";
import "@etherisc/gif-interface/contracts/components/IOracle.sol";
import "@etherisc/gif-interface/contracts/components/IProduct.sol";
import "@etherisc/gif-interface/contracts/components/IRiskpool.sol";
import "@etherisc/gif-interface/contracts/modules/IPolicy.sol";
import "@etherisc/gif-interface/contracts/modules/IRegistry.sol";
import "@etherisc/gif-interface/contracts/services/IComponentOwnerService.sol";
Expand Down Expand Up @@ -137,10 +140,6 @@ contract InstanceService is
return _component.getComponentId(componentAddress);
}

function getComponent(uint256 id) external override view returns(IComponent) {
return _component.getComponent(id);
}

function getComponentType(uint256 componentId)
external override
view
Expand All @@ -157,6 +156,22 @@ contract InstanceService is
componentState = _component.getComponentState(componentId);
}

function getComponent(uint256 id) external override view returns(IComponent) {
return _component.getComponent(id);
}

function getOracleId(uint256 idx) public view returns (uint256 oracleId) {
return _component.getOracleId(idx);
}

function getRiskpoolId(uint256 idx) public view returns (uint256 riskpoolId) {
return _component.getRiskpoolId(idx);
}

function getProductId(uint256 idx) public view returns (uint256 productId) {
return _component.getProductId(idx);
}

/* service staking */
function getStakingRequirements(uint256 id)
external override
Expand Down
12 changes: 6 additions & 6 deletions scripts/ayii_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,15 @@ def __init__(self,
self.clToken = ClToken.deploy(
clTokenOwner,
clTokenSupply,
{'from': oracleProvider})
{'from': oracleProvider},
publish_source=publishSource)

# 2b) chainlink operator deploy
self.chainlinkOperator = ClOperator.deploy(
self.clToken,
chainlinkNodeOperator,
{'from': oracleProvider})
{'from': oracleProvider},
publish_source=publishSource)

# set oracleProvider as authorized to call fullfill on operator
self.chainlinkOperator.setAuthorizedSenders([chainlinkNodeOperator])
Expand All @@ -163,9 +165,8 @@ def __init__(self,
chainLinkOracleAddress,
chainLinkJobId,
chainLinkPaymentAmount,
{'from': oracleProvider})
# {'from': oracleProvider},
# publish_source=publishSource)
{'from': oracleProvider},
publish_source=publishSource)

# 3) oracle owner proposes oracle to instance
componentOwnerService.propose(
Expand Down Expand Up @@ -277,7 +278,6 @@ def getPolicy(self, policyId: str):
return self.policy.getPolicy(policyId)



class GifAyiiProductComplete(object):

def __init__(self,
Expand Down
Loading