@ensuro/core 2.1.0-beta1 → 2.1.0-beta3

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 (25) hide show
  1. package/build/contracts/AccessManager.sol/AccessManager.json +2 -2
  2. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +2 -2
  3. package/build/contracts/EToken.sol/EToken.json +15 -7
  4. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +2 -2
  5. package/build/contracts/Policy.sol/Policy.json +2 -2
  6. package/build/contracts/PolicyPool.sol/PolicyPool.json +2 -2
  7. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +46 -2
  8. package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +2 -2
  9. package/build/contracts/TimeScaled.sol/TimeScaled.json +2 -2
  10. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +2 -2
  11. package/build/contracts/interfaces/IEToken.sol/IEToken.json +0 -5
  12. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +2 -2
  13. package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +2 -2
  14. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +2 -2
  15. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +2 -2
  16. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
  17. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +2 -2
  18. package/contracts/EToken.sol +24 -13
  19. package/contracts/LPManualWhitelist.sol +1 -1
  20. package/contracts/PremiumsAccount.sol +90 -11
  21. package/contracts/RiskModule.sol +2 -2
  22. package/contracts/TimeScaled.sol +2 -9
  23. package/contracts/interfaces/IAccessManager.sol +4 -4
  24. package/contracts/interfaces/IEToken.sol +1 -7
  25. package/package.json +1 -1
@@ -65,9 +65,20 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
65
65
  */
66
66
  int256 internal _surplus;
67
67
 
68
+ /**
69
+ * @dev This struct has the parameters that can be modified by governance
70
+ * @member deficitRatio A value between [0, 1] that defines the percentage of active pure premiums that can be used
71
+ * to cover losses.
72
+ * @member assetManager This is the implementation contract that manages the PremiumsAccount's funds. See
73
+ * {IAssetManager}
74
+ * @member jrLoanLimit This is the maximum amount that can be borrowed from the Junior eToken (without decimals)
75
+ * @member srLoanLimit This is the maximum amount that can be borrowed from the Senior eToken (without decimals)
76
+ */
68
77
  struct PackedParams {
69
78
  uint16 deficitRatio;
70
79
  IAssetManager assetManager;
80
+ uint32 jrLoanLimit;
81
+ uint32 srLoanLimit;
71
82
  }
72
83
 
73
84
  PackedParams internal _params;
@@ -120,7 +131,9 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
120
131
  */
121
132
  _params = PackedParams({
122
133
  deficitRatio: HUNDRED_PERCENT,
123
- assetManager: IAssetManager(address(0))
134
+ assetManager: IAssetManager(address(0)),
135
+ jrLoanLimit: 0,
136
+ srLoanLimit: 0
124
137
  });
125
138
  _validateParameters();
126
139
  }
@@ -240,6 +253,16 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
240
253
  return -int256(_activePurePremiums.wadMul(ratio));
241
254
  }
242
255
 
256
+ function _toAmount(uint32 value) internal view returns (uint256) {
257
+ // 0 decimals to amount decimals
258
+ return uint256(value) * 10**currency().decimals();
259
+ }
260
+
261
+ function _toZeroDecimals(uint256 amount) internal view returns (uint32) {
262
+ // Removes the decimals from the amount
263
+ return (amount / 10**currency().decimals()).toUint32();
264
+ }
265
+
243
266
  /**
244
267
  * @dev Returns the percentage of the active pure premiums that can be used to cover losses of finalized policies.
245
268
  */
@@ -247,6 +270,20 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
247
270
  return uint256(_params.deficitRatio) * FOUR_DECIMAL_TO_WAD; // 4 -> 18 decimals
248
271
  }
249
272
 
273
+ /**
274
+ * @dev Returns the limit on the Junior eToken loans (infinite if _params.jrLoanLimit == 0)
275
+ */
276
+ function jrLoanLimit() public view returns (uint256) {
277
+ return _params.jrLoanLimit == 0 ? type(uint256).max : _toAmount(_params.jrLoanLimit);
278
+ }
279
+
280
+ /**
281
+ * @dev Returns the limit on the Senior eToken loans (infinite if _params.srLoanLimit == 0)
282
+ */
283
+ function srLoanLimit() public view returns (uint256) {
284
+ return _params.srLoanLimit == 0 ? type(uint256).max : _toAmount(_params.srLoanLimit);
285
+ }
286
+
250
287
  /**
251
288
  * @dev Changes the `deficitRatio` parameter.
252
289
  *
@@ -262,7 +299,7 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
262
299
  */
263
300
  function setDeficitRatio(uint256 newRatio, bool adjustment)
264
301
  external
265
- onlyComponentRole(LEVEL2_ROLE)
302
+ onlyGlobalOrComponentRole(LEVEL2_ROLE)
266
303
  {
267
304
  require(newRatio <= 1e18, "Validation: deficitRatio must be <= 1");
268
305
 
@@ -287,6 +324,36 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
287
324
  _parameterChanged(action, newRatio, false);
288
325
  }
289
326
 
327
+ /**
328
+ * @dev Changes the `jrLoanLimit` or `srLoanLimit` parameter.
329
+ *
330
+ * Requirements:
331
+ * - onlyGlobalOrComponentRole(LEVEL2_ROLE)
332
+ *
333
+ * Events:
334
+ * - Emits GovernanceAction with action = setDeficitRatio or setDeficitRatioWithAdjustment if an adjustment was made.
335
+ *
336
+ * @param newLimitJr The new limit to be set for the loans taken from the Junior eToken.
337
+ If newLimitJr == MAX_UINT, it's ignored. If == 0, means the loans are unbounded.
338
+ * @param newLimitSr The new limit to be set for the loans taken from the Senior eToken.
339
+ If newLimitSr == MAX_UINT, it's ignored. If == 0, means the loans are unbounded.
340
+ */
341
+ function setLoanLimits(uint256 newLimitJr, uint256 newLimitSr)
342
+ external
343
+ onlyGlobalOrComponentRole(LEVEL2_ROLE)
344
+ {
345
+ if (newLimitJr != type(uint256).max) {
346
+ _params.jrLoanLimit = _toZeroDecimals(newLimitJr);
347
+ require(_toAmount(_params.jrLoanLimit) == newLimitJr, "Validation: no decimals allowed");
348
+ _parameterChanged(IAccessManager.GovernanceActions.setJrLoanLimit, newLimitJr, false);
349
+ }
350
+ if (newLimitSr != type(uint256).max) {
351
+ _params.srLoanLimit = _toZeroDecimals(newLimitSr);
352
+ require(_toAmount(_params.srLoanLimit) == newLimitSr, "Validation: no decimals allowed");
353
+ _parameterChanged(IAccessManager.GovernanceActions.setSrLoanLimit, newLimitSr, false);
354
+ }
355
+ }
356
+
290
357
  /**
291
358
  * @dev Internal function called when money in the PremiumsAccount is not enough and we need to borrow from the
292
359
  * eTokens.
@@ -302,17 +369,22 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
302
369
  bool jrEtk
303
370
  ) internal {
304
371
  require(receiver != address(0), "PremiumsAccount: receiver cannot be the zero address");
305
- uint256 left;
372
+ uint256 left = borrow;
306
373
  if (jrEtk) {
307
- // Consume Junior Pool until exhausted
308
- left = _juniorEtk.internalLoan(borrow, receiver, false);
309
- } else {
310
- left = borrow;
374
+ if (_juniorEtk.getLoan(address(this)) + borrow <= jrLoanLimit()) {
375
+ left = _juniorEtk.internalLoan(borrow, receiver);
376
+ } else if (_juniorEtk.getLoan(address(this)) < jrLoanLimit()) {
377
+ // Partial loan
378
+ uint256 loanExcess = _juniorEtk.getLoan(address(this)) + borrow - jrLoanLimit();
379
+ left = loanExcess + _juniorEtk.internalLoan(borrow - loanExcess, receiver);
380
+ }
311
381
  }
312
382
  if (left > NEGLIGIBLE_AMOUNT) {
313
383
  // Consume Senior Pool only up to SCR
314
- left = _seniorEtk.internalLoan(left, receiver, true);
315
- require(left <= NEGLIGIBLE_AMOUNT, "Don't know where to take the rest of the money");
384
+ if (_seniorEtk.getLoan(address(this)) + left < srLoanLimit()) {
385
+ left = _seniorEtk.internalLoan(left, receiver);
386
+ } // in the senior eToken doesn't make sense to handle partial loan
387
+ require(left <= NEGLIGIBLE_AMOUNT, "Don't know where to source the rest of the money");
316
388
  }
317
389
  }
318
390
 
@@ -360,9 +432,16 @@ contract PremiumsAccount is IPremiumsAccount, Reserve {
360
432
  * @param amount The amount to be transferred.
361
433
  */
362
434
  function receiveGrant(uint256 amount) external {
363
- _storePurePremiumWon(amount);
364
- emit WonPremiumsInOut(true, amount);
435
+ // I need to receive the money first (without following the Check-Effects-Interactions) pattern because I need
436
+ // the money to pay the eTokens
365
437
  currency().safeTransferFrom(_msgSender(), address(this), amount);
438
+ uint256 purePremiumWon = amount;
439
+ if (address(_seniorEtk) != address(0)) purePremiumWon = _repayLoan(purePremiumWon, _seniorEtk);
440
+ if (address(_juniorEtk) != address(0)) purePremiumWon = _repayLoan(purePremiumWon, _juniorEtk);
441
+
442
+ // Finally store purePremiumWon
443
+ _storePurePremiumWon(purePremiumWon);
444
+ emit WonPremiumsInOut(true, amount);
366
445
  }
367
446
 
368
447
  /**
@@ -185,12 +185,12 @@ abstract contract RiskModule is IRiskModule, PolicyPoolComponent {
185
185
 
186
186
  // solhint-disable-next-line func-name-mixedcase
187
187
  function _XtoAmount(uint8 decimals, uint32 value) internal view returns (uint256) {
188
- // X decimals to Wad (18 decimals)
188
+ // X decimals to currency decimals (6 for USDC)
189
189
  return uint256(value) * 10**(currency().decimals() - decimals);
190
190
  }
191
191
 
192
192
  function _amountToX(uint8 decimals, uint256 value) internal view returns (uint32) {
193
- // Wad to X decimals
193
+ // currency decimals to X decimals (assuming X < currency decimals)
194
194
  return (value / 10**(currency().decimals() - decimals)).toUint32();
195
195
  }
196
196
 
@@ -125,14 +125,7 @@ library TimeScaled {
125
125
  require(scaledAmount.scale >= MIN_SCALE, "Scale too small, can lead to rounding errors");
126
126
  }
127
127
 
128
- function maxNegativeAdjustment(ScaledAmount storage scaledAmount, uint256 interestRate)
129
- internal
130
- view
131
- returns (uint256)
132
- {
133
- uint256 ts = getScaledAmount(scaledAmount, interestRate);
134
- uint256 minTs = uint256(scaledAmount.amount).wadToRay().rayMul(MIN_SCALE).rayToWad();
135
- if (ts > minTs) return ts - minTs;
136
- else return 0;
128
+ function minValue(ScaledAmount storage scaledAmount) internal view returns (uint256) {
129
+ return uint256(scaledAmount.amount).wadToRay().rayMul(MIN_SCALE).rayToWad();
137
130
  }
138
131
  }
@@ -52,10 +52,10 @@ interface IAccessManager is IAccessControlUpgradeable {
52
52
  // PremiumsAccount Governance Actions
53
53
  setDeficitRatio,
54
54
  setDeficitRatioWithAdjustment,
55
- paFiller1,
56
- paFiller2,
57
- paFiller3,
58
- paFiller4,
55
+ setJrLoanLimit,
56
+ setSrLoanLimit,
57
+ paFiller3, // Reserve space for future PremiumsAccount actions
58
+ paFiller4, // Reserve space for future PremiumsAccount actions
59
59
  // AssetManager Governance Actions
60
60
  setLiquidityMin,
61
61
  setLiquidityMiddle,
@@ -152,15 +152,9 @@ interface IEToken is IERC20 {
152
152
  *
153
153
  * @param amount The amount required
154
154
  * @param receiver The received of the funds lent. This is usually the policyholder if the loan is used for a payout.
155
- * @param fromAvailable If `true`, the funds that can be lent are only the available ones, i.e., excluding the funds
156
- * locked as `scr()`. If `false`, all the `totalSupply()` is available to be lent.
157
155
  * @return Returns the amount that wasn't able to fulfil. `amount - lent`
158
156
  */
159
- function internalLoan(
160
- uint256 amount,
161
- address receiver,
162
- bool fromAvailable
163
- ) external returns (uint256);
157
+ function internalLoan(uint256 amount, address receiver) external returns (uint256);
164
158
 
165
159
  /**
166
160
  * @dev Repays a loan taken with `internalLoan`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ensuro/core",
3
3
  "description": "Ensuro - Decentralized insurance protocol",
4
- "version": "v2.1.0-beta1",
4
+ "version": "v2.1.0-beta3",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",