@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.
Files changed (41) hide show
  1. package/README.md +2 -1
  2. package/build/contracts/AccessManager.sol/AccessManager.json +487 -0
  3. package/build/contracts/EToken.sol/EToken.json +4 -4
  4. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +4 -4
  5. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +2 -2
  6. package/build/contracts/PolicyPool.sol/PolicyPool.json +148 -15
  7. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +2 -2
  8. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +4 -4
  9. package/build/contracts/Reserve.sol/Reserve.json +2 -2
  10. package/build/contracts/RiskModule.sol/RiskModule.json +2 -2
  11. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +4 -4
  12. package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +2 -67
  13. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +15 -2
  14. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
  15. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +19 -6
  16. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
  17. package/contracts/AccessManager.sol +72 -0
  18. package/contracts/EToken.sol +6 -13
  19. package/contracts/PolicyNFT.sol +3 -3
  20. package/contracts/PolicyPool.sol +108 -43
  21. package/contracts/PolicyPoolComponent.sol +11 -11
  22. package/contracts/PremiumsAccount.sol +1 -1
  23. package/contracts/RiskModule.sol +4 -8
  24. package/contracts/interfaces/{IPolicyPoolConfig.sol → IAccessManager.sol} +2 -21
  25. package/contracts/interfaces/IPolicyPool.sol +10 -5
  26. package/contracts/mocks/PolicyPoolMock.sol +15 -13
  27. package/js/test-utils.js +177 -119
  28. package/package.json +1 -1
  29. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
  30. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -665
  31. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
  32. package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
  33. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  34. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
  35. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
  36. package/contracts/FlightDelayRiskModule.sol +0 -217
  37. package/contracts/PolicyPoolConfig.sol +0 -185
  38. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  39. package/contracts/mocks/LinkTokenMock.sol +0 -30
  40. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  41. package/contracts/upgraded/PolicyNFTv1.sol +0 -126
@@ -16,8 +16,8 @@
16
16
  "type": "address"
17
17
  },
18
18
  {
19
- "internalType": "contract IPolicyPoolConfig",
20
- "name": "config_",
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": "config",
46
+ "name": "access",
47
47
  "outputs": [
48
48
  {
49
- "internalType": "contract IPolicyPoolConfig",
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": "0x608060405234801561001057600080fd5b506040516102e83803806102e883398101604081905261002f916100bd565b600080546001600160a01b038086166001600160a01b031992831617835560018054868316908416179055600280549185169190921681179091556040805163948cb71960e01b81529051919263948cb7199260048084019382900301818387803b15801561009d57600080fd5b505af11580156100b1573d6000803e3d6000fd5b50505050505050610122565b6000806000606084860312156100d257600080fd5b83516100dd8161010a565b60208501519093506100ee8161010a565b60408501519092506100ff8161010a565b809150509250925092565b6001600160a01b038116811461011f57600080fd5b50565b6101b7806101316000396000f3fe6080604052600436106100435760003560e01c8063098d32281461005a57806379502c5514610083578063d4b27001146100b5578063e5a6b10f146100f257610052565b3661005257610050610110565b005b610050610110565b34801561006657600080fd5b5061007060001981565b6040519081526020015b60405180910390f35b34801561008f57600080fd5b506002546001600160a01b03165b6040516001600160a01b03909116815260200161007a565b3480156100c157600080fd5b506100506100d0366004610151565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b3480156100fe57600080fd5b506001546001600160a01b031661009d565b61012a6101256000546001600160a01b031690565b61012c565b565b366000803760008036600080855af13d6000803e80801561014c573d6000f35b3d6000fd5b60006020828403121561016357600080fd5b81356001600160a01b038116811461017a57600080fd5b939250505056fea2646970667358221220e6192b34ccc4edb74a04897a74de4040f67b7ccaf7f930d6a713d7781890b97b64736f6c63430008060033",
89
- "deployedBytecode": "0x6080604052600436106100435760003560e01c8063098d32281461005a57806379502c5514610083578063d4b27001146100b5578063e5a6b10f146100f257610052565b3661005257610050610110565b005b610050610110565b34801561006657600080fd5b5061007060001981565b6040519081526020015b60405180910390f35b34801561008f57600080fd5b506002546001600160a01b03165b6040516001600160a01b03909116815260200161007a565b3480156100c157600080fd5b506100506100d0366004610151565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b3480156100fe57600080fd5b506001546001600160a01b031661009d565b61012a6101256000546001600160a01b031690565b61012c565b565b366000803760008036600080855af13d6000803e80801561014c573d6000f35b3d6000fd5b60006020828403121561016357600080fd5b81356001600160a01b038116811461017a57600080fd5b939250505056fea2646970667358221220e6192b34ccc4edb74a04897a74de4040f67b7ccaf7f930d6a713d7781890b97b64736f6c63430008060033",
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
+ }
@@ -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 {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
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(IPolicyPoolConfig.GovernanceActions.setLiquidityRequirement, newRate, tweak);
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(IPolicyPoolConfig.GovernanceActions.setMaxUtilizationRate, newRate, tweak);
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(IPolicyPoolConfig.GovernanceActions.setMinUtilizationRate, newRate, tweak);
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) {
@@ -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.config().checkRole2(role1, role2, msg.sender);
31
+ _policyPool.access().checkRole2(role1, role2, msg.sender);
32
32
  _;
33
33
  }
34
34
 
35
35
  modifier onlyPoolRole(bytes32 role) {
36
- _policyPool.config().checkRole(role, msg.sender);
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 config");
78
+ // require(_policyPool.policyNFT() == address(this), "PolicyPool not connected to this access");
79
79
  }
80
80
 
81
81
  function policyPool() external view returns (IPolicyPool) {
@@ -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 {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
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
- IPolicyPoolConfig internal immutable _config;
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
- enum ETokenStatus {
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
- * {ETokenStatus}.
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(IEToken => ETokenStatus) private _eTokens;
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 {ETokenStatus}.
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, ETokenStatus newStatus);
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
- ETokenStatus newStatus
104
+ ComponentStatus newStatus
92
105
  );
93
106
 
107
+ event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
108
+
94
109
  modifier onlyRole(bytes32 role) {
95
- _config.checkRole(role, msg.sender);
110
+ _access.checkRole(role, msg.sender);
96
111
  _;
97
112
  }
98
113
 
99
114
  modifier onlyRole2(bytes32 role1, bytes32 role2) {
100
- _config.checkRole2(role1, role2, msg.sender);
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
- IPolicyPoolConfig config_,
121
+ IAccessManager access_,
107
122
  IPolicyNFT policyNFT_,
108
123
  IERC20Metadata currency_
109
124
  ) {
110
- _config = config_;
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 config() external view virtual override returns (IPolicyPoolConfig) {
139
- return _config;
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
- ETokenStatus status = _eTokens[eToken];
152
- require(status == ETokenStatus.inactive, "eToken already in the pool");
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] = ETokenStatus.active;
160
- emit ETokenStatusChanged(eToken, ETokenStatus.active);
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
- ETokenStatus status = _eTokens[eToken];
165
- require(status == ETokenStatus.deprecated, "EToken not deprecated");
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, ETokenStatus.inactive);
191
+ emit ETokenStatusChanged(eToken, ComponentStatus.inactive);
169
192
  }
170
193
 
171
- function changeETokenStatus(IEToken eToken, ETokenStatus newStatus)
194
+ function changeETokenStatus(IEToken eToken, ComponentStatus newStatus)
172
195
  external
173
196
  onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
174
197
  {
175
- ETokenStatus status = _eTokens[eToken];
176
- require(status != ETokenStatus.inactive, "EToken not found");
198
+ ComponentStatus status = _eTokens[eToken];
199
+ require(status != ComponentStatus.inactive, "EToken not found");
177
200
  require(
178
- newStatus != ETokenStatus.suspended || _config.hasRole(GUARDIAN_ROLE, msg.sender),
179
- "Only GUARDIAN can suspend eTokens"
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 (ETokenStatus) {
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, ETokenStatus.active);
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
- ETokenStatus etkStatus = _eTokens[eToken];
211
- require(etkStatus == ETokenStatus.active, "eToken is not active");
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
- ETokenStatus etkStatus = _eTokens[eToken];
284
+ ComponentStatus etkStatus = _eTokens[eToken];
223
285
  require(
224
- etkStatus == ETokenStatus.active || etkStatus == ETokenStatus.deprecated,
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
- _config.checkAcceptsNewPolicy(rm);
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, _config.treasury(), policy.ensuroCommission);
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
- _config.checkAcceptsResolvePolicy(rm);
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 {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
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(IPolicyPoolConfig.GovernanceActions indexed action, uint256 value);
46
- event ComponentChanged(IPolicyPoolConfig.GovernanceActions indexed action, address value);
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.config().checkRole2(role2, role3, msg.sender);
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.config().checkRole2(role1, role2, msg.sender);
65
+ _policyPool.access().checkRole2(role1, role2, msg.sender);
66
66
  _;
67
67
  }
68
68
 
69
69
  modifier onlyPoolRole(bytes32 role) {
70
- _policyPool.config().checkRole(role, msg.sender);
70
+ _policyPool.access().checkRole(role, msg.sender);
71
71
  _;
72
72
  }
73
73
 
74
74
  modifier onlyComponentRole(bytes32 role) {
75
- _policyPool.config().checkComponentRole(address(this), role, msg.sender);
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.config().hasRole(role, msg.sender);
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
- IPolicyPoolConfig.GovernanceActions action,
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(IPolicyPoolConfig.GovernanceActions action, address value) internal {
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(IPolicyPoolConfig.GovernanceActions action) internal {
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.config().treasury(), amount); // TODO: discuss if destination shoud be msg.sender
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;
@@ -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 {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
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
- IPolicyPoolConfig.GovernanceActions(
242
- uint256(IPolicyPoolConfig.GovernanceActions.setMoc) + uint256(param)
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(