Euler diff: contracts/modules/RiskManager.sol

Before: contract 0xad8a5c16FDF36E568F602d088dD0C0ADe52dd652
After: git 1d8c9f1d548570a0235cda39b13a76e658ae37d3
Files changed (4) hide show
  1. contracts/modules/RiskManager.sol +33 -18
  2. contracts/Interfaces.sol +2 -2
  3. contracts/Base.sol +7 -0
  4. contracts/Constants.sol +2 -0
contracts/modules/RiskManager.sol CHANGED
@@ -261,42 +261,57 @@
261
261
  AssetCache memory assetCache;
262
262
 
263
263
  for (uint i = 0; i < underlyings.length; ++i) {
264
264
  address underlying = underlyings[i];
265
- bool assetCacheAndPriceInited = false;
266
- uint price;
267
265
 
268
266
  config = resolveAssetConfig(underlying);
269
267
  assetStorage = eTokenLookup[config.eTokenAddress];
270
268
 
271
269
  uint balance = assetStorage.users[account].balance;
272
270
  uint owed = assetStorage.users[account].owed;
273
271
 
274
- if (balance != 0 && config.collateralFactor != 0) {
272
+ if (owed != 0) {
275
273
  initAssetCache(underlying, assetStorage, assetCache);
276
- (price,) = getPriceInternal(assetCache, config);
277
- assetCacheAndPriceInited = true;
274
+ (uint price,) = getPriceInternal(assetCache, config);
278
275
 
279
- uint assetCollateral = balanceToUnderlyingAmount(assetCache, balance);
280
- assetCollateral = assetCollateral * price / 1e18;
281
- assetCollateral = assetCollateral * config.collateralFactor / CONFIG_FACTOR_SCALE;
282
- status.collateralValue += assetCollateral;
283
- }
284
-
285
- if (owed != 0) {
286
- if (!assetCacheAndPriceInited) {
287
- initAssetCache(underlying, assetStorage, assetCache);
288
- (price,) = getPriceInternal(assetCache, config);
289
- assetCacheAndPriceInited = true;
290
- }
291
-
292
276
  status.numBorrows++;
293
277
  if (config.borrowIsolated) status.borrowIsolated = true;
294
278
 
295
279
  uint assetLiability = getCurrentOwed(assetStorage, assetCache, account);
280
+
281
+ if (balance != 0) { // self-collateralisation
282
+ uint balanceInUnderlying = balanceToUnderlyingAmount(assetCache, balance);
283
+
284
+ uint selfAmount = assetLiability;
285
+ uint selfAmountAdjusted = assetLiability * CONFIG_FACTOR_SCALE / SELF_COLLATERAL_FACTOR;
286
+
287
+ if (selfAmountAdjusted > balanceInUnderlying) {
288
+ selfAmount = balanceInUnderlying * SELF_COLLATERAL_FACTOR / CONFIG_FACTOR_SCALE;
289
+ selfAmountAdjusted = balanceInUnderlying;
290
+ }
291
+
292
+ {
293
+ uint assetCollateral = (balanceInUnderlying - selfAmountAdjusted) * config.collateralFactor / CONFIG_FACTOR_SCALE;
294
+ assetCollateral += selfAmount;
295
+ status.collateralValue += assetCollateral * price / 1e18;
296
+ }
297
+
298
+ assetLiability -= selfAmount;
299
+ status.liabilityValue += selfAmount * price / 1e18;
300
+ status.borrowIsolated = true; // self-collateralised loans are always isolated
301
+ }
302
+
296
303
  assetLiability = assetLiability * price / 1e18;
297
304
  assetLiability = config.borrowFactor != 0 ? assetLiability * CONFIG_FACTOR_SCALE / config.borrowFactor : MAX_SANE_DEBT_AMOUNT;
298
305
  status.liabilityValue += assetLiability;
306
+ } else if (balance != 0 && config.collateralFactor != 0) {
307
+ initAssetCache(underlying, assetStorage, assetCache);
308
+ (uint price,) = getPriceInternal(assetCache, config);
309
+
310
+ uint balanceInUnderlying = balanceToUnderlyingAmount(assetCache, balance);
311
+ uint assetCollateral = balanceInUnderlying * price / 1e18;
312
+ assetCollateral = assetCollateral * config.collateralFactor / CONFIG_FACTOR_SCALE;
313
+ status.collateralValue += assetCollateral;
299
314
  }
300
315
  }
301
316
  }
302
317
 
contracts/Interfaces.sol CHANGED
@@ -20,10 +20,10 @@
20
20
  }
21
21
 
22
22
  interface IERC20Permit {
23
23
  function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
24
- function nonces(address owner) external view returns (uint);
25
- function DOMAIN_SEPARATOR() external view returns (bytes32);
24
+ function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external;
25
+ function permit(address owner, address spender, uint value, uint deadline, bytes calldata signature) external;
26
26
  }
27
27
 
28
28
  interface IERC3156FlashBorrower {
29
29
  function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32);
contracts/Base.sol CHANGED
@@ -52,8 +52,15 @@
52
52
  modifier reentrantOK() { // documentation only
53
53
  _;
54
54
  }
55
55
 
56
+ // Used to flag functions which do not modify storage, but do perform a delegate call
57
+ // to a view function, which prohibits a standard view modifier. The flag is used to
58
+ // patch state mutability in compiled ABIs and interfaces.
59
+ modifier staticDelegate() {
60
+ _;
61
+ }
62
+
56
63
  // WARNING: Must be very careful with this modifier. It resets the free memory pointer
57
64
  // to the value it was when the function started. This saves gas if more memory will
58
65
  // be allocated in the future. However, if the memory will be later referenced
59
66
  // (for example because the function has returned a pointer to it) then you cannot
contracts/Constants.sol CHANGED
@@ -23,8 +23,9 @@
23
23
  uint internal constant AVERAGE_LIQUIDITY_PERIOD = 24 * 60 * 60;
24
24
  uint16 internal constant MIN_UNISWAP3_OBSERVATION_CARDINALITY = 144;
25
25
  uint24 internal constant DEFAULT_TWAP_WINDOW_SECONDS = 30 * 60;
26
26
  uint32 internal constant DEFAULT_BORROW_FACTOR = uint32(0.28 * 4_000_000_000);
27
+ uint32 internal constant SELF_COLLATERAL_FACTOR = uint32(0.95 * 4_000_000_000);
27
28
 
28
29
 
29
30
  // Implementation internals
30
31
 
@@ -74,8 +75,9 @@
74
75
  // Classes
75
76
  uint internal constant MODULEID__IRM_CLASS__STABLE = 2_000_500;
76
77
  uint internal constant MODULEID__IRM_CLASS__MAJOR = 2_000_501;
77
78
  uint internal constant MODULEID__IRM_CLASS__MIDCAP = 2_000_502;
79
+ uint internal constant MODULEID__IRM_CLASS__MEGA = 2_000_503;
78
80
 
79
81
  // Swap types
80
82
  uint internal constant SWAP_TYPE__UNI_EXACT_INPUT_SINGLE = 1;
81
83
  uint internal constant SWAP_TYPE__UNI_EXACT_INPUT = 2;