@ensuro/core 1.2.7 → 2.0.0-beta10

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.
Files changed (109) hide show
  1. package/README.md +63 -27
  2. package/build/contracts/AccessManager.sol/AccessManager.json +559 -0
  3. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +219 -0
  4. package/build/contracts/EToken.sol/EToken.json +217 -190
  5. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +17 -4
  6. package/build/contracts/{extras/IPriceRiskModule.sol/IPriceRiskModule.json → LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json} +81 -131
  7. package/build/contracts/Policy.sol/Policy.json +2 -2
  8. package/build/contracts/PolicyPool.sol/PolicyPool.json +425 -295
  9. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +15 -2
  10. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +868 -0
  11. package/build/contracts/{BaseAssetManager.sol/BaseAssetManager.json → Reserve.sol/Reserve.json} +37 -166
  12. package/build/contracts/RiskModule.sol/RiskModule.json +85 -312
  13. package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +960 -0
  14. package/build/contracts/{DataTypes.sol/DataTypes.json → TimeScaled.sol/TimeScaled.json} +4 -4
  15. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +134 -336
  16. package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +64 -0
  17. package/build/{interfaces/IExchange.sol/IExchange.json → contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json} +83 -79
  18. package/build/contracts/{WadRayMath.sol → dependencies/WadRayMath.sol}/WadRayMath.json +3 -3
  19. package/build/{interfaces/IPolicyPoolConfig.sol/IPolicyPoolConfig.json → contracts/interfaces/IAccessManager.sol/IAccessManager.json} +79 -77
  20. package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +109 -0
  21. package/build/{interfaces → contracts/interfaces}/IEToken.sol/IEToken.json +39 -91
  22. package/build/{interfaces → contracts/interfaces}/ILPWhitelist.sol/ILPWhitelist.json +1 -1
  23. package/build/{interfaces → contracts/interfaces}/IPolicyHolder.sol/IPolicyHolder.json +1 -1
  24. package/build/{interfaces → contracts/interfaces}/IPolicyPool.sol/IPolicyPool.json +137 -100
  25. package/build/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +1 -1
  26. package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +315 -0
  27. package/build/{interfaces → contracts/interfaces}/IRiskModule.sol/IRiskModule.json +58 -34
  28. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
  29. package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +43 -0
  30. package/build/{interfaces/IInsolvencyHook.sol/IInsolvencyHook.json → contracts/mocks/IMintableERC20.sol/IMintableERC20.json} +13 -8
  31. package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +228 -0
  32. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +35 -0
  33. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +702 -0
  34. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +92 -0
  35. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +764 -0
  36. package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +343 -0
  37. package/build/contracts/mocks/TestNFT.sol/TestNFT.json +388 -0
  38. package/contracts/AccessManager.sol +103 -0
  39. package/contracts/ERC4626AssetManager.sol +52 -0
  40. package/contracts/EToken.sol +254 -299
  41. package/contracts/LPManualWhitelist.sol +4 -4
  42. package/contracts/LiquidityThresholdAssetManager.sol +160 -0
  43. package/contracts/Policy.sol +49 -45
  44. package/contracts/PolicyPool.sol +379 -514
  45. package/contracts/PolicyPoolComponent.sol +41 -41
  46. package/contracts/PremiumsAccount.sol +480 -0
  47. package/contracts/Reserve.sol +213 -0
  48. package/contracts/RiskModule.sol +233 -174
  49. package/contracts/SignedQuoteRiskModule.sol +241 -0
  50. package/contracts/TimeScaled.sol +138 -0
  51. package/contracts/TrustfulRiskModule.sol +85 -23
  52. package/contracts/dependencies/ERC1967Proxy.sol +19 -0
  53. package/contracts/dependencies/IERC20Metadata.sol +19 -0
  54. package/contracts/dependencies/WadRayMath.sol +126 -0
  55. package/contracts/interfaces/IAccessManager.sol +148 -0
  56. package/contracts/interfaces/IAssetManager.sol +84 -0
  57. package/contracts/interfaces/IEToken.sol +195 -0
  58. package/contracts/interfaces/ILPWhitelist.sol +40 -0
  59. package/{interfaces → contracts/interfaces}/IPolicyHolder.sol +0 -0
  60. package/contracts/interfaces/IPolicyPool.sol +145 -0
  61. package/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol +3 -0
  62. package/contracts/interfaces/IPremiumsAccount.sol +76 -0
  63. package/contracts/interfaces/IRiskModule.sol +123 -0
  64. package/contracts/mocks/FixedRateVault.sol +85 -0
  65. package/contracts/mocks/ForwardProxy.sol +66 -0
  66. package/contracts/mocks/IMintableERC20.sol +13 -0
  67. package/contracts/mocks/PolicyHolderMock.sol +89 -0
  68. package/contracts/mocks/PolicyPoolComponentMock.sol +17 -0
  69. package/contracts/mocks/PolicyPoolMock.sol +148 -0
  70. package/contracts/mocks/RiskModuleMock.sol +75 -0
  71. package/contracts/mocks/TestCurrency.sol +35 -0
  72. package/contracts/mocks/TestNFT.sol +23 -0
  73. package/js/test-utils.js +356 -0
  74. package/package.json +2 -2
  75. package/build/contracts/AaveAssetManager.sol/AaveAssetManager.json +0 -742
  76. package/build/contracts/Exchange.sol/Exchange.json +0 -591
  77. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -1112
  78. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -570
  79. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -686
  80. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -50
  81. package/build/contracts/extras/PriceRiskModule.sol/PriceRiskModule.json +0 -1055
  82. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  83. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -571
  84. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -602
  85. package/build/interfaces/IAssetManager.sol/IAssetManager.json +0 -31
  86. package/build/interfaces/IExchange.sol/IPriceOracle.json +0 -30
  87. package/build/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
  88. package/contracts/AaveAssetManager.sol +0 -298
  89. package/contracts/BaseAssetManager.sol +0 -301
  90. package/contracts/DataTypes.sol +0 -287
  91. package/contracts/Exchange.sol +0 -189
  92. package/contracts/FlightDelayRiskModule.sol +0 -208
  93. package/contracts/PolicyNFT.sol +0 -96
  94. package/contracts/PolicyPoolConfig.sol +0 -247
  95. package/contracts/WadRayMath.sol +0 -135
  96. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  97. package/contracts/extras/IPriceRiskModule.sol +0 -41
  98. package/contracts/extras/PriceRiskModule.sol +0 -243
  99. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  100. package/contracts/upgraded/PolicyNFTv1.sol +0 -126
  101. package/interfaces/IAssetManager.sol +0 -23
  102. package/interfaces/IEToken.sol +0 -48
  103. package/interfaces/IExchange.sol +0 -59
  104. package/interfaces/IInsolvencyHook.sol +0 -27
  105. package/interfaces/ILPWhitelist.sol +0 -23
  106. package/interfaces/IPolicyNFT.sol +0 -15
  107. package/interfaces/IPolicyPool.sol +0 -44
  108. package/interfaces/IPolicyPoolConfig.sol +0 -87
  109. package/interfaces/IRiskModule.sol +0 -29
@@ -0,0 +1,213 @@
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 {Address} from "@openzeppelin/contracts/utils/Address.sol";
6
+ import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
7
+ import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
8
+ import {IAssetManager} from "./interfaces/IAssetManager.sol";
9
+ import {IAccessManager} from "./interfaces/IAccessManager.sol";
10
+ import {PolicyPoolComponent} from "./PolicyPoolComponent.sol";
11
+
12
+ /**
13
+ * @title Base contract for Ensuro cash reserves
14
+ * @dev This contract implements the methods related with management of the reserves and payments. {EToken} and
15
+ * {PremiumsAccount} inherit from this contract.
16
+ *
17
+ * These contracts have an asset manager {IAssetManager} that's a strategy contract that runs in the same context
18
+ * (called with delegatecall) that apply some strategy to reinvest the assets managed by the contract to generate
19
+ * additional returns.
20
+ *
21
+ * @custom:security-contact security@ensuro.co
22
+ * @author Ensuro
23
+ */
24
+ abstract contract Reserve is PolicyPoolComponent {
25
+ using SafeERC20 for IERC20Metadata;
26
+ using Address for address;
27
+
28
+ /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
29
+ // solhint-disable-next-line var-name-mixedcase
30
+ uint256 internal immutable NEGLIGIBLE_AMOUNT; // init as 10**(decimals/2) == 0.001 USD
31
+
32
+ /**
33
+ * @dev Reserve constructor. Calculates NEGLIGIBLE_AMOUNT to avoid rounding errors.
34
+ *
35
+ * @param policyPool_ The {PolicyPool} where this reserve will be plugged
36
+ */
37
+ /// @custom:oz-upgrades-unsafe-allow constructor
38
+ constructor(IPolicyPool policyPool_) PolicyPoolComponent(policyPool_) {
39
+ NEGLIGIBLE_AMOUNT = 10**(policyPool_.currency().decimals() / 2);
40
+ }
41
+
42
+ /**
43
+ * @dev Refills the reserve's balance, deinvesting from the asset manager to be able to make a payment
44
+ *
45
+ * @param amount The amount of the payment that needs to be made
46
+ * @return Returns the actual amount deinvested (how much the `currency().balanceof(this)` was increased). It might be
47
+ * more than `amount` because the asset manager might want to give more liquidity to the reserve to avoid further
48
+ * deinvestments. After the call, the `currency().balanceof(this)` should be greater than `amount` (unless unsolvency
49
+ * problem).
50
+ */
51
+ function _refillWallet(uint256 amount) internal returns (uint256) {
52
+ address am = address(assetManager());
53
+ if (am != address(0)) {
54
+ bytes memory result = am.functionDelegateCall(
55
+ abi.encodeWithSelector(IAssetManager.refillWallet.selector, amount),
56
+ "Error refilling wallet"
57
+ );
58
+ return abi.decode(result, (uint256));
59
+ }
60
+ return 0;
61
+ }
62
+
63
+ /**
64
+ * @dev Internal function that transfers money to a destination. It might need to call `_refillWallet` to deinvest
65
+ * some money to have enought liquidity for the payment.
66
+ *
67
+ * @param destination The destination of the transfer.
68
+ * @param amount The amount to be transferred.
69
+ */
70
+ function _transferTo(address destination, uint256 amount) internal {
71
+ if (amount == 0) return;
72
+ uint256 balance = currency().balanceOf(address(this));
73
+ if (balance < amount) {
74
+ balance += _refillWallet(amount);
75
+ if (amount > balance) {
76
+ if ((amount - balance) < NEGLIGIBLE_AMOUNT) {
77
+ amount = balance;
78
+ } // else - No need to do anything since safeTransfer will fail anyway
79
+ }
80
+ }
81
+ currency().safeTransfer(destination, amount);
82
+ }
83
+
84
+ /**
85
+ * @dev Returns the address of the asset manager for this reserve. The asset manager is the contract that manages the
86
+ * funds to generate additional yields. Can be `address(0)` if no asset manager has been set.
87
+ */
88
+ function assetManager() public view virtual returns (IAssetManager);
89
+
90
+ /**
91
+ * @dev Internal function that needs to be implemented by child contracts because they might store the asset manager
92
+ * address in a different way. This function just stores the value, doesn't do any validation (validations are done on
93
+ * `setAssetManager`.
94
+ *
95
+ * @param newAM The address of the new asset manager for the reserve.
96
+ */
97
+ function _setAssetManager(IAssetManager newAM) internal virtual;
98
+
99
+ /**
100
+ * @dev Internal function that needs to be implemented by child contracts to record the earnings (or losses if
101
+ * negative) generated by the asset management.
102
+ *
103
+ * @param earnings The amount of earnings (or losses if negative) generated since last time the earnings were
104
+ * recorded.
105
+ */
106
+ function _assetEarnings(int256 earnings) internal virtual;
107
+
108
+ /**
109
+ * @dev Sets the asset manager for this reserve. If the reserve had previously an asset manager, it will deinvest all
110
+ * the funds, making all of the liquid in the reserve balance.
111
+ *
112
+ * Requirements:
113
+ * - The caller must have been granted of global or component roles GUARDIAN_ROLE or LEVEL1_ROLE.
114
+ *
115
+ * Events:
116
+ * - Emits ComponentChanged with action setAssetManager or setAssetManagerForced
117
+ *
118
+ * @param newAM The address of the new asset manager to assign to the reserve. If is `address(0)` it means the reserve
119
+ * will not have an asset manager. If not `address(0)` it MUST be a contract following the IAssetManager interface.
120
+ * @param force When a previous asset manager exists, before setting the new one, the funds are deinvested. When
121
+ * `force` is true, an error in the deinvestAll() operation is ignored. When `force` is false, if `deinvestAll()`
122
+ * fails, it reverts.
123
+ */
124
+ function setAssetManager(IAssetManager newAM, bool force)
125
+ external
126
+ onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
127
+ {
128
+ require(
129
+ address(newAM) == address(0) || address(newAM).isContract(),
130
+ "The assetManager is not a contract!"
131
+ );
132
+ address am = address(assetManager());
133
+ IAccessManager.GovernanceActions action = IAccessManager.GovernanceActions.setAssetManager;
134
+ if (am != address(0)) {
135
+ if (force) {
136
+ // Ignores success or not
137
+ // solhint-disable-next-line avoid-low-level-calls
138
+ (bool success, bytes memory result) = am.delegatecall(
139
+ abi.encodeWithSelector(IAssetManager.deinvestAll.selector)
140
+ );
141
+ if (!success) {
142
+ action = IAccessManager.GovernanceActions.setAssetManagerForced;
143
+ } else {
144
+ _assetEarnings(abi.decode(result, (int256)));
145
+ }
146
+ } else {
147
+ bytes memory result = am.functionDelegateCall(
148
+ abi.encodeWithSelector(IAssetManager.deinvestAll.selector)
149
+ );
150
+ _assetEarnings(abi.decode(result, (int256)));
151
+ }
152
+ }
153
+ _setAssetManager(newAM);
154
+ am = address(assetManager());
155
+ if (am != address(0)) {
156
+ am.functionDelegateCall(abi.encodeWithSelector(IAssetManager.connect.selector));
157
+ }
158
+ _componentChanged(action, address(newAM));
159
+ }
160
+
161
+ /**
162
+ * @dev Calls {IAssetManager-rebalance} of the assigned asset manager (fails if no asset manager). This operation is
163
+ * intended to give the opportunity to rebalance the liquid and invested for better returns and/or gas optimization.
164
+ *
165
+ * - Emits {IAssetManager-MoneyInvested} or {IAssetManager-MoneyDeinvested}
166
+ */
167
+ function rebalance() public whenNotPaused {
168
+ address(assetManager()).functionDelegateCall(
169
+ abi.encodeWithSelector(IAssetManager.rebalance.selector)
170
+ );
171
+ }
172
+
173
+ /**
174
+ * @dev Calls {IAssetManager-recordEarnings} of the assigned asset manager (fails if no asset manager). The asset
175
+ * manager will return the earnings since last time the earnings where recorded. It then calls `_assetEarnings` to
176
+ * reflect the earnings in the way defined for each reserve.
177
+ *
178
+ * - Emits {IAssetManager-EarningsRecorded}
179
+ */
180
+ function recordEarnings() public whenNotPaused {
181
+ bytes memory result = address(assetManager()).functionDelegateCall(
182
+ abi.encodeWithSelector(IAssetManager.recordEarnings.selector)
183
+ );
184
+ _assetEarnings(abi.decode(result, (int256)));
185
+ }
186
+
187
+ /**
188
+ * @dev Function that calls both `recordEarnings()` and `rebalance()` (in that order). Usually scheduled to run once a
189
+ * day by a keeper or crontask.
190
+ */
191
+ function checkpoint() external whenNotPaused {
192
+ recordEarnings();
193
+ rebalance();
194
+ }
195
+
196
+ /**
197
+ * @dev This function allows to call custom functions of the asset manager (for example for setting parameters).
198
+ * This functions will be called with `delegatecall`, in the context of the reserve.
199
+ *
200
+ * Requirements:
201
+ * - The caller must have been granted of global or component roles LEVEL2_ROLE.
202
+ *
203
+ * @param functionCall Abi encoded function call to make.
204
+ * @return Returns the return value of the function called, to be decoded by the receiver.
205
+ */
206
+ function forwardToAssetManager(bytes memory functionCall)
207
+ external
208
+ onlyGlobalOrComponentRole(LEVEL2_ROLE)
209
+ returns (bytes memory)
210
+ {
211
+ return address(assetManager()).functionDelegateCall(functionCall);
212
+ }
213
+ }