Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated features #888

Merged
merged 22 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3c40299
chore: in the middle of TestMarketLib
QGarchery Oct 15, 2024
7585c13
fix: adapt TestMarketLib
QGarchery Oct 16, 2024
f4f9ba6
fix: remove eMode features
QGarchery Oct 16, 2024
daed681
refactor: rename test without price source
QGarchery Oct 16, 2024
835c675
Merge remote-tracking branch 'origin/refactor/aave-v3-origin' into re…
QGarchery Oct 16, 2024
741d0b0
Merge branch 'refactor/aave-v3-origin' into refactor/remove-deprecated
QGarchery Oct 16, 2024
59a5823
fix: remove stable debt token entirely
QGarchery Oct 16, 2024
4b5dc9a
fix: bounds of ltv and lt
QGarchery Oct 16, 2024
e51cb92
Merge branch 'refactor/aave-v3-origin' into refactor/remove-deprecated
QGarchery Oct 17, 2024
3d85382
chore: remove stable after merge
QGarchery Oct 17, 2024
65c6a17
Merge branch 'refactor/aave-v3-origin' into refactor/remove-deprecated
QGarchery Oct 17, 2024
65096e9
refactor: remove previous compilation setting
QGarchery Oct 17, 2024
1cea52c
test: remove useless struct
MathisGD Oct 25, 2024
f53faad
test: re-add _deprecated_stableDebtToken checks
MathisGD Oct 25, 2024
6d3039e
docs: comment deprecate stableDebtToken slot
QGarchery Oct 25, 2024
72482dd
Merge branch 'refactor/aave-v3-origin' into refactor/remove-deprecated
QGarchery Oct 25, 2024
a00137d
Merge branch 'refactor/aave-v3-origin' into refactor/remove-deprecated
QGarchery Oct 31, 2024
1ca3429
test: tweaks from review
QGarchery Nov 4, 2024
3c3c1ed
refactor: rename has tailored parameters in e-mode
QGarchery Nov 4, 2024
6dd09b7
test: document verify guess
QGarchery Nov 4, 2024
92e53c9
fix: revert unnecessary change storing stable debt token address
QGarchery Nov 4, 2024
fa8eafd
fix: remove reserve stable debt token address again
QGarchery Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ install:
forge install

contracts:
FOUNDRY_PROFILE=build FOUNDRY_TEST=/dev/null FOUNDRY_SCRIPT=/dev/null forge build --via-ir --extra-output-files irOptimized --sizes --force
FOUNDRY_TEST=/dev/null FOUNDRY_SCRIPT=/dev/null forge build --via-ir --extra-output-files irOptimized --sizes --force


test-invariant:
Expand Down
3 changes: 0 additions & 3 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ fs_permissions = [{ access = "read", path = "./config/"}]
gas_limit = "18446744073709551615" # 2^64 - 1, to remove the gas limit
evm_version = "shanghai"

[profile.build]
evm_version = "paris"

[fuzz]
runs = 32

Expand Down
63 changes: 33 additions & 30 deletions src/MorphoInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet
import {DataTypes} from "@aave-v3-origin/protocol/libraries/types/DataTypes.sol";
import {UserConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/UserConfiguration.sol";
import {ReserveConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/ReserveConfiguration.sol";
import {ReserveConfigurationLegacy} from "./libraries/ReserveConfigurationLegacy.sol";
import {EModeConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/EModeConfiguration.sol";

import {MorphoStorage} from "./MorphoStorage.sol";

Expand All @@ -52,7 +52,7 @@ abstract contract MorphoInternal is MorphoStorage {

using UserConfiguration for DataTypes.UserConfigurationMap;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using ReserveConfigurationLegacy for DataTypes.ReserveConfigurationMap;
using EModeConfiguration for uint128;

/* INTERNAL */

Expand Down Expand Up @@ -92,7 +92,7 @@ abstract contract MorphoInternal is MorphoStorage {
market.underlying = underlying;
market.aToken = reserve.aTokenAddress;
market.variableDebtToken = reserve.variableDebtTokenAddress;
market.stableDebtToken = reserve.stableDebtTokenAddress;
QGarchery marked this conversation as resolved.
Show resolved Hide resolved
// Note that reserve.stableDebtTokenAddress is deprecated in v3.2.0.

_marketsCreated.push(underlying);

Expand Down Expand Up @@ -231,7 +231,9 @@ abstract contract MorphoInternal is MorphoStorage {
function _liquidityData(address user) internal view returns (Types.LiquidityData memory liquidityData) {
Types.LiquidityVars memory vars;

if (_eModeCategoryId != 0) vars.eModeCategory = _pool.getEModeCategoryData(_eModeCategoryId);
if (_eModeCategoryId != 0) {
vars.eModeCollateralConfig = _pool.getEModeCategoryCollateralConfig(_eModeCategoryId);
}
vars.oracle = IAaveOracle(_addressesProvider.getPriceOracle());
vars.user = user;

Expand Down Expand Up @@ -307,8 +309,7 @@ abstract contract MorphoInternal is MorphoStorage {
/// @return debtValue The debt value of `vars.user` on the `underlying` market.
function _debt(address underlying, Types.LiquidityVars memory vars) internal view returns (uint256 debtValue) {
DataTypes.ReserveConfigurationMap memory config = _pool.getConfiguration(underlying);
(, uint256 underlyingPrice, uint256 underlyingUnit) =
_assetData(underlying, vars.oracle, config, vars.eModeCategory.priceSource);
(uint256 underlyingPrice, uint256 underlyingUnit) = _assetData(underlying, vars.oracle, config);

Types.Indexes256 memory indexes = _computeIndexes(underlying);
debtValue =
Expand All @@ -329,18 +330,16 @@ abstract contract MorphoInternal is MorphoStorage {
{
DataTypes.ReserveConfigurationMap memory config = _pool.getConfiguration(underlying);

bool isInEMode;
(isInEMode, underlyingPrice, underlyingUnit) =
_assetData(underlying, vars.oracle, config, vars.eModeCategory.priceSource);
(underlyingPrice, underlyingUnit) = _assetData(underlying, vars.oracle, config);

// If the LTV is 0 on Aave V3, the asset cannot be used as collateral to borrow upon a breaking withdraw.
// In response, Morpho disables the asset as collateral and sets its liquidation threshold
// to 0 and the governance should warn users to repay their debt.
if (config.getLtv() == 0) return (underlyingPrice, 0, 0, underlyingUnit);

if (isInEMode) {
ltv = vars.eModeCategory.ltv;
liquidationThreshold = vars.eModeCategory.liquidationThreshold;
if (_hasTailoredParametersInEmode(underlying)) {
ltv = vars.eModeCollateralConfig.ltv;
liquidationThreshold = vars.eModeCollateralConfig.liquidationThreshold;
} else {
ltv = config.getLtv();
liquidationThreshold = config.getLiquidationThreshold();
Expand Down Expand Up @@ -489,33 +488,37 @@ abstract contract MorphoInternal is MorphoStorage {
return liquidityData.debt > 0 ? liquidityData.maxDebt.wadDiv(liquidityData.debt) : type(uint256).max;
}

/// @dev Returns data relative to the given asset and its configuration, according to a given oracle.
/// @return Whether the given asset is part of Morpho's e-mode category.
/// @return The asset's price or the price of the given e-mode price source if the asset is in the e-mode category, according to the given oracle.
/// @dev Returns data relative to the given asset, according to a given oracle.
/// @return The asset's price according to the given oracle.
/// @return The asset's unit.
function _assetData(
address asset,
IAaveOracle oracle,
DataTypes.ReserveConfigurationMap memory config,
address priceSource
) internal view returns (bool, uint256, uint256) {
function _assetData(address asset, IAaveOracle oracle, DataTypes.ReserveConfigurationMap memory config)
internal
view
returns (uint256, uint256)
{
uint256 assetUnit;
unchecked {
assetUnit = 10 ** config.getDecimals();
}

bool isInEMode = _isInEModeCategory(config);
if (isInEMode && priceSource != address(0)) {
uint256 eModePrice = oracle.getAssetPrice(priceSource);
return (oracle.getAssetPrice(asset), assetUnit);
}

if (eModePrice != 0) return (isInEMode, eModePrice, assetUnit);
}
/// @dev Returns whether the underlying asset is enabled as an e-mode collateral on the specific Morpho e-mode.
function _hasTailoredParametersInEmode(address underlying) internal view returns (bool) {
if (_eModeCategoryId == 0) return false;
QGarchery marked this conversation as resolved.
Show resolved Hide resolved

return (isInEMode, oracle.getAssetPrice(asset), assetUnit);
uint256 reserveIndex = _pool.getReserveData(underlying).id;
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
uint128 bitmap = _pool.getEModeCategoryCollateralBitmap(_eModeCategoryId);
return bitmap.isReserveEnabledOnBitmap(reserveIndex);
}

/// @dev Returns whether Morpho is in an e-mode category and the given asset configuration is in the same e-mode category.
function _isInEModeCategory(DataTypes.ReserveConfigurationMap memory config) internal view returns (bool) {
return _eModeCategoryId != 0 && config.getEModeCategory() == _eModeCategoryId;
/// @dev Returns whether the underlying asset is borrowable in the specific Morpho e-mode.
function _isBorrowableInEMode(address underlying) internal view returns (bool) {
if (_eModeCategoryId == 0) return true;
MathisGD marked this conversation as resolved.
Show resolved Hide resolved

uint256 reserveIndex = _pool.getReserveData(underlying).id;
uint128 bitmap = _pool.getEModeCategoryBorrowableBitmap(_eModeCategoryId);
return bitmap.isReserveEnabledOnBitmap(reserveIndex);
}
}
23 changes: 9 additions & 14 deletions src/PositionsManagerInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet
import {DataTypes} from "@aave-v3-origin/protocol/libraries/types/DataTypes.sol";
import {UserConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/UserConfiguration.sol";
import {ReserveConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/ReserveConfiguration.sol";
import {ReserveConfigurationLegacy} from "./libraries/ReserveConfigurationLegacy.sol";

import {ERC20} from "@solmate/tokens/ERC20.sol";

Expand All @@ -48,7 +47,6 @@ abstract contract PositionsManagerInternal is MatchingEngine {

using UserConfiguration for DataTypes.UserConfigurationMap;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using ReserveConfigurationLegacy for DataTypes.ReserveConfigurationMap;

/// @dev Validates the manager's permission.
function _validatePermission(address delegator, address manager) internal view {
Expand Down Expand Up @@ -118,7 +116,7 @@ abstract contract PositionsManagerInternal is MatchingEngine {
revert Errors.SentinelBorrowNotEnabled();
}

if (_eModeCategoryId != 0 && _eModeCategoryId != config.getEModeCategory()) {
if (!_isBorrowableInEMode(underlying)) {
revert Errors.InconsistentEMode();
}

Expand All @@ -127,8 +125,7 @@ abstract contract PositionsManagerInternal is MatchingEngine {

uint256 trueP2PBorrow = market.trueP2PBorrow(indexes);
uint256 borrowCap = config.getBorrowCap() * (10 ** config.getDecimals());
uint256 poolDebt =
ERC20(market.variableDebtToken).totalSupply() + ERC20(market.stableDebtToken).totalSupply();
uint256 poolDebt = ERC20(market.variableDebtToken).totalSupply();

if (amount + trueP2PBorrow + poolDebt > borrowCap) revert Errors.ExceedsBorrowCap();
}
Expand Down Expand Up @@ -599,21 +596,19 @@ abstract contract PositionsManagerInternal is MatchingEngine {
) internal view returns (uint256 amountToRepay, uint256 amountToSeize) {
Types.AmountToSeizeVars memory vars;

DataTypes.EModeCategoryLegacy memory eModeCategory;
if (_eModeCategoryId != 0) eModeCategory = _pool.getEModeCategoryData(_eModeCategoryId);
DataTypes.CollateralConfig memory eModeCollateralConfig;
if (_eModeCategoryId != 0) eModeCollateralConfig = _pool.getEModeCategoryCollateralConfig(_eModeCategoryId);

bool collateralIsInEMode;
IAaveOracle oracle = IAaveOracle(_addressesProvider.getPriceOracle());
DataTypes.ReserveConfigurationMap memory borrowedConfig = _pool.getConfiguration(underlyingBorrowed);
DataTypes.ReserveConfigurationMap memory collateralConfig = _pool.getConfiguration(underlyingCollateral);

(, vars.borrowedPrice, vars.borrowedTokenUnit) =
_assetData(underlyingBorrowed, oracle, borrowedConfig, eModeCategory.priceSource);
(collateralIsInEMode, vars.collateralPrice, vars.collateralTokenUnit) =
_assetData(underlyingCollateral, oracle, collateralConfig, eModeCategory.priceSource);
(vars.borrowedPrice, vars.borrowedTokenUnit) = _assetData(underlyingBorrowed, oracle, borrowedConfig);
(vars.collateralPrice, vars.collateralTokenUnit) = _assetData(underlyingCollateral, oracle, collateralConfig);

vars.liquidationBonus =
collateralIsInEMode ? eModeCategory.liquidationBonus : collateralConfig.getLiquidationBonus();
vars.liquidationBonus = _hasTailoredParametersInEmode(underlyingCollateral)
? eModeCollateralConfig.liquidationBonus
: collateralConfig.getLiquidationBonus();

amountToRepay = maxToRepay;
amountToSeize = (
Expand Down
6 changes: 0 additions & 6 deletions src/interfaces/aave/IStableDebtTokenLegacy.sol

This file was deleted.

25 changes: 0 additions & 25 deletions src/libraries/ReserveConfigurationLegacy.sol

This file was deleted.

17 changes: 2 additions & 15 deletions src/libraries/ReserveDataLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.17;

import {IStableDebtTokenLegacy} from "src/interfaces/aave/IStableDebtTokenLegacy.sol";
import {IVariableDebtToken} from "@aave-v3-origin/interfaces/IVariableDebtToken.sol";

import {Types} from "./Types.sol";
Expand Down Expand Up @@ -36,24 +35,12 @@ library ReserveDataLib {
uint256 reserveFactor = reserve.configuration.getReserveFactor();
if (reserveFactor == 0) return reserve.accruedToTreasury;

(
uint256 currPrincipalStableDebt,
uint256 currTotalStableDebt,
uint256 currAvgStableBorrowRate,
uint40 stableDebtLastUpdateTimestamp
) = IStableDebtTokenLegacy(reserve.stableDebtTokenAddress).getSupplyData();
uint256 scaledTotalVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress).scaledTotalSupply();

uint256 currTotalVariableDebt = scaledTotalVariableDebt.rayMul(indexes.borrow.poolIndex);
uint256 prevTotalVariableDebt = scaledTotalVariableDebt.rayMul(reserve.variableBorrowIndex);
uint256 prevTotalStableDebt = currPrincipalStableDebt.rayMul(
MathUtils.calculateCompoundedInterest(
currAvgStableBorrowRate, stableDebtLastUpdateTimestamp, reserve.lastUpdateTimestamp
)
);

uint256 accruedTotalDebt =
currTotalVariableDebt + currTotalStableDebt - prevTotalVariableDebt - prevTotalStableDebt;

uint256 accruedTotalDebt = currTotalVariableDebt - prevTotalVariableDebt;
if (accruedTotalDebt == 0) return reserve.accruedToTreasury;

uint256 newAccruedToTreasury = accruedTotalDebt.percentMul(reserveFactor).rayDiv(indexes.supply.poolIndex);
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ library Types {
// SLOT 8
address aToken; // 160 bits
// SLOT 9
address stableDebtToken; // 160 bits
address _deprecated_stableDebtToken; // 160 bits (deprecated: will be empty for new markets)
// SLOT 10
uint256 idleSupply; // 256 bits
}
Expand Down Expand Up @@ -169,7 +169,7 @@ library Types {
struct LiquidityVars {
address user; // The user address.
IAaveOracle oracle; // The oracle used by Aave.
DataTypes.EModeCategoryLegacy eModeCategory; // The data related to the eMode category (could be empty if not in any e-mode).
DataTypes.CollateralConfig eModeCollateralConfig; // The data related to the eMode category (could be empty if not in any e-mode).
QGarchery marked this conversation as resolved.
Show resolved Hide resolved
}

/// @notice Variables used during a borrow or withdraw.
Expand Down
35 changes: 10 additions & 25 deletions test/helpers/ForkTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {MathUtils} from "@aave-v3-origin/protocol/libraries/math/MathUtils.sol";
import {DataTypes} from "@aave-v3-origin/protocol/libraries/types/DataTypes.sol";
import {Errors as AaveErrors} from "@aave-v3-origin/protocol/libraries/helpers/Errors.sol";
import {ReserveConfiguration} from "@aave-v3-origin/protocol/libraries/configuration/ReserveConfiguration.sol";
import {ReserveConfigurationLegacy} from "src/libraries/ReserveConfigurationLegacy.sol";

import {PermitHash} from "@permit2/libraries/PermitHash.sol";
import {IAllowanceTransfer, AllowanceTransfer} from "@permit2/AllowanceTransfer.sol";
Expand All @@ -38,7 +37,6 @@ contract ForkTest is BaseTest, Configured {
using ReserveDataLib for DataTypes.ReserveDataLegacy;
using ReserveDataTestLib for DataTypes.ReserveDataLegacy;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using ReserveConfigurationLegacy for DataTypes.ReserveConfigurationMap;

/* CONSTANTS */

Expand Down Expand Up @@ -221,36 +219,23 @@ contract ForkTest is BaseTest, Configured {
return reserve.totalSupplyToCap(poolSupplyIndex, poolBorrowIndex);
}

/// @dev Computes the valid lower bound for ltv and lt for a given CategoryEModeId, conditions required by Aave's code.
/// https://github.com/aave/aave-v3-core/blob/94e571f3a7465201881a59555314cd550ccfda57/contracts/protocol/pool/PoolConfigurator.sol#L369-L376
QGarchery marked this conversation as resolved.
Show resolved Hide resolved
function _getLtvLt(address underlying, uint8 eModeCategoryId)
internal
view
returns (uint256 ltvBound, uint256 ltBound, uint256 ltvConfig, uint256 ltConfig)
{
address[] memory reserves = pool.getReservesList();
for (uint256 i = 0; i < reserves.length; ++i) {
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(reserves[i]);
if (eModeCategoryId == currentConfig.getEModeCategory() || underlying == reserves[i]) {
ltvBound = uint16(Math.max(ltvBound, currentConfig.getLtv()));

ltBound = uint16(Math.max(ltBound, currentConfig.getLiquidationThreshold()));

if (underlying == reserves[i]) {
ltvConfig = uint16(currentConfig.getLtv());
ltConfig = uint16(currentConfig.getLiquidationThreshold());
}
}
}
function _getLtvLt(address underlying) internal view returns (uint256 ltvConfig, uint256 ltConfig) {
DataTypes.ReserveConfigurationMap memory config = pool.getConfiguration(underlying);
ltvConfig = config.getLtv();
ltConfig = config.getLiquidationThreshold();
}

function _setEModeCategoryAsset(
DataTypes.EModeCategoryLegacy memory eModeCategory,
DataTypes.CollateralConfig memory eModeCollateralConfig,
address underlying,
uint8 eModeCategoryId
) internal {
poolAdmin.setEModeCategory(
eModeCategoryId, eModeCategory.ltv, eModeCategory.liquidationThreshold, eModeCategory.liquidationBonus, ""
eModeCategoryId,
eModeCollateralConfig.ltv,
eModeCollateralConfig.liquidationThreshold,
eModeCollateralConfig.liquidationBonus,
""
);
poolAdmin.setAssetBorrowableInEMode(underlying, eModeCategoryId, true);
poolAdmin.setAssetCollateralInEMode(underlying, eModeCategoryId, true);
Expand Down
Loading
Loading