@ensuro/core 2.0.0-beta5 → 2.0.0-beta7

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 (44) hide show
  1. package/build/contracts/AccessManager.sol/AccessManager.json +74 -2
  2. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +219 -0
  3. package/build/contracts/EToken.sol/EToken.json +114 -45
  4. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +2 -2
  5. package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +203 -0
  6. package/build/contracts/Policy.sol/Policy.json +2 -2
  7. package/build/contracts/PolicyPool.sol/PolicyPool.json +324 -100
  8. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +122 -2
  9. package/build/contracts/Reserve.sol/Reserve.json +71 -0
  10. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +3 -3
  11. package/build/contracts/interfaces/IAccessManager.sol/IAccessManager.json +96 -0
  12. package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +109 -0
  13. package/build/contracts/interfaces/IEToken.sol/IEToken.json +13 -0
  14. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +6 -14
  15. package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +13 -0
  16. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
  17. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
  18. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +7 -15
  19. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
  20. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +674 -0
  21. package/contracts/AccessManager.sol +39 -8
  22. package/contracts/ERC4626AssetManager.sol +50 -0
  23. package/contracts/EToken.sol +72 -52
  24. package/contracts/LiquidityThresholdAssetManager.sol +158 -0
  25. package/contracts/PolicyPool.sol +155 -135
  26. package/contracts/PolicyPoolComponent.sol +29 -19
  27. package/contracts/PremiumsAccount.sol +125 -62
  28. package/contracts/Reserve.sol +86 -2
  29. package/contracts/RiskModule.sol +17 -6
  30. package/contracts/TrustfulRiskModule.sol +17 -2
  31. package/contracts/interfaces/IAccessManager.sol +23 -5
  32. package/contracts/interfaces/IAssetManager.sol +22 -0
  33. package/contracts/interfaces/IEToken.sol +21 -1
  34. package/contracts/interfaces/IPolicyPool.sol +6 -11
  35. package/contracts/interfaces/IPremiumsAccount.sol +5 -0
  36. package/contracts/mocks/FixedRateVault.sol +85 -0
  37. package/contracts/mocks/PolicyPoolMock.sol +2 -5
  38. package/contracts/mocks/RiskModuleMock.sol +69 -0
  39. package/js/test-utils.js +38 -31
  40. package/package.json +1 -1
  41. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -583
  42. package/build/contracts/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
  43. package/contracts/PolicyNFT.sol +0 -96
  44. package/contracts/interfaces/IPolicyNFT.sol +0 -15
@@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
4
4
  import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5
5
  import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
6
6
  import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
7
+ import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
7
8
  import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8
9
  import {IAccessManager} from "./interfaces/IAccessManager.sol";
9
10
  import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
@@ -13,7 +14,6 @@ import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
13
14
  import {IRiskModule} from "./interfaces/IRiskModule.sol";
14
15
  import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
15
16
  import {IEToken} from "./interfaces/IEToken.sol";
16
- import {IPolicyNFT} from "./interfaces/IPolicyNFT.sol";
17
17
  import {IPolicyHolder} from "./interfaces/IPolicyHolder.sol";
18
18
  import {Policy} from "./Policy.sol";
19
19
  import {WadRayMath} from "./WadRayMath.sol";
@@ -29,7 +29,7 @@ import {WadRayMath} from "./WadRayMath.sol";
29
29
  * @custom:security-contact security@ensuro.co
30
30
  * @author Ensuro
31
31
  */
32
- contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
32
+ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721Upgradeable {
33
33
  using EnumerableSet for EnumerableSet.AddressSet;
34
34
  using WadRayMath for uint256;
35
35
  using Policy for Policy.PolicyData;
@@ -44,29 +44,52 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
44
44
  IAccessManager internal immutable _access;
45
45
  /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
46
46
  IERC20Metadata internal immutable _currency;
47
- /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
48
- IPolicyNFT internal immutable _policyNFT;
49
47
 
50
48
  address internal _treasury; // address of Ensuro treasury
51
49
 
52
50
  enum ComponentStatus {
53
- inactive, // doesn't exists - All operations rejected
54
- active, // deposit / withdraw / lockScr / unlockScr / newPolicy / resolvePolicy OK
55
- deprecated, // withdraw OK, unlockScr OK, deposit rejected, no new policies
56
- suspended // all operations temporarily rejected
51
+ /**
52
+ * @dev inactive status = 0 means the component doesn't exists - All operations rejected
53
+ */
54
+ inactive,
55
+ /**
56
+ * @dev active means the component is fully functional, all the component operations are allowed.
57
+ * deposit / withdraw for eTokens
58
+ * newPolicy / resolvePolicy for riskModules
59
+ * policyCreated / policyExpired / policyResolvedWithPayout for premiumsAccount
60
+ */
61
+ active,
62
+ /**
63
+ * @dev deprecated means the component is in process of being deactivated. Only some operations are allowed:
64
+ * withdraw for eTokens
65
+ * resolvePolicy / expirePolicy for riskModules
66
+ * policyExpired / policyResolvedWithPayout for premiumsAccount
67
+ */
68
+ deprecated,
69
+ /**
70
+ * @dev suspended means the component is temporarily deactivated. All the operations are rejected. Only GUARDIAN
71
+ * can suspend.
72
+ */
73
+ suspended
74
+ }
75
+
76
+ enum ComponentKind {
77
+ unknown,
78
+ eToken,
79
+ riskModule,
80
+ premiumsAccount
81
+ }
82
+
83
+ struct Component {
84
+ ComponentStatus status;
85
+ ComponentKind kind;
57
86
  }
58
87
 
59
88
  /**
60
- * @dev Mapping of installed eTokens (see {EToken}) in the PolicyPool. For each one it keep an state
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}.
89
+ * @dev Mapping of installed components (see {EToken}, {RiskModule}, {PremiumsAccount}) in the PolicyPool.
90
+ * For each one it keep an state {ComponentStatus}.
68
91
  */
69
- mapping(IRiskModule => ComponentStatus) private _riskModules;
92
+ mapping(IPolicyPoolComponent => Component) private _components;
70
93
 
71
94
  /**
72
95
  * @dev Mapping that stores the active policies (the policyId is the key). It just saves the hash of the policies,
@@ -87,25 +110,23 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
87
110
  event PolicyResolved(IRiskModule indexed riskModule, uint256 indexed policyId, uint256 payout);
88
111
 
89
112
  /**
90
- * @dev Event emitted when a new eToken is added to the pool or the status changes. See {ComponentStatus}.
91
- */
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}.
113
+ * @dev Event emitted when the treasury changes
96
114
  */
97
- event RiskModuleStatusChanged(IRiskModule indexed riskModule, ComponentStatus newStatus);
115
+ event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
98
116
 
99
117
  /**
100
- * @dev Event emitted when a new PremiumsAccount is added to the pool or the status changes. TODO
118
+ * @dev Event emitted when a new component added/removed to the pool or the status changes.
119
+ *
120
+ * @param component The address of the component, it can be an {EToken}, {RiskModule} or {PremiumsAccount}
121
+ * @param kind Value indicating the kind of component. See {ComponentKind}
122
+ * @param newStatus The status of the component after the operation. See {ComponentStatus}
101
123
  */
102
- event PremiumsAccountStatusChanged(
103
- IPremiumsAccount indexed premiumsAccount,
124
+ event ComponentStatusChanged(
125
+ IPolicyPoolComponent indexed component,
126
+ ComponentKind kind,
104
127
  ComponentStatus newStatus
105
128
  );
106
129
 
107
- event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
108
-
109
130
  modifier onlyRole(bytes32 role) {
110
131
  _access.checkRole(role, msg.sender);
111
132
  _;
@@ -117,25 +138,24 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
117
138
  }
118
139
 
119
140
  /// @custom:oz-upgrades-unsafe-allow constructor
120
- constructor(
121
- IAccessManager access_,
122
- IPolicyNFT policyNFT_,
123
- IERC20Metadata currency_
124
- ) {
141
+ constructor(IAccessManager access_, IERC20Metadata currency_) {
125
142
  _access = access_;
126
- _policyNFT = policyNFT_;
127
143
  _currency = currency_;
128
144
  }
129
145
 
130
- function initialize(address treasury_) public initializer {
146
+ function initialize(
147
+ string memory name_,
148
+ string memory symbol_,
149
+ address treasury_
150
+ ) public initializer {
131
151
  __UUPSUpgradeable_init();
152
+ __ERC721_init(name_, symbol_);
132
153
  __Pausable_init();
133
154
  __PolicyPool_init_unchained(treasury_);
134
155
  }
135
156
 
136
157
  // solhint-disable-next-line func-name-mixedcase
137
158
  function __PolicyPool_init_unchained(address treasury_) internal initializer {
138
- _policyNFT.connect();
139
159
  _treasury = treasury_;
140
160
  }
141
161
 
@@ -158,10 +178,6 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
158
178
  return _currency;
159
179
  }
160
180
 
161
- function policyNFT() external view virtual override returns (address) {
162
- return address(_policyNFT);
163
- }
164
-
165
181
  function setTreasury(address treasury_) external onlyRole(LEVEL1_ROLE) {
166
182
  _treasury = treasury_;
167
183
  emit ComponentChanged(IAccessManager.GovernanceActions.setTreasury, _treasury);
@@ -171,106 +187,103 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
171
187
  return _treasury;
172
188
  }
173
189
 
174
- function addEToken(IEToken eToken) external onlyRole(LEVEL1_ROLE) {
175
- ComponentStatus status = _eTokens[eToken];
176
- require(status == ComponentStatus.inactive, "eToken already in the pool");
177
- require(
178
- IPolicyPoolComponent(address(eToken)).policyPool() == this,
179
- "EToken not linked to this pool"
180
- );
181
-
182
- _eTokens[eToken] = ComponentStatus.active;
183
- emit ETokenStatusChanged(eToken, ComponentStatus.active);
190
+ function addComponent(IPolicyPoolComponent component, ComponentKind kind)
191
+ external
192
+ onlyRole(LEVEL1_ROLE)
193
+ {
194
+ Component storage comp = _components[component];
195
+ require(comp.status == ComponentStatus.inactive, "Component already in the pool");
196
+ require(component.policyPool() == this, "Component not linked to this pool");
197
+
198
+ comp.status = ComponentStatus.active;
199
+ comp.kind = kind;
200
+ if (kind == ComponentKind.premiumsAccount) {
201
+ IPremiumsAccount pa = IPremiumsAccount(address(component));
202
+ IEToken etk = pa.juniorEtk();
203
+ if (address(etk) != address(0)) {
204
+ etk.addBorrower(address(pa));
205
+ }
206
+ etk = pa.seniorEtk();
207
+ if (address(etk) != address(0)) {
208
+ etk.addBorrower(address(pa));
209
+ }
210
+ }
211
+ emit ComponentStatusChanged(component, kind, ComponentStatus.active);
184
212
  }
185
213
 
186
- function removeEToken(IEToken eToken) external onlyRole(LEVEL3_ROLE) {
187
- ComponentStatus status = _eTokens[eToken];
188
- require(status == ComponentStatus.deprecated, "EToken not deprecated");
189
- require(eToken.totalSupply() == 0, "EToken has liquidity, can't be removed");
190
- delete _eTokens[eToken];
191
- emit ETokenStatusChanged(eToken, ComponentStatus.inactive);
214
+ function removeComponent(IPolicyPoolComponent component) external onlyRole(LEVEL1_ROLE) {
215
+ Component storage comp = _components[component];
216
+ require(comp.status == ComponentStatus.deprecated, "Component not deprecated");
217
+ if (comp.kind == ComponentKind.eToken) {
218
+ require(
219
+ IEToken(address(component)).totalSupply() == 0,
220
+ "EToken has liquidity, can't be removed"
221
+ );
222
+ } else if (comp.kind == ComponentKind.riskModule) {
223
+ require(
224
+ IRiskModule(address(component)).activeExposure() == 0,
225
+ "Can't remove a module with active policies"
226
+ );
227
+ } else if (comp.kind == ComponentKind.premiumsAccount) {
228
+ IPremiumsAccount pa = IPremiumsAccount(address(component));
229
+ require(pa.purePremiums() == 0, "Can't remove a PremiumsAccount with premiums");
230
+ IEToken etk = pa.juniorEtk();
231
+ if (address(etk) != address(0)) {
232
+ etk.removeBorrower(address(pa));
233
+ }
234
+ etk = pa.seniorEtk();
235
+ if (address(etk) != address(0)) {
236
+ etk.removeBorrower(address(pa));
237
+ }
238
+ }
239
+ emit ComponentStatusChanged(component, comp.kind, ComponentStatus.inactive);
240
+ delete _components[component];
192
241
  }
193
242
 
194
- function changeETokenStatus(IEToken eToken, ComponentStatus newStatus)
243
+ function changeComponentStatus(IPolicyPoolComponent component, ComponentStatus newStatus)
195
244
  external
196
245
  onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
197
246
  {
198
- ComponentStatus status = _eTokens[eToken];
199
- require(status != ComponentStatus.inactive, "EToken not found");
247
+ Component storage comp = _components[component];
248
+ require(comp.status != ComponentStatus.inactive, "Component not found");
200
249
  require(
201
250
  (newStatus == ComponentStatus.active && _access.hasRole(LEVEL1_ROLE, msg.sender)) ||
202
251
  (newStatus == ComponentStatus.suspended && _access.hasRole(GUARDIAN_ROLE, msg.sender)) ||
203
252
  (newStatus == ComponentStatus.deprecated && _access.hasRole(LEVEL1_ROLE, msg.sender)),
204
253
  "Only GUARDIAN can suspend / Only LEVEL1 can activate/deprecate"
205
254
  );
206
- _eTokens[eToken] = newStatus;
207
- emit ETokenStatusChanged(eToken, newStatus);
208
- }
209
-
210
- function getETokenStatus(IEToken eToken) external view returns (ComponentStatus) {
211
- return _eTokens[eToken];
212
- }
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);
255
+ comp.status = newStatus;
256
+ emit ComponentStatusChanged(component, comp.kind, newStatus);
232
257
  }
233
258
 
234
- function changeRiskModuleStatus(IRiskModule riskModule, ComponentStatus newStatus)
259
+ function getComponentStatus(IPolicyPoolComponent component)
235
260
  external
236
- onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
261
+ view
262
+ returns (ComponentStatus)
237
263
  {
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);
264
+ return _components[component].status;
247
265
  }
248
266
 
249
- function getRiskModuleStatus(IRiskModule riskModule) external view returns (ComponentStatus) {
250
- return _riskModules[riskModule];
267
+ function _etkStatus(IEToken eToken) internal view returns (ComponentStatus) {
268
+ Component storage comp = _components[IPolicyPoolComponent(address(eToken))];
269
+ require(comp.kind == ComponentKind.eToken, "Component is not an eToken");
270
+ return comp.status;
251
271
  }
252
272
 
253
- function addPremiumsAccount(IPremiumsAccount pa) external onlyRole(LEVEL1_ROLE) {
254
- // TODO: keep PremiumsAccount status?
255
- require(
256
- IPolicyPoolComponent(address(pa)).policyPool() == this,
257
- "PremiumsAccount not linked to this pool"
258
- );
259
- IEToken etk = pa.juniorEtk();
260
- if (address(etk) != address(0)) {
261
- etk.addBorrower(address(pa));
262
- }
263
- etk = pa.seniorEtk();
264
- if (address(etk) != address(0)) {
265
- etk.addBorrower(address(pa));
266
- }
267
- emit PremiumsAccountStatusChanged(pa, ComponentStatus.active);
268
- // TODO: functions for deactivating premiumsAccount (and remove them as borrower)
273
+ function _rmStatus(IRiskModule riskModule) internal view returns (ComponentStatus) {
274
+ Component storage comp = _components[IPolicyPoolComponent(address(riskModule))];
275
+ require(comp.kind == ComponentKind.riskModule, "Component is not a RiskModule");
276
+ return comp.status;
277
+ }
278
+
279
+ function _paStatus(IPremiumsAccount premiumsAccount) internal view returns (ComponentStatus) {
280
+ Component storage comp = _components[IPolicyPoolComponent(address(premiumsAccount))];
281
+ require(comp.kind == ComponentKind.premiumsAccount, "Component is not a PremiumsAccount");
282
+ return comp.status;
269
283
  }
270
284
 
271
285
  function deposit(IEToken eToken, uint256 amount) external override whenNotPaused {
272
- ComponentStatus etkStatus = _eTokens[eToken];
273
- require(etkStatus == ComponentStatus.active, "eToken is not active");
286
+ require(_etkStatus(eToken) == ComponentStatus.active, "eToken is not active");
274
287
  _currency.safeTransferFrom(msg.sender, address(eToken), amount);
275
288
  eToken.deposit(msg.sender, amount);
276
289
  }
@@ -281,7 +294,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
281
294
  whenNotPaused
282
295
  returns (uint256)
283
296
  {
284
- ComponentStatus etkStatus = _eTokens[eToken];
297
+ ComponentStatus etkStatus = _etkStatus(eToken);
285
298
  require(
286
299
  etkStatus == ComponentStatus.active || etkStatus == ComponentStatus.deprecated,
287
300
  "eToken not found or withdraws not allowed"
@@ -292,27 +305,27 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
292
305
 
293
306
  function newPolicy(
294
307
  Policy.PolicyData memory policy,
295
- address customer,
308
+ address payer,
309
+ address policyHolder,
296
310
  uint96 internalId
297
311
  ) external override whenNotPaused returns (uint256) {
298
312
  IRiskModule rm = policy.riskModule;
299
313
  require(address(rm) == msg.sender, "Only the RM can create new policies");
300
- require(_riskModules[rm] == ComponentStatus.active, "RM module not found or not active");
314
+ require(_rmStatus(rm) == ComponentStatus.active, "RM module not found or not active");
301
315
  policy.id = (uint256(uint160(address(rm))) << 96) + internalId;
302
316
  _policies[policy.id] = policy.hash();
303
317
  IPremiumsAccount pa = rm.premiumsAccount();
318
+ require(_paStatus(pa) == ComponentStatus.active, "PremiumsAccount not found or not active");
304
319
  pa.policyCreated(policy);
305
- _policyNFT.safeMint(customer, policy.id);
320
+ _safeMint(policyHolder, policy.id, "");
306
321
 
307
322
  // Distribute the premium
308
- _currency.safeTransferFrom(customer, address(pa), policy.purePremium);
309
- if (policy.srCoc > 0)
310
- _currency.safeTransferFrom(customer, address(pa.seniorEtk()), policy.srCoc);
311
- if (policy.jrCoc > 0)
312
- _currency.safeTransferFrom(customer, address(pa.juniorEtk()), policy.jrCoc);
313
- _currency.safeTransferFrom(customer, _treasury, policy.ensuroCommission);
314
- if (policy.partnerCommission > 0 && customer != rm.wallet())
315
- _currency.safeTransferFrom(customer, rm.wallet(), policy.partnerCommission);
323
+ _currency.safeTransferFrom(payer, address(pa), policy.purePremium);
324
+ if (policy.srCoc > 0) _currency.safeTransferFrom(payer, address(pa.seniorEtk()), policy.srCoc);
325
+ if (policy.jrCoc > 0) _currency.safeTransferFrom(payer, address(pa.juniorEtk()), policy.jrCoc);
326
+ _currency.safeTransferFrom(payer, _treasury, policy.ensuroCommission);
327
+ if (policy.partnerCommission > 0 && payer != rm.wallet())
328
+ _currency.safeTransferFrom(payer, rm.wallet(), policy.partnerCommission);
316
329
  // TODO: this code does up to 5 ERC20 transfers. How we can avoid this? Delayed transfers?
317
330
 
318
331
  emit NewPolicy(rm, policy);
@@ -365,19 +378,26 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
365
378
  IRiskModule rm = policy.riskModule;
366
379
  require(expired || address(rm) == msg.sender, "Only the RM can resolve policies");
367
380
  require(payout == 0 || policy.expiration > block.timestamp, "Can't pay expired policy");
381
+ ComponentStatus compStatus = _rmStatus(rm);
368
382
  require(
369
- _riskModules[rm] == ComponentStatus.active || _riskModules[rm] == ComponentStatus.deprecated,
383
+ compStatus == ComponentStatus.active || compStatus == ComponentStatus.deprecated,
370
384
  "Module must be active or deprecated to process resolutions"
371
385
  );
372
386
  require(payout <= policy.payout, "payout > policy.payout");
373
387
 
374
388
  bool customerWon = payout > 0;
375
389
 
390
+ IPremiumsAccount pa = rm.premiumsAccount();
391
+ compStatus = _paStatus(pa);
392
+ require(
393
+ compStatus == ComponentStatus.active || compStatus == ComponentStatus.deprecated,
394
+ "PremiumsAccount must be active or deprecated to process resolutions"
395
+ );
376
396
  if (customerWon) {
377
- address policyOwner = _policyNFT.ownerOf(policy.id);
378
- rm.premiumsAccount().policyResolvedWithPayout(policyOwner, policy, payout);
397
+ address policyOwner = ownerOf(policy.id);
398
+ pa.policyResolvedWithPayout(policyOwner, policy, payout);
379
399
  } else {
380
- rm.premiumsAccount().policyExpired(policy);
400
+ pa.policyExpired(policy);
381
401
  }
382
402
 
383
403
  rm.releaseExposure(policy.payout);
@@ -396,7 +416,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
396
416
  * contract explicitly reverts. Doesn't reverts is the callback is not implemented.
397
417
  */
398
418
  function _notifyPayout(uint256 policyId, uint256 payout) internal {
399
- address customer = _policyNFT.ownerOf(policyId);
419
+ address customer = ownerOf(policyId);
400
420
  if (!AddressUpgradeable.isContract(customer)) return;
401
421
  try
402
422
  IPolicyHolder(customer).onPayoutReceived(_msgSender(), address(this), policyId, payout)
@@ -421,7 +441,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable {
421
441
  * @dev Notifies the expiration with a callback if the policyholder is a contract. Never reverts.
422
442
  */
423
443
  function _notifyExpiration(uint256 policyId) internal {
424
- address customer = _policyNFT.ownerOf(policyId);
444
+ address customer = ownerOf(policyId);
425
445
  if (!AddressUpgradeable.isContract(customer)) return;
426
446
  try IPolicyHolder(customer).onPolicyExpired(_msgSender(), address(this), policyId) returns (
427
447
  bytes4
@@ -50,29 +50,30 @@ abstract contract PolicyPoolComponent is
50
50
  _;
51
51
  }
52
52
 
53
- modifier onlyPoolRole3(
54
- bytes32 role1,
55
- bytes32 role2,
56
- bytes32 role3
57
- ) {
58
- if (!hasPoolRole(role1)) {
59
- _policyPool.access().checkRole2(role2, role3, msg.sender);
60
- }
53
+ modifier onlyComponentRole(bytes32 role) {
54
+ _policyPool.access().checkComponentRole(address(this), role, msg.sender, false);
61
55
  _;
62
56
  }
63
57
 
64
- modifier onlyPoolRole2(bytes32 role1, bytes32 role2) {
65
- _policyPool.access().checkRole2(role1, role2, msg.sender);
58
+ modifier onlyGlobalOrComponentRole(bytes32 role) {
59
+ _policyPool.access().checkComponentRole(address(this), role, msg.sender, true);
66
60
  _;
67
61
  }
68
62
 
69
- modifier onlyPoolRole(bytes32 role) {
70
- _policyPool.access().checkRole(role, msg.sender);
63
+ modifier onlyGlobalOrComponentRole2(bytes32 role1, bytes32 role2) {
64
+ _policyPool.access().checkComponentRole2(address(this), role1, role2, msg.sender, true);
71
65
  _;
72
66
  }
73
67
 
74
- modifier onlyComponentRole(bytes32 role) {
75
- _policyPool.access().checkComponentRole(address(this), role, msg.sender);
68
+ modifier onlyGlobalOrComponentRole3(
69
+ bytes32 role1,
70
+ bytes32 role2,
71
+ bytes32 role3
72
+ ) {
73
+ IAccessManager access = _policyPool.access();
74
+ if (!access.hasComponentRole(address(this), role1, msg.sender, true)) {
75
+ _policyPool.access().checkComponentRole2(address(this), role2, role3, msg.sender, true);
76
+ }
76
77
  _;
77
78
  }
78
79
 
@@ -87,14 +88,23 @@ abstract contract PolicyPoolComponent is
87
88
  __Pausable_init();
88
89
  }
89
90
 
90
- // solhint-disable-next-line no-empty-blocks
91
- function _authorizeUpgrade(address) internal override onlyPoolRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {}
91
+ function _authorizeUpgrade(address newImpl)
92
+ internal
93
+ view
94
+ override
95
+ onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
96
+ {
97
+ require(
98
+ IPolicyPoolComponent(newImpl).policyPool() == _policyPool,
99
+ "Can't upgrade changing the PolicyPool!"
100
+ );
101
+ }
92
102
 
93
- function pause() public onlyPoolRole(GUARDIAN_ROLE) {
103
+ function pause() public onlyGlobalOrComponentRole(GUARDIAN_ROLE) {
94
104
  _pause();
95
105
  }
96
106
 
97
- function unpause() public onlyPoolRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {
107
+ function unpause() public onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {
98
108
  _unpause();
99
109
  }
100
110
 
@@ -107,7 +117,7 @@ abstract contract PolicyPoolComponent is
107
117
  }
108
118
 
109
119
  function hasPoolRole(bytes32 role) internal view returns (bool) {
110
- return _policyPool.access().hasRole(role, msg.sender);
120
+ return _policyPool.access().hasComponentRole(address(this), role, msg.sender, true);
111
121
  }
112
122
 
113
123
  function _isTweakRay(