@ensuro/core 2.0.0-beta2 → 2.0.0-beta5
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 +2 -1
- package/build/contracts/AccessManager.sol/AccessManager.json +487 -0
- package/build/contracts/EToken.sol/EToken.json +4 -4
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +4 -4
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +148 -15
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +2 -2
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +4 -4
- package/build/contracts/Reserve.sol/Reserve.json +2 -2
- package/build/contracts/RiskModule.sol/RiskModule.json +2 -2
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +4 -4
- package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +2 -67
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +15 -2
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +19 -6
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
- package/contracts/AccessManager.sol +72 -0
- package/contracts/EToken.sol +6 -13
- package/contracts/PolicyNFT.sol +3 -3
- package/contracts/PolicyPool.sol +108 -43
- package/contracts/PolicyPoolComponent.sol +11 -11
- package/contracts/PremiumsAccount.sol +1 -1
- package/contracts/RiskModule.sol +4 -8
- package/contracts/interfaces/{IPolicyPoolConfig.sol → IAccessManager.sol} +2 -21
- package/contracts/interfaces/IPolicyPool.sol +10 -5
- package/contracts/mocks/PolicyPoolMock.sol +15 -13
- package/js/test-utils.js +177 -119
- package/package.json +1 -1
- package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
- package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -665
- package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
- package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
- package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
- package/contracts/FlightDelayRiskModule.sol +0 -217
- package/contracts/PolicyPoolConfig.sol +0 -185
- package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
- package/contracts/mocks/LinkTokenMock.sol +0 -30
- package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
- package/contracts/upgraded/PolicyNFTv1.sol +0 -126
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"type": "address"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"internalType": "contract
|
|
20
|
-
"name": "
|
|
19
|
+
"internalType": "contract IAccessManager",
|
|
20
|
+
"name": "access_",
|
|
21
21
|
"type": "address"
|
|
22
22
|
}
|
|
23
23
|
],
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"inputs": [],
|
|
46
|
-
"name": "
|
|
46
|
+
"name": "access",
|
|
47
47
|
"outputs": [
|
|
48
48
|
{
|
|
49
|
-
"internalType": "contract
|
|
49
|
+
"internalType": "contract IAccessManager",
|
|
50
50
|
"name": "",
|
|
51
51
|
"type": "address"
|
|
52
52
|
}
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"type": "receive"
|
|
86
86
|
}
|
|
87
87
|
],
|
|
88
|
-
"bytecode": "
|
|
89
|
-
"deployedBytecode": "
|
|
88
|
+
"bytecode": "0x608060405234801561001057600080fd5b5060405161029c38038061029c83398101604081905261002f91610071565b600080546001600160a01b039485166001600160a01b0319918216179091556001805493851693821693909317909255600280549190931691161790556100d6565b60008060006060848603121561008657600080fd5b8351610091816100be565b60208501519093506100a2816100be565b60408501519092506100b3816100be565b809150509250925092565b6001600160a01b03811681146100d357600080fd5b50565b6101b7806100e56000396000f3fe6080604052600436106100435760003560e01c8063098d32281461005a57806371907f1714610083578063d4b27001146100b5578063e5a6b10f146100f257610052565b3661005257610050610110565b005b610050610110565b34801561006657600080fd5b5061007060001981565b6040519081526020015b60405180910390f35b34801561008f57600080fd5b506002546001600160a01b03165b6040516001600160a01b03909116815260200161007a565b3480156100c157600080fd5b506100506100d0366004610151565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b3480156100fe57600080fd5b506001546001600160a01b031661009d565b61012a6101256000546001600160a01b031690565b61012c565b565b366000803760008036600080855af13d6000803e80801561014c573d6000f35b3d6000fd5b60006020828403121561016357600080fd5b81356001600160a01b038116811461017a57600080fd5b939250505056fea2646970667358221220d557744d7b910fc7fa89da179a00dcce31a4dc9474da1b42f972c509d050b83364736f6c63430008060033",
|
|
89
|
+
"deployedBytecode": "0x6080604052600436106100435760003560e01c8063098d32281461005a57806371907f1714610083578063d4b27001146100b5578063e5a6b10f146100f257610052565b3661005257610050610110565b005b610050610110565b34801561006657600080fd5b5061007060001981565b6040519081526020015b60405180910390f35b34801561008f57600080fd5b506002546001600160a01b03165b6040516001600160a01b03909116815260200161007a565b3480156100c157600080fd5b506100506100d0366004610151565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b3480156100fe57600080fd5b506001546001600160a01b031661009d565b61012a6101256000546001600160a01b031690565b61012c565b565b366000803760008036600080855af13d6000803e80801561014c573d6000f35b3d6000fd5b60006020828403121561016357600080fd5b81356001600160a01b038116811461017a57600080fd5b939250505056fea2646970667358221220d557744d7b910fc7fa89da179a00dcce31a4dc9474da1b42f972c509d050b83364736f6c63430008060033",
|
|
90
90
|
"linkReferences": {},
|
|
91
91
|
"deployedLinkReferences": {}
|
|
92
92
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
|
|
5
|
+
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
6
|
+
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
7
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title AccessManager - Protocol access roles
|
|
11
|
+
* @dev Contract that holds the access roles for PolicyPool and other components of the protocol.
|
|
12
|
+
* @custom:security-contact security@ensuro.co
|
|
13
|
+
* @author Ensuro
|
|
14
|
+
*/
|
|
15
|
+
contract AccessManager is Initializable, AccessControlUpgradeable, UUPSUpgradeable, IAccessManager {
|
|
16
|
+
// Core governance roles
|
|
17
|
+
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
|
|
18
|
+
bytes32 public constant LEVEL1_ROLE = keccak256("LEVEL1_ROLE");
|
|
19
|
+
bytes32 public constant LEVEL2_ROLE = keccak256("LEVEL2_ROLE");
|
|
20
|
+
bytes32 public constant LEVEL3_ROLE = keccak256("LEVEL3_ROLE");
|
|
21
|
+
|
|
22
|
+
modifier onlyRole2(bytes32 role1, bytes32 role2) {
|
|
23
|
+
if (!hasRole(role1, _msgSender())) _checkRole(role2, _msgSender());
|
|
24
|
+
_;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function initialize() public initializer {
|
|
28
|
+
__AccessControl_init();
|
|
29
|
+
__UUPSUpgradeable_init();
|
|
30
|
+
__AccessManager_init_unchained();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
34
|
+
function __AccessManager_init_unchained() internal initializer {
|
|
35
|
+
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// solhint-disable-next-line no-empty-blocks
|
|
39
|
+
function _authorizeUpgrade(address) internal override onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {}
|
|
40
|
+
|
|
41
|
+
function getComponentRole(address component, bytes32 role) public pure returns (bytes32) {
|
|
42
|
+
return bytes32(bytes20(component)) ^ role;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function checkComponentRole(
|
|
46
|
+
address component,
|
|
47
|
+
bytes32 role,
|
|
48
|
+
address account
|
|
49
|
+
) external view override {
|
|
50
|
+
_checkRole(getComponentRole(component, role), account);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function grantComponentRole(
|
|
54
|
+
address component,
|
|
55
|
+
bytes32 role,
|
|
56
|
+
address account
|
|
57
|
+
) external onlyRole(getRoleAdmin(getComponentRole(component, role))) {
|
|
58
|
+
_grantRole(getComponentRole(component, role), account);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function checkRole(bytes32 role, address account) external view override {
|
|
62
|
+
_checkRole(role, account);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function checkRole2(
|
|
66
|
+
bytes32 role1,
|
|
67
|
+
bytes32 role2,
|
|
68
|
+
address account
|
|
69
|
+
) external view override {
|
|
70
|
+
if (!hasRole(role1, account)) _checkRole(role2, account);
|
|
71
|
+
}
|
|
72
|
+
}
|
package/contracts/EToken.sol
CHANGED
|
@@ -6,7 +6,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
|
|
|
6
6
|
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
7
7
|
import {Reserve} from "./Reserve.sol";
|
|
8
8
|
import {IEToken} from "./interfaces/IEToken.sol";
|
|
9
|
-
import {
|
|
9
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
10
10
|
import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
|
|
11
11
|
import {ILPWhitelist} from "./interfaces/ILPWhitelist.sol";
|
|
12
12
|
import {WadRayMath} from "./WadRayMath.sol";
|
|
@@ -634,11 +634,7 @@ contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
|
634
634
|
// loan. Since it's a permissioned call, I'm ok with this. If a caller wants to reduce the impact, it can
|
|
635
635
|
// issue 1 wei repayLoan to each active loan, forcing the update of the scales
|
|
636
636
|
_params.internalLoanInterestRate = uint16(newRate / 1e14);
|
|
637
|
-
_parameterChanged(
|
|
638
|
-
IPolicyPoolConfig.GovernanceActions.setInternalLoanInterestRate,
|
|
639
|
-
newRate,
|
|
640
|
-
tweak
|
|
641
|
-
);
|
|
637
|
+
_parameterChanged(IAccessManager.GovernanceActions.setInternalLoanInterestRate, newRate, tweak);
|
|
642
638
|
}
|
|
643
639
|
|
|
644
640
|
function setLiquidityRequirement(uint256 newRate)
|
|
@@ -651,7 +647,7 @@ contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
|
651
647
|
"Tweak exceeded: liquidityRequirement tweaks only up to 10%"
|
|
652
648
|
);
|
|
653
649
|
_params.liquidityRequirement = uint16(newRate / 1e14);
|
|
654
|
-
_parameterChanged(
|
|
650
|
+
_parameterChanged(IAccessManager.GovernanceActions.setLiquidityRequirement, newRate, tweak);
|
|
655
651
|
}
|
|
656
652
|
|
|
657
653
|
function setMaxUtilizationRate(uint256 newRate) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
@@ -661,7 +657,7 @@ contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
|
661
657
|
"Tweak exceeded: maxUtilizationRate tweaks only up to 30%"
|
|
662
658
|
);
|
|
663
659
|
_params.maxUtilizationRate = uint16(newRate / 1e14);
|
|
664
|
-
_parameterChanged(
|
|
660
|
+
_parameterChanged(IAccessManager.GovernanceActions.setMaxUtilizationRate, newRate, tweak);
|
|
665
661
|
}
|
|
666
662
|
|
|
667
663
|
function setMinUtilizationRate(uint256 newRate) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
@@ -671,7 +667,7 @@ contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
|
671
667
|
"Tweak exceeded: minUtilizationRate tweaks only up to 30%"
|
|
672
668
|
);
|
|
673
669
|
_params.minUtilizationRate = uint16(newRate / 1e14);
|
|
674
|
-
_parameterChanged(
|
|
670
|
+
_parameterChanged(IAccessManager.GovernanceActions.setMinUtilizationRate, newRate, tweak);
|
|
675
671
|
}
|
|
676
672
|
|
|
677
673
|
function setWhitelist(ILPWhitelist lpWhitelist_)
|
|
@@ -684,10 +680,7 @@ contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
|
684
680
|
"Component not linked to this PolicyPool"
|
|
685
681
|
);
|
|
686
682
|
_params.whitelist = lpWhitelist_;
|
|
687
|
-
emit ComponentChanged(
|
|
688
|
-
IPolicyPoolConfig.GovernanceActions.setLPWhitelist,
|
|
689
|
-
address(lpWhitelist_)
|
|
690
|
-
);
|
|
683
|
+
emit ComponentChanged(IAccessManager.GovernanceActions.setLPWhitelist, address(lpWhitelist_));
|
|
691
684
|
}
|
|
692
685
|
|
|
693
686
|
function whitelist() external view returns (ILPWhitelist) {
|
package/contracts/PolicyNFT.sol
CHANGED
|
@@ -28,12 +28,12 @@ contract PolicyNFT is UUPSUpgradeable, ERC721Upgradeable, PausableUpgradeable, I
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
modifier onlyPoolRole2(bytes32 role1, bytes32 role2) {
|
|
31
|
-
_policyPool.
|
|
31
|
+
_policyPool.access().checkRole2(role1, role2, msg.sender);
|
|
32
32
|
_;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
modifier onlyPoolRole(bytes32 role) {
|
|
36
|
-
_policyPool.
|
|
36
|
+
_policyPool.access().checkRole(role, msg.sender);
|
|
37
37
|
_;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -75,7 +75,7 @@ contract PolicyNFT is UUPSUpgradeable, ERC721Upgradeable, PausableUpgradeable, I
|
|
|
75
75
|
);
|
|
76
76
|
_policyPool = IPolicyPool(_msgSender());
|
|
77
77
|
// Not possible to do this validation because connect is called in _policyPool initialize :'(
|
|
78
|
-
// require(_policyPool.policyNFT() == address(this), "PolicyPool not connected to this
|
|
78
|
+
// require(_policyPool.policyNFT() == address(this), "PolicyPool not connected to this access");
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
function policyPool() external view returns (IPolicyPool) {
|
package/contracts/PolicyPool.sol
CHANGED
|
@@ -5,7 +5,7 @@ import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IER
|
|
|
5
5
|
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
|
|
6
6
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
7
7
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
8
|
-
import {
|
|
8
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
9
9
|
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
|
|
10
10
|
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
|
11
11
|
import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
|
|
@@ -41,24 +41,32 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
41
41
|
bytes32 public constant LEVEL3_ROLE = keccak256("LEVEL3_ROLE");
|
|
42
42
|
|
|
43
43
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
44
|
-
|
|
44
|
+
IAccessManager internal immutable _access;
|
|
45
45
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
46
46
|
IERC20Metadata internal immutable _currency;
|
|
47
47
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
48
48
|
IPolicyNFT internal immutable _policyNFT;
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
address internal _treasury; // address of Ensuro treasury
|
|
51
|
+
|
|
52
|
+
enum ComponentStatus {
|
|
51
53
|
inactive, // doesn't exists - All operations rejected
|
|
52
|
-
active, // deposit / withdraw / lockScr / unlockScr OK
|
|
54
|
+
active, // deposit / withdraw / lockScr / unlockScr / newPolicy / resolvePolicy OK
|
|
53
55
|
deprecated, // withdraw OK, unlockScr OK, deposit rejected, no new policies
|
|
54
56
|
suspended // all operations temporarily rejected
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* @dev Mapping of installed eTokens (see {EToken}) in the PolicyPool. For each one it keep an state
|
|
59
|
-
* {
|
|
61
|
+
* {ComponentStatus}.
|
|
62
|
+
*/
|
|
63
|
+
mapping(IEToken => ComponentStatus) private _eTokens;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @dev Mapping of installed risk modules (see {RiskModule}) in the PolicyPool. For each one it keep an state
|
|
67
|
+
* {ComponentStatus}.
|
|
60
68
|
*/
|
|
61
|
-
mapping(
|
|
69
|
+
mapping(IRiskModule => ComponentStatus) private _riskModules;
|
|
62
70
|
|
|
63
71
|
/**
|
|
64
72
|
* @dev Mapping that stores the active policies (the policyId is the key). It just saves the hash of the policies,
|
|
@@ -79,49 +87,56 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
79
87
|
event PolicyResolved(IRiskModule indexed riskModule, uint256 indexed policyId, uint256 payout);
|
|
80
88
|
|
|
81
89
|
/**
|
|
82
|
-
* @dev Event emitted when a new eToken is added to the pool or the status changes. See {
|
|
90
|
+
* @dev Event emitted when a new eToken is added to the pool or the status changes. See {ComponentStatus}.
|
|
83
91
|
*/
|
|
84
|
-
event ETokenStatusChanged(IEToken indexed eToken,
|
|
92
|
+
event ETokenStatusChanged(IEToken indexed eToken, ComponentStatus newStatus);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @dev Event emitted when a new RiskModule is added to the pool or the status changes. See {ComponentStatus}.
|
|
96
|
+
*/
|
|
97
|
+
event RiskModuleStatusChanged(IRiskModule indexed riskModule, ComponentStatus newStatus);
|
|
85
98
|
|
|
86
99
|
/**
|
|
87
100
|
* @dev Event emitted when a new PremiumsAccount is added to the pool or the status changes. TODO
|
|
88
101
|
*/
|
|
89
102
|
event PremiumsAccountStatusChanged(
|
|
90
103
|
IPremiumsAccount indexed premiumsAccount,
|
|
91
|
-
|
|
104
|
+
ComponentStatus newStatus
|
|
92
105
|
);
|
|
93
106
|
|
|
107
|
+
event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
|
|
108
|
+
|
|
94
109
|
modifier onlyRole(bytes32 role) {
|
|
95
|
-
|
|
110
|
+
_access.checkRole(role, msg.sender);
|
|
96
111
|
_;
|
|
97
112
|
}
|
|
98
113
|
|
|
99
114
|
modifier onlyRole2(bytes32 role1, bytes32 role2) {
|
|
100
|
-
|
|
115
|
+
_access.checkRole2(role1, role2, msg.sender);
|
|
101
116
|
_;
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
105
120
|
constructor(
|
|
106
|
-
|
|
121
|
+
IAccessManager access_,
|
|
107
122
|
IPolicyNFT policyNFT_,
|
|
108
123
|
IERC20Metadata currency_
|
|
109
124
|
) {
|
|
110
|
-
|
|
125
|
+
_access = access_;
|
|
111
126
|
_policyNFT = policyNFT_;
|
|
112
127
|
_currency = currency_;
|
|
113
128
|
}
|
|
114
129
|
|
|
115
|
-
function initialize() public initializer {
|
|
130
|
+
function initialize(address treasury_) public initializer {
|
|
116
131
|
__UUPSUpgradeable_init();
|
|
117
132
|
__Pausable_init();
|
|
118
|
-
__PolicyPool_init_unchained();
|
|
133
|
+
__PolicyPool_init_unchained(treasury_);
|
|
119
134
|
}
|
|
120
135
|
|
|
121
136
|
// solhint-disable-next-line func-name-mixedcase
|
|
122
|
-
function __PolicyPool_init_unchained() internal initializer {
|
|
123
|
-
_config.connect();
|
|
137
|
+
function __PolicyPool_init_unchained(address treasury_) internal initializer {
|
|
124
138
|
_policyNFT.connect();
|
|
139
|
+
_treasury = treasury_;
|
|
125
140
|
}
|
|
126
141
|
|
|
127
142
|
// solhint-disable-next-line no-empty-blocks
|
|
@@ -135,8 +150,8 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
135
150
|
_unpause();
|
|
136
151
|
}
|
|
137
152
|
|
|
138
|
-
function
|
|
139
|
-
return
|
|
153
|
+
function access() external view virtual override returns (IAccessManager) {
|
|
154
|
+
return _access;
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
function currency() external view virtual override returns (IERC20Metadata) {
|
|
@@ -147,49 +162,96 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
147
162
|
return address(_policyNFT);
|
|
148
163
|
}
|
|
149
164
|
|
|
165
|
+
function setTreasury(address treasury_) external onlyRole(LEVEL1_ROLE) {
|
|
166
|
+
_treasury = treasury_;
|
|
167
|
+
emit ComponentChanged(IAccessManager.GovernanceActions.setTreasury, _treasury);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function treasury() external view override returns (address) {
|
|
171
|
+
return _treasury;
|
|
172
|
+
}
|
|
173
|
+
|
|
150
174
|
function addEToken(IEToken eToken) external onlyRole(LEVEL1_ROLE) {
|
|
151
|
-
|
|
152
|
-
require(status ==
|
|
153
|
-
require(address(eToken) != address(0), "eToken can't be zero");
|
|
175
|
+
ComponentStatus status = _eTokens[eToken];
|
|
176
|
+
require(status == ComponentStatus.inactive, "eToken already in the pool");
|
|
154
177
|
require(
|
|
155
178
|
IPolicyPoolComponent(address(eToken)).policyPool() == this,
|
|
156
179
|
"EToken not linked to this pool"
|
|
157
180
|
);
|
|
158
181
|
|
|
159
|
-
_eTokens[eToken] =
|
|
160
|
-
emit ETokenStatusChanged(eToken,
|
|
182
|
+
_eTokens[eToken] = ComponentStatus.active;
|
|
183
|
+
emit ETokenStatusChanged(eToken, ComponentStatus.active);
|
|
161
184
|
}
|
|
162
185
|
|
|
163
186
|
function removeEToken(IEToken eToken) external onlyRole(LEVEL3_ROLE) {
|
|
164
|
-
|
|
165
|
-
require(status ==
|
|
187
|
+
ComponentStatus status = _eTokens[eToken];
|
|
188
|
+
require(status == ComponentStatus.deprecated, "EToken not deprecated");
|
|
166
189
|
require(eToken.totalSupply() == 0, "EToken has liquidity, can't be removed");
|
|
167
190
|
delete _eTokens[eToken];
|
|
168
|
-
emit ETokenStatusChanged(eToken,
|
|
191
|
+
emit ETokenStatusChanged(eToken, ComponentStatus.inactive);
|
|
169
192
|
}
|
|
170
193
|
|
|
171
|
-
function changeETokenStatus(IEToken eToken,
|
|
194
|
+
function changeETokenStatus(IEToken eToken, ComponentStatus newStatus)
|
|
172
195
|
external
|
|
173
196
|
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
174
197
|
{
|
|
175
|
-
|
|
176
|
-
require(status !=
|
|
198
|
+
ComponentStatus status = _eTokens[eToken];
|
|
199
|
+
require(status != ComponentStatus.inactive, "EToken not found");
|
|
177
200
|
require(
|
|
178
|
-
newStatus
|
|
179
|
-
|
|
201
|
+
(newStatus == ComponentStatus.active && _access.hasRole(LEVEL1_ROLE, msg.sender)) ||
|
|
202
|
+
(newStatus == ComponentStatus.suspended && _access.hasRole(GUARDIAN_ROLE, msg.sender)) ||
|
|
203
|
+
(newStatus == ComponentStatus.deprecated && _access.hasRole(LEVEL1_ROLE, msg.sender)),
|
|
204
|
+
"Only GUARDIAN can suspend / Only LEVEL1 can activate/deprecate"
|
|
180
205
|
);
|
|
181
206
|
_eTokens[eToken] = newStatus;
|
|
182
207
|
emit ETokenStatusChanged(eToken, newStatus);
|
|
183
208
|
}
|
|
184
209
|
|
|
185
|
-
function getETokenStatus(IEToken eToken) external view returns (
|
|
210
|
+
function getETokenStatus(IEToken eToken) external view returns (ComponentStatus) {
|
|
186
211
|
return _eTokens[eToken];
|
|
187
212
|
}
|
|
188
213
|
|
|
214
|
+
function addRiskModule(IRiskModule riskModule) external onlyRole(LEVEL1_ROLE) {
|
|
215
|
+
require(
|
|
216
|
+
_riskModules[riskModule] == ComponentStatus.inactive,
|
|
217
|
+
"Risk Module already in the pool"
|
|
218
|
+
);
|
|
219
|
+
require(
|
|
220
|
+
IPolicyPoolComponent(address(riskModule)).policyPool() == this,
|
|
221
|
+
"RiskModule not linked to this pool"
|
|
222
|
+
);
|
|
223
|
+
_riskModules[riskModule] = ComponentStatus.active;
|
|
224
|
+
emit RiskModuleStatusChanged(riskModule, ComponentStatus.active);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function removeRiskModule(IRiskModule riskModule) external onlyRole(LEVEL2_ROLE) {
|
|
228
|
+
require(_riskModules[riskModule] != ComponentStatus.inactive, "Risk Module not found");
|
|
229
|
+
require(riskModule.activeExposure() == 0, "Can't remove a module with active policies");
|
|
230
|
+
delete _riskModules[riskModule];
|
|
231
|
+
emit RiskModuleStatusChanged(riskModule, ComponentStatus.inactive);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function changeRiskModuleStatus(IRiskModule riskModule, ComponentStatus newStatus)
|
|
235
|
+
external
|
|
236
|
+
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
237
|
+
{
|
|
238
|
+
require(_riskModules[riskModule] != ComponentStatus.inactive, "Risk Module not found");
|
|
239
|
+
require(
|
|
240
|
+
(newStatus == ComponentStatus.active && _access.hasRole(LEVEL1_ROLE, msg.sender)) ||
|
|
241
|
+
(newStatus == ComponentStatus.suspended && _access.hasRole(GUARDIAN_ROLE, msg.sender)) ||
|
|
242
|
+
(newStatus == ComponentStatus.deprecated && _access.hasRole(LEVEL1_ROLE, msg.sender)),
|
|
243
|
+
"Only GUARDIAN can suspend / Only LEVEL1 can activate/deprecate"
|
|
244
|
+
);
|
|
245
|
+
_riskModules[riskModule] = newStatus;
|
|
246
|
+
emit RiskModuleStatusChanged(riskModule, newStatus);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function getRiskModuleStatus(IRiskModule riskModule) external view returns (ComponentStatus) {
|
|
250
|
+
return _riskModules[riskModule];
|
|
251
|
+
}
|
|
252
|
+
|
|
189
253
|
function addPremiumsAccount(IPremiumsAccount pa) external onlyRole(LEVEL1_ROLE) {
|
|
190
|
-
// TODO: limit in # of PremiumsAccount?
|
|
191
254
|
// TODO: keep PremiumsAccount status?
|
|
192
|
-
require(address(pa) != address(0), "PremiumsAccount can't be zero");
|
|
193
255
|
require(
|
|
194
256
|
IPolicyPoolComponent(address(pa)).policyPool() == this,
|
|
195
257
|
"PremiumsAccount not linked to this pool"
|
|
@@ -202,13 +264,13 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
202
264
|
if (address(etk) != address(0)) {
|
|
203
265
|
etk.addBorrower(address(pa));
|
|
204
266
|
}
|
|
205
|
-
emit PremiumsAccountStatusChanged(pa,
|
|
267
|
+
emit PremiumsAccountStatusChanged(pa, ComponentStatus.active);
|
|
206
268
|
// TODO: functions for deactivating premiumsAccount (and remove them as borrower)
|
|
207
269
|
}
|
|
208
270
|
|
|
209
271
|
function deposit(IEToken eToken, uint256 amount) external override whenNotPaused {
|
|
210
|
-
|
|
211
|
-
require(etkStatus ==
|
|
272
|
+
ComponentStatus etkStatus = _eTokens[eToken];
|
|
273
|
+
require(etkStatus == ComponentStatus.active, "eToken is not active");
|
|
212
274
|
_currency.safeTransferFrom(msg.sender, address(eToken), amount);
|
|
213
275
|
eToken.deposit(msg.sender, amount);
|
|
214
276
|
}
|
|
@@ -219,9 +281,9 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
219
281
|
whenNotPaused
|
|
220
282
|
returns (uint256)
|
|
221
283
|
{
|
|
222
|
-
|
|
284
|
+
ComponentStatus etkStatus = _eTokens[eToken];
|
|
223
285
|
require(
|
|
224
|
-
etkStatus ==
|
|
286
|
+
etkStatus == ComponentStatus.active || etkStatus == ComponentStatus.deprecated,
|
|
225
287
|
"eToken not found or withdraws not allowed"
|
|
226
288
|
);
|
|
227
289
|
address provider = msg.sender;
|
|
@@ -235,7 +297,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
235
297
|
) external override whenNotPaused returns (uint256) {
|
|
236
298
|
IRiskModule rm = policy.riskModule;
|
|
237
299
|
require(address(rm) == msg.sender, "Only the RM can create new policies");
|
|
238
|
-
|
|
300
|
+
require(_riskModules[rm] == ComponentStatus.active, "RM module not found or not active");
|
|
239
301
|
policy.id = (uint256(uint160(address(rm))) << 96) + internalId;
|
|
240
302
|
_policies[policy.id] = policy.hash();
|
|
241
303
|
IPremiumsAccount pa = rm.premiumsAccount();
|
|
@@ -248,7 +310,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
248
310
|
_currency.safeTransferFrom(customer, address(pa.seniorEtk()), policy.srCoc);
|
|
249
311
|
if (policy.jrCoc > 0)
|
|
250
312
|
_currency.safeTransferFrom(customer, address(pa.juniorEtk()), policy.jrCoc);
|
|
251
|
-
_currency.safeTransferFrom(customer,
|
|
313
|
+
_currency.safeTransferFrom(customer, _treasury, policy.ensuroCommission);
|
|
252
314
|
if (policy.partnerCommission > 0 && customer != rm.wallet())
|
|
253
315
|
_currency.safeTransferFrom(customer, rm.wallet(), policy.partnerCommission);
|
|
254
316
|
// TODO: this code does up to 5 ERC20 transfers. How we can avoid this? Delayed transfers?
|
|
@@ -303,7 +365,10 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
|
|
|
303
365
|
IRiskModule rm = policy.riskModule;
|
|
304
366
|
require(expired || address(rm) == msg.sender, "Only the RM can resolve policies");
|
|
305
367
|
require(payout == 0 || policy.expiration > block.timestamp, "Can't pay expired policy");
|
|
306
|
-
|
|
368
|
+
require(
|
|
369
|
+
_riskModules[rm] == ComponentStatus.active || _riskModules[rm] == ComponentStatus.deprecated,
|
|
370
|
+
"Module must be active or deprecated to process resolutions"
|
|
371
|
+
);
|
|
307
372
|
require(payout <= policy.payout, "payout > policy.payout");
|
|
308
373
|
|
|
309
374
|
bool customerWon = payout > 0;
|
|
@@ -5,7 +5,7 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U
|
|
|
5
5
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
6
6
|
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
7
7
|
import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
|
|
8
|
-
import {
|
|
8
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
9
9
|
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
|
|
10
10
|
import {WadRayMath} from "./WadRayMath.sol";
|
|
11
11
|
|
|
@@ -42,8 +42,8 @@ abstract contract PolicyPoolComponent is
|
|
|
42
42
|
uint40 internal _lastTweakTimestamp;
|
|
43
43
|
uint56 internal _lastTweakActions; // bitwise map of applied actions
|
|
44
44
|
|
|
45
|
-
event GovernanceAction(
|
|
46
|
-
event ComponentChanged(
|
|
45
|
+
event GovernanceAction(IAccessManager.GovernanceActions indexed action, uint256 value);
|
|
46
|
+
event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
|
|
47
47
|
|
|
48
48
|
modifier onlyPolicyPool() {
|
|
49
49
|
require(_msgSender() == address(_policyPool), "The caller must be the PolicyPool");
|
|
@@ -56,23 +56,23 @@ abstract contract PolicyPoolComponent is
|
|
|
56
56
|
bytes32 role3
|
|
57
57
|
) {
|
|
58
58
|
if (!hasPoolRole(role1)) {
|
|
59
|
-
_policyPool.
|
|
59
|
+
_policyPool.access().checkRole2(role2, role3, msg.sender);
|
|
60
60
|
}
|
|
61
61
|
_;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
modifier onlyPoolRole2(bytes32 role1, bytes32 role2) {
|
|
65
|
-
_policyPool.
|
|
65
|
+
_policyPool.access().checkRole2(role1, role2, msg.sender);
|
|
66
66
|
_;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
modifier onlyPoolRole(bytes32 role) {
|
|
70
|
-
_policyPool.
|
|
70
|
+
_policyPool.access().checkRole(role, msg.sender);
|
|
71
71
|
_;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
modifier onlyComponentRole(bytes32 role) {
|
|
75
|
-
_policyPool.
|
|
75
|
+
_policyPool.access().checkComponentRole(address(this), role, msg.sender);
|
|
76
76
|
_;
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -107,7 +107,7 @@ abstract contract PolicyPoolComponent is
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
function hasPoolRole(bytes32 role) internal view returns (bool) {
|
|
110
|
-
return _policyPool.
|
|
110
|
+
return _policyPool.access().hasRole(role, msg.sender);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function _isTweakRay(
|
|
@@ -144,7 +144,7 @@ abstract contract PolicyPoolComponent is
|
|
|
144
144
|
function _validateParameters() internal view virtual {} // Must be reimplemented with specific validations
|
|
145
145
|
|
|
146
146
|
function _parameterChanged(
|
|
147
|
-
|
|
147
|
+
IAccessManager.GovernanceActions action,
|
|
148
148
|
uint256 value,
|
|
149
149
|
bool tweak
|
|
150
150
|
) internal {
|
|
@@ -153,7 +153,7 @@ abstract contract PolicyPoolComponent is
|
|
|
153
153
|
emit GovernanceAction(action, value);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
function _componentChanged(
|
|
156
|
+
function _componentChanged(IAccessManager.GovernanceActions action, address value) internal {
|
|
157
157
|
_validateParameters();
|
|
158
158
|
emit ComponentChanged(action, value);
|
|
159
159
|
}
|
|
@@ -162,7 +162,7 @@ abstract contract PolicyPoolComponent is
|
|
|
162
162
|
return (_lastTweakTimestamp, _lastTweakActions);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
function _registerTweak(
|
|
165
|
+
function _registerTweak(IAccessManager.GovernanceActions action) internal {
|
|
166
166
|
uint56 actionBitMap = uint56(1 << (uint8(action) - 1));
|
|
167
167
|
if ((uint40(block.timestamp) - _lastTweakTimestamp) > TWEAK_EXPIRATION) {
|
|
168
168
|
_lastTweakTimestamp = uint40(block.timestamp);
|
|
@@ -177,7 +177,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
177
177
|
if (amount > _wonPurePremiums) amount = _wonPurePremiums;
|
|
178
178
|
require(amount > 0, "No premiums to withdraw");
|
|
179
179
|
_wonPurePremiums -= amount;
|
|
180
|
-
_transferTo(_policyPool.
|
|
180
|
+
_transferTo(_policyPool.treasury(), amount); // TODO: discuss if destination shoud be msg.sender
|
|
181
181
|
// TODO: see if this will be a component role
|
|
182
182
|
emit WonPremiumsInOut(false, amount);
|
|
183
183
|
return amount;
|
package/contracts/RiskModule.sol
CHANGED
|
@@ -6,7 +6,7 @@ import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
|
6
6
|
import {PolicyPoolComponent} from "./PolicyPoolComponent.sol";
|
|
7
7
|
import {IRiskModule} from "./interfaces/IRiskModule.sol";
|
|
8
8
|
import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
|
|
9
|
-
import {
|
|
9
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
10
10
|
import {Policy} from "./Policy.sol";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -238,8 +238,8 @@ abstract contract RiskModule is IRiskModule, PolicyPoolComponent {
|
|
|
238
238
|
_params.maxDuration = uint16(newValue);
|
|
239
239
|
}
|
|
240
240
|
_parameterChanged(
|
|
241
|
-
|
|
242
|
-
uint256(
|
|
241
|
+
IAccessManager.GovernanceActions(
|
|
242
|
+
uint256(IAccessManager.GovernanceActions.setMoc) + uint256(param)
|
|
243
243
|
),
|
|
244
244
|
newValue,
|
|
245
245
|
tweak
|
|
@@ -261,11 +261,7 @@ abstract contract RiskModule is IRiskModule, PolicyPoolComponent {
|
|
|
261
261
|
|
|
262
262
|
function setWallet(address wallet_) external onlyComponentRole(RM_PROVIDER_ROLE) {
|
|
263
263
|
_wallet = wallet_;
|
|
264
|
-
_parameterChanged(
|
|
265
|
-
IPolicyPoolConfig.GovernanceActions.setWallet,
|
|
266
|
-
uint256(uint160(wallet_)),
|
|
267
|
-
false
|
|
268
|
-
);
|
|
264
|
+
_parameterChanged(IAccessManager.GovernanceActions.setWallet, uint256(uint160(wallet_)), false);
|
|
269
265
|
}
|
|
270
266
|
|
|
271
267
|
function getMinimumPremium(
|