Euler diff: contracts/modules/DToken.sol

Before: contract 0x03601eDc8aF4b0439d63Eb3a45ed11B01c6975d7
After: git 07b78228505390b960d8b818d343005f00fb185f
Files changed (7) hide show
  1. contracts/modules/DToken.sol +25 -12
  2. contracts/BaseLogic.sol +2 -2
  3. contracts/BaseModule.sol +3 -11
  4. contracts/Interfaces.sol +6 -0
  5. contracts/IRiskManager.sol +5 -5
  6. contracts/Base.sol +7 -0
  7. contracts/Constants.sol +3 -1
contracts/modules/DToken.sol CHANGED
@@ -38,23 +38,30 @@
38
38
  (address underlying,,,) = CALLER();
39
39
  return string(abi.encodePacked("d", IERC20(underlying).symbol()));
40
40
  }
41
41
 
42
- /// @notice Decimals, always normalised to 18.
43
- function decimals() external pure returns (uint8) {
44
- return 18;
42
+ /// @notice Decimals of underlying
43
+ function decimals() external view returns (uint8) {
44
+ (,AssetStorage storage assetStorage,,) = CALLER();
45
+ return assetStorage.underlyingDecimals;
45
46
  }
46
47
 
48
+ /// @notice Address of underlying asset
49
+ function underlyingAsset() external view returns (address) {
50
+ (address underlying,,,) = CALLER();
51
+ return underlying;
52
+ }
47
53
 
54
+
48
55
  /// @notice Sum of all outstanding debts, in underlying units (increases as interest is accrued)
49
56
  function totalSupply() external view returns (uint) {
50
57
  (address underlying, AssetStorage storage assetStorage,,) = CALLER();
51
58
  AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage);
52
59
 
53
60
  return assetCache.totalBorrows / INTERNAL_DEBT_PRECISION / assetCache.underlyingDecimalsScaler;
54
61
  }
55
62
 
56
- /// @notice Sum of all outstanding debts, in underlying units with extra precision (increases as interest is accrued)
63
+ /// @notice Sum of all outstanding debts, in underlying units normalized to 27 decimals (increases as interest is accrued)
57
64
  function totalSupplyExact() external view returns (uint) {
58
65
  (address underlying, AssetStorage storage assetStorage,,) = CALLER();
59
66
  AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage);
60
67
 
@@ -69,9 +76,9 @@
69
76
 
70
77
  return getCurrentOwed(assetStorage, assetCache, account) / assetCache.underlyingDecimalsScaler;
71
78
  }
72
79
 
73
- /// @notice Debt owed by a particular account, in underlying units with extra precision
80
+ /// @notice Debt owed by a particular account, in underlying units normalized to 27 decimals
74
81
  function balanceOfExact(address account) external view returns (uint) {
75
82
  (address underlying, AssetStorage storage assetStorage,,) = CALLER();
76
83
  AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage);
77
84
 
@@ -137,16 +144,19 @@
137
144
 
138
145
  /// @notice Allow spender to send an amount of dTokens to a particular sub-account
139
146
  /// @param subAccountId 0 for primary, 1-255 for a sub-account
140
147
  /// @param spender Trusted address
141
- /// @param amount Use max uint256 for "infinite" allowance
148
+ /// @param amount In underlying units (use max uint256 for "infinite" allowance)
142
149
  function approveDebt(uint subAccountId, address spender, uint amount) public reentrantOK returns (bool) {
143
- (, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER();
150
+ (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER();
144
151
  address account = getSubAccount(msgSender, subAccountId);
145
152
 
146
153
  require(!isSubAccountOf(spender, account), "e/self-approval");
147
154
 
148
- assetStorage.dTokenAllowance[account][spender] = amount;
155
+ AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
156
+
157
+ assetStorage.dTokenAllowance[account][spender] = amount == type(uint).max ? type(uint).max : decodeExternalAmount(assetCache, amount);
158
+
149
159
  emitViaProxy_Approval(proxyAddr, account, spender, amount);
150
160
 
151
161
  return true;
152
162
  }
@@ -154,11 +164,14 @@
154
164
  /// @notice Retrieve the current debt allowance
155
165
  /// @param holder Xor with the desired sub-account ID (if applicable)
156
166
  /// @param spender Trusted address
157
167
  function debtAllowance(address holder, address spender) external view returns (uint) {
158
- (, AssetStorage storage assetStorage,,) = CALLER();
168
+ (address underlying, AssetStorage storage assetStorage,,) = CALLER();
169
+ AssetCache memory assetCache = loadAssetCacheRO(underlying, assetStorage);
159
170
 
160
- return assetStorage.dTokenAllowance[holder][spender];
171
+ uint allowance = assetStorage.dTokenAllowance[holder][spender];
172
+
173
+ return allowance == type(uint).max ? type(uint).max : allowance / assetCache.underlyingDecimalsScaler;
161
174
  }
162
175
 
163
176
 
164
177
 
@@ -171,9 +184,9 @@
171
184
 
172
185
  /// @notice Transfer dTokens from one address to another
173
186
  /// @param from Xor with the desired sub-account ID (if applicable)
174
187
  /// @param to This address must've approved the from address, or be a sub-account of msg.sender
175
- /// @param amount In underlying. Use max uint256 for full balance.
188
+ /// @param amount In underlying units. Use max uint256 for full balance.
176
189
  function transferFrom(address from, address to, uint amount) public nonReentrant returns (bool) {
177
190
  (address underlying, AssetStorage storage assetStorage, address proxyAddr, address msgSender) = CALLER();
178
191
  AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
179
192
 
@@ -191,9 +204,9 @@
191
204
 
192
205
  if (!isSubAccountOf(msgSender, to) && assetStorage.dTokenAllowance[to][msgSender] != type(uint).max) {
193
206
  require(assetStorage.dTokenAllowance[to][msgSender] >= amount, "e/insufficient-debt-allowance");
194
207
  unchecked { assetStorage.dTokenAllowance[to][msgSender] -= amount; }
195
- emitViaProxy_Approval(proxyAddr, to, msgSender, assetStorage.dTokenAllowance[to][msgSender]);
208
+ emitViaProxy_Approval(proxyAddr, to, msgSender, assetStorage.dTokenAllowance[to][msgSender] / assetCache.underlyingDecimalsScaler);
196
209
  }
197
210
 
198
211
  transferBorrow(assetStorage, assetCache, proxyAddr, from, to, amount);
199
212
 
contracts/BaseLogic.sol CHANGED
@@ -441,13 +441,13 @@
441
441
 
442
442
  if (owed > prevOwed) {
443
443
  uint change = owed - prevOwed;
444
444
  emit Borrow(assetCache.underlying, account, change);
445
- emitViaProxy_Transfer(dTokenAddress, address(0), account, change);
445
+ emitViaProxy_Transfer(dTokenAddress, address(0), account, change / assetCache.underlyingDecimalsScaler);
446
446
  } else if (prevOwed > owed) {
447
447
  uint change = prevOwed - owed;
448
448
  emit Repay(assetCache.underlying, account, change);
449
- emitViaProxy_Transfer(dTokenAddress, account, address(0), change);
449
+ emitViaProxy_Transfer(dTokenAddress, account, address(0), change / assetCache.underlyingDecimalsScaler);
450
450
  }
451
451
  }
452
452
 
453
453
  function increaseBorrow(AssetStorage storage assetStorage, AssetCache memory assetCache, address dTokenAddress, address account, uint amount) internal {
contracts/BaseModule.sol CHANGED
@@ -22,24 +22,16 @@
22
22
  // Accessing parameters
23
23
 
24
24
  function unpackTrailingParamMsgSender() internal pure returns (address msgSender) {
25
25
  assembly {
26
- mstore(0, 0)
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
- mstore(0, 0)
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
 
contracts/Interfaces.sol CHANGED
@@ -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
 
contracts/IRiskManager.sol CHANGED
@@ -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
  }
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
@@ -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 = 10;
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;