@ensuro/core 1.2.0 → 1.2.3
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/build/contracts/AaveAssetManager.sol/AaveAssetManager.json +2 -51
- package/build/contracts/DataTypes.sol/DataTypes.json +2 -2
- package/build/contracts/EToken.sol/EToken.json +2 -2
- package/build/contracts/Exchange.sol/Exchange.json +483 -0
- package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +2 -2
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +2 -2
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +2 -90
- package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +28 -2
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +2 -2
- package/build/contracts/extras/IPriceRiskModule.sol/IPriceRiskModule.json +253 -0
- package/build/contracts/extras/PriceRiskModule.sol/PriceRiskModule.json +1036 -0
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +2 -2
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +2 -2
- package/build/interfaces/IEToken.sol/IEToken.json +26 -0
- package/build/interfaces/IExchange.sol/IExchange.json +153 -0
- package/build/interfaces/IExchange.sol/IPriceOracle.json +30 -0
- package/build/interfaces/IPolicyHolder.sol/IPolicyHolder.json +108 -0
- package/build/interfaces/IPolicyPoolConfig.sol/IPolicyPoolConfig.json +13 -0
- package/contracts/AaveAssetManager.sol +35 -63
- package/contracts/BaseAssetManager.sol +55 -37
- package/contracts/EToken.sol +3 -19
- package/contracts/Exchange.sol +142 -0
- package/contracts/PolicyPool.sol +41 -35
- package/contracts/PolicyPoolComponent.sol +4 -0
- package/contracts/PolicyPoolConfig.sol +16 -0
- package/contracts/RiskModule.sol +5 -26
- package/contracts/extras/IPriceRiskModule.sol +41 -0
- package/contracts/extras/PriceRiskModule.sol +243 -0
- package/interfaces/IExchange.sol +47 -0
- package/interfaces/IPolicyHolder.sol +42 -0
- package/interfaces/IPolicyPoolConfig.sol +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_format": "hh-sol-artifact-1",
|
|
3
|
+
"contractName": "IPolicyHolder",
|
|
4
|
+
"sourceName": "interfaces/IPolicyHolder.sol",
|
|
5
|
+
"abi": [
|
|
6
|
+
{
|
|
7
|
+
"inputs": [
|
|
8
|
+
{
|
|
9
|
+
"internalType": "address",
|
|
10
|
+
"name": "operator",
|
|
11
|
+
"type": "address"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"internalType": "address",
|
|
15
|
+
"name": "from",
|
|
16
|
+
"type": "address"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"internalType": "uint256",
|
|
20
|
+
"name": "tokenId",
|
|
21
|
+
"type": "uint256"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"internalType": "bytes",
|
|
25
|
+
"name": "data",
|
|
26
|
+
"type": "bytes"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"name": "onERC721Received",
|
|
30
|
+
"outputs": [
|
|
31
|
+
{
|
|
32
|
+
"internalType": "bytes4",
|
|
33
|
+
"name": "",
|
|
34
|
+
"type": "bytes4"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"stateMutability": "nonpayable",
|
|
38
|
+
"type": "function"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"inputs": [
|
|
42
|
+
{
|
|
43
|
+
"internalType": "address",
|
|
44
|
+
"name": "operator",
|
|
45
|
+
"type": "address"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"internalType": "address",
|
|
49
|
+
"name": "from",
|
|
50
|
+
"type": "address"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"internalType": "uint256",
|
|
54
|
+
"name": "policyId",
|
|
55
|
+
"type": "uint256"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"internalType": "uint256",
|
|
59
|
+
"name": "amount",
|
|
60
|
+
"type": "uint256"
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"name": "onPayoutReceived",
|
|
64
|
+
"outputs": [
|
|
65
|
+
{
|
|
66
|
+
"internalType": "bytes4",
|
|
67
|
+
"name": "",
|
|
68
|
+
"type": "bytes4"
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"stateMutability": "nonpayable",
|
|
72
|
+
"type": "function"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"inputs": [
|
|
76
|
+
{
|
|
77
|
+
"internalType": "address",
|
|
78
|
+
"name": "operator",
|
|
79
|
+
"type": "address"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"internalType": "address",
|
|
83
|
+
"name": "from",
|
|
84
|
+
"type": "address"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"internalType": "uint256",
|
|
88
|
+
"name": "policyId",
|
|
89
|
+
"type": "uint256"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"name": "onPolicyExpired",
|
|
93
|
+
"outputs": [
|
|
94
|
+
{
|
|
95
|
+
"internalType": "bytes4",
|
|
96
|
+
"name": "",
|
|
97
|
+
"type": "bytes4"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"stateMutability": "nonpayable",
|
|
101
|
+
"type": "function"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"bytecode": "0x",
|
|
105
|
+
"deployedBytecode": "0x",
|
|
106
|
+
"linkReferences": {},
|
|
107
|
+
"deployedLinkReferences": {}
|
|
108
|
+
}
|
|
@@ -184,6 +184,19 @@
|
|
|
184
184
|
"stateMutability": "nonpayable",
|
|
185
185
|
"type": "function"
|
|
186
186
|
},
|
|
187
|
+
{
|
|
188
|
+
"inputs": [],
|
|
189
|
+
"name": "exchange",
|
|
190
|
+
"outputs": [
|
|
191
|
+
{
|
|
192
|
+
"internalType": "contract IExchange",
|
|
193
|
+
"name": "",
|
|
194
|
+
"type": "address"
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"stateMutability": "view",
|
|
198
|
+
"type": "function"
|
|
199
|
+
},
|
|
187
200
|
{
|
|
188
201
|
"inputs": [
|
|
189
202
|
{
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
|
+
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
|
|
4
5
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
5
6
|
import {BaseAssetManager} from "./BaseAssetManager.sol";
|
|
6
7
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
7
8
|
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
8
9
|
import {IPolicyPoolConfig} from "../interfaces/IPolicyPoolConfig.sol";
|
|
10
|
+
import {IExchange} from "../interfaces/IExchange.sol";
|
|
9
11
|
import {WadRayMath} from "./WadRayMath.sol";
|
|
10
12
|
import {ILendingPoolAddressesProvider} from "@aave/protocol-v2/contracts/interfaces/ILendingPoolAddressesProvider.sol";
|
|
11
13
|
import {ILendingPool} from "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol";
|
|
12
14
|
import {IAToken} from "@aave/protocol-v2/contracts/interfaces/IAToken.sol";
|
|
13
|
-
import {IPriceOracle} from "@aave/protocol-v2/contracts/interfaces/IPriceOracle.sol";
|
|
14
15
|
import {AaveProtocolDataProvider} from "@aave/protocol-v2/contracts/misc/AaveProtocolDataProvider.sol";
|
|
15
|
-
import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @title AssetManager that reinvests the capital in AAVE
|
|
@@ -29,6 +29,7 @@ import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUn
|
|
|
29
29
|
contract AaveAssetManager is BaseAssetManager {
|
|
30
30
|
using SafeERC20 for IERC20Metadata;
|
|
31
31
|
using WadRayMath for uint256;
|
|
32
|
+
using AddressUpgradeable for address;
|
|
32
33
|
|
|
33
34
|
bytes32 public constant SWAP_REWARDS_ROLE = keccak256("SWAP_REWARDS_ROLE");
|
|
34
35
|
|
|
@@ -41,10 +42,8 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
41
42
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
42
43
|
IERC20Metadata internal immutable _rewardToken;
|
|
43
44
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
44
|
-
IUniswapV2Router02 internal immutable _swapRouter; // We will use SushiSwap in Polygon
|
|
45
45
|
uint256 internal _claimRewardsMin; // Minimum amount of rewards accumulated to claim
|
|
46
46
|
uint256 internal _reinvestRewardsMin; // Minimum amount of rewards to reinvest into AAVE
|
|
47
|
-
uint256 internal _maxSlippage; // Maximum slippage in WAD
|
|
48
47
|
|
|
49
48
|
bytes32 internal constant DATA_PROVIDER_ID =
|
|
50
49
|
0x0100000000000000000000000000000000000000000000000000000000000000;
|
|
@@ -54,13 +53,10 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
54
53
|
event RewardSwapped(uint256 rewardIn, uint256 currencyOut);
|
|
55
54
|
|
|
56
55
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
57
|
-
constructor(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
IUniswapV2Router02 swapRouter_
|
|
61
|
-
) BaseAssetManager(policyPool_) {
|
|
56
|
+
constructor(IPolicyPool policyPool_, ILendingPoolAddressesProvider aaveAddrProv_)
|
|
57
|
+
BaseAssetManager(policyPool_)
|
|
58
|
+
{
|
|
62
59
|
_aaveAddrProv = aaveAddrProv_;
|
|
63
|
-
_swapRouter = swapRouter_;
|
|
64
60
|
AaveProtocolDataProvider dataProvider = AaveProtocolDataProvider(
|
|
65
61
|
aaveAddrProv_.getAddress(DATA_PROVIDER_ID)
|
|
66
62
|
);
|
|
@@ -77,23 +73,19 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
77
73
|
uint256 liquidityMiddle_,
|
|
78
74
|
uint256 liquidityMax_,
|
|
79
75
|
uint256 claimRewardsMin_,
|
|
80
|
-
uint256 reinvestRewardsMin_
|
|
81
|
-
uint256 maxSlippage_
|
|
76
|
+
uint256 reinvestRewardsMin_
|
|
82
77
|
) public initializer {
|
|
83
78
|
__BaseAssetManager_init(liquidityMin_, liquidityMiddle_, liquidityMax_);
|
|
84
|
-
__AaveAssetManager_init(claimRewardsMin_, reinvestRewardsMin_
|
|
79
|
+
__AaveAssetManager_init(claimRewardsMin_, reinvestRewardsMin_);
|
|
85
80
|
}
|
|
86
81
|
|
|
87
82
|
// solhint-disable-next-line func-name-mixedcase
|
|
88
|
-
function __AaveAssetManager_init(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
) internal initializer {
|
|
83
|
+
function __AaveAssetManager_init(uint256 claimRewardsMin_, uint256 reinvestRewardsMin_)
|
|
84
|
+
internal
|
|
85
|
+
initializer
|
|
86
|
+
{
|
|
93
87
|
_claimRewardsMin = claimRewardsMin_;
|
|
94
88
|
_reinvestRewardsMin = reinvestRewardsMin_;
|
|
95
|
-
require(maxSlippage_ <= 1e17, "maxSlippage can't be more than 10%");
|
|
96
|
-
_maxSlippage = maxSlippage_;
|
|
97
89
|
}
|
|
98
90
|
|
|
99
91
|
function getInvestmentValue() public view override returns (uint256) {
|
|
@@ -130,14 +122,14 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
130
122
|
return ILendingPool(_aaveAddrProv.getLendingPool());
|
|
131
123
|
}
|
|
132
124
|
|
|
133
|
-
function priceOracle() public view returns (IPriceOracle) {
|
|
134
|
-
return IPriceOracle(_aaveAddrProv.getPriceOracle());
|
|
135
|
-
}
|
|
136
|
-
|
|
137
125
|
function _aaveDataProvider() internal view returns (AaveProtocolDataProvider) {
|
|
138
126
|
return AaveProtocolDataProvider(_aaveAddrProv.getAddress(DATA_PROVIDER_ID));
|
|
139
127
|
}
|
|
140
128
|
|
|
129
|
+
function _exchange() internal view returns (IExchange) {
|
|
130
|
+
return policyPool().config().exchange();
|
|
131
|
+
}
|
|
132
|
+
|
|
141
133
|
function aToken() public view returns (IAToken) {
|
|
142
134
|
return _aToken;
|
|
143
135
|
}
|
|
@@ -158,19 +150,7 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
158
150
|
}
|
|
159
151
|
|
|
160
152
|
function _rewardToCurrency(uint256 amount) internal view returns (uint256) {
|
|
161
|
-
|
|
162
|
-
IPriceOracle oracle = priceOracle();
|
|
163
|
-
IERC20Metadata from_ = rewardToken();
|
|
164
|
-
IERC20Metadata to_ = currency();
|
|
165
|
-
uint256 exchangeRate = oracle.getAssetPrice(address(from_)).wadDiv(
|
|
166
|
-
oracle.getAssetPrice(address(to_))
|
|
167
|
-
);
|
|
168
|
-
if (from_.decimals() > to_.decimals()) {
|
|
169
|
-
exchangeRate /= 10**(from_.decimals() - to_.decimals());
|
|
170
|
-
} else {
|
|
171
|
-
exchangeRate *= 10**(from_.decimals() - to_.decimals());
|
|
172
|
-
}
|
|
173
|
-
return amount.wadMul(exchangeRate);
|
|
153
|
+
return _exchange().convert(address(rewardToken()), address(currency()), amount);
|
|
174
154
|
}
|
|
175
155
|
|
|
176
156
|
function reinvestRewardToken() public {
|
|
@@ -183,28 +163,31 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
183
163
|
}
|
|
184
164
|
|
|
185
165
|
function _swapRewards(uint256 amount, address outAddr) internal returns (uint256, uint256) {
|
|
186
|
-
|
|
187
|
-
uint256 swapIn =
|
|
166
|
+
IERC20Metadata rw = rewardToken();
|
|
167
|
+
uint256 swapIn = rw.balanceOf(address(this));
|
|
188
168
|
if (swapIn < amount) {
|
|
189
169
|
uint256 toWithdraw = amount - swapIn;
|
|
190
170
|
if (rewardAToken().balanceOf(address(this)) < toWithdraw) {
|
|
191
171
|
toWithdraw = type(uint256).max; // if not enought withdraw all
|
|
192
172
|
}
|
|
193
|
-
swapIn += lendingPool().withdraw(
|
|
173
|
+
swapIn += lendingPool().withdraw(address(rw), toWithdraw, address(this));
|
|
194
174
|
} else {
|
|
195
175
|
swapIn = amount;
|
|
196
176
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
177
|
+
address swapRouter = _exchange().getSwapRouter();
|
|
178
|
+
rw.approve(swapRouter, swapIn);
|
|
179
|
+
bytes memory swapCall = _exchange().sell(
|
|
180
|
+
address(rw),
|
|
181
|
+
address(currency()),
|
|
200
182
|
swapIn,
|
|
201
|
-
swapOutMin,
|
|
202
|
-
path,
|
|
203
183
|
outAddr,
|
|
204
184
|
block.timestamp
|
|
205
185
|
);
|
|
206
|
-
|
|
207
|
-
|
|
186
|
+
|
|
187
|
+
bytes memory response = swapRouter.functionCall(swapCall, "Swap operation failed");
|
|
188
|
+
uint256 swapOut = _exchange().decodeSwapOut(response);
|
|
189
|
+
emit RewardSwapped(swapIn, swapOut);
|
|
190
|
+
return (swapIn, swapOut);
|
|
208
191
|
}
|
|
209
192
|
|
|
210
193
|
function swapRewards(uint256 amount)
|
|
@@ -250,7 +233,11 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
250
233
|
// In this case, it's safe using getAmountsIn to compute how many rewards are needed to swap
|
|
251
234
|
// but then, when I do the swap I validate the slippage with the market price (given by AAVE's Oracle)
|
|
252
235
|
// is acceptable
|
|
253
|
-
uint256 requiredRewards =
|
|
236
|
+
uint256 requiredRewards = _exchange().getAmountIn(
|
|
237
|
+
address(rewardToken()),
|
|
238
|
+
address(currency()),
|
|
239
|
+
remainingAmount
|
|
240
|
+
);
|
|
254
241
|
(, uint256 currencyOut) = _swapRewards(requiredRewards, address(_policyPool));
|
|
255
242
|
if (currencyOut < remainingAmount) {
|
|
256
243
|
remainingAmount -= currencyOut;
|
|
@@ -286,10 +273,6 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
286
273
|
return _reinvestRewardsMin;
|
|
287
274
|
}
|
|
288
275
|
|
|
289
|
-
function maxSlippage() external view returns (uint256) {
|
|
290
|
-
return _maxSlippage;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
276
|
function setClaimRewardsMin(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
294
277
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
295
278
|
require(
|
|
@@ -312,15 +295,4 @@ contract AaveAssetManager is BaseAssetManager {
|
|
|
312
295
|
_reinvestRewardsMin = newValue;
|
|
313
296
|
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setReinvestRewardsMin, newValue, tweak);
|
|
314
297
|
}
|
|
315
|
-
|
|
316
|
-
function setMaxSlippage(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
317
|
-
require(newValue <= 1e17, "maxSlippage can't be more than 10%");
|
|
318
|
-
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
319
|
-
require(
|
|
320
|
-
!tweak || _isTweakWad(_maxSlippage, newValue, 3e26),
|
|
321
|
-
"Tweak exceeded: maxSlippage tweaks only up to 30%"
|
|
322
|
-
);
|
|
323
|
-
_maxSlippage = newValue;
|
|
324
|
-
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setMaxSlippage, newValue, tweak);
|
|
325
|
-
}
|
|
326
298
|
}
|
|
@@ -34,11 +34,6 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
34
34
|
event MoneyDeinvested(uint256 amount);
|
|
35
35
|
event EarningsDistributed(bool positive, uint256 amount);
|
|
36
36
|
|
|
37
|
-
modifier validateParamsAfterChange() {
|
|
38
|
-
_;
|
|
39
|
-
_validateParameters();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
37
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
43
38
|
// solhint-disable-next-line no-empty-blocks
|
|
44
39
|
constructor(IPolicyPool policyPool_) PolicyPoolComponent(policyPool_) {}
|
|
@@ -74,7 +69,7 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
74
69
|
_validateParameters();
|
|
75
70
|
}
|
|
76
71
|
|
|
77
|
-
function _validateParameters() internal view {
|
|
72
|
+
function _validateParameters() internal view override {
|
|
78
73
|
require(
|
|
79
74
|
_liquidityMin <= _liquidityMiddle && _liquidityMiddle <= _liquidityMax,
|
|
80
75
|
"Validation: Liquidity limits are invalid"
|
|
@@ -217,31 +212,7 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
217
212
|
return _liquidityMax;
|
|
218
213
|
}
|
|
219
214
|
|
|
220
|
-
function setLiquidityMin(uint256 newValue)
|
|
221
|
-
external
|
|
222
|
-
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
223
|
-
validateParamsAfterChange
|
|
224
|
-
{
|
|
225
|
-
_setLiquidityMin(newValue);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function setLiquidityMiddle(uint256 newValue)
|
|
229
|
-
external
|
|
230
|
-
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
231
|
-
validateParamsAfterChange
|
|
232
|
-
{
|
|
233
|
-
_setLiquidityMiddle(newValue);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function setLiquidityMax(uint256 newValue)
|
|
237
|
-
external
|
|
238
|
-
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
239
|
-
validateParamsAfterChange
|
|
240
|
-
{
|
|
241
|
-
_setLiquidityMax(newValue);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function _setLiquidityMin(uint256 newValue) internal {
|
|
215
|
+
function setLiquidityMin(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
245
216
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
246
217
|
require(
|
|
247
218
|
!tweak || _isTweakRay(_liquidityMin, newValue, 3e26),
|
|
@@ -251,7 +222,7 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
251
222
|
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMin, newValue, tweak);
|
|
252
223
|
}
|
|
253
224
|
|
|
254
|
-
function
|
|
225
|
+
function setLiquidityMiddle(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
255
226
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
256
227
|
require(
|
|
257
228
|
!tweak || _isTweakRay(_liquidityMiddle, newValue, 3e26),
|
|
@@ -261,7 +232,7 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
261
232
|
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMiddle, newValue, tweak);
|
|
262
233
|
}
|
|
263
234
|
|
|
264
|
-
function
|
|
235
|
+
function setLiquidityMax(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
265
236
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
266
237
|
require(
|
|
267
238
|
!tweak || _isTweakRay(_liquidityMax, newValue, 3e26),
|
|
@@ -275,9 +246,56 @@ abstract contract BaseAssetManager is IAssetManager, PolicyPoolComponent {
|
|
|
275
246
|
uint256 min,
|
|
276
247
|
uint256 middle,
|
|
277
248
|
uint256 max
|
|
278
|
-
) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
249
|
+
) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
250
|
+
bool setMin = min != type(uint256).max;
|
|
251
|
+
bool setMiddle = middle != type(uint256).max;
|
|
252
|
+
bool setMax = max != type(uint256).max;
|
|
253
|
+
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
254
|
+
// First set all - Then call _parameterChanged
|
|
255
|
+
if (setMin) {
|
|
256
|
+
require(
|
|
257
|
+
!tweak || _isTweakRay(_liquidityMin, min, 3e26),
|
|
258
|
+
"Tweak exceeded: liquidityMin tweaks only up to 30%"
|
|
259
|
+
);
|
|
260
|
+
_liquidityMin = min;
|
|
261
|
+
}
|
|
262
|
+
if (setMiddle) {
|
|
263
|
+
require(
|
|
264
|
+
!tweak || _isTweakRay(_liquidityMiddle, middle, 3e26),
|
|
265
|
+
"Tweak exceeded: liquidityMiddle tweaks only up to 30%"
|
|
266
|
+
);
|
|
267
|
+
_liquidityMiddle = middle;
|
|
268
|
+
}
|
|
269
|
+
if (setMax) {
|
|
270
|
+
require(
|
|
271
|
+
!tweak || _isTweakRay(_liquidityMax, max, 3e26),
|
|
272
|
+
"Tweak exceeded: liquidityMax tweaks only up to 30%"
|
|
273
|
+
);
|
|
274
|
+
_liquidityMax = max;
|
|
275
|
+
}
|
|
276
|
+
if (setMin) _parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMin, min, tweak);
|
|
277
|
+
if (setMiddle)
|
|
278
|
+
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMiddle, middle, tweak);
|
|
279
|
+
if (setMax) _parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMax, max, tweak);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function _setLiquidityMiddle(uint256 newValue) internal {
|
|
283
|
+
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
284
|
+
require(
|
|
285
|
+
!tweak || _isTweakRay(_liquidityMiddle, newValue, 3e26),
|
|
286
|
+
"Tweak exceeded: liquidityMiddle tweaks only up to 30%"
|
|
287
|
+
);
|
|
288
|
+
_liquidityMiddle = newValue;
|
|
289
|
+
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMiddle, newValue, tweak);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function _setLiquidityMax(uint256 newValue) internal {
|
|
293
|
+
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
294
|
+
require(
|
|
295
|
+
!tweak || _isTweakRay(_liquidityMax, newValue, 3e26),
|
|
296
|
+
"Tweak exceeded: liquidityMax tweaks only up to 30%"
|
|
297
|
+
);
|
|
298
|
+
_liquidityMax = newValue;
|
|
299
|
+
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityMax, newValue, tweak);
|
|
282
300
|
}
|
|
283
301
|
}
|
package/contracts/EToken.sol
CHANGED
|
@@ -64,11 +64,6 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
64
64
|
_;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
modifier validateParamsAfterChange() {
|
|
68
|
-
_;
|
|
69
|
-
_validateParameters();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
67
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
73
68
|
// solhint-disable-next-line no-empty-blocks
|
|
74
69
|
constructor(IPolicyPool policyPool_) PolicyPoolComponent(policyPool_) {}
|
|
@@ -130,7 +125,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
130
125
|
}
|
|
131
126
|
|
|
132
127
|
// runs validation on EToken parameters
|
|
133
|
-
function _validateParameters() internal view {
|
|
128
|
+
function _validateParameters() internal view override {
|
|
134
129
|
require(
|
|
135
130
|
_liquidityRequirement >= 8e26 && _liquidityRequirement <= 13e26,
|
|
136
131
|
"Validation: liquidityRequirement must be [0.8, 1.3]"
|
|
@@ -703,7 +698,6 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
703
698
|
function setPoolLoanInterestRate(uint256 newRate)
|
|
704
699
|
external
|
|
705
700
|
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
706
|
-
validateParamsAfterChange
|
|
707
701
|
{
|
|
708
702
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
709
703
|
require(
|
|
@@ -718,7 +712,6 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
718
712
|
function setLiquidityRequirement(uint256 newRate)
|
|
719
713
|
external
|
|
720
714
|
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
721
|
-
validateParamsAfterChange
|
|
722
715
|
{
|
|
723
716
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
724
717
|
require(
|
|
@@ -729,11 +722,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
729
722
|
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityRequirement, newRate, tweak);
|
|
730
723
|
}
|
|
731
724
|
|
|
732
|
-
function setMaxUtilizationRate(uint256 newRate)
|
|
733
|
-
external
|
|
734
|
-
onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
735
|
-
validateParamsAfterChange
|
|
736
|
-
{
|
|
725
|
+
function setMaxUtilizationRate(uint256 newRate) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
737
726
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
738
727
|
require(
|
|
739
728
|
!tweak || _isTweakRay(_maxUtilizationRate, newRate, 3e26),
|
|
@@ -743,11 +732,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
743
732
|
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setMaxUtilizationRate, newRate, tweak);
|
|
744
733
|
}
|
|
745
734
|
|
|
746
|
-
function setAcceptAllRMs(bool acceptAllRMs_)
|
|
747
|
-
external
|
|
748
|
-
onlyPoolRole(LEVEL2_ROLE)
|
|
749
|
-
validateParamsAfterChange
|
|
750
|
-
{
|
|
735
|
+
function setAcceptAllRMs(bool acceptAllRMs_) external onlyPoolRole(LEVEL2_ROLE) {
|
|
751
736
|
_acceptAllRMs = acceptAllRMs_;
|
|
752
737
|
_parameterChanged(
|
|
753
738
|
IPolicyPoolConfig.GovernanceActions.setAcceptAllRMs,
|
|
@@ -759,7 +744,6 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
759
744
|
function setAcceptException(address riskModule, bool isException)
|
|
760
745
|
external
|
|
761
746
|
onlyPoolRole(LEVEL2_ROLE)
|
|
762
|
-
validateParamsAfterChange
|
|
763
747
|
{
|
|
764
748
|
_acceptExceptions[riskModule] = isException;
|
|
765
749
|
uint256 value = uint160(riskModule);
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
5
|
+
import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
|
|
6
|
+
import {IPolicyPool} from "../interfaces/IPolicyPool.sol";
|
|
7
|
+
import {IPolicyPoolConfig} from "../interfaces/IPolicyPoolConfig.sol";
|
|
8
|
+
import {PolicyPoolComponent} from "./PolicyPoolComponent.sol";
|
|
9
|
+
import {IExchange, IPriceOracle} from "../interfaces/IExchange.sol";
|
|
10
|
+
import {WadRayMath} from "./WadRayMath.sol";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @title Exchange contract
|
|
14
|
+
* @dev Helper contract that handles exchange operations between assets
|
|
15
|
+
* @custom:security-contact security@ensuro.co
|
|
16
|
+
* @author Ensuro
|
|
17
|
+
*/
|
|
18
|
+
contract Exchange is IExchange, PolicyPoolComponent {
|
|
19
|
+
using WadRayMath for uint256;
|
|
20
|
+
|
|
21
|
+
IPriceOracle internal _oracle;
|
|
22
|
+
IUniswapV2Router02 internal _swapRouter; // We will use SushiSwap in Polygon
|
|
23
|
+
uint256 internal _maxSlippage; // Maximum slippage in WAD
|
|
24
|
+
|
|
25
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
26
|
+
// solhint-disable-next-line no-empty-blocks
|
|
27
|
+
constructor(IPolicyPool policyPool_) PolicyPoolComponent(policyPool_) {}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @dev Initializes the RiskModule
|
|
31
|
+
* @param oracle_ Oracle that provides the price of the assets
|
|
32
|
+
* @param swapRouter_ Uniswap compatible exchange
|
|
33
|
+
* @param maxSlippage_ Maximum slippage admitted for exchange operations
|
|
34
|
+
*/
|
|
35
|
+
function initialize(
|
|
36
|
+
IPriceOracle oracle_,
|
|
37
|
+
IUniswapV2Router02 swapRouter_,
|
|
38
|
+
uint256 maxSlippage_
|
|
39
|
+
) public initializer {
|
|
40
|
+
__PolicyPoolComponent_init();
|
|
41
|
+
__Exchange_init(oracle_, swapRouter_, maxSlippage_);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
45
|
+
function __Exchange_init(
|
|
46
|
+
IPriceOracle oracle_,
|
|
47
|
+
IUniswapV2Router02 swapRouter_,
|
|
48
|
+
uint256 maxSlippage_
|
|
49
|
+
) internal initializer {
|
|
50
|
+
_oracle = oracle_;
|
|
51
|
+
_swapRouter = swapRouter_;
|
|
52
|
+
_maxSlippage = maxSlippage_;
|
|
53
|
+
_validateParameters();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function _validateParameters() internal view override {
|
|
57
|
+
require(_maxSlippage <= 1e17, "maxSlippage can't be more than 10%");
|
|
58
|
+
require(address(_oracle) != address(0), "I need a price oracle");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function convert(
|
|
62
|
+
address assetFrom,
|
|
63
|
+
address assetTo,
|
|
64
|
+
uint256 amount
|
|
65
|
+
) public view override returns (uint256) {
|
|
66
|
+
uint256 exchangeRate = _oracle.getAssetPrice(assetFrom).wadDiv(_oracle.getAssetPrice(assetTo));
|
|
67
|
+
uint8 decFrom = IERC20Metadata(assetFrom).decimals();
|
|
68
|
+
uint8 decTo = IERC20Metadata(assetTo).decimals();
|
|
69
|
+
if (decFrom > decTo) {
|
|
70
|
+
exchangeRate /= 10**(decFrom - decTo);
|
|
71
|
+
} else {
|
|
72
|
+
exchangeRate *= 10**(decTo - decFrom);
|
|
73
|
+
}
|
|
74
|
+
return amount.wadMul(exchangeRate);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getAmountIn(
|
|
78
|
+
address assetIn,
|
|
79
|
+
address assetOut,
|
|
80
|
+
uint256 amountOut
|
|
81
|
+
) external view override returns (uint256) {
|
|
82
|
+
return _swapRouter.getAmountsIn(amountOut, _exchangePath(assetIn, assetOut))[0];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getSwapRouter() external view override returns (address) {
|
|
86
|
+
return address(_swapRouter);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getPriceOracle() external view override returns (IPriceOracle) {
|
|
90
|
+
return IPriceOracle(_oracle);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function _exchangePath(address assetIn, address assetOut)
|
|
94
|
+
internal
|
|
95
|
+
pure
|
|
96
|
+
returns (address[] memory)
|
|
97
|
+
{
|
|
98
|
+
address[] memory path = new address[](2);
|
|
99
|
+
path[0] = assetIn;
|
|
100
|
+
path[1] = assetOut;
|
|
101
|
+
return path;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function sell(
|
|
105
|
+
address assetIn,
|
|
106
|
+
address assetOut,
|
|
107
|
+
uint256 amountInExact,
|
|
108
|
+
address outAddr,
|
|
109
|
+
uint256 deadline
|
|
110
|
+
) external view override returns (bytes memory) {
|
|
111
|
+
uint256 amountOutMin = convert(assetIn, assetOut, amountInExact).wadMul(1e18 - _maxSlippage);
|
|
112
|
+
|
|
113
|
+
return
|
|
114
|
+
abi.encodeWithSignature(
|
|
115
|
+
"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)",
|
|
116
|
+
amountInExact,
|
|
117
|
+
amountOutMin,
|
|
118
|
+
_exchangePath(assetIn, assetOut),
|
|
119
|
+
outAddr,
|
|
120
|
+
deadline
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function decodeSwapOut(bytes memory responseData) external pure override returns (uint256) {
|
|
125
|
+
return abi.decode(responseData, (uint256[]))[1];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function maxSlippage() external view returns (uint256) {
|
|
129
|
+
return _maxSlippage;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function setMaxSlippage(uint256 newValue) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
133
|
+
require(newValue <= 1e17, "maxSlippage can't be more than 10%");
|
|
134
|
+
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
135
|
+
require(
|
|
136
|
+
!tweak || _isTweakWad(_maxSlippage, newValue, 3e26),
|
|
137
|
+
"Tweak exceeded: maxSlippage tweaks only up to 30%"
|
|
138
|
+
);
|
|
139
|
+
_maxSlippage = newValue;
|
|
140
|
+
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setMaxSlippage, newValue, tweak);
|
|
141
|
+
}
|
|
142
|
+
}
|