@ensuro/core 1.2.7 → 2.0.0-beta10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -27
- package/build/contracts/AccessManager.sol/AccessManager.json +559 -0
- package/build/contracts/ERC4626AssetManager.sol/ERC4626AssetManager.json +219 -0
- package/build/contracts/EToken.sol/EToken.json +217 -190
- package/build/contracts/LPManualWhitelist.sol/LPManualWhitelist.json +17 -4
- package/build/contracts/{extras/IPriceRiskModule.sol/IPriceRiskModule.json → LiquidityThresholdAssetManager.sol/LiquidityThresholdAssetManager.json} +81 -131
- package/build/contracts/Policy.sol/Policy.json +2 -2
- package/build/contracts/PolicyPool.sol/PolicyPool.json +425 -295
- package/build/contracts/PolicyPoolComponent.sol/PolicyPoolComponent.json +15 -2
- package/build/contracts/PremiumsAccount.sol/PremiumsAccount.json +868 -0
- package/build/contracts/{BaseAssetManager.sol/BaseAssetManager.json → Reserve.sol/Reserve.json} +37 -166
- package/build/contracts/RiskModule.sol/RiskModule.json +85 -312
- package/build/contracts/SignedQuoteRiskModule.sol/SignedQuoteRiskModule.json +960 -0
- package/build/contracts/{DataTypes.sol/DataTypes.json → TimeScaled.sol/TimeScaled.json} +4 -4
- package/build/contracts/TrustfulRiskModule.sol/TrustfulRiskModule.json +134 -336
- package/build/contracts/dependencies/ERC1967Proxy.sol/ERC1967Proxy.json +64 -0
- package/build/{interfaces/IExchange.sol/IExchange.json → contracts/dependencies/IERC20Metadata.sol/IERC20Metadata.json} +83 -79
- package/build/contracts/{WadRayMath.sol → dependencies/WadRayMath.sol}/WadRayMath.json +3 -3
- package/build/{interfaces/IPolicyPoolConfig.sol/IPolicyPoolConfig.json → contracts/interfaces/IAccessManager.sol/IAccessManager.json} +79 -77
- package/build/contracts/interfaces/IAssetManager.sol/IAssetManager.json +109 -0
- package/build/{interfaces → contracts/interfaces}/IEToken.sol/IEToken.json +39 -91
- package/build/{interfaces → contracts/interfaces}/ILPWhitelist.sol/ILPWhitelist.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyHolder.sol/IPolicyHolder.json +1 -1
- package/build/{interfaces → contracts/interfaces}/IPolicyPool.sol/IPolicyPool.json +137 -100
- package/build/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol/IPolicyPoolComponent.json +1 -1
- package/build/contracts/interfaces/IPremiumsAccount.sol/IPremiumsAccount.json +315 -0
- package/build/{interfaces → contracts/interfaces}/IRiskModule.sol/IRiskModule.json +58 -34
- package/build/contracts/mocks/FixedRateVault.sol/FixedRateVault.json +736 -0
- package/build/contracts/mocks/ForwardProxy.sol/ForwardProxy.json +43 -0
- package/build/{interfaces/IInsolvencyHook.sol/IInsolvencyHook.json → contracts/mocks/IMintableERC20.sol/IMintableERC20.json} +13 -8
- package/build/contracts/mocks/PolicyHolderMock.sol/PolicyHolderMock.json +228 -0
- package/build/contracts/mocks/PolicyPoolComponentMock.sol/PolicyPoolComponentMock.json +35 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMock.json +702 -0
- package/build/contracts/mocks/PolicyPoolMock.sol/PolicyPoolMockForward.json +92 -0
- package/build/contracts/mocks/RiskModuleMock.sol/RiskModuleMock.json +764 -0
- package/build/contracts/mocks/TestCurrency.sol/TestCurrency.json +343 -0
- package/build/contracts/mocks/TestNFT.sol/TestNFT.json +388 -0
- package/contracts/AccessManager.sol +103 -0
- package/contracts/ERC4626AssetManager.sol +52 -0
- package/contracts/EToken.sol +254 -299
- package/contracts/LPManualWhitelist.sol +4 -4
- package/contracts/LiquidityThresholdAssetManager.sol +160 -0
- package/contracts/Policy.sol +49 -45
- package/contracts/PolicyPool.sol +379 -514
- package/contracts/PolicyPoolComponent.sol +41 -41
- package/contracts/PremiumsAccount.sol +480 -0
- package/contracts/Reserve.sol +213 -0
- package/contracts/RiskModule.sol +233 -174
- package/contracts/SignedQuoteRiskModule.sol +241 -0
- package/contracts/TimeScaled.sol +138 -0
- package/contracts/TrustfulRiskModule.sol +85 -23
- package/contracts/dependencies/ERC1967Proxy.sol +19 -0
- package/contracts/dependencies/IERC20Metadata.sol +19 -0
- package/contracts/dependencies/WadRayMath.sol +126 -0
- package/contracts/interfaces/IAccessManager.sol +148 -0
- package/contracts/interfaces/IAssetManager.sol +84 -0
- package/contracts/interfaces/IEToken.sol +195 -0
- package/contracts/interfaces/ILPWhitelist.sol +40 -0
- package/{interfaces → contracts/interfaces}/IPolicyHolder.sol +0 -0
- package/contracts/interfaces/IPolicyPool.sol +145 -0
- package/{interfaces → contracts/interfaces}/IPolicyPoolComponent.sol +3 -0
- package/contracts/interfaces/IPremiumsAccount.sol +76 -0
- package/contracts/interfaces/IRiskModule.sol +123 -0
- package/contracts/mocks/FixedRateVault.sol +85 -0
- package/contracts/mocks/ForwardProxy.sol +66 -0
- package/contracts/mocks/IMintableERC20.sol +13 -0
- package/contracts/mocks/PolicyHolderMock.sol +89 -0
- package/contracts/mocks/PolicyPoolComponentMock.sol +17 -0
- package/contracts/mocks/PolicyPoolMock.sol +148 -0
- package/contracts/mocks/RiskModuleMock.sol +75 -0
- package/contracts/mocks/TestCurrency.sol +35 -0
- package/contracts/mocks/TestNFT.sol +23 -0
- package/js/test-utils.js +356 -0
- package/package.json +2 -2
- package/build/contracts/AaveAssetManager.sol/AaveAssetManager.json +0 -742
- package/build/contracts/Exchange.sol/Exchange.json +0 -591
- package/build/contracts/FlightDelayRiskModule.sol/FlightDelayRiskModule.json +0 -1112
- package/build/contracts/PolicyNFT.sol/PolicyNFT.json +0 -570
- package/build/contracts/PolicyPoolConfig.sol/PolicyPoolConfig.json +0 -686
- package/build/contracts/dependencies/ChainlinkClientUpgradeable.sol/ChainlinkClientUpgradeable.json +0 -50
- package/build/contracts/extras/PriceRiskModule.sol/PriceRiskModule.json +0 -1055
- package/build/contracts/upgraded/IPolicyNFTv1.sol/IPolicyNFTv1.json +0 -322
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1.json +0 -571
- package/build/contracts/upgraded/PolicyNFTv1.sol/PolicyNFTv1_Upgrade.json +0 -602
- package/build/interfaces/IAssetManager.sol/IAssetManager.json +0 -31
- package/build/interfaces/IExchange.sol/IPriceOracle.json +0 -30
- package/build/interfaces/IPolicyNFT.sol/IPolicyNFT.json +0 -321
- package/contracts/AaveAssetManager.sol +0 -298
- package/contracts/BaseAssetManager.sol +0 -301
- package/contracts/DataTypes.sol +0 -287
- package/contracts/Exchange.sol +0 -189
- package/contracts/FlightDelayRiskModule.sol +0 -208
- package/contracts/PolicyNFT.sol +0 -96
- package/contracts/PolicyPoolConfig.sol +0 -247
- package/contracts/WadRayMath.sol +0 -135
- package/contracts/dependencies/ChainlinkClientUpgradeable.sol +0 -371
- package/contracts/extras/IPriceRiskModule.sol +0 -41
- package/contracts/extras/PriceRiskModule.sol +0 -243
- package/contracts/upgraded/IPolicyNFTv1.sol +0 -15
- package/contracts/upgraded/PolicyNFTv1.sol +0 -126
- package/interfaces/IAssetManager.sol +0 -23
- package/interfaces/IEToken.sol +0 -48
- package/interfaces/IExchange.sol +0 -59
- package/interfaces/IInsolvencyHook.sol +0 -27
- package/interfaces/ILPWhitelist.sol +0 -23
- package/interfaces/IPolicyNFT.sol +0 -15
- package/interfaces/IPolicyPool.sol +0 -44
- package/interfaces/IPolicyPoolConfig.sol +0 -87
- package/interfaces/IRiskModule.sol +0 -29
package/contracts/EToken.sol
CHANGED
|
@@ -2,139 +2,139 @@
|
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
4
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
5
|
+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
6
|
+
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
|
|
7
|
+
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
|
|
8
|
+
import {IPolicyPool} from "./interfaces/IPolicyPool.sol";
|
|
9
|
+
import {Reserve} from "./Reserve.sol";
|
|
10
|
+
import {IEToken} from "./interfaces/IEToken.sol";
|
|
11
|
+
import {IAccessManager} from "./interfaces/IAccessManager.sol";
|
|
12
|
+
import {IPolicyPoolComponent} from "./interfaces/IPolicyPoolComponent.sol";
|
|
13
|
+
import {ILPWhitelist} from "./interfaces/ILPWhitelist.sol";
|
|
14
|
+
import {IAssetManager} from "./interfaces/IAssetManager.sol";
|
|
15
|
+
import {WadRayMath} from "./dependencies/WadRayMath.sol";
|
|
16
|
+
import {TimeScaled} from "./TimeScaled.sol";
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* @title Ensuro ERC20 EToken - interest-bearing token
|
|
14
20
|
* @dev Implementation of the interest/earnings bearing token for the Ensuro protocol.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Every operation that changes the utilization rate (_scr/totalSupply) or the
|
|
18
|
-
* first the
|
|
21
|
+
* `_tsScaled.scale` scales the balances stored in _balances. _tsScaled (totalSupply scaled) grows
|
|
22
|
+
* continuoulsly at tokenInterestRate().
|
|
23
|
+
* Every operation that changes the utilization rate (_scr.scr/totalSupply) or the _scr.interestRate, updates
|
|
24
|
+
* first the _tsScaled.scale accumulating the interest accrued since _tsScaled.lastUpdate.
|
|
19
25
|
* @custom:security-contact security@ensuro.co
|
|
20
26
|
* @author Ensuro
|
|
21
27
|
*/
|
|
22
|
-
contract EToken is
|
|
23
|
-
uint256 public constant MIN_SCALE = 1e17; // 0.0000000001 == 1e-10 in ray
|
|
24
|
-
|
|
28
|
+
contract EToken is Reserve, IERC20Metadata, IEToken {
|
|
25
29
|
using WadRayMath for uint256;
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
using TimeScaled for TimeScaled.ScaledAmount;
|
|
31
|
+
using SafeERC20 for IERC20Metadata;
|
|
32
|
+
using SafeCast for uint256;
|
|
28
33
|
|
|
29
34
|
// Attributes taken from ERC20
|
|
30
35
|
mapping(address => uint256) private _balances;
|
|
31
36
|
mapping(address => mapping(address => uint256)) private _allowances;
|
|
32
|
-
uint256 private _totalSupply; // non-scaled totalSupply
|
|
33
37
|
|
|
34
38
|
string private _name;
|
|
35
39
|
string private _symbol;
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
uint256 internal _scaleFactor; // in Ray
|
|
39
|
-
uint40 internal _lastScaleUpdate;
|
|
41
|
+
TimeScaled.ScaledAmount internal _tsScaled; // Total Supply scaled
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
struct Scr {
|
|
44
|
+
uint128 scr; // in Wad - Capital locked as Solvency Capital Requirement of backed up policies
|
|
45
|
+
uint64 interestRate; // in Wad - Interest rate received in exchange of solvency capital
|
|
46
|
+
uint64 tokenInterestRate; // in Wad - Overall interest rate of the token
|
|
47
|
+
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
uint256 internal _poolLoanInterestRate; // in Ray
|
|
49
|
-
uint256 internal _poolLoanScale; // in Ray
|
|
50
|
-
uint40 internal _poolLoanLastUpdate;
|
|
49
|
+
Scr internal _scr;
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
mapping(address => bool) internal _acceptExceptions;
|
|
51
|
+
// Mapping that keeps track of allowed borrowers (PremiumsAccount) and their current debt
|
|
52
|
+
mapping(address => TimeScaled.ScaledAmount) internal _loans;
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
struct PackedParams {
|
|
55
|
+
uint16 liquidityRequirement; // Liquidity requirement to lock more/less than SCR - 4 decimals
|
|
56
|
+
uint16 minUtilizationRate; // Min utilization rate, to reject deposits that leave UR under this value - 4 decimals
|
|
57
|
+
uint16 maxUtilizationRate; // Max utilization rate, to reject lockScr that leave UR above this value - 4 decimals
|
|
58
|
+
uint16 internalLoanInterestRate; // Annualized interest rate charged to internal borrowers (premiums accounts) - 4dec
|
|
59
|
+
ILPWhitelist whitelist; // Whitelist for deposits and transfers
|
|
60
|
+
}
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
PackedParams internal _params;
|
|
63
|
+
|
|
64
|
+
IAssetManager internal _assetManager;
|
|
65
|
+
|
|
66
|
+
event InternalLoan(address indexed borrower, uint256 value, uint256 amountAsked);
|
|
67
|
+
event InternalLoanRepaid(address indexed borrower, uint256 value);
|
|
68
|
+
event InternalBorrowerAdded(address indexed borrower);
|
|
69
|
+
event InternalBorrowerRemoved(address indexed borrower, uint256 defaultedDebt);
|
|
70
|
+
|
|
71
|
+
modifier onlyBorrower() {
|
|
72
|
+
require(_loans[_msgSender()].scale != 0, "The caller must be a borrower");
|
|
64
73
|
_;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
68
77
|
// solhint-disable-next-line no-empty-blocks
|
|
69
|
-
constructor(IPolicyPool policyPool_)
|
|
78
|
+
constructor(IPolicyPool policyPool_) Reserve(policyPool_) {}
|
|
70
79
|
|
|
71
80
|
/**
|
|
72
81
|
* @dev Initializes the eToken
|
|
73
|
-
* @param expirationPeriod_ Maximum expirationPeriod (from block.timestamp) of policies to be accepted
|
|
74
|
-
* @param liquidityRequirement_ Liquidity requirement to allow withdrawal (in Ray - default=1 Ray)
|
|
75
82
|
* @param maxUtilizationRate_ Max utilization rate (scr/totalSupply) (in Ray - default=1 Ray)
|
|
76
|
-
* @param
|
|
83
|
+
* @param internalLoanInterestRate_ Rate of loans givencrto the policy pool (in Ray)
|
|
77
84
|
* @param name_ Name of the eToken
|
|
78
85
|
* @param symbol_ Symbol of the eToken
|
|
79
86
|
*/
|
|
80
87
|
function initialize(
|
|
81
88
|
string memory name_,
|
|
82
89
|
string memory symbol_,
|
|
83
|
-
uint40 expirationPeriod_,
|
|
84
|
-
uint256 liquidityRequirement_,
|
|
85
90
|
uint256 maxUtilizationRate_,
|
|
86
|
-
uint256
|
|
91
|
+
uint256 internalLoanInterestRate_
|
|
87
92
|
) public initializer {
|
|
88
93
|
__PolicyPoolComponent_init();
|
|
89
|
-
__EToken_init_unchained(
|
|
90
|
-
name_,
|
|
91
|
-
symbol_,
|
|
92
|
-
expirationPeriod_,
|
|
93
|
-
liquidityRequirement_,
|
|
94
|
-
maxUtilizationRate_,
|
|
95
|
-
poolLoanInterestRate_
|
|
96
|
-
);
|
|
94
|
+
__EToken_init_unchained(name_, symbol_, maxUtilizationRate_, internalLoanInterestRate_);
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
// solhint-disable-next-line func-name-mixedcase
|
|
100
98
|
function __EToken_init_unchained(
|
|
101
99
|
string memory name_,
|
|
102
100
|
string memory symbol_,
|
|
103
|
-
uint40 expirationPeriod_,
|
|
104
|
-
uint256 liquidityRequirement_,
|
|
105
101
|
uint256 maxUtilizationRate_,
|
|
106
|
-
uint256
|
|
102
|
+
uint256 internalLoanInterestRate_
|
|
107
103
|
) internal initializer {
|
|
108
104
|
_name = name_;
|
|
109
105
|
_symbol = symbol_;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
_tsScaled.init();
|
|
107
|
+
/* _scr = Scr({
|
|
108
|
+
scr: 0,
|
|
109
|
+
interestRate: 0,
|
|
110
|
+
tokenInterestRate: 0
|
|
111
|
+
}); */
|
|
112
|
+
_params = PackedParams({
|
|
113
|
+
maxUtilizationRate: _wadTo4(maxUtilizationRate_),
|
|
114
|
+
liquidityRequirement: 1e4,
|
|
115
|
+
minUtilizationRate: 0,
|
|
116
|
+
internalLoanInterestRate: _wadTo4(internalLoanInterestRate_),
|
|
117
|
+
whitelist: ILPWhitelist(address(0))
|
|
118
|
+
});
|
|
119
|
+
|
|
124
120
|
_validateParameters();
|
|
125
121
|
}
|
|
126
122
|
|
|
127
123
|
// runs validation on EToken parameters
|
|
128
124
|
function _validateParameters() internal view override {
|
|
129
125
|
require(
|
|
130
|
-
|
|
126
|
+
_params.liquidityRequirement >= 8e3 && _params.liquidityRequirement <= 13e3,
|
|
131
127
|
"Validation: liquidityRequirement must be [0.8, 1.3]"
|
|
132
128
|
);
|
|
133
129
|
require(
|
|
134
|
-
|
|
130
|
+
_params.maxUtilizationRate >= 5e3 && _params.maxUtilizationRate <= 1e4,
|
|
135
131
|
"Validation: maxUtilizationRate must be [0.5, 1]"
|
|
136
132
|
);
|
|
137
|
-
require(
|
|
133
|
+
require(_params.minUtilizationRate <= 1e4, "Validation: minUtilizationRate must be [0, 1]");
|
|
134
|
+
require(
|
|
135
|
+
_params.internalLoanInterestRate <= 5e3,
|
|
136
|
+
"Validation: internalLoanInterestRate must be <= 50%"
|
|
137
|
+
);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
/*** BEGIN ERC20 methods - mainly copied from OpenZeppelin but changes in events and scaledAmount */
|
|
@@ -175,7 +175,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
175
175
|
* @dev See {IERC20-totalSupply}.
|
|
176
176
|
*/
|
|
177
177
|
function totalSupply() public view virtual override returns (uint256) {
|
|
178
|
-
return
|
|
178
|
+
return _tsScaled.getScaledAmount(tokenInterestRate());
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/**
|
|
@@ -184,7 +184,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
184
184
|
function balanceOf(address account) public view virtual override returns (uint256) {
|
|
185
185
|
uint256 principalBalance = _balances[account];
|
|
186
186
|
if (principalBalance == 0) return 0;
|
|
187
|
-
return
|
|
187
|
+
return _tsScaled.getScale(tokenInterestRate()).rayMul(principalBalance.wadToRay()).rayToWad();
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
@@ -295,10 +295,6 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
295
295
|
return true;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
function _scaleAmount(uint256 amount) internal view returns (uint256) {
|
|
299
|
-
return amount.wadToRay().rayDiv(_calculateCurrentScale()).rayToWad();
|
|
300
|
-
}
|
|
301
|
-
|
|
302
298
|
/**
|
|
303
299
|
* @dev Moves tokens `amount` from `sender` to `recipient`.
|
|
304
300
|
*
|
|
@@ -322,7 +318,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
322
318
|
require(recipient != address(0), "EToken: transfer to the zero address");
|
|
323
319
|
|
|
324
320
|
_beforeTokenTransfer(sender, recipient, amount);
|
|
325
|
-
uint256 scaledAmount =
|
|
321
|
+
uint256 scaledAmount = _tsScaled.scaleAmountNow(tokenInterestRate(), amount);
|
|
326
322
|
|
|
327
323
|
uint256 senderBalance = _balances[sender];
|
|
328
324
|
require(senderBalance >= scaledAmount, "EToken: transfer amount exceeds balance");
|
|
@@ -345,9 +341,7 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
345
341
|
require(account != address(0), "EToken: mint to the zero address");
|
|
346
342
|
|
|
347
343
|
_beforeTokenTransfer(address(0), account, amount);
|
|
348
|
-
uint256 scaledAmount =
|
|
349
|
-
|
|
350
|
-
_totalSupply += scaledAmount;
|
|
344
|
+
uint256 scaledAmount = _tsScaled.add(amount, tokenInterestRate());
|
|
351
345
|
_balances[account] += scaledAmount;
|
|
352
346
|
emit Transfer(address(0), account, amount);
|
|
353
347
|
}
|
|
@@ -367,11 +361,10 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
367
361
|
require(account != address(0), "EToken: burn from the zero address");
|
|
368
362
|
_beforeTokenTransfer(account, address(0), amount);
|
|
369
363
|
|
|
370
|
-
uint256 scaledAmount =
|
|
364
|
+
uint256 scaledAmount = _tsScaled.sub(amount, tokenInterestRate());
|
|
371
365
|
uint256 accountBalance = _balances[account];
|
|
372
366
|
require(accountBalance >= scaledAmount, "EToken: burn amount exceeds balance");
|
|
373
367
|
_balances[account] = accountBalance - scaledAmount;
|
|
374
|
-
_totalSupply -= scaledAmount;
|
|
375
368
|
|
|
376
369
|
emit Transfer(account, address(0), amount);
|
|
377
370
|
}
|
|
@@ -419,159 +412,169 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
419
412
|
address from,
|
|
420
413
|
address to,
|
|
421
414
|
uint256 amount
|
|
422
|
-
) internal virtual {
|
|
415
|
+
) internal virtual whenNotPaused {
|
|
423
416
|
require(
|
|
424
417
|
from == address(0) ||
|
|
425
418
|
to == address(0) ||
|
|
426
|
-
address(
|
|
427
|
-
|
|
419
|
+
address(_params.whitelist) == address(0) ||
|
|
420
|
+
_params.whitelist.acceptsTransfer(this, from, to, amount),
|
|
428
421
|
"Transfer not allowed - Liquidity Provider not whitelisted"
|
|
429
422
|
);
|
|
430
423
|
}
|
|
431
424
|
|
|
432
425
|
/*** END ERC20 methods - mainly copied from OpenZeppelin but changes in events and scaledAmount */
|
|
433
426
|
|
|
434
|
-
function _updateCurrentScale() internal {
|
|
435
|
-
if (uint40(block.timestamp) == _lastScaleUpdate) return;
|
|
436
|
-
_scaleFactor = _calculateCurrentScale();
|
|
437
|
-
require(_scaleFactor >= MIN_SCALE, "Scale too small, can lead to rounding errors");
|
|
438
|
-
_lastScaleUpdate = uint40(block.timestamp);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
427
|
function _updateTokenInterestRate() internal {
|
|
442
|
-
uint256 totalSupply_ = this.totalSupply()
|
|
443
|
-
if (totalSupply_ == 0)
|
|
444
|
-
else
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return
|
|
451
|
-
_scaleFactor.rayMul(
|
|
452
|
-
((_tokenInterestRate * timeDifference) / SECONDS_PER_YEAR) + WadRayMath.ray()
|
|
453
|
-
);
|
|
428
|
+
uint256 totalSupply_ = this.totalSupply();
|
|
429
|
+
if (totalSupply_ == 0) _scr.tokenInterestRate = 0;
|
|
430
|
+
else {
|
|
431
|
+
_scr.tokenInterestRate = uint256(_scr.interestRate)
|
|
432
|
+
.wadMul(uint256(_scr.scr))
|
|
433
|
+
.wadDiv(totalSupply_)
|
|
434
|
+
.toUint64();
|
|
435
|
+
}
|
|
454
436
|
}
|
|
455
437
|
|
|
456
438
|
function getCurrentScale(bool updated) public view returns (uint256) {
|
|
457
|
-
if (updated) return
|
|
458
|
-
else return
|
|
439
|
+
if (updated) return _tsScaled.getScale(tokenInterestRate());
|
|
440
|
+
else return uint256(_tsScaled.scale);
|
|
459
441
|
}
|
|
460
442
|
|
|
461
|
-
function
|
|
443
|
+
function fundsAvailable() public view returns (uint256) {
|
|
462
444
|
uint256 totalSupply_ = this.totalSupply();
|
|
463
|
-
if (totalSupply_ > _scr) return totalSupply_ - _scr;
|
|
445
|
+
if (totalSupply_ > uint256(_scr.scr)) return totalSupply_ - uint256(_scr.scr);
|
|
464
446
|
else return 0;
|
|
465
447
|
}
|
|
466
448
|
|
|
467
|
-
function
|
|
449
|
+
function fundsAvailableToLock() public view returns (uint256) {
|
|
468
450
|
uint256 totalSupply_ = this.totalSupply();
|
|
469
|
-
if (totalSupply_ >
|
|
451
|
+
if (totalSupply_ > uint256(_scr.scr))
|
|
452
|
+
return (totalSupply_ - uint256(_scr.scr)).wadMul(maxUtilizationRate());
|
|
470
453
|
else return 0;
|
|
471
454
|
}
|
|
472
455
|
|
|
456
|
+
function assetManager() public view override returns (IAssetManager) {
|
|
457
|
+
return _assetManager;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function _setAssetManager(IAssetManager newAM) internal override {
|
|
461
|
+
_assetManager = newAM;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// solhint-disable-next-line func-name-mixedcase
|
|
465
|
+
function _4toWad(uint16 value) internal pure returns (uint256) {
|
|
466
|
+
// 4 decimals to Wad (18 decimals)
|
|
467
|
+
return uint256(value) * 1e14;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function _wadTo4(uint256 value) internal pure returns (uint16) {
|
|
471
|
+
// Wad to 4 decimals
|
|
472
|
+
return (value / 1e14).toUint16();
|
|
473
|
+
}
|
|
474
|
+
|
|
473
475
|
function scr() public view virtual override returns (uint256) {
|
|
474
|
-
return _scr;
|
|
476
|
+
return uint256(_scr.scr);
|
|
475
477
|
}
|
|
476
478
|
|
|
477
479
|
function scrInterestRate() public view override returns (uint256) {
|
|
478
|
-
return
|
|
480
|
+
return uint256(_scr.interestRate);
|
|
479
481
|
}
|
|
480
482
|
|
|
481
483
|
function tokenInterestRate() public view override returns (uint256) {
|
|
482
|
-
return
|
|
484
|
+
return uint256(_scr.tokenInterestRate);
|
|
483
485
|
}
|
|
484
486
|
|
|
485
487
|
function liquidityRequirement() public view returns (uint256) {
|
|
486
|
-
return
|
|
488
|
+
return _4toWad(_params.liquidityRequirement);
|
|
487
489
|
}
|
|
488
490
|
|
|
489
491
|
function maxUtilizationRate() public view returns (uint256) {
|
|
490
|
-
return
|
|
492
|
+
return _4toWad(_params.maxUtilizationRate);
|
|
491
493
|
}
|
|
492
494
|
|
|
493
|
-
function
|
|
494
|
-
return
|
|
495
|
+
function minUtilizationRate() public view returns (uint256) {
|
|
496
|
+
return _4toWad(_params.minUtilizationRate);
|
|
495
497
|
}
|
|
496
498
|
|
|
497
499
|
function utilizationRate() public view returns (uint256) {
|
|
498
|
-
return _scr.wadDiv(this.totalSupply())
|
|
500
|
+
return uint256(_scr.scr).wadDiv(this.totalSupply());
|
|
499
501
|
}
|
|
500
502
|
|
|
501
|
-
function lockScr(uint256
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
503
|
+
function lockScr(uint256 scrAmount, uint256 policyInterestRate)
|
|
504
|
+
external
|
|
505
|
+
override
|
|
506
|
+
onlyBorrower
|
|
507
|
+
whenNotPaused
|
|
508
|
+
{
|
|
509
|
+
require(
|
|
510
|
+
scrAmount <= this.fundsAvailableToLock(),
|
|
511
|
+
"Not enought funds available to cover the SCR"
|
|
512
|
+
);
|
|
513
|
+
_tsScaled.updateScale(tokenInterestRate());
|
|
514
|
+
if (_scr.scr == 0) {
|
|
515
|
+
_scr.scr = scrAmount.toUint128();
|
|
516
|
+
_scr.interestRate = policyInterestRate.toUint64();
|
|
507
517
|
} else {
|
|
508
|
-
uint256 origScr = _scr.
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
policyInterestRate.
|
|
518
|
+
uint256 origScr = uint256(_scr.scr);
|
|
519
|
+
uint256 newScr = origScr + scrAmount;
|
|
520
|
+
_scr.interestRate = (uint256(_scr.interestRate).wadMul(origScr) +
|
|
521
|
+
policyInterestRate.wadMul(scrAmount)).wadDiv(newScr).toUint64();
|
|
522
|
+
_scr.scr = newScr.toUint128();
|
|
512
523
|
}
|
|
513
524
|
emit SCRLocked(policyInterestRate, scrAmount);
|
|
514
525
|
_updateTokenInterestRate();
|
|
515
526
|
}
|
|
516
527
|
|
|
517
|
-
function unlockScr(
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
{
|
|
522
|
-
require(scrAmount <= _scr, "Current SCR less than the amount you want to unlock");
|
|
523
|
-
|
|
528
|
+
function unlockScr(
|
|
529
|
+
uint256 scrAmount,
|
|
530
|
+
uint256 policyInterestRate,
|
|
531
|
+
int256 adjustment
|
|
532
|
+
) external override onlyBorrower {
|
|
533
|
+
require(scrAmount <= uint256(_scr.scr), "Current SCR less than the amount you want to unlock");
|
|
534
|
+
_tsScaled.updateScale(tokenInterestRate());
|
|
524
535
|
|
|
525
|
-
if (_scr == scrAmount) {
|
|
526
|
-
_scr = 0;
|
|
527
|
-
|
|
536
|
+
if (uint256(_scr.scr) == scrAmount) {
|
|
537
|
+
_scr.scr = 0;
|
|
538
|
+
_scr.interestRate = 0;
|
|
528
539
|
} else {
|
|
529
|
-
uint256 origScr = _scr.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
policyInterestRate.
|
|
540
|
+
uint256 origScr = uint256(_scr.scr);
|
|
541
|
+
uint256 newScr = origScr - scrAmount;
|
|
542
|
+
_scr.interestRate = (uint256(_scr.interestRate).wadMul(origScr) -
|
|
543
|
+
policyInterestRate.wadMul(scrAmount)).wadDiv(newScr).toUint64();
|
|
544
|
+
_scr.scr = newScr.toUint128();
|
|
533
545
|
}
|
|
534
546
|
emit SCRUnlocked(policyInterestRate, scrAmount);
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
function _discreteChange(uint256 amount, bool positive) internal {
|
|
539
|
-
uint256 newTotalSupply = positive ? (totalSupply() + amount) : (totalSupply() - amount);
|
|
540
|
-
_scaleFactor = newTotalSupply.wadToRay().rayDiv(_totalSupply.wadToRay());
|
|
541
|
-
require(_scaleFactor >= MIN_SCALE, "Scale too small, can lead to rounding errors");
|
|
542
|
-
_updateTokenInterestRate();
|
|
547
|
+
_discreteChange(adjustment);
|
|
543
548
|
}
|
|
544
549
|
|
|
545
|
-
function
|
|
546
|
-
|
|
547
|
-
_discreteChange(amount, positive);
|
|
550
|
+
function _assetEarnings(int256 earnings) internal override {
|
|
551
|
+
_discreteChange(earnings);
|
|
548
552
|
}
|
|
549
553
|
|
|
550
|
-
function
|
|
551
|
-
|
|
552
|
-
|
|
554
|
+
function _discreteChange(int256 amount) internal {
|
|
555
|
+
_tsScaled.discreteChange(amount, tokenInterestRate());
|
|
556
|
+
_updateTokenInterestRate();
|
|
553
557
|
}
|
|
554
558
|
|
|
555
559
|
function deposit(address provider, uint256 amount)
|
|
556
560
|
external
|
|
557
561
|
override
|
|
558
562
|
onlyPolicyPool
|
|
559
|
-
whenNotPaused
|
|
560
563
|
returns (uint256)
|
|
561
564
|
{
|
|
562
565
|
require(
|
|
563
|
-
address(
|
|
564
|
-
|
|
566
|
+
address(_params.whitelist) == address(0) ||
|
|
567
|
+
_params.whitelist.acceptsDeposit(this, provider, amount),
|
|
565
568
|
"Liquidity Provider not whitelisted"
|
|
566
569
|
);
|
|
567
|
-
_updateCurrentScale();
|
|
568
570
|
_mint(provider, amount);
|
|
569
571
|
_updateTokenInterestRate();
|
|
572
|
+
require(utilizationRate() >= minUtilizationRate(), "Deposit rejected - Utilization Rate < min");
|
|
570
573
|
return balanceOf(provider);
|
|
571
574
|
}
|
|
572
575
|
|
|
573
576
|
function totalWithdrawable() public view virtual override returns (uint256) {
|
|
574
|
-
uint256 locked = _scr.
|
|
577
|
+
uint256 locked = uint256(_scr.scr).wadMul(liquidityRequirement());
|
|
575
578
|
uint256 totalSupply_ = totalSupply();
|
|
576
579
|
if (totalSupply_ >= locked) return totalSupply_ - locked;
|
|
577
580
|
else return 0;
|
|
@@ -581,173 +584,125 @@ contract EToken is PolicyPoolComponent, IERC20Metadata, IEToken {
|
|
|
581
584
|
external
|
|
582
585
|
override
|
|
583
586
|
onlyPolicyPool
|
|
584
|
-
whenNotPaused
|
|
585
587
|
returns (uint256)
|
|
586
588
|
{
|
|
587
|
-
|
|
588
|
-
uint256 balance = balanceOf(provider);
|
|
589
|
-
if (balance == 0) return 0;
|
|
590
|
-
if (amount > balance) amount = balance;
|
|
591
|
-
uint256 withdrawable = totalWithdrawable();
|
|
592
|
-
if (amount > withdrawable) amount = withdrawable;
|
|
589
|
+
amount = Math.min(amount, Math.min(balanceOf(provider), totalWithdrawable()));
|
|
593
590
|
if (amount == 0) return 0;
|
|
594
591
|
_burn(provider, amount);
|
|
595
592
|
_updateTokenInterestRate();
|
|
593
|
+
_transferTo(provider, amount);
|
|
596
594
|
return amount;
|
|
597
595
|
}
|
|
598
596
|
|
|
599
|
-
function
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
returns (bool)
|
|
605
|
-
{
|
|
606
|
-
if (paused()) return false;
|
|
607
|
-
if (_acceptAllRMs == _acceptExceptions[riskModule]) {
|
|
608
|
-
// all accepted except this one or all rejected and this one is not an exception
|
|
609
|
-
return false;
|
|
597
|
+
function addBorrower(address borrower) external override onlyPolicyPool {
|
|
598
|
+
TimeScaled.ScaledAmount storage loan = _loans[borrower];
|
|
599
|
+
if (loan.scale == 0) {
|
|
600
|
+
loan.init();
|
|
601
|
+
emit InternalBorrowerAdded(borrower);
|
|
610
602
|
}
|
|
611
|
-
return policyExpiration < (uint40(block.timestamp) + _expirationPeriod);
|
|
612
603
|
}
|
|
613
604
|
|
|
614
|
-
function
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
605
|
+
function removeBorrower(address borrower) external override onlyPolicyPool {
|
|
606
|
+
uint256 defaultedDebt = getLoan(borrower);
|
|
607
|
+
delete _loans[borrower];
|
|
608
|
+
emit InternalBorrowerRemoved(borrower, defaultedDebt);
|
|
618
609
|
}
|
|
619
610
|
|
|
620
|
-
function
|
|
621
|
-
uint256
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
if (amount == 0) return amount;
|
|
638
|
-
}
|
|
639
|
-
if (_poolLoan == 0) {
|
|
640
|
-
_poolLoan = amount;
|
|
641
|
-
_poolLoanScale = WadRayMath.ray();
|
|
642
|
-
_poolLoanLastUpdate = uint40(block.timestamp);
|
|
643
|
-
} else {
|
|
644
|
-
_updatePoolLoanScale();
|
|
645
|
-
_poolLoan += amount.wadToRay().rayDiv(_poolLoanScale).rayToWad();
|
|
646
|
-
}
|
|
647
|
-
_updateCurrentScale(); // shouldn't do anything because lendToPool is after unlock_scr but doing anyway
|
|
648
|
-
_discreteChange(amount, false);
|
|
649
|
-
emit PoolLoan(amount);
|
|
650
|
-
if (!fromOcean && _scr > totalSupply()) {
|
|
651
|
-
// Notify insolvency_hook - Insuficient solvency
|
|
652
|
-
IInsolvencyHook hook = _policyPool.config().insolvencyHook();
|
|
653
|
-
if (address(hook) != address(0)) {
|
|
654
|
-
hook.insolventEToken(this, _scr - totalSupply());
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
return amount;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
function repayPoolLoan(uint256 amount) external override onlyPolicyPool {
|
|
661
|
-
_updatePoolLoanScale();
|
|
662
|
-
_poolLoan = (getPoolLoan() - amount).wadToRay().rayDiv(_poolLoanScale).rayToWad();
|
|
663
|
-
_updateCurrentScale(); // shouldn't do anything because lendToPool is after unlock_scr but doing anyway
|
|
664
|
-
_discreteChange(amount, true);
|
|
665
|
-
emit PoolLoanRepaid(amount);
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
function _getPoolLoanScale() internal view returns (uint256) {
|
|
669
|
-
if (uint40(block.timestamp) <= _poolLoanLastUpdate) return _poolLoanScale;
|
|
670
|
-
uint256 timeDifference = block.timestamp - _poolLoanLastUpdate;
|
|
671
|
-
return
|
|
672
|
-
_poolLoanScale.rayMul(
|
|
673
|
-
((_poolLoanInterestRate * timeDifference) / SECONDS_PER_YEAR) + WadRayMath.ray()
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function getPoolLoan() public view virtual override returns (uint256) {
|
|
678
|
-
if (_poolLoan == 0) return 0;
|
|
679
|
-
return _poolLoan.wadToRay().rayMul(_getPoolLoanScale()).rayToWad();
|
|
611
|
+
function internalLoan(
|
|
612
|
+
uint256 amount,
|
|
613
|
+
address receiver,
|
|
614
|
+
bool fromAvailable
|
|
615
|
+
) external override onlyBorrower whenNotPaused returns (uint256) {
|
|
616
|
+
uint256 amountAsked = amount;
|
|
617
|
+
amount = Math.min(
|
|
618
|
+
Math.min(amount, fromAvailable ? fundsAvailable() : totalSupply()),
|
|
619
|
+
_tsScaled.maxNegativeAdjustment(tokenInterestRate())
|
|
620
|
+
);
|
|
621
|
+
if (amount == 0) return amountAsked;
|
|
622
|
+
TimeScaled.ScaledAmount storage loan = _loans[_msgSender()];
|
|
623
|
+
loan.add(amount, internalLoanInterestRate());
|
|
624
|
+
_discreteChange(-int256(amount));
|
|
625
|
+
_transferTo(receiver, amount);
|
|
626
|
+
emit InternalLoan(_msgSender(), amount, amountAsked);
|
|
627
|
+
return amountAsked - amount;
|
|
680
628
|
}
|
|
681
629
|
|
|
682
|
-
function
|
|
683
|
-
|
|
630
|
+
function repayLoan(uint256 amount, address onBehalfOf) external override {
|
|
631
|
+
// Anyone can call this method, since it has to pay
|
|
632
|
+
currency().safeTransferFrom(_msgSender(), address(this), amount);
|
|
633
|
+
TimeScaled.ScaledAmount storage loan = _loans[onBehalfOf];
|
|
634
|
+
require(loan.scale != 0, "Not a registered borrower");
|
|
635
|
+
loan.sub(amount, internalLoanInterestRate());
|
|
636
|
+
_discreteChange(int256(amount));
|
|
637
|
+
emit InternalLoanRepaid(onBehalfOf, amount);
|
|
684
638
|
}
|
|
685
639
|
|
|
686
|
-
function
|
|
687
|
-
|
|
640
|
+
function getLoan(address borrower) public view virtual override returns (uint256) {
|
|
641
|
+
TimeScaled.ScaledAmount storage loan = _loans[borrower];
|
|
642
|
+
return loan.getScaledAmount(internalLoanInterestRate());
|
|
688
643
|
}
|
|
689
644
|
|
|
690
|
-
function
|
|
691
|
-
return
|
|
645
|
+
function internalLoanInterestRate() public view returns (uint256) {
|
|
646
|
+
return _4toWad(_params.internalLoanInterestRate);
|
|
692
647
|
}
|
|
693
648
|
|
|
694
|
-
function
|
|
649
|
+
function setParam(Parameter param, uint256 newValue)
|
|
695
650
|
external
|
|
696
|
-
|
|
651
|
+
onlyGlobalOrComponentRole2(LEVEL2_ROLE, LEVEL3_ROLE)
|
|
697
652
|
{
|
|
698
653
|
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
654
|
+
if (param == Parameter.liquidityRequirement) {
|
|
655
|
+
require(
|
|
656
|
+
!tweak || _isTweakWad(liquidityRequirement(), newValue, 1e17),
|
|
657
|
+
"Tweak exceeded: liquidityRequirement tweaks only up to 10%"
|
|
658
|
+
);
|
|
659
|
+
_params.liquidityRequirement = _wadTo4(newValue);
|
|
660
|
+
} else if (param == Parameter.minUtilizationRate) {
|
|
661
|
+
require(
|
|
662
|
+
!tweak || _isTweakWad(minUtilizationRate(), newValue, 3e17),
|
|
663
|
+
"Tweak exceeded: minUtilizationRate tweaks only up to 30%"
|
|
664
|
+
);
|
|
665
|
+
_params.minUtilizationRate = _wadTo4(newValue);
|
|
666
|
+
} else if (param == Parameter.maxUtilizationRate) {
|
|
667
|
+
require(
|
|
668
|
+
!tweak || _isTweakWad(maxUtilizationRate(), newValue, 3e17),
|
|
669
|
+
"Tweak exceeded: maxUtilizationRate tweaks only up to 30%"
|
|
670
|
+
);
|
|
671
|
+
_params.maxUtilizationRate = _wadTo4(newValue);
|
|
672
|
+
} else if (param == Parameter.internalLoanInterestRate) {
|
|
673
|
+
require(
|
|
674
|
+
!tweak || _isTweakWad(internalLoanInterestRate(), newValue, 3e17),
|
|
675
|
+
"Tweak exceeded: internalLoanInterestRate tweaks only up to 30%"
|
|
676
|
+
);
|
|
677
|
+
// This call changes the interest rate without updating the current loans up to this point
|
|
678
|
+
// So, if interest rate goes from 5% to 6%, this change will be retroactive to the lastUpdate of each
|
|
679
|
+
// loan. Since it's a permissioned call, I'm ok with this. If a caller wants to reduce the impact, it can
|
|
680
|
+
// issue 1 wei repayLoan to each active loan, forcing the update of the scales
|
|
681
|
+
_params.internalLoanInterestRate = _wadTo4(newValue);
|
|
682
|
+
}
|
|
683
|
+
_parameterChanged(
|
|
684
|
+
IAccessManager.GovernanceActions(
|
|
685
|
+
uint256(IAccessManager.GovernanceActions.setLiquidityRequirement) + uint256(param)
|
|
686
|
+
),
|
|
687
|
+
newValue,
|
|
688
|
+
tweak
|
|
702
689
|
);
|
|
703
|
-
_updatePoolLoanScale();
|
|
704
|
-
_poolLoanInterestRate = newRate;
|
|
705
|
-
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setPoolLoanInterestRate, newRate, tweak);
|
|
706
690
|
}
|
|
707
691
|
|
|
708
|
-
function
|
|
692
|
+
function setWhitelist(ILPWhitelist lpWhitelist_)
|
|
709
693
|
external
|
|
710
|
-
|
|
694
|
+
onlyGlobalOrComponentRole2(GUARDIAN_ROLE, LEVEL1_ROLE)
|
|
711
695
|
{
|
|
712
|
-
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
713
|
-
require(
|
|
714
|
-
!tweak || _isTweakRay(_liquidityRequirement, newRate, 1e26),
|
|
715
|
-
"Tweak exceeded: liquidityRequirement tweaks only up to 10%"
|
|
716
|
-
);
|
|
717
|
-
_liquidityRequirement = newRate;
|
|
718
|
-
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setLiquidityRequirement, newRate, tweak);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
function setMaxUtilizationRate(uint256 newRate) external onlyPoolRole2(LEVEL2_ROLE, LEVEL3_ROLE) {
|
|
722
|
-
bool tweak = !hasPoolRole(LEVEL2_ROLE);
|
|
723
696
|
require(
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
_maxUtilizationRate = newRate;
|
|
728
|
-
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setMaxUtilizationRate, newRate, tweak);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
function setAcceptAllRMs(bool acceptAllRMs_) external onlyPoolRole(LEVEL2_ROLE) {
|
|
732
|
-
_acceptAllRMs = acceptAllRMs_;
|
|
733
|
-
_parameterChanged(
|
|
734
|
-
IPolicyPoolConfig.GovernanceActions.setAcceptAllRMs,
|
|
735
|
-
acceptAllRMs_ ? 1 : 0,
|
|
736
|
-
false
|
|
697
|
+
address(lpWhitelist_) == address(0) ||
|
|
698
|
+
IPolicyPoolComponent(address(lpWhitelist_)).policyPool() == _policyPool,
|
|
699
|
+
"Component not linked to this PolicyPool"
|
|
737
700
|
);
|
|
701
|
+
_params.whitelist = lpWhitelist_;
|
|
702
|
+
_componentChanged(IAccessManager.GovernanceActions.setLPWhitelist, address(lpWhitelist_));
|
|
738
703
|
}
|
|
739
704
|
|
|
740
|
-
function
|
|
741
|
-
|
|
742
|
-
onlyPoolRole(LEVEL2_ROLE)
|
|
743
|
-
{
|
|
744
|
-
_acceptExceptions[riskModule] = isException;
|
|
745
|
-
uint256 value = uint160(riskModule);
|
|
746
|
-
if (!isException) value |= (1 << 255); // if changed to NOT exception activate first bit
|
|
747
|
-
_parameterChanged(IPolicyPoolConfig.GovernanceActions.setAcceptException, value, false);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
function getInvestable() public view virtual override returns (uint256) {
|
|
751
|
-
return _scr + ocean() + getPoolLoan();
|
|
705
|
+
function whitelist() external view returns (ILPWhitelist) {
|
|
706
|
+
return _params.whitelist;
|
|
752
707
|
}
|
|
753
708
|
}
|