@ensuro/core 2.0.0-beta1 → 2.0.0-beta11

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 (84) hide show
  1. package/README.md +36 -14
  2. package/build/contracts/AccessManager.sol/AccessManager.json +564 -0
  3. package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +238 -0
  4. package/build/contracts/EToken.sol/EToken.json +147 -46
  5. package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +23 -4
  6. package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +222 -0
  7. package/build/contracts/Policy.sol/Policy.json +2 -2
  8. package/build/contracts/PolicyPool.sol/PolicyPool.json +437 -61
  9. package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +21 -2
  10. package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +142 -16
  11. package/build/contracts/Reserve.sol/Reserve.json +85 -8
  12. package/build/contracts/RiskModule.sol/RiskModule.json +21 -2
  13. package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +979 -0
  14. package/build/contracts/TimeScaled.sol/TimeScaled.json +3 -17
  15. package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +24 -5
  16. package/build/contracts/{WadRayMath.sol → dependencies/WadRayMath.sol}/WadRayMath.json +3 -3
  17. package/build/contracts/interfaces/{IPolicyPoolConfig.sol/IPolicyPoolConfig.json → IAccessManager.sol/IAccessManager.json} +77 -59
  18. package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +128 -0
  19. package/build/contracts/interfaces/IEToken.sol/IEToken.json +13 -0
  20. package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +40 -16
  21. package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +19 -0
  22. package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +13 -0
  23. package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
  24. package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +2 -2
  25. package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +180 -0
  26. package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +28 -2
  27. package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +21 -2
  28. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +118 -19
  29. package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +6 -6
  30. package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +783 -0
  31. package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +2 -2
  32. package/build/contracts/mocks/TestNFT.sol/TestNFT.json +2 -2
  33. package/contracts/AccessManager.sol +132 -0
  34. package/contracts/ERC4626AssetManager.sol +55 -0
  35. package/contracts/EToken.sol +208 -102
  36. package/contracts/LPManualWhitelist.sol +19 -3
  37. package/contracts/LiquidityThresholdAssetManager.sol +175 -0
  38. package/contracts/Policy.sol +5 -3
  39. package/contracts/PolicyPool.sol +381 -116
  40. package/contracts/PolicyPoolComponent.sol +61 -44
  41. package/contracts/PremiumsAccount.sol +324 -86
  42. package/contracts/Reserve.sol +199 -4
  43. package/contracts/RiskModule.sol +62 -31
  44. package/contracts/SignedQuoteRiskModule.sol +248 -0
  45. package/contracts/TimeScaled.sol +19 -15
  46. package/contracts/TrustfulRiskModule.sol +69 -2
  47. package/contracts/dependencies/WadRayMath.sol +126 -0
  48. package/contracts/interfaces/IAccessManager.sol +148 -0
  49. package/contracts/interfaces/IAssetManager.sol +89 -0
  50. package/contracts/interfaces/IEToken.sol +25 -2
  51. package/contracts/interfaces/ILPWhitelist.sol +17 -0
  52. package/contracts/interfaces/IPolicyPool.sol +21 -14
  53. package/contracts/interfaces/IPolicyPoolComponent.sol +5 -1
  54. package/contracts/interfaces/IPremiumsAccount.sol +5 -0
  55. package/contracts/interfaces/IRiskModule.sol +67 -4
  56. package/contracts/mocks/FixedRateVault.sol +85 -0
  57. package/contracts/mocks/InterfaceIdCalculator.sol +32 -0
  58. package/contracts/mocks/PolicyHolderMock.sol +21 -0
  59. package/contracts/mocks/PolicyPoolComponentMock.sol +10 -0
  60. package/contracts/mocks/PolicyPoolMock.sol +41 -15
  61. package/contracts/mocks/RiskModuleMock.sol +75 -0
  62. package/js/deploy.js +704 -0
  63. package/js/test-utils.js +339 -159
  64. package/package.json +1 -1
  65. package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -890
  66. package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -583
  67. package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -691
  68. package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -63
  69. package/build/contracts/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
  70. package/build/contracts/mocks/LinkTokenMock.sol/LinkTokenMock.json +0 -370
  71. package/build/contracts/mocks/TestCurrencyUUPS.sol/TestCurrencyUUPS.json +0 -353
  72. package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
  73. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -584
  74. package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -615
  75. package/contracts/FlightDelayRiskModule.sol +0 -217
  76. package/contracts/PolicyNFT.sol +0 -96
  77. package/contracts/PolicyPoolConfig.sol +0 -204
  78. package/contracts/WadRayMath.sol +0 -135
  79. package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
  80. package/contracts/interfaces/IPolicyNFT.sol +0 -15
  81. package/contracts/interfaces/IPolicyPoolConfig.sol +0 -96
  82. package/contracts/mocks/LinkTokenMock.sol +0 -30
  83. package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
  84. package/contracts/upgraded/PolicyNFTv1.sol +0 -126
@@ -0,0 +1,248 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
5
+ import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
6
+ import {IPremiumsAccount} from "./interfaces/IPremiumsAccount.sol";
7
+ import {RiskModule} from "./RiskModule.sol";
8
+ import {Policy} from "./Policy.sol";
9
+
10
+ /**
11
+ * @title SignedQuote Risk Module
12
+ * @dev Risk Module that for policy creation verifies the different components of the price have been signed by a
13
+ trusted account (PRICER_ROLE). For the resolution (resolvePolicy), it has to be called by an authorized user
14
+ * @custom:security-contact security@ensuro.co
15
+ * @author Ensuro
16
+ */
17
+ contract SignedQuoteRiskModule is RiskModule {
18
+ bytes32 public constant POLICY_CREATOR_ROLE = keccak256("POLICY_CREATOR_ROLE");
19
+ bytes32 public constant PRICER_ROLE = keccak256("PRICER_ROLE");
20
+ bytes32 public constant RESOLVER_ROLE = keccak256("RESOLVER_ROLE");
21
+
22
+ /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
23
+ bool internal immutable _creationIsOpen;
24
+
25
+ event NewSignedPolicy(uint256 indexed policyId, bytes32 policyData);
26
+
27
+ /// @custom:oz-upgrades-unsafe-allow constructor
28
+ constructor(
29
+ IPolicyPool policyPool_,
30
+ IPremiumsAccount premiumsAccount_,
31
+ bool creationIsOpen_
32
+ ) RiskModule(policyPool_, premiumsAccount_) {
33
+ _creationIsOpen = creationIsOpen_;
34
+ }
35
+
36
+ /**
37
+ * @dev Initializes the RiskModule
38
+ * @param name_ Name of the Risk Module
39
+ * @param collRatio_ Collateralization ratio to compute solvency requirement as % of payout (in ray)
40
+ * @param ensuroPpFee_ % of pure premium that will go for Ensuro treasury (in ray)
41
+ * @param srRoc_ return on capital paid to Senior LPs (annualized percentage - in ray)
42
+ * @param maxPayoutPerPolicy_ Maximum payout per policy (in wad)
43
+ * @param exposureLimit_ Max exposure (sum of payouts) to be allocated to this module (in wad)
44
+ * @param wallet_ Address of the RiskModule provider
45
+ */
46
+ function initialize(
47
+ string memory name_,
48
+ uint256 collRatio_,
49
+ uint256 ensuroPpFee_,
50
+ uint256 srRoc_,
51
+ uint256 maxPayoutPerPolicy_,
52
+ uint256 exposureLimit_,
53
+ address wallet_
54
+ ) public initializer {
55
+ __RiskModule_init(
56
+ name_,
57
+ collRatio_,
58
+ ensuroPpFee_,
59
+ srRoc_,
60
+ maxPayoutPerPolicy_,
61
+ exposureLimit_,
62
+ wallet_
63
+ );
64
+ }
65
+
66
+ function _newPolicySigned(
67
+ uint256 payout,
68
+ uint256 premium,
69
+ uint256 lossProb,
70
+ uint40 expiration,
71
+ bytes32 policyData,
72
+ bytes32 quoteSignatureR,
73
+ bytes32 quoteSignatureVS,
74
+ uint40 quoteValidUntil,
75
+ address payer,
76
+ address onBehalfOf
77
+ ) internal returns (uint256 policyId) {
78
+ if (!_creationIsOpen)
79
+ _policyPool.access().checkComponentRole(
80
+ address(this),
81
+ POLICY_CREATOR_ROLE,
82
+ _msgSender(),
83
+ false
84
+ );
85
+ require(quoteValidUntil >= block.timestamp, "Quote expired");
86
+
87
+ /**
88
+ * Checks the quote has been signed by an authorized user
89
+ * The "quote" is computed as hash of the following fields (encodePacked):
90
+ * - address(this): the address of this RiskModule
91
+ * - payout, premium, lossProb, expiration: the base parameters of the policy
92
+ * - policyData: a hash of the private details of the policy. The calculation should include some
93
+ * unique id (quoteId), so each policyData identifies a policy.
94
+ * - quoteValidUntil: the maximum validity of the quote
95
+ */
96
+ bytes32 quoteHash = ECDSA.toEthSignedMessageHash(
97
+ abi.encodePacked(
98
+ address(this),
99
+ payout,
100
+ premium,
101
+ lossProb,
102
+ expiration,
103
+ policyData,
104
+ quoteValidUntil
105
+ )
106
+ );
107
+ address signer = ECDSA.recover(quoteHash, quoteSignatureR, quoteSignatureVS);
108
+ _policyPool.access().checkComponentRole(address(this), PRICER_ROLE, signer, false);
109
+ uint96 internalId = uint96(uint256(policyData) % 2**96);
110
+
111
+ policyId = _newPolicy(payout, premium, lossProb, expiration, payer, onBehalfOf, internalId).id;
112
+ emit NewSignedPolicy(policyId, policyData);
113
+ return policyId;
114
+ }
115
+
116
+ /**
117
+  * @dev Creates a new Policy using a signed quote. The caller is the payer of the policy.
118
+  *
119
+  * Requirements:
120
+  * - The caller approved the spending of the premium to the PolicyPool
121
+  * - The quote has been signed by an address with the component role PRICER_ROLE
122
+  *
123
+  * Emits:
124
+  * - {PolicyPool.NewPolicy}
125
+  * - {NewSignedPolicy}
126
+  *
127
+  * @param payout The exposure (maximum payout) of the policy
128
+  * @param premium The premium that will be paid by the payer
129
+  * @param lossProb The probability of having to pay the maximum payout (wad)
130
+  * @param expiration The expiration of the policy (timestamp)
131
+  * @param onBehalfOf The policy holder
132
+  * @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
133
+  * @param quoteSignatureR The signature of the "quote". R component (EIP-2098 signature)
134
+  * @param quoteSignatureVS The signature of the "quote". VS component (EIP-2098 signature)
135
+  * @param quoteValidUntil The expiration of the quote
136
+  * @return Returns the id of the created policy
137
+  */
138
+ function newPolicy(
139
+ uint256 payout,
140
+ uint256 premium,
141
+ uint256 lossProb,
142
+ uint40 expiration,
143
+ address onBehalfOf,
144
+ bytes32 policyData,
145
+ bytes32 quoteSignatureR,
146
+ bytes32 quoteSignatureVS,
147
+ uint40 quoteValidUntil
148
+ ) external returns (uint256) {
149
+ return
150
+ _newPolicySigned(
151
+ payout,
152
+ premium,
153
+ lossProb,
154
+ expiration,
155
+ policyData,
156
+ quoteSignatureR,
157
+ quoteSignatureVS,
158
+ quoteValidUntil,
159
+ _msgSender(),
160
+ onBehalfOf
161
+ );
162
+ }
163
+
164
+ /**
165
+  * @dev Creates a new Policy using a signed quote. The payer is the policy holder
166
+  *
167
+  * Requirements:
168
+  * - currency().allowance(onBehalfOf, _msgSender()) > 0
169
+  * - The quote has been signed by an address with the component role PRICER_ROLE
170
+  *
171
+  * Emits:
172
+  * - {PolicyPool.NewPolicy}
173
+  * - {NewSignedPolicy}
174
+  *
175
+  * @param payout The exposure (maximum payout) of the policy
176
+  * @param premium The premium that will be paid by the payer
177
+  * @param lossProb The probability of having to pay the maximum payout (wad)
178
+  * @param expiration The expiration of the policy (timestamp)
179
+  * @param onBehalfOf The policy holder
180
+  * @param policyData A hash of the private details of the policy. The last 96 bits will be used as internalId
181
+  * @param quoteSignatureR The signature of the "quote". R component (EIP-2098 signature)
182
+  * @param quoteSignatureVS The signature of the "quote". VS component (EIP-2098 signature)
183
+  * @param quoteValidUntil The expiration of the quote
184
+  * @return Returns the id of the created policy
185
+  */
186
+ function newPolicyPaidByHolder(
187
+ uint256 payout,
188
+ uint256 premium,
189
+ uint256 lossProb,
190
+ uint40 expiration,
191
+ address onBehalfOf,
192
+ bytes32 policyData,
193
+ bytes32 quoteSignatureR,
194
+ bytes32 quoteSignatureVS,
195
+ uint40 quoteValidUntil
196
+ ) external returns (uint256) {
197
+ require(
198
+ onBehalfOf == _msgSender() || currency().allowance(onBehalfOf, _msgSender()) > 0,
199
+ "Sender is not authorized to create policies onBehalfOf"
200
+ );
201
+ /**
202
+ * The standard is the payer should be the _msgSender() but usually, in this type of module,
203
+ * the sender is an operative account managed by software, where the onBehalfOf is a more
204
+ * secure account (hardware wallet) that does the cash movements.
205
+ * This non standard behaviour allows for a more secure setup, where the sender never manages
206
+ * cash.
207
+ * We leverage the currency's allowance mechanism to allow the sender access to the payer's
208
+ * funds.
209
+ * Note that this allowance won't be spent, so anything above 0 is accepted.
210
+ */
211
+ return
212
+ _newPolicySigned(
213
+ payout,
214
+ premium,
215
+ lossProb,
216
+ expiration,
217
+ policyData,
218
+ quoteSignatureR,
219
+ quoteSignatureVS,
220
+ quoteValidUntil,
221
+ onBehalfOf,
222
+ onBehalfOf
223
+ );
224
+ }
225
+
226
+ function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
227
+ external
228
+ onlyComponentRole(RESOLVER_ROLE)
229
+ whenNotPaused
230
+ {
231
+ _policyPool.resolvePolicy(policy, payout);
232
+ }
233
+
234
+ function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
235
+ external
236
+ onlyComponentRole(RESOLVER_ROLE)
237
+ whenNotPaused
238
+ {
239
+ _policyPool.resolvePolicyFullPayout(policy, customerWon);
240
+ }
241
+
242
+ /**
243
+ * @dev This empty reserved space is put in place to allow future versions to add new
244
+ * variables without shifting down storage in the inheritance chain.
245
+ * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
246
+ */
247
+ uint256[50] private __gap;
248
+ }
@@ -2,7 +2,8 @@
2
2
 
3
3
  pragma solidity ^0.8.0;
4
4
 
5
- import {WadRayMath} from "./WadRayMath.sol";
5
+ import {WadRayMath} from "./dependencies/WadRayMath.sol";
6
+ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
6
7
 
7
8
  /**
8
9
  * @title TimeScaled
@@ -12,13 +13,15 @@ import {WadRayMath} from "./WadRayMath.sol";
12
13
  */
13
14
  library TimeScaled {
14
15
  using WadRayMath for uint256;
16
+ using SafeCast for uint256;
15
17
 
16
- uint256 internal constant SECONDS_PER_YEAR = 365 days;
17
- uint128 public constant MIN_SCALE = 1e17; // 0.0000000001 == 1e-10 in ray
18
+ uint256 private constant SECONDS_PER_YEAR = 365 days;
19
+ uint112 private constant MIN_SCALE = 1e17; // 0.0000000001 == 1e-10 in ray
20
+ uint112 private constant RAY112 = 1e27;
18
21
 
19
22
  struct ScaledAmount {
20
- uint128 scale;
21
- uint96 amount;
23
+ uint112 scale;
24
+ uint112 amount;
22
25
  uint32 lastUpdate;
23
26
  }
24
27
 
@@ -27,7 +30,7 @@ library TimeScaled {
27
30
  if (scaledAmount.amount == 0) {
28
31
  scaledAmount.lastUpdate = uint32(block.timestamp);
29
32
  } else {
30
- scaledAmount.scale = uint128(getScale(scaledAmount, interestRate));
33
+ scaledAmount.scale = getScale(scaledAmount, interestRate).toUint112();
31
34
  scaledAmount.lastUpdate = uint32(block.timestamp);
32
35
  }
33
36
  }
@@ -44,7 +47,7 @@ library TimeScaled {
44
47
  uint256 timeDifference = uint256(now_ - scaledAmount.lastUpdate);
45
48
  return
46
49
  uint256(scaledAmount.scale).rayMul(
47
- ((interestRate.wadToRay() * timeDifference) / SECONDS_PER_YEAR) + WadRayMath.ray()
50
+ ((interestRate.wadToRay() * timeDifference) / SECONDS_PER_YEAR) + WadRayMath.RAY
48
51
  );
49
52
  }
50
53
 
@@ -61,7 +64,7 @@ library TimeScaled {
61
64
  }
62
65
 
63
66
  function init(ScaledAmount storage scaledAmount) internal {
64
- scaledAmount.scale = uint128(WadRayMath.ray());
67
+ scaledAmount.scale = RAY112;
65
68
  scaledAmount.amount = 0;
66
69
  scaledAmount.lastUpdate = uint32(block.timestamp);
67
70
  }
@@ -89,7 +92,7 @@ library TimeScaled {
89
92
  ) internal returns (uint256) {
90
93
  updateScale(scaledAmount, interestRate);
91
94
  uint256 scaledAdd = scaleAmount(scaledAmount, amount);
92
- scaledAmount.amount += uint96(scaledAdd);
95
+ scaledAmount.amount += scaledAdd.toUint96();
93
96
  return scaledAdd;
94
97
  }
95
98
 
@@ -100,10 +103,10 @@ library TimeScaled {
100
103
  ) internal returns (uint256) {
101
104
  updateScale(scaledAmount, interestRate);
102
105
  uint256 scaledSub = scaleAmount(scaledAmount, amount);
103
- scaledAmount.amount -= uint96(scaledSub);
106
+ scaledAmount.amount -= scaledSub.toUint96();
104
107
  if (scaledAmount.amount == 0) {
105
108
  // Reset scale if amount == 0
106
- scaledAmount.scale = uint128(WadRayMath.ray());
109
+ scaledAmount.scale = RAY112;
107
110
  }
108
111
  return scaledSub;
109
112
  }
@@ -115,9 +118,10 @@ library TimeScaled {
115
118
  ) internal {
116
119
  updateScale(scaledAmount, interestRate);
117
120
  uint256 newScaledAmount = uint256(int256(getScaledAmount(scaledAmount, interestRate)) + amount);
118
- scaledAmount.scale = uint128(
119
- newScaledAmount.wadToRay().rayDiv(uint256(scaledAmount.amount).wadToRay())
120
- );
121
+ scaledAmount.scale = newScaledAmount
122
+ .wadToRay()
123
+ .rayDiv(uint256(scaledAmount.amount).wadToRay())
124
+ .toUint112();
121
125
  require(scaledAmount.scale >= MIN_SCALE, "Scale too small, can lead to rounding errors");
122
126
  }
123
127
 
@@ -127,7 +131,7 @@ library TimeScaled {
127
131
  returns (uint256)
128
132
  {
129
133
  uint256 ts = getScaledAmount(scaledAmount, interestRate);
130
- uint256 minTs = uint256(scaledAmount.amount).wadToRay().rayMul(MIN_SCALE * 10).rayToWad();
134
+ uint256 minTs = uint256(scaledAmount.amount).wadToRay().rayMul(MIN_SCALE).rayToWad();
131
135
  if (ts > minTs) return ts - minTs;
132
136
  else return 0;
133
137
  }
@@ -54,17 +54,63 @@ contract TrustfulRiskModule is RiskModule {
54
54
  );
55
55
  }
56
56
 
57
+ /**
58
+ * @dev Creates a new Policy
59
+ *
60
+ * Requirements:
61
+ * - The caller has been granted componentRole(PRICER_ROLE)
62
+ *
63
+ * Emits:
64
+ * - {PolicyPool.NewPolicy}
65
+ *
66
+ * @param payout The exposure (maximum payout) of the policy
67
+ * @param premium The premium that will be paid by the policyHolder
68
+ * @param lossProb The probability of having to pay the maximum payout (wad)
69
+ * @param expiration The expiration of the policy (timestamp)
70
+ * @param onBehalfOf The policy holder
71
+ * @param internalId An id that's unique within this module and it will be used to identify the policy
72
+ * @return Returns the id of the created policy
73
+ */
57
74
  function newPolicy(
58
75
  uint256 payout,
59
76
  uint256 premium,
60
77
  uint256 lossProb,
61
78
  uint40 expiration,
62
- address customer,
79
+ address onBehalfOf,
63
80
  uint96 internalId
64
81
  ) external onlyComponentRole(PRICER_ROLE) returns (uint256) {
65
- return _newPolicy(payout, premium, lossProb, expiration, customer, internalId).id;
82
+ address payer = onBehalfOf;
83
+ if (payer != _msgSender() && _policyPool.currency().allowance(payer, _msgSender()) < premium)
84
+ /**
85
+ * The standard is the payer should be the _msgSender() but usually, in this type of module,
86
+ * the sender is an operative account managed by software, where the onBehalfOf is a more
87
+ * secure account (hardware wallet) that does the cash movements.
88
+ * This non standard behaviour allows for a more secure setup, where the sender never manages
89
+ * cash.
90
+ * We leverage the currency's allowance mechanism to allow the sender access to the payer's
91
+ * funds.
92
+ * Note that this allowance won't be spent, so it can be set as the maximum amount of a single
93
+ * premium even for multiple policies.
94
+ */
95
+ payer = _msgSender();
96
+
97
+ return _newPolicy(payout, premium, lossProb, expiration, payer, onBehalfOf, internalId).id;
66
98
  }
67
99
 
100
+ /**
101
+ * @dev Resolves a policy, if payout > 0, it pays to the policy holder.
102
+ *
103
+ * Requirements:
104
+ * - The caller has been granted componentRole(RESOLVER_ROLE)
105
+ * - payout <= policy.payout
106
+ * - block.timestamp >= policy.expiration
107
+ *
108
+ * Emits:
109
+ * - {PolicyPool.PolicyResolved}
110
+ *
111
+ * @param policy The policy previously created (from {NewPolicy} event)
112
+ * @param payout The payout to transfer to the policy holder
113
+ */
68
114
  function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
69
115
  external
70
116
  onlyComponentRole(RESOLVER_ROLE)
@@ -73,6 +119,20 @@ contract TrustfulRiskModule is RiskModule {
73
119
  _policyPool.resolvePolicy(policy, payout);
74
120
  }
75
121
 
122
+ /**
123
+ * @dev Resolves a policy with full payout (policy.payout) if customerWon == true
124
+ *
125
+ * Requirements:
126
+ * - The caller has been granted componentRole(RESOLVER_ROLE)
127
+ * - block.timestamp >= policy.expiration
128
+ *
129
+ * Emits:
130
+ * - {PolicyPool.PolicyResolved}
131
+ *
132
+ * @param policy The policy previously created (from {NewPolicy} event)
133
+ * @param customerWon If true, policy.payout is transferred to the policy holder. If false, the policy is resolved
134
+ * without payout and can't be longer claimed.
135
+ */
76
136
  function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
77
137
  external
78
138
  onlyComponentRole(RESOLVER_ROLE)
@@ -80,4 +140,11 @@ contract TrustfulRiskModule is RiskModule {
80
140
  {
81
141
  _policyPool.resolvePolicyFullPayout(policy, customerWon);
82
142
  }
143
+
144
+ /**
145
+ * @dev This empty reserved space is put in place to allow future versions to add new
146
+ * variables without shifting down storage in the inheritance chain.
147
+ * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
148
+ */
149
+ uint256[50] private __gap;
83
150
  }
@@ -0,0 +1,126 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity ^0.8.0;
3
+
4
+ /**
5
+ * @title WadRayMath library
6
+ * @author Aave
7
+ * @notice Provides functions to perform calculations with Wad and Ray units
8
+ * @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers
9
+ * with 27 digits of precision)
10
+ * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.
11
+ **/
12
+ library WadRayMath {
13
+ // HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly
14
+ uint256 internal constant WAD = 1e18;
15
+ uint256 internal constant HALF_WAD = 0.5e18;
16
+
17
+ uint256 internal constant RAY = 1e27;
18
+ uint256 internal constant HALF_RAY = 0.5e27;
19
+
20
+ uint256 internal constant WAD_RAY_RATIO = 1e9;
21
+
22
+ /**
23
+ * @dev Multiplies two wad, rounding half up to the nearest wad
24
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
25
+ * @param a Wad
26
+ * @param b Wad
27
+ * @return c = a*b, in wad
28
+ **/
29
+ function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
30
+ // to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b
31
+ assembly {
32
+ if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) {
33
+ revert(0, 0)
34
+ }
35
+
36
+ c := div(add(mul(a, b), HALF_WAD), WAD)
37
+ }
38
+ }
39
+
40
+ /**
41
+ * @dev Divides two wad, rounding half up to the nearest wad
42
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
43
+ * @param a Wad
44
+ * @param b Wad
45
+ * @return c = a/b, in wad
46
+ **/
47
+ function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
48
+ // to avoid overflow, a <= (type(uint256).max - halfB) / WAD
49
+ assembly {
50
+ if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) {
51
+ revert(0, 0)
52
+ }
53
+
54
+ c := div(add(mul(a, WAD), div(b, 2)), b)
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @notice Multiplies two ray, rounding half up to the nearest ray
60
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
61
+ * @param a Ray
62
+ * @param b Ray
63
+ * @return c = a raymul b
64
+ **/
65
+ function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
66
+ // to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b
67
+ assembly {
68
+ if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {
69
+ revert(0, 0)
70
+ }
71
+
72
+ c := div(add(mul(a, b), HALF_RAY), RAY)
73
+ }
74
+ }
75
+
76
+ /**
77
+ * @notice Divides two ray, rounding half up to the nearest ray
78
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
79
+ * @param a Ray
80
+ * @param b Ray
81
+ * @return c = a raydiv b
82
+ **/
83
+ function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
84
+ // to avoid overflow, a <= (type(uint256).max - halfB) / RAY
85
+ assembly {
86
+ if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {
87
+ revert(0, 0)
88
+ }
89
+
90
+ c := div(add(mul(a, RAY), div(b, 2)), b)
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @dev Casts ray down to wad
96
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
97
+ * @param a Ray
98
+ * @return b = a converted to wad, rounded half up to the nearest wad
99
+ **/
100
+ function rayToWad(uint256 a) internal pure returns (uint256 b) {
101
+ assembly {
102
+ b := div(a, WAD_RAY_RATIO)
103
+ let remainder := mod(a, WAD_RAY_RATIO)
104
+ if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {
105
+ b := add(b, 1)
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * @dev Converts wad up to ray
112
+ * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
113
+ * @param a Wad
114
+ * @return b = a converted in ray
115
+ **/
116
+ function wadToRay(uint256 a) internal pure returns (uint256 b) {
117
+ // to avoid overflow, b/WAD_RAY_RATIO == a
118
+ assembly {
119
+ b := mul(a, WAD_RAY_RATIO)
120
+
121
+ if iszero(eq(div(b, WAD_RAY_RATIO), a)) {
122
+ revert(0, 0)
123
+ }
124
+ }
125
+ }
126
+ }