@ensuro/core 2.0.0-beta9 → 2.0.1
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 +14 -0
- package/build/contracts/AccessManager.sol/AccessManager.json +7 -2
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +21 -2
- package/build/contracts/EToken.sol/EToken.json +21 -2
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +21 -2
- package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +19 -0
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +21 -2
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +19 -0
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +21 -2
- package/build/contracts/Reserve.sol/Reserve.json +19 -0
- package/build/contracts/RiskModule.sol/RiskModule.json +19 -0
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +1110 -0
- package/build/contracts/TimeScaled.sol/TimeScaled.json +2 -2
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +137 -2
- package/build/contracts/dependencies/WadRayMath.sol/WadRayMath.json +2 -2
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +19 -0
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +19 -0
- package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +19 -0
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +2 -2
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +2 -2
- package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +180 -0
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +2 -2
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +21 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +21 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +21 -2
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +2 -2
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +2 -2
- package/contracts/AccessManager.sol +30 -1
- package/contracts/ERC4626AssetManager.sol +3 -0
- package/contracts/EToken.sol +89 -19
- package/contracts/LPManualWhitelist.sol +18 -2
- package/contracts/LiquidityThresholdAssetManager.sol +17 -2
- package/contracts/Policy.sol +4 -2
- package/contracts/PolicyPool.sol +72 -13
- package/contracts/PolicyPoolComponent.sol +29 -3
- package/contracts/PremiumsAccount.sol +72 -24
- package/contracts/Reserve.sol +19 -3
- package/contracts/RiskModule.sol +46 -13
- package/contracts/SignedQuoteRiskModule.sol +310 -0
- package/contracts/TrustfulRiskModule.sol +104 -3
- package/contracts/interfaces/IAssetManager.sol +8 -3
- package/contracts/interfaces/IPolicyPool.sol +15 -4
- package/contracts/interfaces/IPolicyPoolComponent.sol +2 -1
- package/contracts/mocks/InterfaceIdCalculator.sol +32 -0
- package/contracts/mocks/PolicyPoolComponentMock.sol +10 -0
- package/contracts/mocks/PolicyPoolMock.sol +4 -0
- package/js/deploy.js +779 -0
- package/js/test-utils.js +139 -37
- package/package.json +4 -2
- package/scripts/change-pragma.sh +19 -0
- package/scripts/deploySmokeTest-fork.sh +53 -0
- package/scripts/deploySmokeTest.sh +51 -0
- package/scripts/storageLayout.js +33 -0
- package/scripts/utils.sh +65 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
5
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
6
|
+
import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
|
|
7
|
+
import {RiskModule} from "./RiskModule.sol";
|
|
8
|
+
import {Policy} from "./Policy.sol";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @title SignedQuote Risk Module
|
|
12
|
+
* @dev Risk Module that for policy creation verifies the different components of the price have been signed by a
|
|
13
|
+
trusted account (PRICER_ROLE). For the resolution (resolvePolicy), it has to be called by an authorized user
|
|
14
|
+
* @custom:security-contact security@ensuro.co
|
|
15
|
+
* @author Ensuro
|
|
16
|
+
*/
|
|
17
|
+
contract SignedQuoteRiskModule is RiskModule {
|
|
18
|
+
bytes32 public constant POLICY_CREATOR_ROLE = keccak256("POLICY_CREATOR_ROLE");
|
|
19
|
+
bytes32 public constant PRICER_ROLE = keccak256("PRICER_ROLE");
|
|
20
|
+
bytes32 public constant RESOLVER_ROLE = keccak256("RESOLVER_ROLE");
|
|
21
|
+
|
|
22
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
23
|
+
bool internal immutable _creationIsOpen;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @dev Event emitted every time a new policy is created. It allows to link the policyData with a particular policy
|
|
27
|
+
*
|
|
28
|
+
* @param policyId The id of the policy
|
|
29
|
+
* @param policyData The value sent in `policyData` parameter that's the hash of the off-chain stored data.
|
|
30
|
+
*/
|
|
31
|
+
event NewSignedPolicy(uint256 indexed policyId, bytes32 policyData);
|
|
32
|
+
|
|
33
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
34
|
+
constructor(
|
|
35
|
+
IPolicyPool policyPool_,
|
|
36
|
+
IPremiumsAccount premiumsAccount_,
|
|
37
|
+
bool creationIsOpen_
|
|
38
|
+
) RiskModule(policyPool_, premiumsAccount_) {
|
|
39
|
+
_creationIsOpen = creationIsOpen_;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @dev Initializes the RiskModule
|
|
44
|
+
* @param name_ Name of the Risk Module
|
|
45
|
+
* @param collRatio_ Collateralization ratio to compute solvency requirement as % of payout (in ray)
|
|
46
|
+
* @param ensuroPpFee_ % of pure premium that will go for Ensuro treasury (in ray)
|
|
47
|
+
* @param srRoc_ return on capital paid to Senior LPs (annualized percentage - in ray)
|
|
48
|
+
* @param maxPayoutPerPolicy_ Maximum payout per policy (in wad)
|
|
49
|
+
* @param exposureLimit_ Max exposure (sum of payouts) to be allocated to this module (in wad)
|
|
50
|
+
* @param wallet_ Address of the RiskModule provider
|
|
51
|
+
*/
|
|
52
|
+
function initialize(
|
|
53
|
+
string memory name_,
|
|
54
|
+
uint256 collRatio_,
|
|
55
|
+
uint256 ensuroPpFee_,
|
|
56
|
+
uint256 srRoc_,
|
|
57
|
+
uint256 maxPayoutPerPolicy_,
|
|
58
|
+
uint256 exposureLimit_,
|
|
59
|
+
address wallet_
|
|
60
|
+
) public initializer {
|
|
61
|
+
__RiskModule_init(
|
|
62
|
+
name_,
|
|
63
|
+
collRatio_,
|
|
64
|
+
ensuroPpFee_,
|
|
65
|
+
srRoc_,
|
|
66
|
+
maxPayoutPerPolicy_,
|
|
67
|
+
exposureLimit_,
|
|
68
|
+
wallet_
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function _newPolicySigned(
|
|
73
|
+
uint256 payout,
|
|
74
|
+
uint256 premium,
|
|
75
|
+
uint256 lossProb,
|
|
76
|
+
uint40 expiration,
|
|
77
|
+
bytes32 policyData,
|
|
78
|
+
bytes32 quoteSignatureR,
|
|
79
|
+
bytes32 quoteSignatureVS,
|
|
80
|
+
uint40 quoteValidUntil,
|
|
81
|
+
address payer,
|
|
82
|
+
address onBehalfOf
|
|
83
|
+
) internal returns (Policy.PolicyData memory createdPolicy) {
|
|
84
|
+
if (!_creationIsOpen)
|
|
85
|
+
_policyPool.access().checkComponentRole(
|
|
86
|
+
address(this),
|
|
87
|
+
POLICY_CREATOR_ROLE,
|
|
88
|
+
_msgSender(),
|
|
89
|
+
false
|
|
90
|
+
);
|
|
91
|
+
require(quoteValidUntil >= block.timestamp, "Quote expired");
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Checks the quote has been signed by an authorized user
|
|
95
|
+
* The "quote" is computed as hash of the following fields (encodePacked):
|
|
96
|
+
* - address(this): the address of this RiskModule
|
|
97
|
+
* - payout, premium, lossProb, expiration: the base parameters of the policy
|
|
98
|
+
* - policyData: a hash of the private details of the policy. The calculation should include some
|
|
99
|
+
* unique id (quoteId), so each policyData identifies a policy.
|
|
100
|
+
* - quoteValidUntil: the maximum validity of the quote
|
|
101
|
+
*/
|
|
102
|
+
bytes32 quoteHash = ECDSA.toEthSignedMessageHash(
|
|
103
|
+
abi.encodePacked(
|
|
104
|
+
address(this),
|
|
105
|
+
payout,
|
|
106
|
+
premium,
|
|
107
|
+
lossProb,
|
|
108
|
+
expiration,
|
|
109
|
+
policyData,
|
|
110
|
+
quoteValidUntil
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
address signer = ECDSA.recover(quoteHash, quoteSignatureR, quoteSignatureVS);
|
|
114
|
+
_policyPool.access().checkComponentRole(address(this), PRICER_ROLE, signer, false);
|
|
115
|
+
uint96 internalId = uint96(uint256(policyData) % 2**96);
|
|
116
|
+
|
|
117
|
+
createdPolicy = _newPolicy(
|
|
118
|
+
payout,
|
|
119
|
+
premium,
|
|
120
|
+
lossProb,
|
|
121
|
+
expiration,
|
|
122
|
+
payer,
|
|
123
|
+
onBehalfOf,
|
|
124
|
+
internalId
|
|
125
|
+
);
|
|
126
|
+
emit NewSignedPolicy(createdPolicy.id, policyData);
|
|
127
|
+
return createdPolicy;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @dev Creates a new Policy using a signed quote. The caller is the payer of the policy. Returns all the struct, not just the id.
|
|
132
|
+
*
|
|
133
|
+
* Requirements:
|
|
134
|
+
* - The caller approved the spending of the premium to the PolicyPool
|
|
135
|
+
* - The quote has been signed by an address with the component role PRICER_ROLE
|
|
136
|
+
*
|
|
137
|
+
* Emits:
|
|
138
|
+
* - {PolicyPool.NewPolicy}
|
|
139
|
+
* - {NewSignedPolicy}
|
|
140
|
+
*
|
|
141
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
142
|
+
* @param premium The premium that will be paid by the payer
|
|
143
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
144
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
145
|
+
* @param onBehalfOf The policy holder
|
|
146
|
+
* @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
|
|
147
|
+
* @param quoteSignatureR The signature of the quote. R component (EIP-2098 signature)
|
|
148
|
+
* @param quoteSignatureVS The signature of the quote. VS component (EIP-2098 signature)
|
|
149
|
+
* @param quoteValidUntil The expiration of the quote
|
|
150
|
+
* @return createdPolicy Returns the created policy
|
|
151
|
+
*/
|
|
152
|
+
function newPolicyFull(
|
|
153
|
+
uint256 payout,
|
|
154
|
+
uint256 premium,
|
|
155
|
+
uint256 lossProb,
|
|
156
|
+
uint40 expiration,
|
|
157
|
+
address onBehalfOf,
|
|
158
|
+
bytes32 policyData,
|
|
159
|
+
bytes32 quoteSignatureR,
|
|
160
|
+
bytes32 quoteSignatureVS,
|
|
161
|
+
uint40 quoteValidUntil
|
|
162
|
+
) external returns (Policy.PolicyData memory createdPolicy) {
|
|
163
|
+
return
|
|
164
|
+
_newPolicySigned(
|
|
165
|
+
payout,
|
|
166
|
+
premium,
|
|
167
|
+
lossProb,
|
|
168
|
+
expiration,
|
|
169
|
+
policyData,
|
|
170
|
+
quoteSignatureR,
|
|
171
|
+
quoteSignatureVS,
|
|
172
|
+
quoteValidUntil,
|
|
173
|
+
_msgSender(),
|
|
174
|
+
onBehalfOf
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @dev Creates a new Policy using a signed quote. The caller is the payer of the policy.
|
|
180
|
+
*
|
|
181
|
+
* Requirements:
|
|
182
|
+
* - The caller approved the spending of the premium to the PolicyPool
|
|
183
|
+
* - The quote has been signed by an address with the component role PRICER_ROLE
|
|
184
|
+
*
|
|
185
|
+
* Emits:
|
|
186
|
+
* - {PolicyPool.NewPolicy}
|
|
187
|
+
* - {NewSignedPolicy}
|
|
188
|
+
*
|
|
189
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
190
|
+
* @param premium The premium that will be paid by the payer
|
|
191
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
192
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
193
|
+
* @param onBehalfOf The policy holder
|
|
194
|
+
* @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
|
|
195
|
+
* @param quoteSignatureR The signature of the quote. R component (EIP-2098 signature)
|
|
196
|
+
* @param quoteSignatureVS The signature of the quote. VS component (EIP-2098 signature)
|
|
197
|
+
* @param quoteValidUntil The expiration of the quote
|
|
198
|
+
* @return Returns the id of the created policy
|
|
199
|
+
*/
|
|
200
|
+
function newPolicy(
|
|
201
|
+
uint256 payout,
|
|
202
|
+
uint256 premium,
|
|
203
|
+
uint256 lossProb,
|
|
204
|
+
uint40 expiration,
|
|
205
|
+
address onBehalfOf,
|
|
206
|
+
bytes32 policyData,
|
|
207
|
+
bytes32 quoteSignatureR,
|
|
208
|
+
bytes32 quoteSignatureVS,
|
|
209
|
+
uint40 quoteValidUntil
|
|
210
|
+
) external returns (uint256) {
|
|
211
|
+
return
|
|
212
|
+
_newPolicySigned(
|
|
213
|
+
payout,
|
|
214
|
+
premium,
|
|
215
|
+
lossProb,
|
|
216
|
+
expiration,
|
|
217
|
+
policyData,
|
|
218
|
+
quoteSignatureR,
|
|
219
|
+
quoteSignatureVS,
|
|
220
|
+
quoteValidUntil,
|
|
221
|
+
_msgSender(),
|
|
222
|
+
onBehalfOf
|
|
223
|
+
).id;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @dev Creates a new Policy using a signed quote. The payer is the policy holder
|
|
228
|
+
*
|
|
229
|
+
* Requirements:
|
|
230
|
+
* - currency().allowance(onBehalfOf, _msgSender()) > 0
|
|
231
|
+
* - The quote has been signed by an address with the component role PRICER_ROLE
|
|
232
|
+
*
|
|
233
|
+
* Emits:
|
|
234
|
+
* - {PolicyPool.NewPolicy}
|
|
235
|
+
* - {NewSignedPolicy}
|
|
236
|
+
*
|
|
237
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
238
|
+
* @param premium The premium that will be paid by the payer
|
|
239
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
240
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
241
|
+
* @param onBehalfOf The policy holder
|
|
242
|
+
* @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
|
|
243
|
+
* @param quoteSignatureR The signature of the quote. R component (EIP-2098 signature)
|
|
244
|
+
* @param quoteSignatureVS The signature of the quote. VS component (EIP-2098 signature)
|
|
245
|
+
* @param quoteValidUntil The expiration of the quote
|
|
246
|
+
* @return Returns the id of the created policy
|
|
247
|
+
*/
|
|
248
|
+
function newPolicyPaidByHolder(
|
|
249
|
+
uint256 payout,
|
|
250
|
+
uint256 premium,
|
|
251
|
+
uint256 lossProb,
|
|
252
|
+
uint40 expiration,
|
|
253
|
+
address onBehalfOf,
|
|
254
|
+
bytes32 policyData,
|
|
255
|
+
bytes32 quoteSignatureR,
|
|
256
|
+
bytes32 quoteSignatureVS,
|
|
257
|
+
uint40 quoteValidUntil
|
|
258
|
+
) external returns (uint256) {
|
|
259
|
+
require(
|
|
260
|
+
onBehalfOf == _msgSender() || currency().allowance(onBehalfOf, _msgSender()) > 0,
|
|
261
|
+
"Sender is not authorized to create policies onBehalfOf"
|
|
262
|
+
);
|
|
263
|
+
/**
|
|
264
|
+
* The standard is the payer should be the _msgSender() but usually, in this type of module,
|
|
265
|
+
* the sender is an operative account managed by software, where the onBehalfOf is a more
|
|
266
|
+
* secure account (hardware wallet) that does the cash movements.
|
|
267
|
+
* This non standard behaviour allows for a more secure setup, where the sender never manages
|
|
268
|
+
* cash.
|
|
269
|
+
* We leverage the currency's allowance mechanism to allow the sender access to the payer's
|
|
270
|
+
* funds.
|
|
271
|
+
* Note that this allowance won't be spent, so anything above 0 is accepted.
|
|
272
|
+
*/
|
|
273
|
+
return
|
|
274
|
+
_newPolicySigned(
|
|
275
|
+
payout,
|
|
276
|
+
premium,
|
|
277
|
+
lossProb,
|
|
278
|
+
expiration,
|
|
279
|
+
policyData,
|
|
280
|
+
quoteSignatureR,
|
|
281
|
+
quoteSignatureVS,
|
|
282
|
+
quoteValidUntil,
|
|
283
|
+
onBehalfOf,
|
|
284
|
+
onBehalfOf
|
|
285
|
+
).id;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
|
|
289
|
+
external
|
|
290
|
+
onlyComponentRole(RESOLVER_ROLE)
|
|
291
|
+
whenNotPaused
|
|
292
|
+
{
|
|
293
|
+
_policyPool.resolvePolicy(policy, payout);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
|
|
297
|
+
external
|
|
298
|
+
onlyComponentRole(RESOLVER_ROLE)
|
|
299
|
+
whenNotPaused
|
|
300
|
+
{
|
|
301
|
+
_policyPool.resolvePolicyFullPayout(policy, customerWon);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @dev This empty reserved space is put in place to allow future versions to add new
|
|
306
|
+
* variables without shifting down storage in the inheritance chain.
|
|
307
|
+
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
|
|
308
|
+
*/
|
|
309
|
+
uint256[50] private __gap;
|
|
310
|
+
}
|
|
@@ -54,6 +54,23 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @dev Creates a new Policy
|
|
59
|
+
*
|
|
60
|
+
* Requirements:
|
|
61
|
+
* - The caller has been granted componentRole(PRICER_ROLE)
|
|
62
|
+
*
|
|
63
|
+
* Emits:
|
|
64
|
+
* - {PolicyPool.NewPolicy}
|
|
65
|
+
*
|
|
66
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
67
|
+
* @param premium The premium that will be paid by the policyHolder
|
|
68
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
69
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
70
|
+
* @param onBehalfOf The policy holder
|
|
71
|
+
* @param internalId An id that's unique within this module and it will be used to identify the policy
|
|
72
|
+
* @return Returns the id of the created policy
|
|
73
|
+
*/
|
|
57
74
|
function newPolicy(
|
|
58
75
|
uint256 payout,
|
|
59
76
|
uint256 premium,
|
|
@@ -62,7 +79,57 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
62
79
|
address onBehalfOf,
|
|
63
80
|
uint96 internalId
|
|
64
81
|
) external onlyComponentRole(PRICER_ROLE) returns (uint256) {
|
|
65
|
-
|
|
82
|
+
return
|
|
83
|
+
_newPolicy(
|
|
84
|
+
payout,
|
|
85
|
+
premium,
|
|
86
|
+
lossProb,
|
|
87
|
+
expiration,
|
|
88
|
+
_getPayer(onBehalfOf, premium),
|
|
89
|
+
onBehalfOf,
|
|
90
|
+
internalId
|
|
91
|
+
).id;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @dev Creates a new Policy. Version that returns all the PolicyData struct, not just the id.
|
|
96
|
+
*
|
|
97
|
+
* Requirements:
|
|
98
|
+
* - The caller has been granted componentRole(PRICER_ROLE)
|
|
99
|
+
*
|
|
100
|
+
* Emits:
|
|
101
|
+
* - {PolicyPool.NewPolicy}
|
|
102
|
+
*
|
|
103
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
104
|
+
* @param premium The premium that will be paid by the policyHolder
|
|
105
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
106
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
107
|
+
* @param onBehalfOf The policy holder
|
|
108
|
+
* @param internalId An id that's unique within this module and it will be used to identify the policy
|
|
109
|
+
* @return createdPolicy Returns the id of the created policy
|
|
110
|
+
*/
|
|
111
|
+
function newPolicyFull(
|
|
112
|
+
uint256 payout,
|
|
113
|
+
uint256 premium,
|
|
114
|
+
uint256 lossProb,
|
|
115
|
+
uint40 expiration,
|
|
116
|
+
address onBehalfOf,
|
|
117
|
+
uint96 internalId
|
|
118
|
+
) external onlyComponentRole(PRICER_ROLE) returns (Policy.PolicyData memory createdPolicy) {
|
|
119
|
+
return
|
|
120
|
+
_newPolicy(
|
|
121
|
+
payout,
|
|
122
|
+
premium,
|
|
123
|
+
lossProb,
|
|
124
|
+
expiration,
|
|
125
|
+
_getPayer(onBehalfOf, premium),
|
|
126
|
+
onBehalfOf,
|
|
127
|
+
internalId
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function _getPayer(address onBehalfOf, uint256 premium) internal view returns (address payer) {
|
|
132
|
+
payer = onBehalfOf;
|
|
66
133
|
if (payer != _msgSender() && _policyPool.currency().allowance(payer, _msgSender()) < premium)
|
|
67
134
|
/**
|
|
68
135
|
* The standard is the payer should be the _msgSender() but usually, in this type of module,
|
|
@@ -76,10 +143,23 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
76
143
|
* premium even for multiple policies.
|
|
77
144
|
*/
|
|
78
145
|
payer = _msgSender();
|
|
79
|
-
|
|
80
|
-
return _newPolicy(payout, premium, lossProb, expiration, payer, onBehalfOf, internalId).id;
|
|
146
|
+
return payer;
|
|
81
147
|
}
|
|
82
148
|
|
|
149
|
+
/**
|
|
150
|
+
* @dev Resolves a policy, if payout > 0, it pays to the policy holder.
|
|
151
|
+
*
|
|
152
|
+
* Requirements:
|
|
153
|
+
* - The caller has been granted componentRole(RESOLVER_ROLE)
|
|
154
|
+
* - payout <= policy.payout
|
|
155
|
+
* - block.timestamp >= policy.expiration
|
|
156
|
+
*
|
|
157
|
+
* Emits:
|
|
158
|
+
* - {PolicyPool.PolicyResolved}
|
|
159
|
+
*
|
|
160
|
+
* @param policy The policy previously created (from {NewPolicy} event)
|
|
161
|
+
* @param payout The payout to transfer to the policy holder
|
|
162
|
+
*/
|
|
83
163
|
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
|
|
84
164
|
external
|
|
85
165
|
onlyComponentRole(RESOLVER_ROLE)
|
|
@@ -88,6 +168,20 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
88
168
|
_policyPool.resolvePolicy(policy, payout);
|
|
89
169
|
}
|
|
90
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @dev Resolves a policy with full payout (policy.payout) if customerWon == true
|
|
173
|
+
*
|
|
174
|
+
* Requirements:
|
|
175
|
+
* - The caller has been granted componentRole(RESOLVER_ROLE)
|
|
176
|
+
* - block.timestamp >= policy.expiration
|
|
177
|
+
*
|
|
178
|
+
* Emits:
|
|
179
|
+
* - {PolicyPool.PolicyResolved}
|
|
180
|
+
*
|
|
181
|
+
* @param policy The policy previously created (from {NewPolicy} event)
|
|
182
|
+
* @param customerWon If true, policy.payout is transferred to the policy holder. If false, the policy is resolved
|
|
183
|
+
* without payout and can't be longer claimed.
|
|
184
|
+
*/
|
|
91
185
|
function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
|
|
92
186
|
external
|
|
93
187
|
onlyComponentRole(RESOLVER_ROLE)
|
|
@@ -95,4 +189,11 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
95
189
|
{
|
|
96
190
|
_policyPool.resolvePolicyFullPayout(policy, customerWon);
|
|
97
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @dev This empty reserved space is put in place to allow future versions to add new
|
|
195
|
+
* variables without shifting down storage in the inheritance chain.
|
|
196
|
+
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
|
|
197
|
+
*/
|
|
198
|
+
uint256[50] private __gap;
|
|
98
199
|
}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @title IAssetManager - Interface of the asset management strategy that's plugged into the reserves
|
|
6
8
|
* @dev The asset manager is a contract that's plugged and called with `delegatecall` (operates in the context of the
|
|
7
9
|
* reserve - see {Reserve}). The asset manager contract applies a strategy to invest the reserve funds and
|
|
8
10
|
* get additional yields.
|
|
11
|
+
*
|
|
12
|
+
* All implementations of this contract should use the Diamond Storage pattern to avoid overwriting the calling contract's state.
|
|
13
|
+
* See https://eips.ethereum.org/EIPS/eip-2535#storage
|
|
9
14
|
* @author Ensuro
|
|
10
15
|
*/
|
|
11
|
-
interface IAssetManager {
|
|
16
|
+
interface IAssetManager is IERC165 {
|
|
12
17
|
/**
|
|
13
18
|
* @dev Event emitted when funds are removed from Reserve liquidity and invested in the investment strategy,
|
|
14
19
|
* @param amount The amount invested
|
|
@@ -57,8 +62,8 @@ interface IAssetManager {
|
|
|
57
62
|
function recordEarnings() external returns (int256);
|
|
58
63
|
|
|
59
64
|
/**
|
|
60
|
-
* @dev Refills the reserve balance with
|
|
61
|
-
* to be made and there's no
|
|
65
|
+
* @dev Refills the reserve balance with enough money to do a payment. Called from the reserve when a payment needs
|
|
66
|
+
* to be made and there's no enough liquid balance (`currency().balanceOf(reserve) < paymentAmount`)
|
|
62
67
|
*
|
|
63
68
|
* Events:
|
|
64
69
|
* - Emits {MoneyDeinvested} with the amount transferred to the liquid balance.
|
|
@@ -101,12 +101,23 @@ interface IPolicyPool {
|
|
|
101
101
|
function expirePolicy(Policy.PolicyData calldata policy) external;
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
* @dev Returns whether
|
|
105
|
-
*
|
|
106
|
-
*
|
|
104
|
+
* @dev Returns whether a policy is active, i.e., it's still in the PolicyPool, not yet resolved or expired.
|
|
105
|
+
* Be aware that a policy might be active but the `block.timestamp` might be after the expiration date, so it
|
|
106
|
+
* can't be triggered with a payout.
|
|
107
|
+
*
|
|
108
|
+
* @param policyId The id of the policy queried
|
|
109
|
+
* @return Whether the policy is active or not
|
|
107
110
|
*/
|
|
108
111
|
function isActive(uint256 policyId) external view returns (bool);
|
|
109
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @dev Returns the stored hash of the policy. It's `bytes32(0)` is the policy isn't active.
|
|
115
|
+
*
|
|
116
|
+
* @param policyId The id of the policy queried
|
|
117
|
+
* @return Returns the hash of a given policy id
|
|
118
|
+
*/
|
|
119
|
+
function getPolicyHash(uint256 policyId) external view returns (bytes32);
|
|
120
|
+
|
|
110
121
|
/**
|
|
111
122
|
* @dev Deposits liquidity into an eToken. Forwards the call to {EToken-deposit}, after transferring the funds.
|
|
112
123
|
* The user will receive etokens for the same amount deposited.
|
|
@@ -137,7 +148,7 @@ interface IPolicyPool {
|
|
|
137
148
|
*
|
|
138
149
|
* @param eToken The address of the eToken from where the user wants to withdraw liquidity
|
|
139
150
|
* @param amount The amount to withdraw. If equal to type(uint256).max, means full withdrawal.
|
|
140
|
-
* If the balance is not
|
|
151
|
+
* If the balance is not enough or can't be withdrawn (locked as SCR), it withdraws
|
|
141
152
|
* as much as it can, but doesn't fails.
|
|
142
153
|
* @return Returns the actual amount withdrawn.
|
|
143
154
|
*/
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
import {IPolicyPool} from "./IPolicyPool.sol";
|
|
5
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @title IPolicyPoolComponent interface
|
|
8
9
|
* @dev Interface for Contracts linked (owned) by a PolicyPool. Useful to avoid cyclic dependencies
|
|
9
10
|
* @author Ensuro
|
|
10
11
|
*/
|
|
11
|
-
interface IPolicyPoolComponent {
|
|
12
|
+
interface IPolicyPoolComponent is IERC165 {
|
|
12
13
|
/**
|
|
13
14
|
* @dev Returns the address of the PolicyPool (see {PolicyPool}) where this component belongs.
|
|
14
15
|
*/
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
6
|
+
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
7
|
+
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
8
|
+
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
|
|
9
|
+
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
10
|
+
import {IPolicyPoolComponent} from "../interfaces/IPolicyPoolComponent.sol";
|
|
11
|
+
import {IEToken} from "../interfaces/IEToken.sol";
|
|
12
|
+
import {IRiskModule} from "../interfaces/IRiskModule.sol";
|
|
13
|
+
import {IPremiumsAccount} from "../interfaces/IPremiumsAccount.sol";
|
|
14
|
+
import {ILPWhitelist} from "../interfaces/ILPWhitelist.sol";
|
|
15
|
+
import {IAccessManager} from "../interfaces/IAccessManager.sol";
|
|
16
|
+
import {IAssetManager} from "../interfaces/IAssetManager.sol";
|
|
17
|
+
|
|
18
|
+
contract InterfaceIdCalculator {
|
|
19
|
+
bytes4 public constant IERC165_INTERFACEID = type(IERC165).interfaceId;
|
|
20
|
+
bytes4 public constant IERC20_INTERFACEID = type(IERC20).interfaceId;
|
|
21
|
+
bytes4 public constant IERC20METADATA_INTERFACEID = type(IERC20Metadata).interfaceId;
|
|
22
|
+
bytes4 public constant IERC721_INTERFACEID = type(IERC721).interfaceId;
|
|
23
|
+
bytes4 public constant IACCESSCONTROL_INTERFACEID = type(IAccessControl).interfaceId;
|
|
24
|
+
bytes4 public constant IPOLICYPOOL_INTERFACEID = type(IPolicyPool).interfaceId;
|
|
25
|
+
bytes4 public constant IPOLICYPOOLCOMPONENT_INTERFACEID = type(IPolicyPoolComponent).interfaceId;
|
|
26
|
+
bytes4 public constant IETOKEN_INTERFACEID = type(IEToken).interfaceId;
|
|
27
|
+
bytes4 public constant IRISKMODULE_INTERFACEID = type(IRiskModule).interfaceId;
|
|
28
|
+
bytes4 public constant IPREMIUMSACCOUNT_INTERFACEID = type(IPremiumsAccount).interfaceId;
|
|
29
|
+
bytes4 public constant ILPWHITELIST_INTERFACEID = type(ILPWhitelist).interfaceId;
|
|
30
|
+
bytes4 public constant IACCESSMANAGER_INTERFACEID = type(IAccessManager).interfaceId;
|
|
31
|
+
bytes4 public constant IASSETMANAGER_INTERFACEID = type(IAssetManager).interfaceId;
|
|
32
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
4
5
|
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
5
6
|
import {IPolicyPoolComponent} from "../interfaces/IPolicyPoolComponent.sol";
|
|
6
7
|
|
|
@@ -14,4 +15,13 @@ contract PolicyPoolComponentMock is IPolicyPoolComponent {
|
|
|
14
15
|
function policyPool() external view override returns (IPolicyPool) {
|
|
15
16
|
return _policyPool;
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @dev See {IERC165-supportsInterface}.
|
|
21
|
+
*/
|
|
22
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
|
23
|
+
return
|
|
24
|
+
interfaceId == type(IERC165).interfaceId ||
|
|
25
|
+
interfaceId == type(IPolicyPoolComponent).interfaceId;
|
|
26
|
+
}
|
|
17
27
|
}
|
|
@@ -85,6 +85,10 @@ contract PolicyPoolMock is IPolicyPool {
|
|
|
85
85
|
return policyHashes[policyId] != bytes32(0);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
function getPolicyHash(uint256 policyId) external view override returns (bytes32) {
|
|
89
|
+
return policyHashes[policyId];
|
|
90
|
+
}
|
|
91
|
+
|
|
88
92
|
function deposit(IEToken, uint256) external pure override {
|
|
89
93
|
revert("Not Implemented deposit");
|
|
90
94
|
}
|