@ensuro/core 2.0.0-beta6 → 2.0.0-beta8
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/build/contracts/AccessManager.sol/AccessManager.json +74 -2
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +213 -0
- package/build/contracts/EToken.sol/EToken.json +114 -45
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +2 -2
- package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +197 -0
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +324 -100
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +122 -2
- package/build/contracts/Reserve.sol/Reserve.json +71 -0
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +3 -3
- package/build/contracts/interfaces/IAccessManager.sol/IAccessManager.json +96 -0
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +103 -0
- package/build/contracts/interfaces/IEToken.sol/IEToken.json +13 -0
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +6 -14
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +13 -0
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +7 -15
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +674 -0
- package/contracts/AccessManager.sol +39 -8
- package/contracts/ERC4626AssetManager.sol +49 -0
- package/contracts/EToken.sol +72 -52
- package/contracts/LiquidityThresholdAssetManager.sol +159 -0
- package/contracts/PolicyPool.sol +155 -135
- package/contracts/PolicyPoolComponent.sol +29 -19
- package/contracts/PremiumsAccount.sol +125 -62
- package/contracts/Reserve.sol +86 -2
- package/contracts/RiskModule.sol +17 -6
- package/contracts/TrustfulRiskModule.sol +17 -2
- package/contracts/interfaces/IAccessManager.sol +23 -5
- package/contracts/interfaces/IAssetManager.sol +22 -0
- package/contracts/interfaces/IEToken.sol +21 -1
- package/contracts/interfaces/IPolicyPool.sol +6 -11
- package/contracts/interfaces/IPremiumsAccount.sol +5 -0
- package/contracts/mocks/FixedRateVault.sol +85 -0
- package/contracts/mocks/PolicyPoolMock.sol +2 -5
- package/contracts/mocks/RiskModuleMock.sol +69 -0
- package/js/test-utils.js +35 -26
- package/package.json +1 -1
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -583
- package/build/contracts/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
- package/contracts/PolicyNFT.sol +0 -96
- package/contracts/interfaces/IPolicyNFT.sol +0 -15
package/contracts/PolicyPool.sol
CHANGED
|
@@ -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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
115
|
+
event ComponentChanged(IAccessManager.GovernanceActions indexed action, address value);
|
|
98
116
|
|
|
99
117
|
/**
|
|
100
|
-
* @dev Event emitted when a new
|
|
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
|
|
103
|
-
|
|
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(
|
|
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
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
|
187
|
-
|
|
188
|
-
require(status == ComponentStatus.deprecated, "
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
|
243
|
+
function changeComponentStatus(IPolicyPoolComponent component, ComponentStatus newStatus)
|
|
195
244
|
external
|
|
196
245
|
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
197
246
|
{
|
|
198
|
-
|
|
199
|
-
require(status != ComponentStatus.inactive, "
|
|
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
|
-
|
|
207
|
-
emit
|
|
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
|
|
259
|
+
function getComponentStatus(IPolicyPoolComponent component)
|
|
235
260
|
external
|
|
236
|
-
|
|
261
|
+
view
|
|
262
|
+
returns (ComponentStatus)
|
|
237
263
|
{
|
|
238
|
-
|
|
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
|
|
250
|
-
|
|
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
|
|
254
|
-
|
|
255
|
-
require(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
-
|
|
320
|
+
_safeMint(policyHolder, policy.id, "");
|
|
306
321
|
|
|
307
322
|
// Distribute the premium
|
|
308
|
-
_currency.safeTransferFrom(
|
|
309
|
-
if (policy.srCoc > 0)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
-
|
|
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 =
|
|
378
|
-
|
|
397
|
+
address policyOwner = ownerOf(policy.id);
|
|
398
|
+
pa.policyResolvedWithPayout(policyOwner, policy, payout);
|
|
379
399
|
} else {
|
|
380
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
54
|
-
|
|
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
|
|
65
|
-
_policyPool.access().
|
|
58
|
+
modifier onlyGlobalOrComponentRole(bytes32 role) {
|
|
59
|
+
_policyPool.access().checkComponentRole(address(this), role, msg.sender, true);
|
|
66
60
|
_;
|
|
67
61
|
}
|
|
68
62
|
|
|
69
|
-
modifier
|
|
70
|
-
_policyPool.access().
|
|
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
|
|
75
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|
|
103
|
+
function pause() public onlyGlobalOrComponentRole(GUARDIAN_ROLE) {
|
|
94
104
|
_pause();
|
|
95
105
|
}
|
|
96
106
|
|
|
97
|
-
function unpause() public
|
|
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().
|
|
120
|
+
return _policyPool.access().hasComponentRole(address(this), role, msg.sender, true);
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
function _isTweakRay(
|