@ensuro/core 1.2.7 → 2.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -17
- package/build/contracts/EToken.sol/EToken.json +122 -177
- package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +101 -323
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +15 -2
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +16 -3
- package/build/contracts/PolicyPool.sol/PolicyPool.json +105 -351
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +13 -0
- package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +77 -72
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +761 -0
- package/build/contracts/{BaseAssetManager.sol/BaseAssetManager.json → Reserve.sol/Reserve.json} +15 -202
- package/build/contracts/RiskModule.sol/RiskModule.json +83 -310
- package/build/contracts/TimeScaled.sol/TimeScaled.json +24 -0
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +131 -333
- package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +15 -2
- package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +64 -0
- package/build/{interfaces/IExchange.sol/IExchange.json → contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json} +83 -79
- package/build/{interfaces → contracts/interfaces}/IEToken.sol/IEToken.json +32 -97
- package/build/{interfaces → contracts/interfaces}/ILPWhitelist.sol/ILPWhitelist.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyHolder.sol/IPolicyHolder.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyNFT.sol/IPolicyNFT.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyPool.sol/IPolicyPool.json +121 -108
- package/build/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyPoolConfig.sol/IPolicyPoolConfig.json +20 -36
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +302 -0
- package/build/{interfaces → contracts/interfaces}/IRiskModule.sol/IRiskModule.json +58 -34
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +43 -0
- package/build/{interfaces/IInsolvencyHook.sol/IInsolvencyHook.json → contracts/mocks/IMintableERC20.sol/IMintableERC20.json} +13 -8
- package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +370 -0
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +202 -0
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +35 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +603 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +92 -0
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +343 -0
- package/build/contracts/mocks/TestCurrencyUUPS.sol/TestCurrencyUUPS.json +353 -0
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +388 -0
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +16 -3
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +16 -3
- package/contracts/EToken.sol +188 -269
- package/contracts/FlightDelayRiskModule.sol +30 -21
- package/contracts/LPManualWhitelist.sol +3 -3
- package/contracts/Policy.sol +48 -44
- package/contracts/PolicyNFT.sol +2 -2
- package/contracts/PolicyPool.sol +114 -467
- package/contracts/PolicyPoolComponent.sol +8 -3
- package/contracts/PolicyPoolConfig.sol +30 -73
- package/contracts/PremiumsAccount.sol +274 -0
- package/contracts/Reserve.sol +34 -0
- package/contracts/RiskModule.sol +216 -164
- package/contracts/TimeScaled.sol +134 -0
- package/contracts/TrustfulRiskModule.sol +23 -21
- package/contracts/dependencies/ERC1967Proxy.sol +19 -0
- package/contracts/dependencies/IERC20Metadata.sol +19 -0
- package/contracts/interfaces/IEToken.sol +172 -0
- package/{interfaces → contracts/interfaces}/ILPWhitelist.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyHolder.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyNFT.sol +0 -0
- package/contracts/interfaces/IPolicyPool.sol +138 -0
- package/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyPoolConfig.sol +29 -20
- package/contracts/interfaces/IPremiumsAccount.sol +71 -0
- package/contracts/interfaces/IRiskModule.sol +60 -0
- package/contracts/mocks/ForwardProxy.sol +66 -0
- package/contracts/mocks/IMintableERC20.sol +13 -0
- package/contracts/mocks/LinkTokenMock.sol +30 -0
- package/contracts/mocks/PolicyHolderMock.sol +68 -0
- package/contracts/mocks/PolicyPoolComponentMock.sol +17 -0
- package/contracts/mocks/PolicyPoolMock.sol +122 -0
- package/contracts/mocks/TestCurrency.sol +35 -0
- package/contracts/mocks/TestNFT.sol +23 -0
- package/contracts/upgraded/PolicyNFTv1.sol +1 -1
- package/js/test-utils.js +278 -0
- package/package.json +2 -2
- package/build/contracts/AaveAssetManager.sol/AaveAssetManager.json +0 -742
- package/build/contracts/DataTypes.sol/DataTypes.json +0 -10
- package/build/contracts/Exchange.sol/Exchange.json +0 -591
- package/build/contracts/extras/IPriceRiskModule.sol/IPriceRiskModule.json +0 -253
- package/build/contracts/extras/PriceRiskModule.sol/PriceRiskModule.json +0 -1055
- package/build/interfaces/IAssetManager.sol/IAssetManager.json +0 -31
- package/build/interfaces/IExchange.sol/IPriceOracle.json +0 -30
- package/contracts/AaveAssetManager.sol +0 -298
- package/contracts/BaseAssetManager.sol +0 -301
- package/contracts/DataTypes.sol +0 -287
- package/contracts/Exchange.sol +0 -189
- package/contracts/extras/IPriceRiskModule.sol +0 -41
- package/contracts/extras/PriceRiskModule.sol +0 -243
- package/interfaces/IAssetManager.sol +0 -23
- package/interfaces/IEToken.sol +0 -48
- package/interfaces/IExchange.sol +0 -59
- package/interfaces/IInsolvencyHook.sol +0 -27
- package/interfaces/IPolicyPool.sol +0 -44
- package/interfaces/IRiskModule.sol +0 -29
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.0;
|
|
4
|
+
|
|
5
|
+
import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @dev This contract provides a fallback function that forwards all calls to another contract using the EVM
|
|
9
|
+
* instruction `call`.
|
|
10
|
+
*
|
|
11
|
+
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
|
|
12
|
+
* different contract through the {_delegate} function.
|
|
13
|
+
*
|
|
14
|
+
* The success and return data of the delegated call will be returned back to the caller of the proxy.
|
|
15
|
+
*/
|
|
16
|
+
contract ForwardProxy is Proxy {
|
|
17
|
+
address internal _forwardTo;
|
|
18
|
+
|
|
19
|
+
constructor(address forwardTo) {
|
|
20
|
+
_forwardTo = forwardTo;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @dev Delegates the current call to `implementation`.
|
|
25
|
+
*
|
|
26
|
+
* This function does not return to its internall call site, it will return directly to the external caller.
|
|
27
|
+
*/
|
|
28
|
+
function _delegate(address implementation) internal virtual override {
|
|
29
|
+
// solhint-disable-next-line no-inline-assembly
|
|
30
|
+
assembly {
|
|
31
|
+
// Copy msg.data. We take full control of memory in this inline assembly
|
|
32
|
+
// block because it will not return to Solidity code. We overwrite the
|
|
33
|
+
// Solidity scratch pad at memory position 0.
|
|
34
|
+
calldatacopy(0, 0, calldatasize())
|
|
35
|
+
|
|
36
|
+
// Call the implementation.
|
|
37
|
+
// out and outsize are 0 because we don't know the size yet.
|
|
38
|
+
// let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
|
|
39
|
+
let result := call(gas(), implementation, 0, 0, calldatasize(), 0, 0)
|
|
40
|
+
|
|
41
|
+
// Copy the returned data.
|
|
42
|
+
returndatacopy(0, 0, returndatasize())
|
|
43
|
+
|
|
44
|
+
switch result
|
|
45
|
+
// delegatecall returns 0 on error.
|
|
46
|
+
case 0 {
|
|
47
|
+
revert(0, returndatasize())
|
|
48
|
+
}
|
|
49
|
+
default {
|
|
50
|
+
return(0, returndatasize())
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
|
|
57
|
+
* and {_fallback} should delegate.
|
|
58
|
+
*/
|
|
59
|
+
function _implementation() internal view virtual override returns (address) {
|
|
60
|
+
return _forwardTo;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function setForwardTo(address forwardTo) external {
|
|
64
|
+
_forwardTo = forwardTo;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title IMintableERC20 interface
|
|
6
|
+
* @dev Interface for mintable / burnable ERC20 - for testing
|
|
7
|
+
* @author Ensuro
|
|
8
|
+
*/
|
|
9
|
+
interface IMintableERC20 {
|
|
10
|
+
function mint(address recipient, uint256 amount) external;
|
|
11
|
+
|
|
12
|
+
function burn(address recipient, uint256 amount) external;
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
|
|
6
|
+
|
|
7
|
+
contract LinkTokenMock is ERC20 {
|
|
8
|
+
address public lastTransferTo;
|
|
9
|
+
uint256 public lastTransferValue;
|
|
10
|
+
bytes public lastTransferData;
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
string memory name_,
|
|
14
|
+
string memory symbol_,
|
|
15
|
+
uint256 initialSupply
|
|
16
|
+
) ERC20(name_, symbol_) {
|
|
17
|
+
_mint(msg.sender, initialSupply);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function transferAndCall(
|
|
21
|
+
address to,
|
|
22
|
+
uint256 value,
|
|
23
|
+
bytes calldata data
|
|
24
|
+
) external returns (bool success) {
|
|
25
|
+
lastTransferTo = to;
|
|
26
|
+
lastTransferValue = value;
|
|
27
|
+
lastTransferData = data;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IPolicyHolder} from "../interfaces/IPolicyHolder.sol";
|
|
5
|
+
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
|
|
6
|
+
|
|
7
|
+
contract PolicyHolderMock is IPolicyHolder {
|
|
8
|
+
uint256 public policyId;
|
|
9
|
+
uint256 public payout;
|
|
10
|
+
bool public fail;
|
|
11
|
+
|
|
12
|
+
event NotificationReceived(uint256 kind, uint256 policyId, address operator, address from);
|
|
13
|
+
|
|
14
|
+
constructor(bool fail_) {
|
|
15
|
+
fail = fail_;
|
|
16
|
+
payout = type(uint256).max;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function setFail(bool fail_) external {
|
|
20
|
+
fail = fail_;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function onERC721Received(
|
|
24
|
+
address operator,
|
|
25
|
+
address from,
|
|
26
|
+
uint256 policyId_,
|
|
27
|
+
bytes calldata
|
|
28
|
+
) external override returns (bytes4) {
|
|
29
|
+
if (fail) revert("onERC721Received: They told me I have to fail");
|
|
30
|
+
policyId = policyId_;
|
|
31
|
+
emit NotificationReceived(0, policyId_, operator, from);
|
|
32
|
+
return IERC721Receiver.onERC721Received.selector;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function onPolicyExpired(
|
|
36
|
+
address operator,
|
|
37
|
+
address from,
|
|
38
|
+
uint256 policyId_
|
|
39
|
+
) external override returns (bytes4) {
|
|
40
|
+
if (fail) revert("onPolicyExpired: They told me I have to fail");
|
|
41
|
+
policyId = policyId_;
|
|
42
|
+
payout = 0;
|
|
43
|
+
emit NotificationReceived(1, policyId_, operator, from);
|
|
44
|
+
return IPolicyHolder.onPolicyExpired.selector;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @dev Whenever an Policy is resolved with payout > 0, this function is called
|
|
49
|
+
*
|
|
50
|
+
* It must return its Solidity selector to confirm the payout.
|
|
51
|
+
* If interface is not implemented by the recipient, it will be ignored and the payout will be successful.
|
|
52
|
+
* If any other value is returned or it reverts, the policy resolution / payout will be reverted.
|
|
53
|
+
*
|
|
54
|
+
* The selector can be obtained in Solidity with `IPolicyPool.onPayoutReceived.selector`.
|
|
55
|
+
*/
|
|
56
|
+
function onPayoutReceived(
|
|
57
|
+
address operator,
|
|
58
|
+
address from,
|
|
59
|
+
uint256 policyId_,
|
|
60
|
+
uint256 amount
|
|
61
|
+
) external override returns (bytes4) {
|
|
62
|
+
if (fail) revert("onPayoutReceived: They told me I have to fail");
|
|
63
|
+
policyId = policyId_;
|
|
64
|
+
payout = amount;
|
|
65
|
+
emit NotificationReceived(2, policyId_, operator, from);
|
|
66
|
+
return IPolicyHolder.onPayoutReceived.selector;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
5
|
+
import {IPolicyPoolComponent} from "../interfaces/IPolicyPoolComponent.sol";
|
|
6
|
+
|
|
7
|
+
contract PolicyPoolComponentMock is IPolicyPoolComponent {
|
|
8
|
+
IPolicyPool internal immutable _policyPool;
|
|
9
|
+
|
|
10
|
+
constructor(IPolicyPool policyPool_) {
|
|
11
|
+
_policyPool = policyPool_;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function policyPool() external view override returns (IPolicyPool) {
|
|
15
|
+
return _policyPool;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
5
|
+
import {IRiskModule} from "../interfaces/IRiskModule.sol";
|
|
6
|
+
import {IEToken} from "../interfaces/IEToken.sol";
|
|
7
|
+
import {IPolicyPoolConfig} from "../interfaces/IPolicyPoolConfig.sol";
|
|
8
|
+
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
|
|
9
|
+
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
10
|
+
import {Policy} from "../Policy.sol";
|
|
11
|
+
import {ForwardProxy} from "./ForwardProxy.sol";
|
|
12
|
+
|
|
13
|
+
contract PolicyPoolMock is IPolicyPool {
|
|
14
|
+
using Policy for Policy.PolicyData;
|
|
15
|
+
|
|
16
|
+
uint256 public constant MAX_INT =
|
|
17
|
+
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
|
|
18
|
+
|
|
19
|
+
IERC20Metadata internal _currency;
|
|
20
|
+
IPolicyPoolConfig internal _config;
|
|
21
|
+
|
|
22
|
+
mapping(uint256 => Policy.PolicyData) internal policies;
|
|
23
|
+
mapping(uint256 => bytes32) internal policyHashes;
|
|
24
|
+
|
|
25
|
+
event NewPolicy(IRiskModule indexed riskModule, Policy.PolicyData policy);
|
|
26
|
+
event PolicyResolved(IRiskModule indexed riskModule, uint256 indexed policyId, uint256 payout);
|
|
27
|
+
|
|
28
|
+
constructor(IERC20Metadata currency_, IPolicyPoolConfig config_) {
|
|
29
|
+
_currency = currency_;
|
|
30
|
+
_config = config_;
|
|
31
|
+
_config.connect();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function currency() external view override returns (IERC20Metadata) {
|
|
35
|
+
return _currency;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function config() external view override returns (IPolicyPoolConfig) {
|
|
39
|
+
return _config;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function policyNFT() external pure override returns (address) {
|
|
43
|
+
return address(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function newPolicy(
|
|
47
|
+
Policy.PolicyData memory policy,
|
|
48
|
+
address, /* customer */
|
|
49
|
+
uint96 internalId
|
|
50
|
+
) external override returns (uint256) {
|
|
51
|
+
policy.id = (uint256(uint160(address(policy.riskModule))) << 96) + internalId;
|
|
52
|
+
policyHashes[policy.id] = policy.hash();
|
|
53
|
+
emit NewPolicy(IRiskModule(msg.sender), policy);
|
|
54
|
+
return policy.id;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function _resolvePolicy(Policy.PolicyData memory policy, uint256 payout) internal {
|
|
58
|
+
require(policy.id != 0, "Policy not found");
|
|
59
|
+
require(policy.hash() == policyHashes[policy.id], "Hash doesn't match");
|
|
60
|
+
require(
|
|
61
|
+
msg.sender == address(policy.riskModule),
|
|
62
|
+
"Only riskModule is authorized to resolve the policy"
|
|
63
|
+
);
|
|
64
|
+
delete policies[policy.id];
|
|
65
|
+
delete policyHashes[policy.id];
|
|
66
|
+
emit PolicyResolved(IRiskModule(msg.sender), policy.id, payout);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout) external override {
|
|
70
|
+
_resolvePolicy(policy, payout);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function expirePolicy(Policy.PolicyData calldata policy) external override {
|
|
74
|
+
_resolvePolicy(policy, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
|
|
78
|
+
external
|
|
79
|
+
override
|
|
80
|
+
{
|
|
81
|
+
return _resolvePolicy(policy, customerWon ? policy.payout : 0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function deposit(IEToken, uint256) external pure override {
|
|
85
|
+
revert("Not Implemented deposit");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function withdraw(IEToken, uint256) external pure override returns (uint256) {
|
|
89
|
+
revert("Not Implemented withdraw");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @title PolicyPoolMockForward
|
|
95
|
+
* @dev PolicyPool that forwards fallback calls to another contract. Used to simulate calls to EToken
|
|
96
|
+
* and other contracts that have functions that can be called only from PolicyPool
|
|
97
|
+
*/
|
|
98
|
+
contract PolicyPoolMockForward is ForwardProxy {
|
|
99
|
+
uint256 public constant MAX_INT =
|
|
100
|
+
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
|
|
101
|
+
|
|
102
|
+
IERC20Metadata internal _currency;
|
|
103
|
+
IPolicyPoolConfig internal _config;
|
|
104
|
+
|
|
105
|
+
constructor(
|
|
106
|
+
address forwardTo,
|
|
107
|
+
IERC20Metadata currency_,
|
|
108
|
+
IPolicyPoolConfig config_
|
|
109
|
+
) ForwardProxy(forwardTo) {
|
|
110
|
+
_currency = currency_;
|
|
111
|
+
_config = config_;
|
|
112
|
+
_config.connect();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function currency() external view returns (IERC20Metadata) {
|
|
116
|
+
return _currency;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function config() external view returns (IPolicyPoolConfig) {
|
|
120
|
+
return _config;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import {IMintableERC20} from "./IMintableERC20.sol";
|
|
6
|
+
|
|
7
|
+
contract TestCurrency is ERC20, IMintableERC20 {
|
|
8
|
+
address private _owner;
|
|
9
|
+
uint8 internal immutable _decimals;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
string memory name_,
|
|
13
|
+
string memory symbol_,
|
|
14
|
+
uint256 initialSupply,
|
|
15
|
+
uint8 decimals_
|
|
16
|
+
) ERC20(name_, symbol_) {
|
|
17
|
+
_owner = msg.sender;
|
|
18
|
+
_decimals = decimals_;
|
|
19
|
+
_mint(msg.sender, initialSupply);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function decimals() public view virtual override returns (uint8) {
|
|
23
|
+
return _decimals;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function mint(address recipient, uint256 amount) external override {
|
|
27
|
+
// require(msg.sender == _owner, "Only owner can mint");
|
|
28
|
+
return _mint(recipient, amount);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function burn(address recipient, uint256 amount) external override {
|
|
32
|
+
// require(msg.sender == _owner, "Only owner can burn");
|
|
33
|
+
return _burn(recipient, amount);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//SPDX-License-Identifier: Unlicense
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
pragma experimental ABIEncoderV2;
|
|
4
|
+
|
|
5
|
+
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
|
6
|
+
|
|
7
|
+
contract TestNFT is ERC721 {
|
|
8
|
+
address private _owner;
|
|
9
|
+
|
|
10
|
+
constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {
|
|
11
|
+
_owner = msg.sender;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function mint(address recipient, uint256 tokenId) public {
|
|
15
|
+
// require(msg.sender == _owner, "Only owner can mint");
|
|
16
|
+
return _mint(recipient, tokenId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function burn(uint256 tokenId) public {
|
|
20
|
+
require(ERC721.ownerOf(tokenId) == msg.sender, "ERC721: burn of token that is not own");
|
|
21
|
+
return _burn(tokenId);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -5,7 +5,7 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U
|
|
|
5
5
|
import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
|
|
6
6
|
import {CountersUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
|
|
7
7
|
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
|
|
8
|
-
import {IPolicyPool} from "
|
|
8
|
+
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
9
9
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
10
10
|
import {IPolicyNFTv1} from "./IPolicyNFTv1.sol";
|
|
11
11
|
|
package/js/test-utils.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
const { expect } = require("chai");
|
|
2
|
+
const { BigNumber } = require("ethers");
|
|
3
|
+
const {LogDescription} = require("ethers/lib/utils");
|
|
4
|
+
exports.WEEK = 3600 * 24 * 7;
|
|
5
|
+
exports.DAY = 3600 * 24;
|
|
6
|
+
|
|
7
|
+
exports.initCurrency = async function(options, initial_targets, initial_balances) {
|
|
8
|
+
const Currency = await ethers.getContractFactory("TestCurrency");
|
|
9
|
+
let currency = await Currency.deploy(
|
|
10
|
+
options.name || "Test Currency",
|
|
11
|
+
options.symbol || "TEST",
|
|
12
|
+
options.initial_supply,
|
|
13
|
+
options.decimals || 18,
|
|
14
|
+
);
|
|
15
|
+
initial_targets = initial_targets || [];
|
|
16
|
+
await Promise.all(initial_targets.map(async function (user, index) {
|
|
17
|
+
await currency.transfer(user.address, initial_balances[index]);
|
|
18
|
+
}));
|
|
19
|
+
return currency;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.approve_multiple = async function(currency, spender, sources, amounts) {
|
|
23
|
+
return Promise.all(sources.map(async function (source, index) {
|
|
24
|
+
await currency.connect(source).approve(spender.address, amounts[index]);
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.check_balances = async function(currency, users, amounts) {
|
|
29
|
+
return Promise.all(users.map(async function (user, index) {
|
|
30
|
+
expect(await currency.balanceOf(user.address)).to.equal(amounts[index]);
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.now = function() {
|
|
35
|
+
return Math.floor(new Date().getTime() / 1000);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.addRiskModule = async function(pool, premiumsAccount, contractFactory, {
|
|
39
|
+
rmName, scrPercentage, scrInterestRate, ensuroFee, maxScrPerPolicy,
|
|
40
|
+
scrLimit, moc, wallet, extraArgs, extraConstructorArgs
|
|
41
|
+
}) {
|
|
42
|
+
extraArgs = extraArgs || [];
|
|
43
|
+
extraConstructorArgs = extraConstructorArgs || [];
|
|
44
|
+
const _A = pool._A || _W;
|
|
45
|
+
const rm = await hre.upgrades.deployProxy(contractFactory, [
|
|
46
|
+
rmName || "RiskModule",
|
|
47
|
+
_W(scrPercentage) || _W(1),
|
|
48
|
+
_W(ensuroFee) || _W(0),
|
|
49
|
+
_W(scrInterestRate) || _W(0.1),
|
|
50
|
+
_A(maxScrPerPolicy) || _A(1000),
|
|
51
|
+
_A(scrLimit) || _A(1000000),
|
|
52
|
+
wallet || "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", // Random address
|
|
53
|
+
...extraArgs
|
|
54
|
+
], {
|
|
55
|
+
kind: 'uups',
|
|
56
|
+
unsafeAllow: ["delegatecall"],
|
|
57
|
+
constructorArgs: [pool.address, premiumsAccount.address, ...extraConstructorArgs]
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await rm.deployed();
|
|
61
|
+
|
|
62
|
+
if (moc !== undefined && moc != 1.0) {
|
|
63
|
+
moc = _W(moc);
|
|
64
|
+
await rm.setParam(0, moc);
|
|
65
|
+
}
|
|
66
|
+
const policyPoolConfig = await hre.ethers.getContractAt("PolicyPoolConfig", await pool.config());
|
|
67
|
+
await policyPoolConfig.addRiskModule(rm.address);
|
|
68
|
+
return rm;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
exports.addEToken = async function(pool, {
|
|
72
|
+
etkName, etkSymbol, maxUtilizationRate,
|
|
73
|
+
poolLoanInterestRate, extraArgs, extraConstructorArgs
|
|
74
|
+
}) {
|
|
75
|
+
const EToken = await ethers.getContractFactory("EToken");
|
|
76
|
+
extraArgs = extraArgs || [];
|
|
77
|
+
extraConstructorArgs = extraConstructorArgs || [];
|
|
78
|
+
const etk = await hre.upgrades.deployProxy(EToken, [
|
|
79
|
+
etkName || "EToken",
|
|
80
|
+
etkSymbol || "eUSD1YEAR",
|
|
81
|
+
_W(maxUtilizationRate) || _W(1),
|
|
82
|
+
_W(poolLoanInterestRate) || _W("0.05"),
|
|
83
|
+
...extraArgs
|
|
84
|
+
], {
|
|
85
|
+
kind: 'uups',
|
|
86
|
+
unsafeAllow: ["delegatecall"],
|
|
87
|
+
constructorArgs: [pool.address, ...extraConstructorArgs]
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await etk.deployed();
|
|
91
|
+
await pool.addEToken(etk.address);
|
|
92
|
+
return etk;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
exports.expected_change = async function(protocol_attribute, initial, change) {
|
|
96
|
+
change = BigNumber.from(change);
|
|
97
|
+
let actual_value = await protocol_attribute();
|
|
98
|
+
expect(actual_value.sub(initial)).to.equal(change);
|
|
99
|
+
return actual_value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
exports.impersonate = async function(address, setBalanceTo) {
|
|
103
|
+
const ok = await hre.network.provider.request(
|
|
104
|
+
{method: "hardhat_impersonateAccount", params: [address]}
|
|
105
|
+
);
|
|
106
|
+
if (!ok)
|
|
107
|
+
throw "Error impersonatting " + address;
|
|
108
|
+
|
|
109
|
+
if (setBalanceTo !== undefined)
|
|
110
|
+
await hre.network.provider.request(
|
|
111
|
+
{method: "hardhat_setBalance", params: [address, setBalanceTo.toHexString()]}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return await ethers.getSigner(address);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Finds an event in the receipt
|
|
120
|
+
* @param {Interface} interface The interface of the contract that contains the requested event
|
|
121
|
+
* @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
|
|
122
|
+
* @param {String} eventName The name of the event we are interested in
|
|
123
|
+
* @returns {LogDescription}
|
|
124
|
+
*/
|
|
125
|
+
exports.getTransactionEvent = function(interface, receipt, eventName) {
|
|
126
|
+
// for each log in the transaction receipt
|
|
127
|
+
for (const log of receipt.events) {
|
|
128
|
+
let parsedLog;
|
|
129
|
+
try {
|
|
130
|
+
parsedLog = interface.parseLog(log);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (parsedLog.name == eventName) {
|
|
135
|
+
return parsedLog;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null; // not found
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
exports.deployPool = async function(hre, options) {
|
|
142
|
+
const PolicyPool = await ethers.getContractFactory("PolicyPool");
|
|
143
|
+
const PolicyPoolConfig = await ethers.getContractFactory("PolicyPoolConfig");
|
|
144
|
+
const PolicyNFT = await ethers.getContractFactory("PolicyNFT");
|
|
145
|
+
|
|
146
|
+
// Deploy PolicyNFT
|
|
147
|
+
const policyNFT = await hre.upgrades.deployProxy(
|
|
148
|
+
PolicyNFT,
|
|
149
|
+
[
|
|
150
|
+
options.nftName || "Policy NFT",
|
|
151
|
+
options.nftSymbol || "EPOL",
|
|
152
|
+
options.policyPoolDetAddress || ethers.constants.AddressZero
|
|
153
|
+
],
|
|
154
|
+
{kind: 'uups'}
|
|
155
|
+
);
|
|
156
|
+
await policyNFT.deployed();
|
|
157
|
+
|
|
158
|
+
// Deploy PolicyPoolConfig
|
|
159
|
+
const policyPoolConfig = await hre.upgrades.deployProxy(PolicyPoolConfig, [
|
|
160
|
+
options.policyPoolDetAddress || ethers.constants.AddressZero,
|
|
161
|
+
options.treasuryAddress || ethers.constants.AddressZero
|
|
162
|
+
], {kind: 'uups'});
|
|
163
|
+
|
|
164
|
+
await policyPoolConfig.deployed();
|
|
165
|
+
|
|
166
|
+
const policyPool = await hre.upgrades.deployProxy(PolicyPool, [], {
|
|
167
|
+
constructorArgs: [policyPoolConfig.address, policyNFT.address, options.currency],
|
|
168
|
+
kind: 'uups',
|
|
169
|
+
unsafeAllow: ["delegatecall"],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await policyPool.deployed();
|
|
173
|
+
|
|
174
|
+
for (const role of (options.grantRoles || [])) {
|
|
175
|
+
await grantRole(hre, policyPoolConfig, role);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await grantRole(hre, policyPoolConfig, "LEVEL1_ROLE");
|
|
179
|
+
await grantRole(hre, policyPoolConfig, "LEVEL2_ROLE");
|
|
180
|
+
await grantRole(hre, policyPoolConfig, "LEVEL3_ROLE");
|
|
181
|
+
return policyPool;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
exports.deployPremiumsAccount = async function (hre, pool, options) {
|
|
185
|
+
const PremiumsAccount = await ethers.getContractFactory("PremiumsAccount");
|
|
186
|
+
const premiumsAccount = await hre.upgrades.deployProxy(PremiumsAccount, [], {
|
|
187
|
+
constructorArgs: [
|
|
188
|
+
pool.address,
|
|
189
|
+
options.jrEtkAddr || ethers.constants.AddressZero,
|
|
190
|
+
options.srEtkAddr || ethers.constants.AddressZero,
|
|
191
|
+
],
|
|
192
|
+
kind: 'uups',
|
|
193
|
+
unsafeAllow: ["delegatecall"],
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await premiumsAccount.deployed();
|
|
197
|
+
await pool.addPremiumsAccount(premiumsAccount.address);
|
|
198
|
+
return premiumsAccount;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function _getDefaultSigner(hre) {
|
|
202
|
+
const signers = await hre.ethers.getSigners();
|
|
203
|
+
return signers[0];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function grantRole(hre, contract, role, user) {
|
|
207
|
+
let userAddress;
|
|
208
|
+
if (user === undefined) {
|
|
209
|
+
user = await _getDefaultSigner(hre);
|
|
210
|
+
userAddress = user.address;
|
|
211
|
+
} else {
|
|
212
|
+
userAddress = user;
|
|
213
|
+
}
|
|
214
|
+
const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
|
|
215
|
+
if (!await contract.hasRole(roleHex, userAddress)) {
|
|
216
|
+
await contract.grantRole(roleHex, userAddress);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
exports.grantRole = grantRole;
|
|
221
|
+
|
|
222
|
+
async function grantComponentRole(hre, contract, component, role, user) {
|
|
223
|
+
let userAddress;
|
|
224
|
+
if (user === undefined) {
|
|
225
|
+
user = await _getDefaultSigner(hre);
|
|
226
|
+
userAddress = user.address;
|
|
227
|
+
} else {
|
|
228
|
+
userAddress = user;
|
|
229
|
+
}
|
|
230
|
+
const roleHex = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(role));
|
|
231
|
+
const componentRole = await contract.getComponentRole(component.address, roleHex);
|
|
232
|
+
if (!await contract.hasRole(componentRole, userAddress)) {
|
|
233
|
+
await contract.grantComponentRole(component.address, roleHex, userAddress);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
exports.grantComponentRole = grantComponentRole;
|
|
238
|
+
|
|
239
|
+
exports._E = ethers.utils.parseEther;
|
|
240
|
+
|
|
241
|
+
const _BN = ethers.BigNumber.from;
|
|
242
|
+
const WAD = _BN(1e10).mul(_BN(1e8)); // 1e10*1e8=1e18
|
|
243
|
+
const RAY = WAD.mul(_BN(1e9)); // 1e18*1e9=1e27
|
|
244
|
+
|
|
245
|
+
exports._BN = _BN;
|
|
246
|
+
|
|
247
|
+
const _W = function(value) {
|
|
248
|
+
if (value === undefined)
|
|
249
|
+
return undefined;
|
|
250
|
+
if (!Number.isInteger(value))
|
|
251
|
+
return _BN(Math.round(value * 1e9)).mul(_BN(1e9));
|
|
252
|
+
return _BN(value).mul(WAD);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
exports._W = _W;
|
|
256
|
+
|
|
257
|
+
const _R = function(value) {
|
|
258
|
+
if (value === undefined)
|
|
259
|
+
return undefined;
|
|
260
|
+
if (!Number.isInteger(value))
|
|
261
|
+
return _BN(Math.round(value * 1e9)).mul(WAD);
|
|
262
|
+
return _BN(value).mul(RAY);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
exports._R = _R;
|
|
266
|
+
|
|
267
|
+
exports.amountFunction = function (decimals) {
|
|
268
|
+
// Decimals must be at least 6
|
|
269
|
+
return function (value) {
|
|
270
|
+
if (value === undefined)
|
|
271
|
+
return undefined;
|
|
272
|
+
if (typeof value === 'string' || value instanceof String) {
|
|
273
|
+
return _BN(value).mul(_BN(Math.pow(10, decimals)));
|
|
274
|
+
} else {
|
|
275
|
+
return _BN(Math.round(value * 1e6)).mul(_BN(Math.pow(10, decimals - 6)));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ensuro/core",
|
|
3
3
|
"description": "Ensuro - Decentralized insurance protocol",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0-beta1",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.sol",
|
|
7
7
|
"/build/contracts/*.json",
|
|
8
8
|
"/build/interfaces/*.json",
|
|
9
|
-
"
|
|
9
|
+
"/js/*.js"
|
|
10
10
|
],
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|