@ensuro/core 2.8.0 → 2.8.2
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 +618 -0
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +238 -0
- package/build/contracts/EToken.sol/EToken.json +1287 -0
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +657 -0
- package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +222 -0
- package/build/contracts/Policy.sol/Policy.json +10 -0
- package/build/contracts/PolicyPool.sol/PolicyPool.json +1775 -0
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +342 -0
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +1142 -0
- package/build/contracts/Reserve.sol/Reserve.json +413 -0
- package/build/contracts/RiskModule.sol/RiskModule.json +589 -0
- package/build/contracts/SignedBucketRiskModule.sol/SignedBucketRiskModule.json +1251 -0
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +1145 -0
- package/build/contracts/TimeScaled.sol/TimeScaled.json +10 -0
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +1143 -0
- package/build/contracts/dependencies/WadRayMath.sol/WadRayMath.json +10 -0
- package/build/contracts/interfaces/IAccessManager.sol/IAccessManager.json +343 -0
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +128 -0
- package/build/contracts/interfaces/IEToken.sol/IEToken.json +460 -0
- package/build/contracts/interfaces/ILPWhitelist.sol/ILPWhitelist.json +103 -0
- package/build/contracts/interfaces/IPolicyHolder.sol/IPolicyHolder.json +108 -0
- package/build/contracts/interfaces/IPolicyHolderV2.sol/IPolicyHolderV2.json +142 -0
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +820 -0
- package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +43 -0
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +477 -0
- package/build/contracts/interfaces/IRiskModule.sol/IRiskModule.json +165 -0
- package/build/contracts/migration/LPManualWhitelistV20.sol/LPManualWhitelistV20.json +491 -0
- package/build/contracts/migration/LPManualWhitelistV20Upgraded.sol/LPManualWhitelistV20Upgraded.json +502 -0
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +43 -0
- package/build/contracts/mocks/IMintableERC20.sol/IMintableERC20.json +47 -0
- package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +193 -0
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +457 -0
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +54 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +929 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +92 -0
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +1316 -0
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +343 -0
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +388 -0
- package/contracts/Policy.sol +58 -21
- package/contracts/PolicyPool.sol +155 -37
- package/contracts/PolicyPoolComponent.sol +5 -2
- package/contracts/RiskModule.sol +27 -30
- package/contracts/SignedBucketRiskModule.sol +32 -95
- package/contracts/SignedQuoteRiskModule.sol +3 -1
- package/contracts/interfaces/IPolicyHolder.sol +2 -2
- package/contracts/interfaces/IPolicyHolderV2.sol +29 -0
- package/contracts/mocks/PolicyHolderMock.sol +71 -10
- package/js/deploy.js +6 -25
- package/js/utils.js +9 -4
- package/package.json +3 -5
- package/contracts/TieredSignedQuoteRiskModule.sol +0 -159
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
5
|
+
|
|
5
6
|
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
6
7
|
import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
|
|
7
|
-
import {RiskModule} from "./RiskModule.sol";
|
|
8
8
|
import {Policy} from "./Policy.sol";
|
|
9
|
+
import {RiskModule} from "./RiskModule.sol";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
* @title
|
|
12
|
+
* @title SignedBucket Risk Module
|
|
12
13
|
* @dev Risk Module that for policy creation verifies the different components of the price have been signed by a
|
|
13
|
-
trusted account (PRICER_ROLE). One of the components of the price
|
|
14
|
+
trusted account (PRICER_ROLE). One of the components of the price is a bucket id that groups policies within
|
|
14
15
|
a risk module, with different parameters (such as collaterallization levels or fees).
|
|
15
16
|
For the resolution (resolvePolicy), it has to be called by an authorized user
|
|
16
17
|
* @custom:security-contact security@ensuro.co
|
|
@@ -18,12 +19,10 @@ import {Policy} from "./Policy.sol";
|
|
|
18
19
|
*/
|
|
19
20
|
contract SignedBucketRiskModule is RiskModule {
|
|
20
21
|
bytes32 public constant POLICY_CREATOR_ROLE = keccak256("POLICY_CREATOR_ROLE");
|
|
22
|
+
bytes32 public constant REPLACER_ROLE = keccak256("REPLACER_ROLE");
|
|
21
23
|
bytes32 public constant PRICER_ROLE = keccak256("PRICER_ROLE");
|
|
22
24
|
bytes32 public constant RESOLVER_ROLE = keccak256("RESOLVER_ROLE");
|
|
23
25
|
|
|
24
|
-
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
25
|
-
bool internal immutable _creationIsOpen;
|
|
26
|
-
|
|
27
26
|
mapping(uint256 => PackedParams) internal _buckets;
|
|
28
27
|
|
|
29
28
|
/**
|
|
@@ -47,14 +46,12 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
47
46
|
*/
|
|
48
47
|
event NewSignedPolicy(uint256 indexed policyId, bytes32 policyData);
|
|
49
48
|
|
|
49
|
+
error QuoteExpired();
|
|
50
|
+
error BucketCannotBeZero();
|
|
51
|
+
error BucketNotFound();
|
|
52
|
+
|
|
50
53
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
51
|
-
constructor(
|
|
52
|
-
IPolicyPool policyPool_,
|
|
53
|
-
IPremiumsAccount premiumsAccount_,
|
|
54
|
-
bool creationIsOpen_
|
|
55
|
-
) RiskModule(policyPool_, premiumsAccount_) {
|
|
56
|
-
_creationIsOpen = creationIsOpen_;
|
|
57
|
-
}
|
|
54
|
+
constructor(IPolicyPool policyPool_, IPremiumsAccount premiumsAccount_) RiskModule(policyPool_, premiumsAccount_) {}
|
|
58
55
|
|
|
59
56
|
/**
|
|
60
57
|
* @dev Initializes the RiskModule
|
|
@@ -89,9 +86,7 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
89
86
|
bytes32 quoteSignatureVS,
|
|
90
87
|
uint40 quoteValidUntil
|
|
91
88
|
) internal view {
|
|
92
|
-
if (
|
|
93
|
-
_policyPool.access().checkComponentRole(address(this), POLICY_CREATOR_ROLE, _msgSender(), false);
|
|
94
|
-
require(quoteValidUntil >= block.timestamp, "Quote expired");
|
|
89
|
+
if (quoteValidUntil < block.timestamp) revert QuoteExpired();
|
|
95
90
|
|
|
96
91
|
/**
|
|
97
92
|
* Checks the quote has been signed by an authorized user
|
|
@@ -134,55 +129,6 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
134
129
|
return createdPolicy;
|
|
135
130
|
}
|
|
136
131
|
|
|
137
|
-
/**
|
|
138
|
-
* @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.
|
|
139
|
-
*
|
|
140
|
-
* Requirements:
|
|
141
|
-
* - The caller approved the spending of the premium to the PolicyPool
|
|
142
|
-
* - The quote has been signed by an address with the component role PRICER_ROLE
|
|
143
|
-
*
|
|
144
|
-
* Emits:
|
|
145
|
-
* - {PolicyPool.NewPolicy}
|
|
146
|
-
* - {NewSignedPolicy}
|
|
147
|
-
*
|
|
148
|
-
* @param payout The exposure (maximum payout) of the policy
|
|
149
|
-
* @param premium The premium that will be paid by the payer
|
|
150
|
-
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
151
|
-
* @param expiration The expiration of the policy (timestamp)
|
|
152
|
-
* @param onBehalfOf The policy holder
|
|
153
|
-
* @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
|
|
154
|
-
* @param bucketId Identifies the group to which the policy belongs (that defines the RM parameters applicable to it)
|
|
155
|
-
* @param quoteSignatureR The signature of the quote. R component (EIP-2098 signature)
|
|
156
|
-
* @param quoteSignatureVS The signature of the quote. VS component (EIP-2098 signature)
|
|
157
|
-
* @param quoteValidUntil The expiration of the quote
|
|
158
|
-
* @return createdPolicy Returns the created policy
|
|
159
|
-
*/
|
|
160
|
-
function newPolicyFull(
|
|
161
|
-
uint256 payout,
|
|
162
|
-
uint256 premium,
|
|
163
|
-
uint256 lossProb,
|
|
164
|
-
uint40 expiration,
|
|
165
|
-
address onBehalfOf,
|
|
166
|
-
bytes32 policyData,
|
|
167
|
-
uint256 bucketId,
|
|
168
|
-
bytes32 quoteSignatureR,
|
|
169
|
-
bytes32 quoteSignatureVS,
|
|
170
|
-
uint40 quoteValidUntil
|
|
171
|
-
) external whenNotPaused returns (Policy.PolicyData memory createdPolicy) {
|
|
172
|
-
_checkSignature(
|
|
173
|
-
payout,
|
|
174
|
-
premium,
|
|
175
|
-
lossProb,
|
|
176
|
-
expiration,
|
|
177
|
-
policyData,
|
|
178
|
-
bucketId,
|
|
179
|
-
quoteSignatureR,
|
|
180
|
-
quoteSignatureVS,
|
|
181
|
-
quoteValidUntil
|
|
182
|
-
);
|
|
183
|
-
return _newPolicySigned(payout, premium, lossProb, expiration, policyData, bucketId, _msgSender(), onBehalfOf);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
132
|
/**
|
|
187
133
|
* @dev Creates a new Policy using a signed quote. The caller is the payer of the policy.
|
|
188
134
|
*
|
|
@@ -217,7 +163,7 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
217
163
|
bytes32 quoteSignatureR,
|
|
218
164
|
bytes32 quoteSignatureVS,
|
|
219
165
|
uint40 quoteValidUntil
|
|
220
|
-
) external whenNotPaused returns (uint256) {
|
|
166
|
+
) external whenNotPaused onlyComponentRole(POLICY_CREATOR_ROLE) returns (uint256) {
|
|
221
167
|
_checkSignature(
|
|
222
168
|
payout,
|
|
223
169
|
premium,
|
|
@@ -233,21 +179,22 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
233
179
|
}
|
|
234
180
|
|
|
235
181
|
/**
|
|
236
|
-
* @dev
|
|
182
|
+
* @dev Replace a policy with a new one, reusing the premium and the capital locked
|
|
237
183
|
*
|
|
238
184
|
* Requirements:
|
|
239
|
-
* -
|
|
185
|
+
* - The caller approved the spending of the premium to the PolicyPool
|
|
240
186
|
* - The quote has been signed by an address with the component role PRICER_ROLE
|
|
187
|
+
* - The caller has been granted component role REPLACER_ROLE or creation is open
|
|
241
188
|
*
|
|
242
189
|
* Emits:
|
|
190
|
+
* - {PolicyPool.PolicyReplaced}
|
|
243
191
|
* - {PolicyPool.NewPolicy}
|
|
244
|
-
* - {NewSignedPolicy}
|
|
245
192
|
*
|
|
246
|
-
* @param
|
|
247
|
-
* @param
|
|
193
|
+
* @param oldPolicy The policy to be replaced
|
|
194
|
+
* @param payout The exposure (maximum payout) of the new policy
|
|
195
|
+
* @param premium The premium that will be paid by the caller
|
|
248
196
|
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
249
197
|
* @param expiration The expiration of the policy (timestamp)
|
|
250
|
-
* @param onBehalfOf The policy holder
|
|
251
198
|
* @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
|
|
252
199
|
* @param bucketId Identifies the group to which the policy belongs (that defines the RM parameters applicable to it)
|
|
253
200
|
* @param quoteSignatureR The signature of the quote. R component (EIP-2098 signature)
|
|
@@ -255,32 +202,18 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
255
202
|
* @param quoteValidUntil The expiration of the quote
|
|
256
203
|
* @return Returns the id of the created policy
|
|
257
204
|
*/
|
|
258
|
-
function
|
|
205
|
+
function replacePolicy(
|
|
206
|
+
Policy.PolicyData calldata oldPolicy,
|
|
259
207
|
uint256 payout,
|
|
260
208
|
uint256 premium,
|
|
261
209
|
uint256 lossProb,
|
|
262
210
|
uint40 expiration,
|
|
263
|
-
address onBehalfOf,
|
|
264
211
|
bytes32 policyData,
|
|
265
212
|
uint256 bucketId,
|
|
266
213
|
bytes32 quoteSignatureR,
|
|
267
214
|
bytes32 quoteSignatureVS,
|
|
268
215
|
uint40 quoteValidUntil
|
|
269
|
-
) external whenNotPaused returns (uint256) {
|
|
270
|
-
require(
|
|
271
|
-
onBehalfOf == _msgSender() || currency().allowance(onBehalfOf, _msgSender()) > 0,
|
|
272
|
-
"Sender is not authorized to create policies onBehalfOf"
|
|
273
|
-
);
|
|
274
|
-
/**
|
|
275
|
-
* The standard is the payer should be the _msgSender() but usually, in this type of module,
|
|
276
|
-
* the sender is an operative account managed by software, where the onBehalfOf is a more
|
|
277
|
-
* secure account (hardware wallet) that does the cash movements.
|
|
278
|
-
* This non standard behaviour allows for a more secure setup, where the sender never manages
|
|
279
|
-
* cash.
|
|
280
|
-
* We leverage the currency's allowance mechanism to allow the sender access to the payer's
|
|
281
|
-
* funds.
|
|
282
|
-
* Note that this allowance won't be spent, so anything above 0 is accepted.
|
|
283
|
-
*/
|
|
216
|
+
) external whenNotPaused onlyComponentRole(REPLACER_ROLE) returns (uint256) {
|
|
284
217
|
_checkSignature(
|
|
285
218
|
payout,
|
|
286
219
|
premium,
|
|
@@ -292,7 +225,10 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
292
225
|
quoteSignatureVS,
|
|
293
226
|
quoteValidUntil
|
|
294
227
|
);
|
|
295
|
-
|
|
228
|
+
uint96 internalId = uint96(uint256(policyData) % 2 ** 96);
|
|
229
|
+
return
|
|
230
|
+
_replacePolicy(oldPolicy, payout, premium, lossProb, expiration, _msgSender(), internalId, bucketParams(bucketId))
|
|
231
|
+
.id;
|
|
296
232
|
}
|
|
297
233
|
|
|
298
234
|
function resolvePolicy(
|
|
@@ -316,7 +252,7 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
316
252
|
uint256 bucketId,
|
|
317
253
|
Params calldata params_
|
|
318
254
|
) external onlyGlobalOrComponentRole2(LEVEL1_ROLE, LEVEL2_ROLE) {
|
|
319
|
-
|
|
255
|
+
if (bucketId == 0) revert BucketCannotBeZero();
|
|
320
256
|
_buckets[bucketId] = PackedParams({
|
|
321
257
|
moc: _wadTo4(params_.moc),
|
|
322
258
|
jrCollRatio: _wadTo4(params_.jrCollRatio),
|
|
@@ -343,7 +279,8 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
343
279
|
* @param bucketId Group identifier for the policies that will have these parameters
|
|
344
280
|
*/
|
|
345
281
|
function deleteBucket(uint256 bucketId) external onlyGlobalOrComponentRole2(LEVEL1_ROLE, LEVEL2_ROLE) {
|
|
346
|
-
|
|
282
|
+
if (bucketId == 0) revert BucketCannotBeZero();
|
|
283
|
+
if (_buckets[bucketId].moc == 0) revert BucketNotFound();
|
|
347
284
|
delete _buckets[bucketId];
|
|
348
285
|
emit BucketDeleted(bucketId);
|
|
349
286
|
}
|
|
@@ -351,12 +288,12 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
351
288
|
/**
|
|
352
289
|
* @dev returns the risk bucket parameters for the given bucketId
|
|
353
290
|
*
|
|
354
|
-
* @param bucketId Id of the bucket
|
|
291
|
+
* @param bucketId Id of the bucket or 0 if you want the default params
|
|
355
292
|
*/
|
|
356
293
|
function bucketParams(uint256 bucketId) public view returns (Params memory params_) {
|
|
357
294
|
if (bucketId != 0) {
|
|
358
295
|
PackedParams storage bucketParams_ = _buckets[bucketId];
|
|
359
|
-
|
|
296
|
+
if (bucketParams_.moc == 0) revert BucketNotFound();
|
|
360
297
|
params_ = _unpackParams(bucketParams_);
|
|
361
298
|
} else {
|
|
362
299
|
params_ = params();
|
|
@@ -377,7 +314,7 @@ contract SignedBucketRiskModule is RiskModule {
|
|
|
377
314
|
uint40 expiration,
|
|
378
315
|
uint256 bucketId
|
|
379
316
|
) public view virtual returns (uint256) {
|
|
380
|
-
return _getMinimumPremium(payout, lossProb, expiration, bucketParams(bucketId));
|
|
317
|
+
return _getMinimumPremium(payout, lossProb, expiration, uint40(block.timestamp), bucketParams(bucketId));
|
|
381
318
|
}
|
|
382
319
|
|
|
383
320
|
/**
|
|
@@ -30,6 +30,8 @@ contract SignedQuoteRiskModule is RiskModule {
|
|
|
30
30
|
*/
|
|
31
31
|
event NewSignedPolicy(uint256 indexed policyId, bytes32 policyData);
|
|
32
32
|
|
|
33
|
+
error QuoteExpired();
|
|
34
|
+
|
|
33
35
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
34
36
|
constructor(
|
|
35
37
|
IPolicyPool policyPool_,
|
|
@@ -75,7 +77,7 @@ contract SignedQuoteRiskModule is RiskModule {
|
|
|
75
77
|
) internal returns (Policy.PolicyData memory createdPolicy) {
|
|
76
78
|
if (!_creationIsOpen)
|
|
77
79
|
_policyPool.access().checkComponentRole(address(this), POLICY_CREATOR_ROLE, _msgSender(), false);
|
|
78
|
-
|
|
80
|
+
if (quoteValidUntil < block.timestamp) revert QuoteExpired();
|
|
79
81
|
|
|
80
82
|
/**
|
|
81
83
|
* Checks the quote has been signed by an authorized user
|
|
@@ -16,7 +16,7 @@ interface IPolicyHolder is IERC721Receiver {
|
|
|
16
16
|
* No mather what's the return value or even if this function reverts, this function will not revert the policy
|
|
17
17
|
* expiration.
|
|
18
18
|
*
|
|
19
|
-
* The selector can be obtained in Solidity with `
|
|
19
|
+
* The selector can be obtained in Solidity with `IPolicyHolder.onPolicyExpired.selector`.
|
|
20
20
|
*/
|
|
21
21
|
function onPolicyExpired(address operator, address from, uint256 policyId) external returns (bytes4);
|
|
22
22
|
|
|
@@ -27,7 +27,7 @@ interface IPolicyHolder is IERC721Receiver {
|
|
|
27
27
|
* If interface is not implemented by the recipient, it will be ignored and the payout will be successful.
|
|
28
28
|
* If any other value is returned or it reverts, the policy resolution / payout will be reverted.
|
|
29
29
|
*
|
|
30
|
-
* The selector can be obtained in Solidity with `
|
|
30
|
+
* The selector can be obtained in Solidity with `IPolicyHolder.onPayoutReceived.selector`.
|
|
31
31
|
*/
|
|
32
32
|
function onPayoutReceived(address operator, address from, uint256 policyId, uint256 amount) external returns (bytes4);
|
|
33
33
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IPolicyHolder} from "./IPolicyHolder.sol";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @title Policy holder interface - V2 of the interface that adds onPolicyReplaced endpoint
|
|
8
|
+
* @dev Interface for any contract that wants to be a holder of Ensuro Policies and receive notification of payouts and
|
|
9
|
+
* replacements.
|
|
10
|
+
*
|
|
11
|
+
* Implementors of this interface MUST return true on supportsInterface for both IPolicyHolder and IPolicyHolderV2.
|
|
12
|
+
*/
|
|
13
|
+
interface IPolicyHolderV2 is IPolicyHolder {
|
|
14
|
+
/**
|
|
15
|
+
* @dev Whenever a policy is replaced, this function is called
|
|
16
|
+
*
|
|
17
|
+
* It must return its Solidity selector to confirm the payout.
|
|
18
|
+
* If interface is not implemented by the recipient, it will be ignored and the replacement will be successful.
|
|
19
|
+
* If any other value is returned or it reverts, the policy replacement will be reverted.
|
|
20
|
+
*
|
|
21
|
+
* The selector can be obtained in Solidity with `IPolicyHolderV2.onPolicyReplaced.selector`.
|
|
22
|
+
*/
|
|
23
|
+
function onPolicyReplaced(
|
|
24
|
+
address operator,
|
|
25
|
+
address from,
|
|
26
|
+
uint256 oldPolicyId,
|
|
27
|
+
uint256 newPolicyId
|
|
28
|
+
) external returns (bytes4);
|
|
29
|
+
}
|
|
@@ -2,22 +2,29 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
import {IPolicyHolder} from "../interfaces/IPolicyHolder.sol";
|
|
5
|
+
import {IPolicyHolderV2} from "../interfaces/IPolicyHolderV2.sol";
|
|
5
6
|
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
|
|
6
7
|
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
8
|
+
import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol";
|
|
7
9
|
|
|
8
|
-
contract PolicyHolderMock is
|
|
10
|
+
contract PolicyHolderMock is IPolicyHolderV2 {
|
|
9
11
|
uint256 public policyId;
|
|
10
12
|
uint256 public payout;
|
|
11
13
|
bool public fail;
|
|
14
|
+
bool public failReplace;
|
|
12
15
|
bool public emptyRevert;
|
|
13
16
|
bool public notImplemented;
|
|
14
17
|
bool public badlyImplemented;
|
|
18
|
+
bool public badlyImplementedReplace;
|
|
15
19
|
bool public noERC165;
|
|
20
|
+
bool public noV2;
|
|
21
|
+
uint256 public spendGasCount;
|
|
16
22
|
|
|
17
23
|
enum NotificationKind {
|
|
18
24
|
PolicyReceived,
|
|
19
25
|
PayoutReceived,
|
|
20
|
-
PolicyExpired
|
|
26
|
+
PolicyExpired,
|
|
27
|
+
PolicyReplaced
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
event NotificationReceived(NotificationKind kind, uint256 policyId, address operator, address from);
|
|
@@ -29,12 +36,21 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
29
36
|
emptyRevert = false;
|
|
30
37
|
noERC165 = false;
|
|
31
38
|
payout = type(uint256).max;
|
|
39
|
+
spendGasCount = 0;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
function setFail(bool fail_) external {
|
|
35
43
|
fail = fail_;
|
|
36
44
|
}
|
|
37
45
|
|
|
46
|
+
function setFailReplace(bool failReplace_) external {
|
|
47
|
+
failReplace = failReplace_;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function setSpendGasCount(uint256 spendGasCount_) external {
|
|
51
|
+
spendGasCount = spendGasCount_;
|
|
52
|
+
}
|
|
53
|
+
|
|
38
54
|
function setNotImplemented(bool notImplemented_) external {
|
|
39
55
|
notImplemented = notImplemented_;
|
|
40
56
|
}
|
|
@@ -43,6 +59,14 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
43
59
|
badlyImplemented = badlyImplemented_;
|
|
44
60
|
}
|
|
45
61
|
|
|
62
|
+
function setBadlyImplementedReplace(bool badlyImplementedReplace_) external {
|
|
63
|
+
badlyImplementedReplace = badlyImplementedReplace_;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function setNoV2(bool noV2_) external {
|
|
67
|
+
noV2 = noV2_;
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
function setNoERC165(bool noERC165_) external {
|
|
47
71
|
noERC165 = noERC165_;
|
|
48
72
|
}
|
|
@@ -51,6 +75,13 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
51
75
|
emptyRevert = emptyRevert_;
|
|
52
76
|
}
|
|
53
77
|
|
|
78
|
+
function spendGas() internal {
|
|
79
|
+
// Spends gas doing storage writes
|
|
80
|
+
for (uint256 i = 0; i < spendGasCount; i++) {
|
|
81
|
+
StorageSlot.getUint256Slot(bytes32(100 + i)).value = i + 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
54
85
|
/**
|
|
55
86
|
* @dev See {IERC165-supportsInterface}.
|
|
56
87
|
*/
|
|
@@ -60,7 +91,10 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
60
91
|
revert(0, 0)
|
|
61
92
|
}
|
|
62
93
|
if (notImplemented) return false;
|
|
63
|
-
return
|
|
94
|
+
return
|
|
95
|
+
interfaceId == type(IPolicyHolder).interfaceId ||
|
|
96
|
+
(!noV2 && interfaceId == type(IPolicyHolderV2).interfaceId) ||
|
|
97
|
+
interfaceId == type(IERC165).interfaceId;
|
|
64
98
|
}
|
|
65
99
|
|
|
66
100
|
function onERC721Received(
|
|
@@ -82,6 +116,8 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
82
116
|
|
|
83
117
|
if (badlyImplemented) return bytes4(0x0badf00d);
|
|
84
118
|
|
|
119
|
+
spendGas();
|
|
120
|
+
|
|
85
121
|
return IERC721Receiver.onERC721Received.selector;
|
|
86
122
|
}
|
|
87
123
|
|
|
@@ -98,17 +134,13 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
98
134
|
|
|
99
135
|
if (badlyImplemented) return bytes4(0x0badf00d);
|
|
100
136
|
|
|
137
|
+
spendGas();
|
|
138
|
+
|
|
101
139
|
return IPolicyHolder.onPolicyExpired.selector;
|
|
102
140
|
}
|
|
103
141
|
|
|
104
142
|
/**
|
|
105
|
-
* @dev
|
|
106
|
-
*
|
|
107
|
-
* It must return its Solidity selector to confirm the payout.
|
|
108
|
-
* If interface is not implemented by the recipient, it will be ignored and the payout will be successful.
|
|
109
|
-
* If any other value is returned or it reverts, the policy resolution / payout will be reverted.
|
|
110
|
-
*
|
|
111
|
-
* The selector can be obtained in Solidity with `IPolicyPool.onPayoutReceived.selector`.
|
|
143
|
+
* @dev See {IPolicyHolderV2-onPayoutReceived}.
|
|
112
144
|
*/
|
|
113
145
|
function onPayoutReceived(
|
|
114
146
|
address operator,
|
|
@@ -128,6 +160,35 @@ contract PolicyHolderMock is IPolicyHolder {
|
|
|
128
160
|
|
|
129
161
|
if (badlyImplemented) return bytes4(0x0badf00d);
|
|
130
162
|
|
|
163
|
+
spendGas();
|
|
164
|
+
|
|
131
165
|
return IPolicyHolder.onPayoutReceived.selector;
|
|
132
166
|
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @dev See {IPolicyHolderV2-onPolicyReplaced}.
|
|
170
|
+
*/
|
|
171
|
+
function onPolicyReplaced(
|
|
172
|
+
address operator,
|
|
173
|
+
address from,
|
|
174
|
+
uint256 oldPolicyId,
|
|
175
|
+
uint256 newPolicyId
|
|
176
|
+
) external override returns (bytes4) {
|
|
177
|
+
if (noV2) revert("Shouldn't call this method if V2 not enabled");
|
|
178
|
+
if (failReplace)
|
|
179
|
+
if (emptyRevert)
|
|
180
|
+
assembly {
|
|
181
|
+
revert(0, 0)
|
|
182
|
+
}
|
|
183
|
+
else revert("onPolicyReplaced: They told me I have to fail");
|
|
184
|
+
policyId = oldPolicyId;
|
|
185
|
+
payout = newPolicyId;
|
|
186
|
+
emit NotificationReceived(NotificationKind.PolicyReplaced, oldPolicyId, operator, from);
|
|
187
|
+
|
|
188
|
+
if (badlyImplementedReplace) return bytes4(0x0badf00d);
|
|
189
|
+
|
|
190
|
+
spendGas();
|
|
191
|
+
|
|
192
|
+
return IPolicyHolderV2.onPolicyReplaced.selector;
|
|
193
|
+
}
|
|
133
194
|
}
|
package/js/deploy.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const upgrades_core = require("@openzeppelin/upgrades-core");
|
|
2
1
|
const helpers = require("@nomicfoundation/hardhat-network-helpers");
|
|
3
2
|
const fs = require("fs");
|
|
4
3
|
const ethers = require("ethers");
|
|
@@ -75,16 +74,12 @@ async function logContractCreated(hre, contractName, address) {
|
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
async function verifyContract(hre, contract, isProxy, constructorArguments) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const contractAddr = await ethers.resolveAddress(contract);
|
|
81
|
-
const address = isProxy
|
|
82
|
-
? await upgrades_core.getImplementationAddress(hre.network.provider, contractAddr)
|
|
83
|
-
: contractAddr;
|
|
77
|
+
constructorArguments = constructorArguments || [];
|
|
78
|
+
const address = await ethers.resolveAddress(contract);
|
|
84
79
|
try {
|
|
85
80
|
await hre.run("verify:verify", {
|
|
86
|
-
address
|
|
87
|
-
constructorArguments
|
|
81
|
+
address,
|
|
82
|
+
constructorArguments,
|
|
88
83
|
});
|
|
89
84
|
} catch (error) {
|
|
90
85
|
console.log("Error verifying contract implementation: ", error);
|
|
@@ -95,18 +90,6 @@ async function verifyContract(hre, contract, isProxy, constructorArguments) {
|
|
|
95
90
|
.join(" ")}`
|
|
96
91
|
);
|
|
97
92
|
}
|
|
98
|
-
try {
|
|
99
|
-
if (isProxy) {
|
|
100
|
-
await hre.run("verify:verify", {
|
|
101
|
-
address: contractAddr,
|
|
102
|
-
constructorArguments: constructorArguments,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.log("Error verifying contract proxy: ", error);
|
|
107
|
-
const endpoints = await hre.run("verify:get-etherscan-endpoint");
|
|
108
|
-
console.log(`You should do it manually at ${endpoints.urls.browserURL}/proxyContractChecker?a=${contractAddr}`);
|
|
109
|
-
}
|
|
110
93
|
}
|
|
111
94
|
|
|
112
95
|
async function deployContract({ saveAddr, verify, contractClass, constructorArgs }, hre) {
|
|
@@ -114,8 +97,7 @@ async function deployContract({ saveAddr, verify, contractClass, constructorArgs
|
|
|
114
97
|
const contract = await ContractFactory.deploy(...constructorArgs, txOverrides());
|
|
115
98
|
const contractAddr = await ethers.resolveAddress(contract);
|
|
116
99
|
if (verify) {
|
|
117
|
-
|
|
118
|
-
await contract.deployTransaction.wait(6);
|
|
100
|
+
await contract.deploymentTransaction().wait(6);
|
|
119
101
|
} else {
|
|
120
102
|
await contract.waitForDeployment();
|
|
121
103
|
}
|
|
@@ -138,8 +120,7 @@ async function deployProxyContract(
|
|
|
138
120
|
});
|
|
139
121
|
const contractAddr = await ethers.resolveAddress(contract);
|
|
140
122
|
if (verify) {
|
|
141
|
-
|
|
142
|
-
await contract.deployTransaction.wait(6);
|
|
123
|
+
await contract.deploymentTransaction().wait(6);
|
|
143
124
|
} else {
|
|
144
125
|
await contract.waitForDeployment();
|
|
145
126
|
}
|
package/js/utils.js
CHANGED
|
@@ -144,22 +144,27 @@ async function grantRole(hre, contract, role, user, txOverrides = {}, log = () =
|
|
|
144
144
|
* @param {Interface} interface The interface of the contract that contains the requested event
|
|
145
145
|
* @param {TransactionReceipt} receipt Transaction receipt containing the events in the logs
|
|
146
146
|
* @param {String} eventName The name of the event we are interested in
|
|
147
|
+
* @param {Boolean} firstOnly If false, returns all the events matching the name
|
|
148
|
+
* @param {String} contractAddress If not null, if returns only those events generated by the specified contract
|
|
147
149
|
* @returns {LogDescription}
|
|
148
150
|
*/
|
|
149
|
-
function getTransactionEvent(interface, receipt, eventName) {
|
|
151
|
+
function getTransactionEvent(interface, receipt, eventName, firstOnly = true, contractAddress = null) {
|
|
152
|
+
const ret = [];
|
|
150
153
|
// for each log in the transaction receipt
|
|
151
154
|
for (const log of receipt.logs) {
|
|
152
155
|
let parsedLog;
|
|
156
|
+
if (contractAddress !== null && contractAddress !== log.address) continue;
|
|
153
157
|
try {
|
|
154
158
|
parsedLog = interface.parseLog(log);
|
|
155
159
|
} catch (error) {
|
|
156
160
|
continue;
|
|
157
161
|
}
|
|
158
162
|
if (parsedLog?.name == eventName) {
|
|
159
|
-
return parsedLog;
|
|
163
|
+
if (firstOnly) return parsedLog;
|
|
164
|
+
ret.push(parsedLog);
|
|
160
165
|
}
|
|
161
166
|
}
|
|
162
|
-
return null
|
|
167
|
+
return firstOnly ? null : ret;
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
/**
|
|
@@ -246,7 +251,7 @@ async function defaultPolicyParams(
|
|
|
246
251
|
_A = amountFunction(6)
|
|
247
252
|
) {
|
|
248
253
|
const now = await helpers.time.latest();
|
|
249
|
-
const rmAddress = rm ?
|
|
254
|
+
const rmAddress = rm ? getAddress(rm) : null;
|
|
250
255
|
return {
|
|
251
256
|
rmAddress,
|
|
252
257
|
payout: payout || _A(1000),
|
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ensuro/core",
|
|
3
3
|
"description": "Ensuro - Decentralized insurance protocol",
|
|
4
|
-
"version": "2.8.
|
|
4
|
+
"version": "2.8.2",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.sol",
|
|
7
|
-
"/build
|
|
8
|
-
"/build/interfaces/*.json",
|
|
7
|
+
"/build",
|
|
9
8
|
"/js/*.js",
|
|
10
|
-
"/scripts
|
|
11
|
-
"/scripts/*.js"
|
|
9
|
+
"/scripts"
|
|
12
10
|
],
|
|
13
11
|
"repository": {
|
|
14
12
|
"type": "git",
|