@ensuro/core 2.0.0-beta8 → 2.0.0
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 +31 -14
- package/build/contracts/AccessManager.sol/AccessManager.json +7 -2
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +28 -3
- package/build/contracts/EToken.sol/EToken.json +21 -15
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +21 -2
- package/build/contracts/LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json +26 -1
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +40 -2
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +19 -0
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +21 -15
- package/build/contracts/Reserve.sol/Reserve.json +19 -13
- package/build/contracts/RiskModule.sol/RiskModule.json +19 -0
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +1110 -0
- package/build/contracts/TimeScaled.sol/TimeScaled.json +3 -17
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +137 -2
- package/build/contracts/{WadRayMath.sol → dependencies/WadRayMath.sol}/WadRayMath.json +3 -3
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +26 -1
- package/build/contracts/interfaces/IPolicyPool.sol/IPolicyPool.json +38 -0
- package/build/contracts/interfaces/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +19 -0
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +2 -2
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +2 -2
- package/build/contracts/mocks/InterfaceIdCalculator.sol/InterfaceIdCalculator.json +180 -0
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +28 -2
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +21 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +115 -2
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +2 -2
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +111 -2
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +2 -2
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +2 -2
- package/contracts/AccessManager.sol +31 -2
- package/contracts/ERC4626AssetManager.sol +8 -2
- package/contracts/EToken.sol +129 -60
- package/contracts/LPManualWhitelist.sol +18 -2
- package/contracts/LiquidityThresholdAssetManager.sol +28 -12
- package/contracts/Policy.sol +5 -3
- package/contracts/PolicyPool.sol +221 -29
- package/contracts/PolicyPoolComponent.sol +36 -25
- package/contracts/PremiumsAccount.sol +220 -32
- package/contracts/Reserve.sol +130 -19
- package/contracts/RiskModule.sol +53 -20
- package/contracts/SignedQuoteRiskModule.sol +310 -0
- package/contracts/TimeScaled.sol +19 -15
- package/contracts/TrustfulRiskModule.sol +107 -6
- package/contracts/dependencies/WadRayMath.sol +126 -0
- package/contracts/interfaces/IAccessManager.sol +68 -13
- package/contracts/interfaces/IAssetManager.sol +69 -2
- package/contracts/interfaces/IEToken.sol +4 -1
- package/contracts/interfaces/ILPWhitelist.sol +17 -0
- package/contracts/interfaces/IPolicyPool.sol +19 -1
- package/contracts/interfaces/IPolicyPoolComponent.sol +5 -1
- package/contracts/interfaces/IRiskModule.sol +67 -4
- package/contracts/mocks/InterfaceIdCalculator.sol +32 -0
- package/contracts/mocks/PolicyHolderMock.sol +21 -0
- package/contracts/mocks/PolicyPoolComponentMock.sol +10 -0
- package/contracts/mocks/PolicyPoolMock.sol +31 -0
- package/contracts/mocks/RiskModuleMock.sol +7 -1
- package/js/deploy.js +734 -0
- package/js/test-utils.js +184 -69
- package/package.json +4 -2
- package/scripts/change-pragma.sh +19 -0
- package/scripts/deploySmokeTest-fork.sh +53 -0
- package/scripts/deploySmokeTest.sh +51 -0
- package/scripts/storageLayout.js +33 -0
- package/scripts/utils.sh +65 -0
- package/contracts/WadRayMath.sol +0 -135
package/contracts/TimeScaled.sol
CHANGED
|
@@ -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
|
|
17
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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 =
|
|
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.
|
|
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 =
|
|
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 +=
|
|
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 -=
|
|
106
|
+
scaledAmount.amount -= scaledSub.toUint96();
|
|
104
107
|
if (scaledAmount.amount == 0) {
|
|
105
108
|
// Reset scale if amount == 0
|
|
106
|
-
scaledAmount.scale =
|
|
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 =
|
|
119
|
-
|
|
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
|
|
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,6 +54,23 @@ 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,
|
|
@@ -62,10 +79,60 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
62
79
|
address onBehalfOf,
|
|
63
80
|
uint96 internalId
|
|
64
81
|
) external onlyComponentRole(PRICER_ROLE) returns (uint256) {
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
return
|
|
83
|
+
_newPolicy(
|
|
84
|
+
payout,
|
|
85
|
+
premium,
|
|
86
|
+
lossProb,
|
|
87
|
+
expiration,
|
|
88
|
+
_getPayer(onBehalfOf, premium),
|
|
89
|
+
onBehalfOf,
|
|
90
|
+
internalId
|
|
91
|
+
).id;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @dev Creates a new Policy. Version that returns all the PolicyData struct, not just the id.
|
|
96
|
+
*
|
|
97
|
+
* Requirements:
|
|
98
|
+
* - The caller has been granted componentRole(PRICER_ROLE)
|
|
99
|
+
*
|
|
100
|
+
* Emits:
|
|
101
|
+
* - {PolicyPool.NewPolicy}
|
|
102
|
+
*
|
|
103
|
+
* @param payout The exposure (maximum payout) of the policy
|
|
104
|
+
* @param premium The premium that will be paid by the policyHolder
|
|
105
|
+
* @param lossProb The probability of having to pay the maximum payout (wad)
|
|
106
|
+
* @param expiration The expiration of the policy (timestamp)
|
|
107
|
+
* @param onBehalfOf The policy holder
|
|
108
|
+
* @param internalId An id that's unique within this module and it will be used to identify the policy
|
|
109
|
+
* @return createdPolicy Returns the id of the created policy
|
|
110
|
+
*/
|
|
111
|
+
function newPolicyFull(
|
|
112
|
+
uint256 payout,
|
|
113
|
+
uint256 premium,
|
|
114
|
+
uint256 lossProb,
|
|
115
|
+
uint40 expiration,
|
|
116
|
+
address onBehalfOf,
|
|
117
|
+
uint96 internalId
|
|
118
|
+
) external onlyComponentRole(PRICER_ROLE) returns (Policy.PolicyData memory createdPolicy) {
|
|
119
|
+
return
|
|
120
|
+
_newPolicy(
|
|
121
|
+
payout,
|
|
122
|
+
premium,
|
|
123
|
+
lossProb,
|
|
124
|
+
expiration,
|
|
125
|
+
_getPayer(onBehalfOf, premium),
|
|
126
|
+
onBehalfOf,
|
|
127
|
+
internalId
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function _getPayer(address onBehalfOf, uint256 premium) internal view returns (address payer) {
|
|
132
|
+
payer = onBehalfOf;
|
|
133
|
+
if (payer != _msgSender() && _policyPool.currency().allowance(payer, _msgSender()) < premium)
|
|
67
134
|
/**
|
|
68
|
-
* The standard is the payer should be the
|
|
135
|
+
* The standard is the payer should be the _msgSender() but usually, in this type of module,
|
|
69
136
|
* the sender is an operative account managed by software, where the onBehalfOf is a more
|
|
70
137
|
* secure account (hardware wallet) that does the cash movements.
|
|
71
138
|
* This non standard behaviour allows for a more secure setup, where the sender never manages
|
|
@@ -75,11 +142,24 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
75
142
|
* Note that this allowance won't be spent, so it can be set as the maximum amount of a single
|
|
76
143
|
* premium even for multiple policies.
|
|
77
144
|
*/
|
|
78
|
-
payer =
|
|
79
|
-
|
|
80
|
-
return _newPolicy(payout, premium, lossProb, expiration, payer, onBehalfOf, internalId).id;
|
|
145
|
+
payer = _msgSender();
|
|
146
|
+
return payer;
|
|
81
147
|
}
|
|
82
148
|
|
|
149
|
+
/**
|
|
150
|
+
* @dev Resolves a policy, if payout > 0, it pays to the policy holder.
|
|
151
|
+
*
|
|
152
|
+
* Requirements:
|
|
153
|
+
* - The caller has been granted componentRole(RESOLVER_ROLE)
|
|
154
|
+
* - payout <= policy.payout
|
|
155
|
+
* - block.timestamp >= policy.expiration
|
|
156
|
+
*
|
|
157
|
+
* Emits:
|
|
158
|
+
* - {PolicyPool.PolicyResolved}
|
|
159
|
+
*
|
|
160
|
+
* @param policy The policy previously created (from {NewPolicy} event)
|
|
161
|
+
* @param payout The payout to transfer to the policy holder
|
|
162
|
+
*/
|
|
83
163
|
function resolvePolicy(Policy.PolicyData calldata policy, uint256 payout)
|
|
84
164
|
external
|
|
85
165
|
onlyComponentRole(RESOLVER_ROLE)
|
|
@@ -88,6 +168,20 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
88
168
|
_policyPool.resolvePolicy(policy, payout);
|
|
89
169
|
}
|
|
90
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @dev Resolves a policy with full payout (policy.payout) if customerWon == true
|
|
173
|
+
*
|
|
174
|
+
* Requirements:
|
|
175
|
+
* - The caller has been granted componentRole(RESOLVER_ROLE)
|
|
176
|
+
* - block.timestamp >= policy.expiration
|
|
177
|
+
*
|
|
178
|
+
* Emits:
|
|
179
|
+
* - {PolicyPool.PolicyResolved}
|
|
180
|
+
*
|
|
181
|
+
* @param policy The policy previously created (from {NewPolicy} event)
|
|
182
|
+
* @param customerWon If true, policy.payout is transferred to the policy holder. If false, the policy is resolved
|
|
183
|
+
* without payout and can't be longer claimed.
|
|
184
|
+
*/
|
|
91
185
|
function resolvePolicyFullPayout(Policy.PolicyData calldata policy, bool customerWon)
|
|
92
186
|
external
|
|
93
187
|
onlyComponentRole(RESOLVER_ROLE)
|
|
@@ -95,4 +189,11 @@ contract TrustfulRiskModule is RiskModule {
|
|
|
95
189
|
{
|
|
96
190
|
_policyPool.resolvePolicyFullPayout(policy, customerWon);
|
|
97
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @dev This empty reserved space is put in place to allow future versions to add new
|
|
195
|
+
* variables without shifting down storage in the inheritance chain.
|
|
196
|
+
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
|
|
197
|
+
*/
|
|
198
|
+
uint256[50] private __gap;
|
|
98
199
|
}
|
|
@@ -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
|
+
}
|
|
@@ -9,18 +9,20 @@ import {IAccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/acc
|
|
|
9
9
|
* @author Ensuro
|
|
10
10
|
*/
|
|
11
11
|
interface IAccessManager is IAccessControlUpgradeable {
|
|
12
|
+
/**
|
|
13
|
+
* @dev Enum with the different governance actions supported in the protocol.
|
|
14
|
+
* It's good to keep actions of the same component consecutive, parts of the code relay on that,
|
|
15
|
+
* so we put some fillers in case new actions are added.
|
|
16
|
+
*/
|
|
12
17
|
enum GovernanceActions {
|
|
13
18
|
none,
|
|
14
19
|
setTreasury, // Changes PolicyPool treasury address
|
|
15
20
|
setAssetManager, // Change in the asset manager strategy of a reserve
|
|
16
|
-
setInsolvencyHook, // Changes PolicyPool InsolvencyHook
|
|
17
|
-
setLPWhitelist, // Changes PolicyPool Liquidity Providers Whitelist
|
|
18
|
-
addRiskModule,
|
|
19
|
-
removeRiskModule,
|
|
20
21
|
setAssetManagerForced, // Change in the asset manager strategy of a reserve, forced (deinvest failed)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
ppFiller1, // Reserve space for future PolicyPool or AccessManager actions
|
|
23
|
+
ppFiller2, // Reserve space for future PolicyPool or AccessManager actions
|
|
24
|
+
ppFiller3, // Reserve space for future PolicyPool or AccessManager actions
|
|
25
|
+
ppFiller4, // Reserve space for future PolicyPool or AccessManager actions
|
|
24
26
|
// RiskModule Governance Actions
|
|
25
27
|
setMoc,
|
|
26
28
|
setJrCollRatio,
|
|
@@ -38,6 +40,7 @@ interface IAccessManager is IAccessControlUpgradeable {
|
|
|
38
40
|
rmFiller3, // Reserve space for future RM actions
|
|
39
41
|
rmFiller4, // Reserve space for future RM actions
|
|
40
42
|
// EToken Governance Actions
|
|
43
|
+
setLPWhitelist, // Changes EToken Liquidity Providers Whitelist
|
|
41
44
|
setLiquidityRequirement,
|
|
42
45
|
setMinUtilizationRate,
|
|
43
46
|
setMaxUtilizationRate,
|
|
@@ -46,21 +49,43 @@ interface IAccessManager is IAccessControlUpgradeable {
|
|
|
46
49
|
etkFiller2, // Reserve space for future EToken actions
|
|
47
50
|
etkFiller3, // Reserve space for future EToken actions
|
|
48
51
|
etkFiller4, // Reserve space for future EToken actions
|
|
52
|
+
// PremiumsAccount Governance Actions
|
|
53
|
+
setDeficitRatio,
|
|
54
|
+
setDeficitRatioWithAdjustment,
|
|
55
|
+
paFiller1,
|
|
56
|
+
paFiller2,
|
|
57
|
+
paFiller3,
|
|
58
|
+
paFiller4,
|
|
49
59
|
// AssetManager Governance Actions
|
|
50
60
|
setLiquidityMin,
|
|
51
61
|
setLiquidityMiddle,
|
|
52
62
|
setLiquidityMax,
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
setPriceOracle, // Changes exchange's PriceOracle
|
|
58
|
-
setSwapRouter, // Changes exchange's SwapRouter
|
|
63
|
+
amFiller1, // Reserve space for future Asset Manager actions
|
|
64
|
+
amFiller2, // Reserve space for future Asset Manager actions
|
|
65
|
+
amFiller3, // Reserve space for future Asset Manager actions
|
|
66
|
+
amFiller4, // Reserve space for future Asset Manager actions
|
|
59
67
|
last
|
|
60
68
|
}
|
|
61
69
|
|
|
70
|
+
/**
|
|
71
|
+
* @dev Gets a role identifier mixing the hash of the global role and the address of the component
|
|
72
|
+
*
|
|
73
|
+
* @param component The component where this role will apply
|
|
74
|
+
* @param role A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
75
|
+
* @return A new role, mixing (XOR) the component address and the role.
|
|
76
|
+
*/
|
|
62
77
|
function getComponentRole(address component, bytes32 role) external view returns (bytes32);
|
|
63
78
|
|
|
79
|
+
/**
|
|
80
|
+
* @dev Tells if a user has been granted a given role for a component
|
|
81
|
+
*
|
|
82
|
+
* @param component The component where this role will apply
|
|
83
|
+
* @param role A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
84
|
+
* @param account The user address for who we want to verify the permission
|
|
85
|
+
* @param alsoGlobal If true, it will return if the users has either the component role, or the role itself.
|
|
86
|
+
* If false, only the component role is accepted
|
|
87
|
+
* @return Whether the user has or not any of the roles
|
|
88
|
+
*/
|
|
64
89
|
function hasComponentRole(
|
|
65
90
|
address component,
|
|
66
91
|
bytes32 role,
|
|
@@ -68,14 +93,35 @@ interface IAccessManager is IAccessControlUpgradeable {
|
|
|
68
93
|
bool alsoGlobal
|
|
69
94
|
) external view returns (bool);
|
|
70
95
|
|
|
96
|
+
/**
|
|
97
|
+
* @dev Checks if a user has been granted a given role and reverts if it doesn't
|
|
98
|
+
*
|
|
99
|
+
* @param role A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
100
|
+
* @param account The user address for who we want to verify the permission
|
|
101
|
+
*/
|
|
71
102
|
function checkRole(bytes32 role, address account) external view;
|
|
72
103
|
|
|
104
|
+
/**
|
|
105
|
+
* @dev Checks if a user has been granted any of the two roles specified and reverts if it doesn't
|
|
106
|
+
*
|
|
107
|
+
* @param role1 A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
108
|
+
* @param role2 Another role such as `keccak256("GUARDIAN_ROLE")` that's global
|
|
109
|
+
* @param account The user address for who we want to verify the permission
|
|
110
|
+
*/
|
|
73
111
|
function checkRole2(
|
|
74
112
|
bytes32 role1,
|
|
75
113
|
bytes32 role2,
|
|
76
114
|
address account
|
|
77
115
|
) external view;
|
|
78
116
|
|
|
117
|
+
/**
|
|
118
|
+
* @dev Checks if a user has been granted a given component role and reverts if it doesn't
|
|
119
|
+
*
|
|
120
|
+
* @param role A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
121
|
+
* @param account The user address for who we want to verify the permission
|
|
122
|
+
* @param alsoGlobal If true, it will accept not only the component role, but also the (global) `role` itself.
|
|
123
|
+
* If false, only the component role is accepted
|
|
124
|
+
*/
|
|
79
125
|
function checkComponentRole(
|
|
80
126
|
address component,
|
|
81
127
|
bytes32 role,
|
|
@@ -83,6 +129,15 @@ interface IAccessManager is IAccessControlUpgradeable {
|
|
|
83
129
|
bool alsoGlobal
|
|
84
130
|
) external view;
|
|
85
131
|
|
|
132
|
+
/**
|
|
133
|
+
* @dev Checks if a user has been granted any of the two component roles specified and reverts if it doesn't
|
|
134
|
+
*
|
|
135
|
+
* @param role1 A role such as `keccak256("LEVEL1_ROLE")` that's global
|
|
136
|
+
* @param role2 Another role such as `keccak256("GUARDIAN_ROLE")` that's global
|
|
137
|
+
* @param account The user address for who we want to verify the permission
|
|
138
|
+
* @param alsoGlobal If true, it will accept not only the component roles, but also the global ones.
|
|
139
|
+
* If false, only the component roles are accepted
|
|
140
|
+
*/
|
|
86
141
|
function checkComponentRole2(
|
|
87
142
|
address component,
|
|
88
143
|
bytes32 role1,
|
|
@@ -1,22 +1,89 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @title IAssetManager - Interface of the asset management strategy that's plugged into the reserves
|
|
8
|
+
* @dev The asset manager is a contract that's plugged and called with `delegatecall` (operates in the context of the
|
|
9
|
+
* reserve - see {Reserve}). The asset manager contract applies a strategy to invest the reserve funds and
|
|
10
|
+
* get additional yields.
|
|
11
|
+
*
|
|
12
|
+
* All implementations of this contract should use the Diamond Storage pattern to avoid overwriting the calling contract's state.
|
|
13
|
+
* See https://eips.ethereum.org/EIPS/eip-2535#storage
|
|
6
14
|
* @author Ensuro
|
|
7
15
|
*/
|
|
8
|
-
interface IAssetManager {
|
|
16
|
+
interface IAssetManager is IERC165 {
|
|
17
|
+
/**
|
|
18
|
+
* @dev Event emitted when funds are removed from Reserve liquidity and invested in the investment strategy,
|
|
19
|
+
* @param amount The amount invested
|
|
20
|
+
*/
|
|
9
21
|
event MoneyInvested(uint256 amount);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @dev Event emitted when funds are deinvested from the investment strategy and returned to the reserve as liquid
|
|
25
|
+
* funds.
|
|
26
|
+
*
|
|
27
|
+
* @param amount The amount de-invested
|
|
28
|
+
*/
|
|
10
29
|
event MoneyDeinvested(uint256 amount);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @dev Event emitted when investment yields are accounted in the reserve
|
|
33
|
+
*
|
|
34
|
+
* @param earnings The amount of earnings generated since last record. It's positive in the case of earnings or
|
|
35
|
+
* negative when there are losses.
|
|
36
|
+
*/
|
|
11
37
|
event EarningsRecorded(int256 earnings);
|
|
12
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @dev Function called when an asset manager is plugged into a reserve. Useful for initialization tasks
|
|
41
|
+
*/
|
|
13
42
|
function connect() external;
|
|
14
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @dev Gives the opportunity to the asset manager to rebalance the funds between those that are kept liquid in the
|
|
46
|
+
* reserve balance and those that are invested. Called with delegatecall by the reserve from the external function
|
|
47
|
+
* rebalance (see {Reserve-rebalance}).
|
|
48
|
+
*
|
|
49
|
+
* Events:
|
|
50
|
+
* - Emits {MoneyInvested} or {MoneyDeinvested}
|
|
51
|
+
*/
|
|
15
52
|
function rebalance() external;
|
|
16
53
|
|
|
54
|
+
/**
|
|
55
|
+
* @dev Gives the opportunity to the asset manager to rebalance the funds between those that are kept liquid in the
|
|
56
|
+
* reserve balance and those that are invested. Called with delegatecall by the reserve from the external function
|
|
57
|
+
* rebalance (see {Reserve-rebalance}).
|
|
58
|
+
*
|
|
59
|
+
* Events:
|
|
60
|
+
* - Emits {MoneyInvested} or {MoneyDeinvested}
|
|
61
|
+
*/
|
|
17
62
|
function recordEarnings() external returns (int256);
|
|
18
63
|
|
|
19
|
-
|
|
64
|
+
/**
|
|
65
|
+
* @dev Refills the reserve balance with enough money to do a payment. Called from the reserve when a payment needs
|
|
66
|
+
* to be made and there's no enough liquid balance (`currency().balanceOf(reserve) < paymentAmount`)
|
|
67
|
+
*
|
|
68
|
+
* Events:
|
|
69
|
+
* - Emits {MoneyDeinvested} with the amount transferred to the liquid balance.
|
|
70
|
+
*
|
|
71
|
+
* @param paymentAmount The total amount of the payment that needs to be made. If this function is called, it's
|
|
72
|
+
* because paymentAmount > balanceOf(reserve). The minimum amount that needs to be transferred to the reserve is
|
|
73
|
+
* `paymentAmount - balanceOf(reserve)`, but it can transfer more.
|
|
74
|
+
* @return Returns the actual amount transferred
|
|
75
|
+
*/
|
|
76
|
+
function refillWallet(uint256 paymentAmount) external returns (uint256);
|
|
20
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @dev Deinvests all the funds transfer all the assets to the liquid balance. Called from the reserve when the asset
|
|
80
|
+
* manager is unplugged.
|
|
81
|
+
*
|
|
82
|
+
* Events:
|
|
83
|
+
* - Emits {MoneyDeinvested} with the amount transferred to the liquid balance.
|
|
84
|
+
* - Emits {EarningsRecorded} with the amount of earnings since earnings were recorded last time.
|
|
85
|
+
*
|
|
86
|
+
* @return Returns the earnings or losses (negative) since last time earnings were recorded.
|
|
87
|
+
*/
|
|
21
88
|
function deinvestAll() external returns (int256);
|
|
22
89
|
}
|
|
@@ -9,6 +9,9 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
|
9
9
|
* @author Ensuro
|
|
10
10
|
*/
|
|
11
11
|
interface IEToken is IERC20 {
|
|
12
|
+
/**
|
|
13
|
+
* @dev Enum of the different parameters that are configurable in an EToken.
|
|
14
|
+
*/
|
|
12
15
|
enum Parameter {
|
|
13
16
|
liquidityRequirement,
|
|
14
17
|
minUtilizationRate,
|
|
@@ -84,7 +87,7 @@ interface IEToken is IERC20 {
|
|
|
84
87
|
*
|
|
85
88
|
* @param provider The address of the liquidity provider
|
|
86
89
|
* @param amount The amount deposited.
|
|
87
|
-
* @return The actual balance of the provider
|
|
90
|
+
* @return The actual balance of the provider
|
|
88
91
|
*/
|
|
89
92
|
function deposit(address provider, uint256 amount) external returns (uint256);
|
|
90
93
|
|
|
@@ -8,12 +8,29 @@ import {IEToken} from "./IEToken.sol";
|
|
|
8
8
|
* @author Ensuro
|
|
9
9
|
*/
|
|
10
10
|
interface ILPWhitelist {
|
|
11
|
+
/**
|
|
12
|
+
* @dev Indicates whether or not a liquidity provider can do a deposit in an eToken.
|
|
13
|
+
*
|
|
14
|
+
* @param etoken The eToken (see {EToken}) where the provider wants to deposit money.
|
|
15
|
+
* @param provider The address of the liquidity provider (user) that wants to deposit
|
|
16
|
+
* @param amount The amount of the deposit
|
|
17
|
+
* @return true if `provider` deposit is accepted, false if not
|
|
18
|
+
*/
|
|
11
19
|
function acceptsDeposit(
|
|
12
20
|
IEToken etoken,
|
|
13
21
|
address provider,
|
|
14
22
|
uint256 amount
|
|
15
23
|
) external view returns (bool);
|
|
16
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @dev Indicates whether or not the eTokens can be transferred from `providerFrom` to `providerTo`
|
|
27
|
+
*
|
|
28
|
+
* @param etoken The eToken (see {EToken}) that the LPs have the intention to transfer.
|
|
29
|
+
* @param providerFrom The current owner of the tokens
|
|
30
|
+
* @param providerTo The destination of the tokens if the transfer is accepted
|
|
31
|
+
* @param amount The amount of tokens to be transferred
|
|
32
|
+
* @return true if the transfer operation is accepted, false if not.
|
|
33
|
+
*/
|
|
17
34
|
function acceptsTransfer(
|
|
18
35
|
IEToken etoken,
|
|
19
36
|
address providerFrom,
|
|
@@ -100,6 +100,24 @@ interface IPolicyPool {
|
|
|
100
100
|
*/
|
|
101
101
|
function expirePolicy(Policy.PolicyData calldata policy) external;
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* @dev Returns whether a policy is active, i.e., it's still in the PolicyPool, not yet resolved or expired.
|
|
105
|
+
* Be aware that a policy might be active but the `block.timestamp` might be after the expiration date, so it
|
|
106
|
+
* can't be triggered with a payout.
|
|
107
|
+
*
|
|
108
|
+
* @param policyId The id of the policy queried
|
|
109
|
+
* @return Whether the policy is active or not
|
|
110
|
+
*/
|
|
111
|
+
function isActive(uint256 policyId) external view returns (bool);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @dev Returns the stored hash of the policy. It's `bytes32(0)` is the policy isn't active.
|
|
115
|
+
*
|
|
116
|
+
* @param policyId The id of the policy queried
|
|
117
|
+
* @return Returns the hash of a given policy id
|
|
118
|
+
*/
|
|
119
|
+
function getPolicyHash(uint256 policyId) external view returns (bytes32);
|
|
120
|
+
|
|
103
121
|
/**
|
|
104
122
|
* @dev Deposits liquidity into an eToken. Forwards the call to {EToken-deposit}, after transferring the funds.
|
|
105
123
|
* The user will receive etokens for the same amount deposited.
|
|
@@ -130,7 +148,7 @@ interface IPolicyPool {
|
|
|
130
148
|
*
|
|
131
149
|
* @param eToken The address of the eToken from where the user wants to withdraw liquidity
|
|
132
150
|
* @param amount The amount to withdraw. If equal to type(uint256).max, means full withdrawal.
|
|
133
|
-
* If the balance is not
|
|
151
|
+
* If the balance is not enough or can't be withdrawn (locked as SCR), it withdraws
|
|
134
152
|
* as much as it can, but doesn't fails.
|
|
135
153
|
* @return Returns the actual amount withdrawn.
|
|
136
154
|
*/
|