@ensuro/core 2.7.0 → 2.8.0-beta2
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 +13 -7
- package/contracts/AccessManager.sol +3 -13
- package/contracts/EToken.sol +29 -95
- package/contracts/LPManualWhitelist.sol +11 -26
- package/contracts/LiquidityThresholdAssetManager.sol +10 -21
- package/contracts/Policy.sol +10 -20
- package/contracts/PolicyPool.sol +110 -127
- package/contracts/PolicyPoolComponent.sol +9 -32
- package/contracts/PremiumsAccount.sol +41 -47
- package/contracts/Reserve.sol +10 -16
- package/contracts/RiskModule.sol +74 -83
- package/contracts/SignedBucketRiskModule.sol +18 -80
- package/contracts/SignedQuoteRiskModule.sol +13 -44
- package/contracts/TieredSignedQuoteRiskModule.sol +7 -13
- package/contracts/TimeScaled.sol +8 -39
- package/contracts/TrustfulRiskModule.sol +47 -42
- package/contracts/interfaces/IAccessManager.sol +2 -11
- package/contracts/interfaces/IEToken.sol +1 -5
- package/contracts/interfaces/ILPWhitelist.sol +2 -10
- package/contracts/interfaces/IPolicyHolder.sol +2 -11
- package/contracts/interfaces/IPolicyPool.sol +59 -3
- package/contracts/interfaces/IPremiumsAccount.sol +17 -5
- package/contracts/migration/LPManualWhitelistV20.sol +3 -15
- package/contracts/migration/LPManualWhitelistV20Upgraded.sol +1 -5
- package/contracts/mocks/FixedRateVault.sol +1 -6
- package/contracts/mocks/InterfaceIdCalculator.sol +2 -0
- package/contracts/mocks/PolicyHolderMock.sol +3 -13
- package/contracts/mocks/PolicyPoolComponentMock.sol +1 -3
- package/contracts/mocks/PolicyPoolMock.sol +25 -25
- package/contracts/mocks/RiskModuleMock.sol +39 -16
- package/contracts/mocks/TestNFT.sol +1 -1
- package/js/deploy.js +44 -39
- package/js/test-utils.js +30 -19
- package/js/utils.js +62 -29
- package/package.json +1 -1
- package/scripts/utils.sh +23 -12
- package/build/contracts/AccessManager.sol/AccessManager.json +0 -618
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +0 -238
- package/build/contracts/EToken.sol/EToken.json +0 -1277
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +0 -647
- package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +0 -222
- package/build/contracts/Policy.sol/Policy.json +0 -10
- package/build/contracts/PolicyPool.sol/PolicyPool.json +0 -1416
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +0 -332
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +0 -970
- package/build/contracts/Reserve.sol/Reserve.json +0 -403
- package/build/contracts/RiskModule.sol/RiskModule.json +0 -559
- package/build/contracts/SignedBucketRiskModule.sol/SignedBucketRiskModule.json +0 -1262
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +0 -1110
- package/build/contracts/TieredSignedQuoteRiskModule.sol/TieredSignedQuoteRiskModule.json +0 -1316
- package/build/contracts/TimeScaled.sol/TimeScaled.json +0 -10
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +0 -984
- package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +0 -64
- package/build/contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json +0 -233
- package/build/contracts/dependencies/WadRayMath.sol/WadRayMath.json +0 -10
- package/build/contracts/interfaces/IAccessManager.sol/IAccessManager.json +0 -343
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +0 -128
- package/build/contracts/interfaces/IEToken.sol/IEToken.json +0 -460
- package/build/contracts/interfaces/ILPWhitelist.sol/ILPWhitelist.json +0 -103
- package/build/contracts/interfaces/IPolicyHolder.sol/IPolicyHolder.json +0 -108
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +0 -501
- package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +0 -43
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +0 -315
- package/build/contracts/interfaces/IRiskModule.sol/IRiskModule.json +0 -165
- package/build/contracts/migration/LPManualWhitelistV20.sol/LPManualWhitelistV20.json +0 -481
- package/build/contracts/migration/LPManualWhitelistV20Upgraded.sol/LPManualWhitelistV20Upgraded.json +0 -492
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +0 -736
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +0 -43
- package/build/contracts/mocks/IMintableERC20.sol/IMintableERC20.json +0 -47
- package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +0 -180
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +0 -319
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +0 -54
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +0 -721
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +0 -92
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +0 -783
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +0 -343
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +0 -388
- package/contracts/dependencies/ERC1967Proxy.sol +0 -19
- package/contracts/dependencies/IERC20Metadata.sol +0 -19
package/contracts/PolicyPool.sol
CHANGED
|
@@ -125,25 +125,6 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
125
125
|
*/
|
|
126
126
|
string internal _nftBaseURI;
|
|
127
127
|
|
|
128
|
-
/**
|
|
129
|
-
* @dev Event emitted every time a new policy is added to the pool. Contains all the data about the policy that is
|
|
130
|
-
* later required for doing operations with the policy like resolution or expiration.
|
|
131
|
-
*
|
|
132
|
-
* @param riskModule The risk module that created the policy
|
|
133
|
-
* @param policy The {Policy-PolicyData} struct with all the immutable fields of the policy.
|
|
134
|
-
*/
|
|
135
|
-
event NewPolicy(IRiskModule indexed riskModule, Policy.PolicyData policy);
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @dev Event emitted every time a policy is removed from the pool. If the policy expired, the `payout` is 0,
|
|
139
|
-
* otherwise is the amount transferred to the policyholder.
|
|
140
|
-
*
|
|
141
|
-
* @param riskModule The risk module where that created the policy initially.
|
|
142
|
-
* @param policyId The unique id of the policy
|
|
143
|
-
* @param payout The payout that has been paid to the policy holder. 0 when the policy expired.
|
|
144
|
-
*/
|
|
145
|
-
event PolicyResolved(IRiskModule indexed riskModule, uint256 indexed policyId, uint256 payout);
|
|
146
|
-
|
|
147
128
|
/**
|
|
148
129
|
* @dev Event emitted when the treasury changes
|
|
149
130
|
*
|
|
@@ -159,11 +140,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
159
140
|
* @param kind Value indicating the kind of component. See {ComponentKind}
|
|
160
141
|
* @param newStatus The status of the component after the operation. See {ComponentStatus}
|
|
161
142
|
*/
|
|
162
|
-
event ComponentStatusChanged(
|
|
163
|
-
IPolicyPoolComponent indexed component,
|
|
164
|
-
ComponentKind kind,
|
|
165
|
-
ComponentStatus newStatus
|
|
166
|
-
);
|
|
143
|
+
event ComponentStatusChanged(IPolicyPoolComponent indexed component, ComponentKind kind, ComponentStatus newStatus);
|
|
167
144
|
|
|
168
145
|
/**
|
|
169
146
|
* @dev Modifier that checks the caller has a given role
|
|
@@ -204,11 +181,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
204
181
|
* @param symbol_ The symbol of the ERC721 token.
|
|
205
182
|
* @param treasury_ The address of the treasury that will receive the protocol fees.
|
|
206
183
|
*/
|
|
207
|
-
function initialize(
|
|
208
|
-
string memory name_,
|
|
209
|
-
string memory symbol_,
|
|
210
|
-
address treasury_
|
|
211
|
-
) public initializer {
|
|
184
|
+
function initialize(string memory name_, string memory symbol_, address treasury_) public initializer {
|
|
212
185
|
require(bytes(name_).length > 0, "PolicyPool: name cannot be empty");
|
|
213
186
|
require(bytes(symbol_).length > 0, "PolicyPool: symbol cannot be empty");
|
|
214
187
|
__UUPSUpgradeable_init();
|
|
@@ -229,12 +202,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
229
202
|
_setTreasury(treasury_);
|
|
230
203
|
}
|
|
231
204
|
|
|
232
|
-
function _authorizeUpgrade(address newImpl)
|
|
233
|
-
internal
|
|
234
|
-
view
|
|
235
|
-
override
|
|
236
|
-
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
237
|
-
{
|
|
205
|
+
function _authorizeUpgrade(address newImpl) internal view override onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {
|
|
238
206
|
IPolicyPool newPool = IPolicyPool(newImpl);
|
|
239
207
|
require(newPool.access() == _access, "Can't upgrade changing the access manager");
|
|
240
208
|
require(newPool.currency() == _currency, "Can't upgrade changing the currency");
|
|
@@ -310,20 +278,15 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
310
278
|
* to this specific {PolicyPool} and matching the `kind` specified in the next paramter.
|
|
311
279
|
* @param kind The type of component to be added.
|
|
312
280
|
*/
|
|
313
|
-
function addComponent(IPolicyPoolComponent component, ComponentKind kind)
|
|
314
|
-
external
|
|
315
|
-
onlyRole(LEVEL1_ROLE)
|
|
316
|
-
{
|
|
281
|
+
function addComponent(IPolicyPoolComponent component, ComponentKind kind) external onlyRole(LEVEL1_ROLE) {
|
|
317
282
|
Component storage comp = _components[component];
|
|
318
283
|
require(comp.status == ComponentStatus.inactive, "Component already in the pool");
|
|
319
284
|
require(component.policyPool() == this, "Component not linked to this pool");
|
|
320
285
|
|
|
321
286
|
require(
|
|
322
287
|
(kind == ComponentKind.eToken && component.supportsInterface(type(IEToken).interfaceId)) ||
|
|
323
|
-
(kind == ComponentKind.premiumsAccount &&
|
|
324
|
-
|
|
325
|
-
(kind == ComponentKind.riskModule &&
|
|
326
|
-
component.supportsInterface(type(IRiskModule).interfaceId)),
|
|
288
|
+
(kind == ComponentKind.premiumsAccount && component.supportsInterface(type(IPremiumsAccount).interfaceId)) ||
|
|
289
|
+
(kind == ComponentKind.riskModule && component.supportsInterface(type(IRiskModule).interfaceId)),
|
|
327
290
|
"PolicyPool: Not the right kind"
|
|
328
291
|
);
|
|
329
292
|
|
|
@@ -360,15 +323,9 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
360
323
|
Component storage comp = _components[component];
|
|
361
324
|
require(comp.status == ComponentStatus.deprecated, "Component not deprecated");
|
|
362
325
|
if (comp.kind == ComponentKind.eToken) {
|
|
363
|
-
require(
|
|
364
|
-
IEToken(address(component)).totalSupply() == 0,
|
|
365
|
-
"EToken has liquidity, can't be removed"
|
|
366
|
-
);
|
|
326
|
+
require(IEToken(address(component)).totalSupply() == 0, "EToken has liquidity, can't be removed");
|
|
367
327
|
} else if (comp.kind == ComponentKind.riskModule) {
|
|
368
|
-
require(
|
|
369
|
-
IRiskModule(address(component)).activeExposure() == 0,
|
|
370
|
-
"Can't remove a module with active policies"
|
|
371
|
-
);
|
|
328
|
+
require(IRiskModule(address(component)).activeExposure() == 0, "Can't remove a module with active policies");
|
|
372
329
|
} else if (comp.kind == ComponentKind.premiumsAccount) {
|
|
373
330
|
IPremiumsAccount pa = IPremiumsAccount(address(component));
|
|
374
331
|
require(pa.purePremiums() == 0, "Can't remove a PremiumsAccount with premiums");
|
|
@@ -398,10 +355,10 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
398
355
|
* @param component The address of component contract. Must be a component added before.
|
|
399
356
|
* @param newStatus The new status, must be either `active`, `deprecated` or `suspended`.
|
|
400
357
|
*/
|
|
401
|
-
function changeComponentStatus(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
{
|
|
358
|
+
function changeComponentStatus(
|
|
359
|
+
IPolicyPoolComponent component,
|
|
360
|
+
ComponentStatus newStatus
|
|
361
|
+
) external onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {
|
|
405
362
|
Component storage comp = _components[component];
|
|
406
363
|
require(comp.status != ComponentStatus.inactive, "Component not found");
|
|
407
364
|
require(
|
|
@@ -420,52 +377,38 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
420
377
|
* @param component The address of the component
|
|
421
378
|
* @return The status of the component. See {ComponentStatus}
|
|
422
379
|
*/
|
|
423
|
-
function getComponentStatus(IPolicyPoolComponent component)
|
|
424
|
-
external
|
|
425
|
-
view
|
|
426
|
-
returns (ComponentStatus)
|
|
427
|
-
{
|
|
380
|
+
function getComponentStatus(IPolicyPoolComponent component) external view returns (ComponentStatus) {
|
|
428
381
|
return _components[component].status;
|
|
429
382
|
}
|
|
430
383
|
|
|
431
|
-
function
|
|
432
|
-
Component storage comp = _components[IPolicyPoolComponent(
|
|
433
|
-
require(comp.kind ==
|
|
384
|
+
function _componentStatus(address component, ComponentKind kind) internal view returns (ComponentStatus) {
|
|
385
|
+
Component storage comp = _components[IPolicyPoolComponent(component)];
|
|
386
|
+
require(comp.kind == kind, "Component is not of the right kind");
|
|
434
387
|
return comp.status;
|
|
435
388
|
}
|
|
436
389
|
|
|
437
|
-
function
|
|
438
|
-
Component
|
|
439
|
-
require(comp.kind == ComponentKind.riskModule, "Component is not a RiskModule");
|
|
440
|
-
return comp.status;
|
|
390
|
+
function _requireCompActive(address component, ComponentKind kind) internal view {
|
|
391
|
+
require(_componentStatus(component, kind) == ComponentStatus.active, "Component not found or not active");
|
|
441
392
|
}
|
|
442
393
|
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
require(
|
|
446
|
-
|
|
394
|
+
function _requireCompActiveOrDeprecated(address component, ComponentKind kind) internal view {
|
|
395
|
+
ComponentStatus status = _componentStatus(component, kind);
|
|
396
|
+
require(
|
|
397
|
+
status == ComponentStatus.active || status == ComponentStatus.deprecated,
|
|
398
|
+
"Component must be active or deprecated"
|
|
399
|
+
);
|
|
447
400
|
}
|
|
448
401
|
|
|
449
402
|
function deposit(IEToken eToken, uint256 amount) external override whenNotPaused {
|
|
450
|
-
|
|
403
|
+
_requireCompActive(address(eToken), ComponentKind.eToken);
|
|
451
404
|
uint256 balanceBefore = _currency.balanceOf(address(eToken));
|
|
452
405
|
_currency.safeTransferFrom(_msgSender(), address(eToken), amount);
|
|
453
406
|
eToken.deposit(_msgSender(), _currency.balanceOf(address(eToken)) - balanceBefore);
|
|
454
407
|
}
|
|
455
408
|
|
|
456
|
-
function withdraw(IEToken eToken, uint256 amount)
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
whenNotPaused
|
|
460
|
-
returns (uint256)
|
|
461
|
-
{
|
|
462
|
-
ComponentStatus etkStatus = _etkStatus(eToken);
|
|
463
|
-
require(
|
|
464
|
-
etkStatus == ComponentStatus.active || etkStatus == ComponentStatus.deprecated,
|
|
465
|
-
"eToken not found or withdraws not allowed"
|
|
466
|
-
);
|
|
467
|
-
address provider = _msgSender();
|
|
468
|
-
return eToken.withdraw(provider, amount);
|
|
409
|
+
function withdraw(IEToken eToken, uint256 amount) external override whenNotPaused returns (uint256) {
|
|
410
|
+
_requireCompActiveOrDeprecated(address(eToken), ComponentKind.eToken);
|
|
411
|
+
return eToken.withdraw(_msgSender(), amount);
|
|
469
412
|
}
|
|
470
413
|
|
|
471
414
|
function newPolicy(
|
|
@@ -477,14 +420,15 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
477
420
|
// Checks
|
|
478
421
|
IRiskModule rm = policy.riskModule;
|
|
479
422
|
require(address(rm) == _msgSender(), "Only the RM can create new policies");
|
|
480
|
-
|
|
423
|
+
_requireCompActive(address(rm), ComponentKind.riskModule);
|
|
481
424
|
IPremiumsAccount pa = rm.premiumsAccount();
|
|
482
|
-
|
|
425
|
+
_requireCompActive(address(pa), ComponentKind.premiumsAccount);
|
|
483
426
|
|
|
484
427
|
// Effects
|
|
485
|
-
policy.id = (
|
|
428
|
+
policy.id = makePolicyId(rm, internalId);
|
|
486
429
|
require(_policies[policy.id] == bytes32(0), "Policy already exists");
|
|
487
430
|
_policies[policy.id] = policy.hash();
|
|
431
|
+
_safeMint(policyHolder, policy.id, "");
|
|
488
432
|
|
|
489
433
|
// Interactions
|
|
490
434
|
pa.policyCreated(policy);
|
|
@@ -501,16 +445,81 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
501
445
|
* transfers. This might be considered in the future, but to avoid increasing the complexity and since so far we
|
|
502
446
|
* operate on low gas-cost blockchains, we keep it as it is.
|
|
503
447
|
*/
|
|
504
|
-
_safeMint(policyHolder, policy.id, "");
|
|
505
448
|
|
|
506
449
|
emit NewPolicy(rm, policy);
|
|
507
450
|
return policy.id;
|
|
508
451
|
}
|
|
509
452
|
|
|
453
|
+
function replacePolicy(
|
|
454
|
+
Policy.PolicyData memory oldPolicy,
|
|
455
|
+
Policy.PolicyData memory newPolicy_,
|
|
456
|
+
address payer,
|
|
457
|
+
uint96 internalId
|
|
458
|
+
) external override whenNotPaused returns (uint256) {
|
|
459
|
+
// Checks
|
|
460
|
+
_validatePolicy(oldPolicy);
|
|
461
|
+
IRiskModule rm = oldPolicy.riskModule;
|
|
462
|
+
require(address(rm) == _msgSender(), "Only the RM can create new policies");
|
|
463
|
+
_requireCompActive(address(rm), ComponentKind.riskModule);
|
|
464
|
+
IPremiumsAccount pa = rm.premiumsAccount();
|
|
465
|
+
_requireCompActive(address(pa), ComponentKind.premiumsAccount);
|
|
466
|
+
require(oldPolicy.expiration > uint40(block.timestamp), "Old policy is expired");
|
|
467
|
+
require(oldPolicy.start == newPolicy_.start, "Both policies must have the same starting date");
|
|
468
|
+
require(
|
|
469
|
+
oldPolicy.payout <= newPolicy_.payout &&
|
|
470
|
+
oldPolicy.purePremium <= newPolicy_.purePremium &&
|
|
471
|
+
oldPolicy.ensuroCommission <= newPolicy_.ensuroCommission &&
|
|
472
|
+
oldPolicy.jrCoc <= newPolicy_.jrCoc &&
|
|
473
|
+
oldPolicy.srCoc <= newPolicy_.srCoc &&
|
|
474
|
+
oldPolicy.jrScr <= newPolicy_.jrScr &&
|
|
475
|
+
oldPolicy.srScr <= newPolicy_.srScr &&
|
|
476
|
+
oldPolicy.partnerCommission <= newPolicy_.partnerCommission &&
|
|
477
|
+
oldPolicy.expiration <= newPolicy_.expiration &&
|
|
478
|
+
rm == newPolicy_.riskModule,
|
|
479
|
+
"New policy must be greater or equal than old policy"
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
// Effects
|
|
483
|
+
newPolicy_.id = makePolicyId(rm, internalId);
|
|
484
|
+
require(_policies[newPolicy_.id] == bytes32(0), "Policy already exists");
|
|
485
|
+
_policies[newPolicy_.id] = newPolicy_.hash();
|
|
486
|
+
address policyHolder = ownerOf(oldPolicy.id);
|
|
487
|
+
_safeMint(policyHolder, newPolicy_.id, "");
|
|
488
|
+
delete _policies[oldPolicy.id];
|
|
489
|
+
|
|
490
|
+
// Interactions
|
|
491
|
+
pa.policyReplaced(oldPolicy, newPolicy_);
|
|
492
|
+
|
|
493
|
+
// Distribute the premium
|
|
494
|
+
uint256 aux = newPolicy_.purePremium - oldPolicy.purePremium;
|
|
495
|
+
if (aux > 0) _currency.safeTransferFrom(payer, address(pa), aux);
|
|
496
|
+
aux = newPolicy_.srCoc - oldPolicy.srCoc;
|
|
497
|
+
if (aux > 0) _currency.safeTransferFrom(payer, address(pa.seniorEtk()), aux);
|
|
498
|
+
aux = newPolicy_.jrCoc - oldPolicy.jrCoc;
|
|
499
|
+
if (aux > 0) _currency.safeTransferFrom(payer, address(pa.juniorEtk()), aux);
|
|
500
|
+
aux = newPolicy_.ensuroCommission - oldPolicy.ensuroCommission;
|
|
501
|
+
if (aux > 0) _currency.safeTransferFrom(payer, _treasury, aux);
|
|
502
|
+
aux = newPolicy_.partnerCommission - oldPolicy.partnerCommission;
|
|
503
|
+
if (aux > 0 && payer != rm.wallet()) _currency.safeTransferFrom(payer, rm.wallet(), aux);
|
|
504
|
+
/**
|
|
505
|
+
* This code does up to 5 ERC20 transfers. This can be avoided to reduce the gas cost, by implementing delayed
|
|
506
|
+
* transfers. This might be considered in the future, but to avoid increasing the complexity and since so far we
|
|
507
|
+
* operate on low gas-cost blockchains, we keep it as it is.
|
|
508
|
+
*/
|
|
509
|
+
|
|
510
|
+
emit NewPolicy(rm, newPolicy_);
|
|
511
|
+
emit PolicyReplaced(rm, oldPolicy.id, newPolicy_.id);
|
|
512
|
+
return newPolicy_.id;
|
|
513
|
+
}
|
|
514
|
+
|
|
510
515
|
function _validatePolicy(Policy.PolicyData memory policy) internal view {
|
|
511
516
|
require(policy.id != 0 && policy.hash() == _policies[policy.id], "Policy not found");
|
|
512
517
|
}
|
|
513
518
|
|
|
519
|
+
function makePolicyId(IRiskModule rm, uint96 internalId) public pure returns (uint256) {
|
|
520
|
+
return (uint256(uint160(address(rm))) << 96) + internalId;
|
|
521
|
+
}
|
|
522
|
+
|
|
514
523
|
function expirePolicy(Policy.PolicyData calldata policy) external override whenNotPaused {
|
|
515
524
|
require(policy.expiration <= block.timestamp, "Policy not expired yet");
|
|
516
525
|
return _resolvePolicy(policy, 0, true);
|
|
@@ -523,19 +532,14 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
523
532
|
}
|
|
524
533
|
}
|
|
525
534
|
|
|
526
|
-
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
|
|
527
|
-
external
|
|
528
|
-
override
|
|
529
|
-
whenNotPaused
|
|
530
|
-
{
|
|
535
|
+
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout) external override whenNotPaused {
|
|
531
536
|
return _resolvePolicy(policy, payout, false);
|
|
532
537
|
}
|
|
533
538
|
|
|
534
|
-
function resolvePolicyFullPayout(
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
{
|
|
539
|
+
function resolvePolicyFullPayout(
|
|
540
|
+
Policy.PolicyData calldata policy,
|
|
541
|
+
bool customerWon
|
|
542
|
+
) external override whenNotPaused {
|
|
539
543
|
return _resolvePolicy(policy, customerWon ? policy.payout : 0, false);
|
|
540
544
|
}
|
|
541
545
|
|
|
@@ -558,31 +562,20 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
558
562
|
* @param payout The amount to paid to the policyholder
|
|
559
563
|
* @param expired True for expiration resolution (`payout` must be 0)
|
|
560
564
|
*/
|
|
561
|
-
function _resolvePolicy(
|
|
562
|
-
Policy.PolicyData memory policy,
|
|
563
|
-
uint256 payout,
|
|
564
|
-
bool expired
|
|
565
|
-
) internal {
|
|
565
|
+
function _resolvePolicy(Policy.PolicyData memory policy, uint256 payout, bool expired) internal {
|
|
566
566
|
// Checks
|
|
567
567
|
_validatePolicy(policy);
|
|
568
568
|
IRiskModule rm = policy.riskModule;
|
|
569
569
|
require(expired || address(rm) == _msgSender(), "Only the RM can resolve policies");
|
|
570
570
|
require(payout == 0 || policy.expiration > block.timestamp, "Can't pay expired policy");
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
compStatus == ComponentStatus.active || compStatus == ComponentStatus.deprecated,
|
|
574
|
-
"Module must be active or deprecated to process resolutions"
|
|
575
|
-
);
|
|
571
|
+
_requireCompActiveOrDeprecated(address(rm), ComponentKind.riskModule);
|
|
572
|
+
|
|
576
573
|
require(payout <= policy.payout, "payout > policy.payout");
|
|
577
574
|
|
|
578
575
|
bool customerWon = payout > 0;
|
|
579
576
|
|
|
580
577
|
IPremiumsAccount pa = rm.premiumsAccount();
|
|
581
|
-
|
|
582
|
-
require(
|
|
583
|
-
compStatus == ComponentStatus.active || compStatus == ComponentStatus.deprecated,
|
|
584
|
-
"PremiumsAccount must be active or deprecated to process resolutions"
|
|
585
|
-
);
|
|
578
|
+
_requireCompActiveOrDeprecated(address(pa), ComponentKind.premiumsAccount);
|
|
586
579
|
// Effects
|
|
587
580
|
delete _policies[policy.id];
|
|
588
581
|
// Interactions
|
|
@@ -612,16 +605,8 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
612
605
|
if (!AddressUpgradeable.isContract(customer)) return;
|
|
613
606
|
if (!ERC165Checker.supportsInterface(customer, type(IPolicyHolder).interfaceId)) return;
|
|
614
607
|
|
|
615
|
-
bytes4 retval = IPolicyHolder(customer).onPayoutReceived(
|
|
616
|
-
|
|
617
|
-
address(this),
|
|
618
|
-
policyId,
|
|
619
|
-
payout
|
|
620
|
-
);
|
|
621
|
-
require(
|
|
622
|
-
retval == IPolicyHolder.onPayoutReceived.selector,
|
|
623
|
-
"PolicyPool: Invalid return value from IPolicyHolder"
|
|
624
|
-
);
|
|
608
|
+
bytes4 retval = IPolicyHolder(customer).onPayoutReceived(_msgSender(), address(this), policyId, payout);
|
|
609
|
+
require(retval == IPolicyHolder.onPayoutReceived.selector, "PolicyPool: Invalid return value from IPolicyHolder");
|
|
625
610
|
}
|
|
626
611
|
|
|
627
612
|
/**
|
|
@@ -632,9 +617,7 @@ contract PolicyPool is IPolicyPool, PausableUpgradeable, UUPSUpgradeable, ERC721
|
|
|
632
617
|
if (!AddressUpgradeable.isContract(customer)) return;
|
|
633
618
|
if (!ERC165Checker.supportsInterface(customer, type(IPolicyHolder).interfaceId)) return;
|
|
634
619
|
|
|
635
|
-
try IPolicyHolder(customer).onPolicyExpired(_msgSender(), address(this), policyId) returns (
|
|
636
|
-
bytes4
|
|
637
|
-
) {
|
|
620
|
+
try IPolicyHolder(customer).onPolicyExpired(_msgSender(), address(this), policyId) returns (bytes4) {
|
|
638
621
|
return;
|
|
639
622
|
} catch {
|
|
640
623
|
return;
|
|
@@ -24,11 +24,7 @@ import {WadRayMath} from "./dependencies/WadRayMath.sol";
|
|
|
24
24
|
* @custom:security-contact security@ensuro.co
|
|
25
25
|
* @author Ensuro
|
|
26
26
|
*/
|
|
27
|
-
abstract contract PolicyPoolComponent is
|
|
28
|
-
UUPSUpgradeable,
|
|
29
|
-
PausableUpgradeable,
|
|
30
|
-
IPolicyPoolComponent
|
|
31
|
-
{
|
|
27
|
+
abstract contract PolicyPoolComponent is UUPSUpgradeable, PausableUpgradeable, IPolicyPoolComponent {
|
|
32
28
|
using WadRayMath for uint256;
|
|
33
29
|
|
|
34
30
|
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
|
|
@@ -80,10 +76,7 @@ abstract contract PolicyPoolComponent is
|
|
|
80
76
|
|
|
81
77
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
82
78
|
constructor(IPolicyPool policyPool_) {
|
|
83
|
-
require(
|
|
84
|
-
address(policyPool_) != address(0),
|
|
85
|
-
"PolicyPoolComponent: policyPool cannot be zero address"
|
|
86
|
-
);
|
|
79
|
+
require(address(policyPool_) != address(0), "PolicyPoolComponent: policyPool cannot be zero address");
|
|
87
80
|
_disableInitializers();
|
|
88
81
|
_policyPool = policyPool_;
|
|
89
82
|
}
|
|
@@ -94,29 +87,21 @@ abstract contract PolicyPoolComponent is
|
|
|
94
87
|
__Pausable_init();
|
|
95
88
|
}
|
|
96
89
|
|
|
97
|
-
function _authorizeUpgrade(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
override
|
|
101
|
-
onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
102
|
-
{
|
|
90
|
+
function _authorizeUpgrade(
|
|
91
|
+
address newImpl
|
|
92
|
+
) internal view override onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {
|
|
103
93
|
_upgradeValidations(newImpl);
|
|
104
94
|
}
|
|
105
95
|
|
|
106
96
|
function _upgradeValidations(address newImpl) internal view virtual {
|
|
107
|
-
require(
|
|
108
|
-
IPolicyPoolComponent(newImpl).policyPool() == _policyPool,
|
|
109
|
-
"Can't upgrade changing the PolicyPool!"
|
|
110
|
-
);
|
|
97
|
+
require(IPolicyPoolComponent(newImpl).policyPool() == _policyPool, "Can't upgrade changing the PolicyPool!");
|
|
111
98
|
}
|
|
112
99
|
|
|
113
100
|
/**
|
|
114
101
|
* @dev See {IERC165-supportsInterface}.
|
|
115
102
|
*/
|
|
116
103
|
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
|
117
|
-
return
|
|
118
|
-
interfaceId == type(IERC165).interfaceId ||
|
|
119
|
-
interfaceId == type(IPolicyPoolComponent).interfaceId;
|
|
104
|
+
return interfaceId == type(IERC165).interfaceId || interfaceId == type(IPolicyPoolComponent).interfaceId;
|
|
120
105
|
}
|
|
121
106
|
|
|
122
107
|
function pause() public onlyGlobalOrComponentRole(GUARDIAN_ROLE) {
|
|
@@ -139,11 +124,7 @@ abstract contract PolicyPoolComponent is
|
|
|
139
124
|
return _policyPool.access().hasComponentRole(address(this), role, _msgSender(), true);
|
|
140
125
|
}
|
|
141
126
|
|
|
142
|
-
function _isTweakWad(
|
|
143
|
-
uint256 oldValue,
|
|
144
|
-
uint256 newValue,
|
|
145
|
-
uint256 maxTweak
|
|
146
|
-
) internal pure returns (bool) {
|
|
127
|
+
function _isTweakWad(uint256 oldValue, uint256 newValue, uint256 maxTweak) internal pure returns (bool) {
|
|
147
128
|
if (oldValue == newValue) return true;
|
|
148
129
|
if (oldValue == 0) return maxTweak >= WadRayMath.WAD;
|
|
149
130
|
if (newValue == 0) return false;
|
|
@@ -157,11 +138,7 @@ abstract contract PolicyPoolComponent is
|
|
|
157
138
|
// solhint-disable-next-line no-empty-blocks
|
|
158
139
|
function _validateParameters() internal view virtual {} // Must be reimplemented with specific validations
|
|
159
140
|
|
|
160
|
-
function _parameterChanged(
|
|
161
|
-
IAccessManager.GovernanceActions action,
|
|
162
|
-
uint256 value,
|
|
163
|
-
bool tweak
|
|
164
|
-
) internal {
|
|
141
|
+
function _parameterChanged(IAccessManager.GovernanceActions action, uint256 value, bool tweak) internal {
|
|
165
142
|
_validateParameters();
|
|
166
143
|
if (tweak) _registerTweak(action);
|
|
167
144
|
emit GovernanceAction(action, value);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
|
5
|
+
import {SignedMath} from "@openzeppelin/contracts/utils/math/SignedMath.sol";
|
|
5
6
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
6
7
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
7
8
|
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
|
|
@@ -113,11 +114,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
113
114
|
* @param seniorEtk_ Address of the Senior EToken (2nd loss lender). `address(0)` if not present.
|
|
114
115
|
*/
|
|
115
116
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
116
|
-
constructor(
|
|
117
|
-
IPolicyPool policyPool_,
|
|
118
|
-
IEToken juniorEtk_,
|
|
119
|
-
IEToken seniorEtk_
|
|
120
|
-
) Reserve(policyPool_) {
|
|
117
|
+
constructor(IPolicyPool policyPool_, IEToken juniorEtk_, IEToken seniorEtk_) Reserve(policyPool_) {
|
|
121
118
|
_juniorEtk = juniorEtk_;
|
|
122
119
|
_seniorEtk = seniorEtk_;
|
|
123
120
|
}
|
|
@@ -169,8 +166,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
169
166
|
* @dev See {IERC165-supportsInterface}.
|
|
170
167
|
*/
|
|
171
168
|
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
|
172
|
-
return
|
|
173
|
-
super.supportsInterface(interfaceId) || interfaceId == type(IPremiumsAccount).interfaceId;
|
|
169
|
+
return super.supportsInterface(interfaceId) || interfaceId == type(IPremiumsAccount).interfaceId;
|
|
174
170
|
}
|
|
175
171
|
|
|
176
172
|
function assetManager() public view override returns (IAssetManager) {
|
|
@@ -274,12 +270,12 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
274
270
|
|
|
275
271
|
function _toAmount(uint32 value) internal view returns (uint256) {
|
|
276
272
|
// 0 decimals to amount decimals
|
|
277
|
-
return uint256(value) * 10**currency().decimals();
|
|
273
|
+
return uint256(value) * 10 ** currency().decimals();
|
|
278
274
|
}
|
|
279
275
|
|
|
280
276
|
function _toZeroDecimals(uint256 amount) internal view returns (uint32) {
|
|
281
277
|
// Removes the decimals from the amount
|
|
282
|
-
return (amount / 10**currency().decimals()).toUint32();
|
|
278
|
+
return (amount / 10 ** currency().decimals()).toUint32();
|
|
283
279
|
}
|
|
284
280
|
|
|
285
281
|
/**
|
|
@@ -316,15 +312,9 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
316
312
|
* `_maxDeficit()` and borrows the difference from the eTokens.
|
|
317
313
|
* If false and the new ratio leaves `_surplus < -_maxDeficit()`, the operation is reverted.
|
|
318
314
|
*/
|
|
319
|
-
function setDeficitRatio(uint256 newRatio, bool adjustment)
|
|
320
|
-
external
|
|
321
|
-
onlyGlobalOrComponentRole(LEVEL2_ROLE)
|
|
322
|
-
{
|
|
315
|
+
function setDeficitRatio(uint256 newRatio, bool adjustment) external onlyGlobalOrComponentRole(LEVEL2_ROLE) {
|
|
323
316
|
uint16 truncatedRatio = (newRatio / FOUR_DECIMAL_TO_WAD).toUint16();
|
|
324
|
-
require(
|
|
325
|
-
uint256(truncatedRatio) * FOUR_DECIMAL_TO_WAD == newRatio,
|
|
326
|
-
"Validation: only up to 4 decimals allowed"
|
|
327
|
-
);
|
|
317
|
+
require(uint256(truncatedRatio) * FOUR_DECIMAL_TO_WAD == newRatio, "Validation: only up to 4 decimals allowed");
|
|
328
318
|
|
|
329
319
|
int256 maxDeficit = _maxDeficit(newRatio);
|
|
330
320
|
require(adjustment || _surplus >= maxDeficit, "Validation: surplus must be >= maxDeficit");
|
|
@@ -356,10 +346,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
356
346
|
* @param newLimitSr The new limit to be set for the loans taken from the Senior eToken.
|
|
357
347
|
If newLimitSr == MAX_UINT, it's ignored. If == 0, means the loans are unbounded.
|
|
358
348
|
*/
|
|
359
|
-
function setLoanLimits(uint256 newLimitJr, uint256 newLimitSr)
|
|
360
|
-
external
|
|
361
|
-
onlyGlobalOrComponentRole(LEVEL2_ROLE)
|
|
362
|
-
{
|
|
349
|
+
function setLoanLimits(uint256 newLimitJr, uint256 newLimitSr) external onlyGlobalOrComponentRole(LEVEL2_ROLE) {
|
|
363
350
|
if (newLimitJr != type(uint256).max) {
|
|
364
351
|
_params.jrLoanLimit = _toZeroDecimals(newLimitJr);
|
|
365
352
|
require(_toAmount(_params.jrLoanLimit) == newLimitJr, "Validation: no decimals allowed");
|
|
@@ -381,11 +368,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
381
368
|
* in the context of a policy payout.
|
|
382
369
|
* @param jrEtk If true it indicates that the loan is asked first from the junior eToken.
|
|
383
370
|
*/
|
|
384
|
-
function _borrowFromEtk(
|
|
385
|
-
uint256 borrow,
|
|
386
|
-
address receiver,
|
|
387
|
-
bool jrEtk
|
|
388
|
-
) internal {
|
|
371
|
+
function _borrowFromEtk(uint256 borrow, address receiver, bool jrEtk) internal {
|
|
389
372
|
uint256 left = borrow;
|
|
390
373
|
if (jrEtk) {
|
|
391
374
|
if (_juniorEtk.getLoan(address(this)) + borrow <= jrLoanLimit()) {
|
|
@@ -471,11 +454,10 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
471
454
|
* @param destination The address that will receive the transferred funds.
|
|
472
455
|
* @return Returns the actual amount withdrawn.
|
|
473
456
|
*/
|
|
474
|
-
function withdrawWonPremiums(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
{
|
|
457
|
+
function withdrawWonPremiums(
|
|
458
|
+
uint256 amount,
|
|
459
|
+
address destination
|
|
460
|
+
) external onlyGlobalOrComponentRole(WITHDRAW_WON_PREMIUMS_ROLE) returns (uint256) {
|
|
479
461
|
require(destination != address(0), "PremiumsAccount: destination cannot be the zero address");
|
|
480
462
|
if (_surplus <= 0) {
|
|
481
463
|
amount = 0;
|
|
@@ -489,17 +471,36 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
489
471
|
return amount;
|
|
490
472
|
}
|
|
491
473
|
|
|
492
|
-
function policyCreated(Policy.PolicyData memory policy)
|
|
493
|
-
external
|
|
494
|
-
override
|
|
495
|
-
onlyPolicyPool
|
|
496
|
-
whenNotPaused
|
|
497
|
-
{
|
|
474
|
+
function policyCreated(Policy.PolicyData memory policy) external override onlyPolicyPool whenNotPaused {
|
|
498
475
|
_activePurePremiums += policy.purePremium;
|
|
499
476
|
if (policy.jrScr > 0) _juniorEtk.lockScr(policy.jrScr, policy.jrInterestRate());
|
|
500
477
|
if (policy.srScr > 0) _seniorEtk.lockScr(policy.srScr, policy.srInterestRate());
|
|
501
478
|
}
|
|
502
479
|
|
|
480
|
+
function policyReplaced(
|
|
481
|
+
Policy.PolicyData memory oldPolicy,
|
|
482
|
+
Policy.PolicyData memory newPolicy
|
|
483
|
+
) external override onlyPolicyPool whenNotPaused {
|
|
484
|
+
if (oldPolicy.srScr > 0 && newPolicy.srScr > 0) {
|
|
485
|
+
int256 diff = int256(oldPolicy.srInterestRate()) - int256(newPolicy.srInterestRate());
|
|
486
|
+
require(SignedMath.abs(diff) < 1e14, "Interest rate can't change");
|
|
487
|
+
}
|
|
488
|
+
if (oldPolicy.jrScr > 0 && newPolicy.jrScr > 0) {
|
|
489
|
+
int256 diff = int256(oldPolicy.jrInterestRate()) - int256(newPolicy.jrInterestRate());
|
|
490
|
+
require(SignedMath.abs(diff) < 1e14, "Interest rate can't change");
|
|
491
|
+
}
|
|
492
|
+
/*
|
|
493
|
+
* Supporting interest rate change is possible, but it would require complex computations.
|
|
494
|
+
* If new IR > old IR, then we must adjust positivelly to accrue the interests not accrued
|
|
495
|
+
* If new IR < old IR, then we must adjust negativelly to substract the interests accrued in excess
|
|
496
|
+
*/
|
|
497
|
+
_activePurePremiums += newPolicy.purePremium - oldPolicy.purePremium;
|
|
498
|
+
if (oldPolicy.jrScr > 0) _juniorEtk.unlockScr(oldPolicy.jrScr, oldPolicy.jrInterestRate(), 0);
|
|
499
|
+
if (oldPolicy.srScr > 0) _seniorEtk.unlockScr(oldPolicy.srScr, oldPolicy.srInterestRate(), 0);
|
|
500
|
+
if (newPolicy.jrScr > 0) _juniorEtk.lockScr(newPolicy.jrScr, newPolicy.jrInterestRate());
|
|
501
|
+
if (newPolicy.srScr > 0) _seniorEtk.lockScr(newPolicy.srScr, newPolicy.srInterestRate());
|
|
502
|
+
}
|
|
503
|
+
|
|
503
504
|
function policyResolvedWithPayout(
|
|
504
505
|
address policyHolder,
|
|
505
506
|
Policy.PolicyData memory policy,
|
|
@@ -550,10 +551,8 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
550
551
|
returns (uint256 available)
|
|
551
552
|
{
|
|
552
553
|
available = fundsAvailable();
|
|
553
|
-
if (available != 0 && address(_seniorEtk) != address(0))
|
|
554
|
-
|
|
555
|
-
if (available != 0 && address(_juniorEtk) != address(0))
|
|
556
|
-
available = _repayLoan(available, _juniorEtk);
|
|
554
|
+
if (available != 0 && address(_seniorEtk) != address(0)) available = _repayLoan(available, _seniorEtk);
|
|
555
|
+
if (available != 0 && address(_juniorEtk) != address(0)) available = _repayLoan(available, _juniorEtk);
|
|
557
556
|
return available;
|
|
558
557
|
}
|
|
559
558
|
|
|
@@ -589,12 +588,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
|
589
588
|
return fundsAvailable_ - repayAmount;
|
|
590
589
|
}
|
|
591
590
|
|
|
592
|
-
function policyExpired(Policy.PolicyData memory policy)
|
|
593
|
-
external
|
|
594
|
-
override
|
|
595
|
-
onlyPolicyPool
|
|
596
|
-
whenNotPaused
|
|
597
|
-
{
|
|
591
|
+
function policyExpired(Policy.PolicyData memory policy) external override onlyPolicyPool whenNotPaused {
|
|
598
592
|
_activePurePremiums -= policy.purePremium;
|
|
599
593
|
_storePurePremiumWon(policy.purePremium);
|
|
600
594
|
_unlockScr(policy);
|