@ensuro/core 1.2.7 → 2.0.0-beta1
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 +44 -17
- package/build/contracts/EToken.sol/EToken.json +122 -177
- package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +101 -323
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +15 -2
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +16 -3
- package/build/contracts/PolicyPool.sol/PolicyPool.json +105 -351
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +13 -0
- package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +77 -72
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +761 -0
- package/build/contracts/{BaseAssetManager.sol/BaseAssetManager.json → Reserve.sol/Reserve.json} +15 -202
- package/build/contracts/RiskModule.sol/RiskModule.json +83 -310
- package/build/contracts/TimeScaled.sol/TimeScaled.json +24 -0
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +131 -333
- package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +15 -2
- package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +64 -0
- package/build/{interfaces/IExchange.sol/IExchange.json → contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json} +83 -79
- package/build/{interfaces → contracts/interfaces}/IEToken.sol/IEToken.json +32 -97
- package/build/{interfaces → contracts/interfaces}/ILPWhitelist.sol/ILPWhitelist.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyHolder.sol/IPolicyHolder.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyNFT.sol/IPolicyNFT.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyPool.sol/IPolicyPool.json +121 -108
- package/build/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyPoolConfig.sol/IPolicyPoolConfig.json +20 -36
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +302 -0
- package/build/{interfaces → contracts/interfaces}/IRiskModule.sol/IRiskModule.json +58 -34
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +43 -0
- package/build/{interfaces/IInsolvencyHook.sol/IInsolvencyHook.json → contracts/mocks/IMintableERC20.sol/IMintableERC20.json} +13 -8
- package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +370 -0
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +202 -0
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +35 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +603 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +92 -0
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +343 -0
- package/build/contracts/mocks/TestCurrencyUUPS.sol/TestCurrencyUUPS.json +353 -0
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +388 -0
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +16 -3
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +16 -3
- package/contracts/EToken.sol +188 -269
- package/contracts/FlightDelayRiskModule.sol +30 -21
- package/contracts/LPManualWhitelist.sol +3 -3
- package/contracts/Policy.sol +48 -44
- package/contracts/PolicyNFT.sol +2 -2
- package/contracts/PolicyPool.sol +114 -467
- package/contracts/PolicyPoolComponent.sol +8 -3
- package/contracts/PolicyPoolConfig.sol +30 -73
- package/contracts/PremiumsAccount.sol +274 -0
- package/contracts/Reserve.sol +34 -0
- package/contracts/RiskModule.sol +216 -164
- package/contracts/TimeScaled.sol +134 -0
- package/contracts/TrustfulRiskModule.sol +23 -21
- package/contracts/dependencies/ERC1967Proxy.sol +19 -0
- package/contracts/dependencies/IERC20Metadata.sol +19 -0
- package/contracts/interfaces/IEToken.sol +172 -0
- package/{interfaces → contracts/interfaces}/ILPWhitelist.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyHolder.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyNFT.sol +0 -0
- package/contracts/interfaces/IPolicyPool.sol +138 -0
- package/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol +0 -0
- package/{interfaces → contracts/interfaces}/IPolicyPoolConfig.sol +29 -20
- package/contracts/interfaces/IPremiumsAccount.sol +71 -0
- package/contracts/interfaces/IRiskModule.sol +60 -0
- package/contracts/mocks/ForwardProxy.sol +66 -0
- package/contracts/mocks/IMintableERC20.sol +13 -0
- package/contracts/mocks/LinkTokenMock.sol +30 -0
- package/contracts/mocks/PolicyHolderMock.sol +68 -0
- package/contracts/mocks/PolicyPoolComponentMock.sol +17 -0
- package/contracts/mocks/PolicyPoolMock.sol +122 -0
- package/contracts/mocks/TestCurrency.sol +35 -0
- package/contracts/mocks/TestNFT.sol +23 -0
- package/contracts/upgraded/PolicyNFTv1.sol +1 -1
- package/js/test-utils.js +278 -0
- package/package.json +2 -2
- package/build/contracts/AaveAssetManager.sol/AaveAssetManager.json +0 -742
- package/build/contracts/DataTypes.sol/DataTypes.json +0 -10
- package/build/contracts/Exchange.sol/Exchange.json +0 -591
- package/build/contracts/extras/IPriceRiskModule.sol/IPriceRiskModule.json +0 -253
- package/build/contracts/extras/PriceRiskModule.sol/PriceRiskModule.json +0 -1055
- package/build/interfaces/IAssetManager.sol/IAssetManager.json +0 -31
- package/build/interfaces/IExchange.sol/IPriceOracle.json +0 -30
- package/contracts/AaveAssetManager.sol +0 -298
- package/contracts/BaseAssetManager.sol +0 -301
- package/contracts/DataTypes.sol +0 -287
- package/contracts/Exchange.sol +0 -189
- package/contracts/extras/IPriceRiskModule.sol +0 -41
- package/contracts/extras/PriceRiskModule.sol +0 -243
- package/interfaces/IAssetManager.sol +0 -23
- package/interfaces/IEToken.sol +0 -48
- package/interfaces/IExchange.sol +0 -59
- package/interfaces/IInsolvencyHook.sol +0 -27
- package/interfaces/IPolicyPool.sol +0 -44
- package/interfaces/IRiskModule.sol +0 -29
|
@@ -3,9 +3,9 @@ pragma solidity ^0.8.0;
|
|
|
3
3
|
|
|
4
4
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
5
5
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
6
|
-
import {IPolicyPool} from "
|
|
7
|
-
import {IPolicyPoolComponent} from "
|
|
8
|
-
import {IPolicyPoolConfig} from "
|
|
6
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
7
|
+
import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
|
|
8
|
+
import {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
|
|
9
9
|
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
|
|
10
10
|
import {WadRayMath} from "./WadRayMath.sol";
|
|
11
11
|
|
|
@@ -71,6 +71,11 @@ abstract contract PolicyPoolComponent is
|
|
|
71
71
|
_;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
modifier onlyComponentRole(bytes32 role) {
|
|
75
|
+
_policyPool.config().checkComponentRole(address(this), role, msg.sender);
|
|
76
|
+
_;
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
75
80
|
constructor(IPolicyPool policyPool_) {
|
|
76
81
|
_policyPool = policyPool_;
|
|
@@ -4,14 +4,11 @@ pragma solidity ^0.8.0;
|
|
|
4
4
|
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
|
|
5
5
|
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
6
6
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {ILPWhitelist} from "../interfaces/ILPWhitelist.sol";
|
|
13
|
-
import {IExchange} from "../interfaces/IExchange.sol";
|
|
14
|
-
import {IPolicyPoolComponent} from "../interfaces/IPolicyPoolComponent.sol";
|
|
7
|
+
import {IPolicyPoolConfig} from "./interfaces/IPolicyPoolConfig.sol";
|
|
8
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
9
|
+
import {IRiskModule} from "./interfaces/IRiskModule.sol";
|
|
10
|
+
import {ILPWhitelist} from "./interfaces/ILPWhitelist.sol";
|
|
11
|
+
import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
|
|
15
12
|
import {WadRayMath} from "./WadRayMath.sol";
|
|
16
13
|
|
|
17
14
|
/**
|
|
@@ -37,11 +34,8 @@ contract PolicyPoolConfig is
|
|
|
37
34
|
uint256 public constant L2_RM_LIMIT = 5e16; // 5% in WAD
|
|
38
35
|
|
|
39
36
|
address internal _treasury; // address of Ensuro treasury
|
|
40
|
-
IAssetManager internal _assetManager; // asset manager
|
|
41
|
-
IInsolvencyHook internal _insolvencyHook; // Contract that handles insolvency situations
|
|
42
37
|
IPolicyPool internal _policyPool;
|
|
43
38
|
ILPWhitelist internal _lpWhitelist; // Contract that handles whitelisting of Liquidity Providers
|
|
44
|
-
IExchange internal _exchange; // Contract that handles exchange operations between assets
|
|
45
39
|
|
|
46
40
|
mapping(IRiskModule => RiskModuleStatus) private _riskModules;
|
|
47
41
|
|
|
@@ -100,6 +94,26 @@ contract PolicyPoolConfig is
|
|
|
100
94
|
// solhint-disable-next-line no-empty-blocks
|
|
101
95
|
function _authorizeUpgrade(address) internal override onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE) {}
|
|
102
96
|
|
|
97
|
+
function getComponentRole(address component, bytes32 role) public pure returns (bytes32) {
|
|
98
|
+
return bytes32(bytes20(component)) ^ role;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function checkComponentRole(
|
|
102
|
+
address component,
|
|
103
|
+
bytes32 role,
|
|
104
|
+
address account
|
|
105
|
+
) external view override {
|
|
106
|
+
_checkRole(getComponentRole(component, role), account);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function grantComponentRole(
|
|
110
|
+
address component,
|
|
111
|
+
bytes32 role,
|
|
112
|
+
address account
|
|
113
|
+
) external onlyRole(getRoleAdmin(getComponentRole(component, role))) {
|
|
114
|
+
_grantRole(getComponentRole(component, role), account);
|
|
115
|
+
}
|
|
116
|
+
|
|
103
117
|
function checkRole(bytes32 role, address account) external view override {
|
|
104
118
|
_checkRole(role, account);
|
|
105
119
|
}
|
|
@@ -112,21 +126,6 @@ contract PolicyPoolConfig is
|
|
|
112
126
|
if (!hasRole(role1, account)) _checkRole(role2, account);
|
|
113
127
|
}
|
|
114
128
|
|
|
115
|
-
function setAssetManager(IAssetManager assetManager_) external onlyRole(LEVEL1_ROLE) {
|
|
116
|
-
require(
|
|
117
|
-
address(assetManager_) == address(0) ||
|
|
118
|
-
IPolicyPoolComponent(address(assetManager_)).policyPool() == _policyPool,
|
|
119
|
-
"Component not linked to this PolicyPool"
|
|
120
|
-
);
|
|
121
|
-
_policyPool.setAssetManager(assetManager_);
|
|
122
|
-
_assetManager = assetManager_;
|
|
123
|
-
emit ComponentChanged(GovernanceActions.setAssetManager, address(_assetManager));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function assetManager() external view virtual override returns (IAssetManager) {
|
|
127
|
-
return _assetManager;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
129
|
function setTreasury(address treasury_) external onlyRole(LEVEL1_ROLE) {
|
|
131
130
|
_treasury = treasury_;
|
|
132
131
|
emit ComponentChanged(GovernanceActions.setTreasury, _treasury);
|
|
@@ -136,23 +135,6 @@ contract PolicyPoolConfig is
|
|
|
136
135
|
return _treasury;
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
function setInsolvencyHook(IInsolvencyHook insolvencyHook_)
|
|
140
|
-
external
|
|
141
|
-
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
142
|
-
{
|
|
143
|
-
require(
|
|
144
|
-
address(insolvencyHook_) == address(0) ||
|
|
145
|
-
IPolicyPoolComponent(address(insolvencyHook_)).policyPool() == _policyPool,
|
|
146
|
-
"Component not linked to this PolicyPool"
|
|
147
|
-
);
|
|
148
|
-
_insolvencyHook = insolvencyHook_;
|
|
149
|
-
emit ComponentChanged(GovernanceActions.setInsolvencyHook, address(_insolvencyHook));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function insolvencyHook() external view override returns (IInsolvencyHook) {
|
|
153
|
-
return _insolvencyHook;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
138
|
function setLPWhitelist(ILPWhitelist lpWhitelist_)
|
|
157
139
|
external
|
|
158
140
|
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
@@ -170,21 +152,7 @@ contract PolicyPoolConfig is
|
|
|
170
152
|
return _lpWhitelist;
|
|
171
153
|
}
|
|
172
154
|
|
|
173
|
-
function
|
|
174
|
-
require(
|
|
175
|
-
address(exchange_) == address(0) ||
|
|
176
|
-
IPolicyPoolComponent(address(exchange_)).policyPool() == _policyPool,
|
|
177
|
-
"Component not linked to this PolicyPool"
|
|
178
|
-
);
|
|
179
|
-
_exchange = exchange_;
|
|
180
|
-
emit ComponentChanged(GovernanceActions.setExchange, address(_exchange));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function exchange() external view override returns (IExchange) {
|
|
184
|
-
return _exchange;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function addRiskModule(IRiskModule riskModule) external onlyRole2(LEVEL1_ROLE, LEVEL2_ROLE) {
|
|
155
|
+
function addRiskModule(IRiskModule riskModule) external onlyRole(LEVEL1_ROLE) {
|
|
188
156
|
require(
|
|
189
157
|
_riskModules[riskModule] == RiskModuleStatus.inactive,
|
|
190
158
|
"Risk Module already in the pool"
|
|
@@ -194,26 +162,20 @@ contract PolicyPoolConfig is
|
|
|
194
162
|
IPolicyPoolComponent(address(riskModule)).policyPool() == _policyPool,
|
|
195
163
|
"RiskModule not linked to this pool"
|
|
196
164
|
);
|
|
197
|
-
require(
|
|
198
|
-
hasRole(LEVEL1_ROLE, msg.sender) ||
|
|
199
|
-
_policyPool.totalETokenSupply() > (riskModule.scrLimit().wadMul(L2_RM_LIMIT)),
|
|
200
|
-
"RiskModule SCR Limit exceeds the limit for LEVEL2 user"
|
|
201
|
-
);
|
|
202
165
|
_riskModules[riskModule] = RiskModuleStatus.active;
|
|
203
166
|
emit RiskModuleStatusChanged(riskModule, RiskModuleStatus.active);
|
|
204
167
|
}
|
|
205
168
|
|
|
206
169
|
function removeRiskModule(IRiskModule riskModule) external onlyRole(LEVEL2_ROLE) {
|
|
207
170
|
require(_riskModules[riskModule] != RiskModuleStatus.inactive, "Risk Module not found");
|
|
208
|
-
require(riskModule.
|
|
171
|
+
require(riskModule.activeExposure() == 0, "Can't remove a module with active policies");
|
|
209
172
|
delete _riskModules[riskModule];
|
|
210
173
|
emit RiskModuleStatusChanged(riskModule, RiskModuleStatus.inactive);
|
|
211
174
|
}
|
|
212
175
|
|
|
213
|
-
// #if_succeeds_disabled _riskModules.get(riskModule) == newStatus;
|
|
214
176
|
function changeRiskModuleStatus(IRiskModule riskModule, RiskModuleStatus newStatus)
|
|
215
177
|
external
|
|
216
|
-
|
|
178
|
+
onlyRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
217
179
|
{
|
|
218
180
|
require(_riskModules[riskModule] != RiskModuleStatus.inactive, "Risk Module not found");
|
|
219
181
|
require(
|
|
@@ -221,13 +183,8 @@ contract PolicyPoolConfig is
|
|
|
221
183
|
"Only GUARDIAN can suspend modules"
|
|
222
184
|
);
|
|
223
185
|
// To activate LEVEL1 required or LEVEL2 if <5% of total liquidity
|
|
224
|
-
require(
|
|
225
|
-
|
|
226
|
-
hasRole(LEVEL1_ROLE, msg.sender) ||
|
|
227
|
-
_policyPool.totalETokenSupply() > (riskModule.scrLimit().wadMul(L2_RM_LIMIT)),
|
|
228
|
-
"RiskModule SCR Limit exceeds the limit for LEVEL2 user"
|
|
229
|
-
);
|
|
230
|
-
// Anyone (LEVEL1, LEVEL2, GUARDIAN) can deprecate
|
|
186
|
+
require(hasRole(LEVEL1_ROLE, msg.sender), "Only LEVEL1 can activate modules");
|
|
187
|
+
// Anyone (LEVEL1, GUARDIAN) can deprecate
|
|
231
188
|
_riskModules[riskModule] = newStatus;
|
|
232
189
|
emit RiskModuleStatusChanged(riskModule, newStatus);
|
|
233
190
|
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
|
5
|
+
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
6
|
+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
7
|
+
import {WadRayMath} from "./WadRayMath.sol";
|
|
8
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
9
|
+
import {IEToken} from "./interfaces/IEToken.sol";
|
|
10
|
+
import {Reserve} from "./Reserve.sol";
|
|
11
|
+
import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
|
|
12
|
+
import {Policy} from "./Policy.sol";
|
|
13
|
+
import {IEToken} from "./interfaces/IEToken.sol";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @title Ensuro Premiums Account
|
|
17
|
+
* @dev This contract holds the premiums of a set of risk modules
|
|
18
|
+
* @custom:security-contact security@ensuro.co
|
|
19
|
+
* @author Ensuro
|
|
20
|
+
*/
|
|
21
|
+
contract PremiumsAccount is IPremiumsAccount, Reserve {
|
|
22
|
+
using Policy for Policy.PolicyData;
|
|
23
|
+
using WadRayMath for uint256;
|
|
24
|
+
using SafeERC20 for IERC20Metadata;
|
|
25
|
+
|
|
26
|
+
bytes32 public constant WITHDRAW_WON_PREMIUMS_ROLE = keccak256("WITHDRAW_WON_PREMIUMS_ROLE");
|
|
27
|
+
|
|
28
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
29
|
+
IEToken internal immutable _juniorEtk;
|
|
30
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
31
|
+
IEToken internal immutable _seniorEtk;
|
|
32
|
+
|
|
33
|
+
uint256 internal _activePurePremiums; // sum of pure-premiums of active policies - In Wad
|
|
34
|
+
uint256 internal _borrowedActivePP; // amount borrowed from active pure premiums to pay defaulted policies
|
|
35
|
+
uint256 internal _wonPurePremiums; // amount of pure premiums won from non-defaulted policies
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* Premiums can come in (for free, without liability) with receiveGrant.
|
|
39
|
+
* And can come out (withdrawed to treasury) with withdrawWonPremiums
|
|
40
|
+
*/
|
|
41
|
+
event WonPremiumsInOut(bool moneyIn, uint256 value);
|
|
42
|
+
|
|
43
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
44
|
+
// solhint-disable-next-line no-empty-blocks
|
|
45
|
+
constructor(
|
|
46
|
+
IPolicyPool policyPool_,
|
|
47
|
+
IEToken juniorEtk_,
|
|
48
|
+
IEToken seniorEtk_
|
|
49
|
+
) Reserve(policyPool_) {
|
|
50
|
+
_juniorEtk = juniorEtk_;
|
|
51
|
+
_seniorEtk = seniorEtk_;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @dev Public initialize Initializes the PremiumsAccount
|
|
56
|
+
*/
|
|
57
|
+
function initialize() public initializer {
|
|
58
|
+
__PremiumsAccount_init();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @dev Initializes the PremiumsAccount
|
|
63
|
+
*/
|
|
64
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
65
|
+
function __PremiumsAccount_init() internal initializer {
|
|
66
|
+
__PolicyPoolComponent_init();
|
|
67
|
+
__PremiumsAccount_init_unchained();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
71
|
+
function __PremiumsAccount_init_unchained() internal initializer {
|
|
72
|
+
/*
|
|
73
|
+
_activePurePremiums = 0;
|
|
74
|
+
_borrowedActivePP = 0;
|
|
75
|
+
_wonPurePremiums = 0;
|
|
76
|
+
*/
|
|
77
|
+
if (address(_juniorEtk) != address(0))
|
|
78
|
+
currency().approve(address(_juniorEtk), type(uint256).max);
|
|
79
|
+
if (address(_seniorEtk) != address(0))
|
|
80
|
+
currency().approve(address(_seniorEtk), type(uint256).max);
|
|
81
|
+
_validateParameters();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// solhint-disable-next-line no-empty-blocks
|
|
85
|
+
function _validateParameters() internal view override {}
|
|
86
|
+
|
|
87
|
+
function purePremiums() public view returns (uint256) {
|
|
88
|
+
return _activePurePremiums + _wonPurePremiums - _borrowedActivePP;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function activePurePremiums() external view returns (uint256) {
|
|
92
|
+
return _activePurePremiums;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function wonPurePremiums() external view returns (uint256) {
|
|
96
|
+
return _wonPurePremiums;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function borrowedActivePP() external view returns (uint256) {
|
|
100
|
+
return _borrowedActivePP;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function seniorEtk() external view override returns (IEToken) {
|
|
104
|
+
return _seniorEtk;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function juniorEtk() external view override returns (IEToken) {
|
|
108
|
+
return _juniorEtk;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _payFromPool(uint256 toPay) internal returns (uint256) {
|
|
112
|
+
// 1. take from won_pure_premiums
|
|
113
|
+
if (toPay <= _wonPurePremiums) {
|
|
114
|
+
_wonPurePremiums -= toPay;
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
toPay -= _wonPurePremiums;
|
|
118
|
+
_wonPurePremiums = 0;
|
|
119
|
+
// 2. borrow from active pure premiums
|
|
120
|
+
if (_activePurePremiums > _borrowedActivePP) {
|
|
121
|
+
if (toPay <= (_activePurePremiums - _borrowedActivePP)) {
|
|
122
|
+
_borrowedActivePP += toPay;
|
|
123
|
+
return 0;
|
|
124
|
+
} else {
|
|
125
|
+
toPay -= _activePurePremiums - _borrowedActivePP;
|
|
126
|
+
_borrowedActivePP = _activePurePremiums;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return toPay;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function _storePurePremiumWon(uint256 purePremiumWon) internal {
|
|
133
|
+
// TODO: merge _wonPurePremiums and _borrowedActivePP into single int256 variable
|
|
134
|
+
// and this will be just `_wonPurePremiums += purePremiumWon;`
|
|
135
|
+
if (purePremiumWon == 0) return;
|
|
136
|
+
if (_borrowedActivePP >= purePremiumWon) {
|
|
137
|
+
_borrowedActivePP -= purePremiumWon;
|
|
138
|
+
} else {
|
|
139
|
+
_wonPurePremiums += (purePremiumWon - _borrowedActivePP);
|
|
140
|
+
_borrowedActivePP = 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// TODO: restore repayETokenLoan?
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
*
|
|
148
|
+
* Endpoint to receive "free money" and inject that money into the premium pool.
|
|
149
|
+
*
|
|
150
|
+
* Can be used for example if the PolicyPool subscribes an excess loss policy with other company.
|
|
151
|
+
*
|
|
152
|
+
*/
|
|
153
|
+
function receiveGrant(uint256 amount) external {
|
|
154
|
+
currency().safeTransferFrom(msg.sender, address(this), amount);
|
|
155
|
+
_storePurePremiumWon(amount);
|
|
156
|
+
emit WonPremiumsInOut(true, amount);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
*
|
|
161
|
+
* Withdraws excess premiums to PolicyPool's treasury.
|
|
162
|
+
* This might be needed in some cases for example if we are deprecating the protocol or the excess premiums
|
|
163
|
+
* are needed to compensate something. Shouldn't be used. Can be disabled revoking role WITHDRAW_WON_PREMIUMS_ROLE
|
|
164
|
+
*
|
|
165
|
+
* returns The amount withdrawed
|
|
166
|
+
*
|
|
167
|
+
* Requirements:
|
|
168
|
+
*
|
|
169
|
+
* - onlyPoolRole(WITHDRAW_WON_PREMIUMS_ROLE)
|
|
170
|
+
* - _wonPurePremiums > 0
|
|
171
|
+
*/
|
|
172
|
+
function withdrawWonPremiums(uint256 amount)
|
|
173
|
+
external
|
|
174
|
+
onlyPoolRole(WITHDRAW_WON_PREMIUMS_ROLE)
|
|
175
|
+
returns (uint256)
|
|
176
|
+
{
|
|
177
|
+
if (amount > _wonPurePremiums) amount = _wonPurePremiums;
|
|
178
|
+
require(amount > 0, "No premiums to withdraw");
|
|
179
|
+
_wonPurePremiums -= amount;
|
|
180
|
+
_transferTo(_policyPool.config().treasury(), amount); // TODO: discuss if destination shoud be msg.sender
|
|
181
|
+
// TODO: see if this will be a component role
|
|
182
|
+
emit WonPremiumsInOut(false, amount);
|
|
183
|
+
return amount;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function policyCreated(Policy.PolicyData memory policy) external override onlyPolicyPool {
|
|
187
|
+
_activePurePremiums += policy.purePremium;
|
|
188
|
+
if (policy.jrScr > 0) _juniorEtk.lockScr(policy.jrScr, policy.jrInterestRate());
|
|
189
|
+
if (policy.srScr > 0) _seniorEtk.lockScr(policy.srScr, policy.srInterestRate());
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function policyResolvedWithPayout(
|
|
193
|
+
address policyHolder,
|
|
194
|
+
Policy.PolicyData memory policy,
|
|
195
|
+
uint256 payout
|
|
196
|
+
) external override onlyPolicyPool {
|
|
197
|
+
_activePurePremiums -= policy.purePremium;
|
|
198
|
+
if (policy.purePremium >= payout) {
|
|
199
|
+
uint256 purePremiumWon = policy.purePremium - payout;
|
|
200
|
+
if (address(_seniorEtk) != address(0))
|
|
201
|
+
purePremiumWon = _repayLoan(purePremiumWon, _seniorEtk);
|
|
202
|
+
if (address(_juniorEtk) != address(0))
|
|
203
|
+
purePremiumWon = _repayLoan(purePremiumWon, _juniorEtk);
|
|
204
|
+
_storePurePremiumWon(purePremiumWon);
|
|
205
|
+
_unlockScr(policy);
|
|
206
|
+
_transferTo(policyHolder, payout);
|
|
207
|
+
} else {
|
|
208
|
+
uint256 borrowFromScr = _payFromPool(payout - policy.purePremium);
|
|
209
|
+
_unlockScr(policy);
|
|
210
|
+
if (borrowFromScr > 0) {
|
|
211
|
+
uint256 left;
|
|
212
|
+
if (policy.jrScr > 0) {
|
|
213
|
+
// Consume Junior Pool until exhausted
|
|
214
|
+
left = _juniorEtk.internalLoan(borrowFromScr, policyHolder, false);
|
|
215
|
+
} else {
|
|
216
|
+
left = borrowFromScr;
|
|
217
|
+
}
|
|
218
|
+
if (left > NEGLIGIBLE_AMOUNT) {
|
|
219
|
+
// Consume Senior Pool only up to SCR
|
|
220
|
+
left = _seniorEtk.internalLoan(left, policyHolder, true);
|
|
221
|
+
require(left <= NEGLIGIBLE_AMOUNT, "Don't know where to take the rest of the money");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
_transferTo(policyHolder, payout - borrowFromScr);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function _unlockScr(Policy.PolicyData memory policy) internal {
|
|
229
|
+
if (policy.jrScr > 0) {
|
|
230
|
+
_juniorEtk.unlockScr(
|
|
231
|
+
policy.jrScr,
|
|
232
|
+
policy.jrInterestRate(),
|
|
233
|
+
int256(policy.jrCoc) - int256(policy.jrAccruedInterest())
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (policy.srScr > 0) {
|
|
237
|
+
_seniorEtk.unlockScr(
|
|
238
|
+
policy.srScr,
|
|
239
|
+
policy.srInterestRate(),
|
|
240
|
+
int256(policy.srCoc) - int256(policy.srAccruedInterest())
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function _repayLoan(uint256 purePremiumWon, IEToken etk) internal returns (uint256) {
|
|
246
|
+
if (purePremiumWon < NEGLIGIBLE_AMOUNT) return purePremiumWon;
|
|
247
|
+
uint256 borrowedFromEtk = etk.getLoan(address(this));
|
|
248
|
+
if (borrowedFromEtk == 0) return purePremiumWon;
|
|
249
|
+
uint256 repayAmount = borrowedFromEtk > purePremiumWon ? purePremiumWon : borrowedFromEtk;
|
|
250
|
+
// TODO: make sure the balance is available or deinvest
|
|
251
|
+
etk.repayLoan(repayAmount, address(this));
|
|
252
|
+
return purePremiumWon - repayAmount;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function policyExpired(Policy.PolicyData memory policy) external override onlyPolicyPool {
|
|
256
|
+
uint256 aux;
|
|
257
|
+
uint256 purePremiumWon = policy.purePremium;
|
|
258
|
+
_activePurePremiums -= purePremiumWon;
|
|
259
|
+
|
|
260
|
+
// If negative _activePurePremiums, repay this first (shouldn't happen)
|
|
261
|
+
if (_borrowedActivePP > _activePurePremiums) {
|
|
262
|
+
aux = Math.min(_borrowedActivePP - _activePurePremiums, purePremiumWon);
|
|
263
|
+
_borrowedActivePP -= aux;
|
|
264
|
+
purePremiumWon -= aux;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (address(_seniorEtk) != address(0)) purePremiumWon = _repayLoan(purePremiumWon, _seniorEtk);
|
|
268
|
+
if (address(_juniorEtk) != address(0)) purePremiumWon = _repayLoan(purePremiumWon, _juniorEtk);
|
|
269
|
+
|
|
270
|
+
// Finally store purePremiumWon
|
|
271
|
+
_storePurePremiumWon(purePremiumWon);
|
|
272
|
+
_unlockScr(policy);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
5
|
+
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
6
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
7
|
+
import {PolicyPoolComponent} from "./PolicyPoolComponent.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title Base contract for Ensuro cash reserves
|
|
11
|
+
* @dev This contract implements the methods related with management of the reserves and payments
|
|
12
|
+
* @custom:security-contact security@ensuro.co
|
|
13
|
+
* @author Ensuro
|
|
14
|
+
*/
|
|
15
|
+
abstract contract Reserve is PolicyPoolComponent {
|
|
16
|
+
using SafeERC20 for IERC20Metadata;
|
|
17
|
+
|
|
18
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
19
|
+
// solhint-disable-next-line var-name-mixedcase
|
|
20
|
+
uint256 public immutable NEGLIGIBLE_AMOUNT; // init as 10**(decimals/2) == 0.001 USD
|
|
21
|
+
|
|
22
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
23
|
+
constructor(IPolicyPool policyPool_) PolicyPoolComponent(policyPool_) {
|
|
24
|
+
NEGLIGIBLE_AMOUNT = 10**(policyPool_.currency().decimals() / 2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function _transferTo(address destination, uint256 amount) internal {
|
|
28
|
+
if (amount == 0) return;
|
|
29
|
+
uint256 balance = currency().balanceOf(address(this));
|
|
30
|
+
if (balance < amount && (amount - balance) < NEGLIGIBLE_AMOUNT) amount = balance;
|
|
31
|
+
// TODO: asset management
|
|
32
|
+
currency().safeTransfer(destination, amount);
|
|
33
|
+
}
|
|
34
|
+
}
|