@@ -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 (
|
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
|
|
@@ -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
|
25
|
-
function
|
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);
|
@@ -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
|
@@ -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;
|