@@ -33,14 +33,12 @@
|
|
33
33
|
}
|
34
34
|
|
35
35
|
// Accessors
|
36
36
|
|
37
|
-
// These are not view methods, since they can perform state writes in the uniswap contract while retrieving prices
|
38
|
-
|
39
37
|
/// @notice Compute aggregate liquidity for an account
|
40
38
|
/// @param account User address
|
41
39
|
/// @return status Aggregate liquidity (sum of all entered assets)
|
42
|
-
function liquidity(address account) external
|
40
|
+
function liquidity(address account) external staticDelegate returns (IRiskManager.LiquidityStatus memory status) {
|
43
41
|
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
|
44
42
|
abi.encodeWithSelector(IRiskManager.computeLiquidity.selector, account));
|
45
43
|
|
46
44
|
(status) = abi.decode(result, (IRiskManager.LiquidityStatus));
|
@@ -48,9 +46,9 @@
|
|
48
46
|
|
49
47
|
/// @notice Compute detailed liquidity for an account, broken down by asset
|
50
48
|
/// @param account User address
|
51
49
|
/// @return assets List of user's entered assets and each asset's corresponding liquidity
|
52
|
-
function detailedLiquidity(address account) public
|
50
|
+
function detailedLiquidity(address account) public staticDelegate returns (IRiskManager.AssetLiquidity[] memory assets) {
|
53
51
|
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
|
54
52
|
abi.encodeWithSelector(IRiskManager.computeAssetLiquidities.selector, account));
|
55
53
|
|
56
54
|
(assets) = abi.decode(result, (IRiskManager.AssetLiquidity[]));
|
@@ -59,9 +57,9 @@
|
|
59
57
|
/// @notice Retrieve Euler's view of an asset's price
|
60
58
|
/// @param underlying Token address
|
61
59
|
/// @return twap Time-weighted average price
|
62
60
|
/// @return twapPeriod TWAP duration, either the twapWindow value in AssetConfig, or less if that duration not available
|
63
|
-
function getPrice(address underlying) external
|
61
|
+
function getPrice(address underlying) external staticDelegate returns (uint twap, uint twapPeriod) {
|
64
62
|
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
|
65
63
|
abi.encodeWithSelector(IRiskManager.getPrice.selector, underlying));
|
66
64
|
|
67
65
|
(twap, twapPeriod) = abi.decode(result, (uint, uint));
|
@@ -71,9 +69,9 @@
|
|
71
69
|
/// @param underlying Token address
|
72
70
|
/// @return twap Time-weighted average price
|
73
71
|
/// @return twapPeriod TWAP duration, either the twapWindow value in AssetConfig, or less if that duration not available
|
74
72
|
/// @return currPrice The current marginal price on uniswap3 (informational: not used anywhere in the Euler protocol)
|
75
|
-
function getPriceFull(address underlying) external
|
73
|
+
function getPriceFull(address underlying) external staticDelegate returns (uint twap, uint twapPeriod, uint currPrice) {
|
76
74
|
bytes memory result = callInternalModule(MODULEID__RISK_MANAGER,
|
77
75
|
abi.encodeWithSelector(IRiskManager.getPriceFull.selector, underlying));
|
78
76
|
|
79
77
|
(twap, twapPeriod, currPrice) = abi.decode(result, (uint, uint, uint));
|
@@ -277,5 +275,60 @@
|
|
277
275
|
require(pTokenAddr != address(0), "e/exec/ptoken-not-found");
|
278
276
|
|
279
277
|
PToken(pTokenAddr).forceUnwrap(msgSender, amount);
|
280
278
|
}
|
279
|
+
|
280
|
+
/// @notice Apply EIP2612 signed permit on a target token from sender to euler contract
|
281
|
+
/// @param token Token address
|
282
|
+
/// @param value Allowance value
|
283
|
+
/// @param deadline Permit expiry timestamp
|
284
|
+
/// @param v secp256k1 signature v
|
285
|
+
/// @param r secp256k1 signature r
|
286
|
+
/// @param s secp256k1 signature s
|
287
|
+
function usePermit(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external nonReentrant {
|
288
|
+
require(underlyingLookup[token].eTokenAddress != address(0), "e/exec/market-not-activated");
|
289
|
+
address msgSender = unpackTrailingParamMsgSender();
|
290
|
+
|
291
|
+
IERC20Permit(token).permit(msgSender, address(this), value, deadline, v, r, s);
|
292
|
+
}
|
293
|
+
|
294
|
+
/// @notice Apply DAI like (allowed) signed permit on a target token from sender to euler contract
|
295
|
+
/// @param token Token address
|
296
|
+
/// @param nonce Sender nonce
|
297
|
+
/// @param expiry Permit expiry timestamp
|
298
|
+
/// @param allowed If true, set unlimited allowance, otherwise set zero allowance
|
299
|
+
/// @param v secp256k1 signature v
|
300
|
+
/// @param r secp256k1 signature r
|
301
|
+
/// @param s secp256k1 signature s
|
302
|
+
function usePermitAllowed(address token, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external nonReentrant {
|
303
|
+
require(underlyingLookup[token].eTokenAddress != address(0), "e/exec/market-not-activated");
|
304
|
+
address msgSender = unpackTrailingParamMsgSender();
|
305
|
+
|
306
|
+
IERC20Permit(token).permit(msgSender, address(this), nonce, expiry, allowed, v, r, s);
|
307
|
+
}
|
308
|
+
|
309
|
+
/// @notice Apply allowance to tokens expecting the signature packed in a single bytes param
|
310
|
+
/// @param token Token address
|
311
|
+
/// @param value Allowance value
|
312
|
+
/// @param deadline Permit expiry timestamp
|
313
|
+
/// @param signature secp256k1 signature encoded as rsv
|
314
|
+
function usePermitPacked(address token, uint256 value, uint256 deadline, bytes calldata signature) external nonReentrant {
|
315
|
+
require(underlyingLookup[token].eTokenAddress != address(0), "e/exec/market-not-activated");
|
316
|
+
address msgSender = unpackTrailingParamMsgSender();
|
317
|
+
|
318
|
+
IERC20Permit(token).permit(msgSender, address(this), value, deadline, signature);
|
319
|
+
}
|
320
|
+
|
321
|
+
/// @notice Execute a staticcall to an arbitrary address with an arbitrary payload.
|
322
|
+
/// @param contractAddress Address of the contract to call
|
323
|
+
/// @param payload Encoded call payload
|
324
|
+
/// @return result Encoded return data
|
325
|
+
/// @dev Intended to be used in static-called batches, to e.g. provide detailed information about the impacts of the simulated operation.
|
326
|
+
function doStaticCall(address contractAddress, bytes memory payload) external view returns (bytes memory) {
|
327
|
+
(bool success, bytes memory result) = contractAddress.staticcall(payload);
|
328
|
+
if (!success) revertBytes(result);
|
329
|
+
|
330
|
+
assembly {
|
331
|
+
return(add(32, result), mload(result))
|
332
|
+
}
|
333
|
+
}
|
281
334
|
}
|
@@ -497,9 +497,9 @@
|
|
497
497
|
|
498
498
|
if (toOwed == 0) doEnterMarket(to, assetCache.underlying);
|
499
499
|
|
500
500
|
// If amount was rounded up, transfer exact amount owed
|
501
|
-
if (amount > fromOwed && amount - fromOwed < INTERNAL_DEBT_PRECISION) amount = fromOwed;
|
501
|
+
if (amount > fromOwed && amount - fromOwed < INTERNAL_DEBT_PRECISION * assetCache.underlyingDecimalsScaler) amount = fromOwed;
|
502
502
|
|
503
503
|
require(fromOwed >= amount, "e/insufficient-balance");
|
504
504
|
unchecked { fromOwed -= amount; }
|
505
505
|
|
@@ -27,11 +27,11 @@
|
|
27
27
|
}
|
28
28
|
|
29
29
|
function getNewMarketParameters(address underlying) external returns (NewMarketParameters memory);
|
30
30
|
|
31
|
-
function requireLiquidity(address account) external;
|
32
|
-
function computeLiquidity(address account) external returns (LiquidityStatus memory status);
|
33
|
-
function computeAssetLiquidities(address account) external returns (AssetLiquidity[] memory assets);
|
31
|
+
function requireLiquidity(address account) external view;
|
32
|
+
function computeLiquidity(address account) external view returns (LiquidityStatus memory status);
|
33
|
+
function computeAssetLiquidities(address account) external view returns (AssetLiquidity[] memory assets);
|
34
34
|
|
35
|
-
function getPrice(address underlying) external returns (uint twap, uint twapPeriod);
|
36
|
-
function getPriceFull(address underlying) external returns (uint twap, uint twapPeriod, uint currPrice);
|
35
|
+
function getPrice(address underlying) external view returns (uint twap, uint twapPeriod);
|
36
|
+
function getPriceFull(address underlying) external view returns (uint twap, uint twapPeriod, uint currPrice);
|
37
37
|
}
|
@@ -18,8 +18,14 @@
|
|
18
18
|
function transfer(address to, uint value) external returns (bool);
|
19
19
|
function transferFrom(address from, address to, uint value) external returns (bool);
|
20
20
|
}
|
21
21
|
|
22
|
+
interface IERC20Permit {
|
23
|
+
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
|
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
|
+
}
|
27
|
+
|
22
28
|
interface IERC3156FlashBorrower {
|
23
29
|
function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32);
|
24
30
|
}
|
25
31
|
|
@@ -22,24 +22,16 @@
|
|
22
22
|
// Accessing parameters
|
23
23
|
|
24
24
|
function unpackTrailingParamMsgSender() internal pure returns (address msgSender) {
|
25
25
|
assembly {
|
26
|
-
|
27
|
-
|
28
|
-
calldatacopy(12, sub(calldatasize(), 40), 20)
|
29
|
-
msgSender := mload(0)
|
26
|
+
msgSender := shr(96, calldataload(sub(calldatasize(), 40)))
|
30
27
|
}
|
31
28
|
}
|
32
29
|
|
33
30
|
function unpackTrailingParams() internal pure returns (address msgSender, address proxyAddr) {
|
34
31
|
assembly {
|
35
|
-
|
36
|
-
|
37
|
-
calldatacopy(12, sub(calldatasize(), 40), 20)
|
38
|
-
msgSender := mload(0)
|
39
|
-
|
40
|
-
calldatacopy(12, sub(calldatasize(), 20), 20)
|
41
|
-
proxyAddr := mload(0)
|
32
|
+
msgSender := shr(96, calldataload(sub(calldatasize(), 40)))
|
33
|
+
proxyAddr := shr(96, calldataload(sub(calldatasize(), 20)))
|
42
34
|
}
|
43
35
|
}
|
44
36
|
|
45
37
|
|
@@ -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
|
@@ -20,11 +20,12 @@
|
|
20
20
|
uint internal constant RESERVE_FEE_SCALE = 4_000_000_000; // must fit into a uint32
|
21
21
|
uint32 internal constant DEFAULT_RESERVE_FEE = uint32(0.23 * 4_000_000_000);
|
22
22
|
uint internal constant INITIAL_INTEREST_ACCUMULATOR = 1e27;
|
23
23
|
uint internal constant AVERAGE_LIQUIDITY_PERIOD = 24 * 60 * 60;
|
24
|
-
uint16 internal constant MIN_UNISWAP3_OBSERVATION_CARDINALITY =
|
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,12 +75,16 @@
|
|
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;
|
82
84
|
uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_SINGLE = 3;
|
83
85
|
uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT = 4;
|
84
86
|
uint internal constant SWAP_TYPE__1INCH = 5;
|
87
|
+
|
88
|
+
uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_SINGLE_REPAY = 6;
|
89
|
+
uint internal constant SWAP_TYPE__UNI_EXACT_OUTPUT_REPAY = 7;
|
85
90
|
}
|