From ac432008fd106697007ecf158125b5410416e72a Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 13:17:16 +0530 Subject: [PATCH 01/13] docs: fix natspec on swapToVariable (1) --- src/core/contracts/interfaces/IPool.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/contracts/interfaces/IPool.sol b/src/core/contracts/interfaces/IPool.sol index f746d172..4e49aa40 100644 --- a/src/core/contracts/interfaces/IPool.sol +++ b/src/core/contracts/interfaces/IPool.sol @@ -381,10 +381,10 @@ interface IPool { function swapBorrowRateMode(address asset, uint256 interestRateMode) external; /** - * @notice Allows a borrower to swap his debt between stable and variable mode, - * @dev introduce in a flavor stable rate deprecation + * @notice Permissionless method which allows anyone to swap a users stable debt to variable debt + * @dev Introduced in favor of stable rate deprecation * @param asset The address of the underlying asset borrowed - * @param user The address of the user to be swapped + * @param user The address of the user whose debt will be swapped from stable to variable */ function swapToVariable(address asset, address user) external; From c9d88ba42508727dabccf9de9db0c1260bb83453 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 13:22:25 +0530 Subject: [PATCH 02/13] docs: fix natspec on executeSwapBorrowRateMode (2) --- src/core/contracts/protocol/libraries/logic/BorrowLogic.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol b/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol index 91ea0fa6..5364da4f 100644 --- a/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol @@ -309,6 +309,7 @@ library BorrowLogic { * @param userConfig The user configuration mapping that tracks the supplied/borrowed assets * @param asset The asset of the position being swapped * @param interestRateMode The current interest rate mode of the position being swapped + * @param user The user whose debt position is being swapped */ function executeSwapBorrowRateMode( DataTypes.ReserveData storage reserve, From 54821fe70092691bf825765b98b65ea4aa7e60df Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 13:26:30 +0530 Subject: [PATCH 03/13] refactor: fix VIRTUAL_ACC_ACTIVE_MASK (5) --- docs/Aave-v3.1-features.md | 2 +- .../libraries/configuration/ReserveConfiguration.sol | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Aave-v3.1-features.md b/docs/Aave-v3.1-features.md index 0e3a2b95..27dfe34d 100644 --- a/docs/Aave-v3.1-features.md +++ b/docs/Aave-v3.1-features.md @@ -72,7 +72,7 @@ Given its implications and criticality, virtual accounting can be considered the - [ConfigurationInputTypes](../src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol) - Added flag `useVirtualBalance` for a new listing to use or not virtual balance. - [ReserveConfiguration](../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol) - - Added logic to store and set/get the new `VIRTUAL_ACC_ACTIVE` flag. + - Added logic to store and set/get the new `VIRTUAL_ACC_ACTIVE_MASK` flag. - [Errors](../src/core/contracts/protocol/libraries/helpers/Errors.sol) - In relation with this feature, added the `WITHDRAW_TO_ATOKEN` and `SUPPLY_TO_ATOKEN` errors. - [Pool](../src/core/contracts/protocol/pool/Pool.sol) diff --git a/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 700b129a..2b04a0f3 100644 --- a/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -29,7 +29,7 @@ library ReserveConfiguration { uint256 internal constant EMODE_CATEGORY_MASK = 0xFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore uint256 internal constant UNBACKED_MINT_CAP_MASK = 0xFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore uint256 internal constant DEBT_CEILING_MASK = 0xF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant VIRTUAL_ACC_ACTIVE = 0xEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant VIRTUAL_ACC_ACTIVE_MASK = 0xEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed uint256 internal constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; @@ -556,7 +556,7 @@ library ReserveConfiguration { bool active ) internal pure { self.data = - (self.data & VIRTUAL_ACC_ACTIVE) | + (self.data & VIRTUAL_ACC_ACTIVE_MASK) | (uint256(active ? 1 : 0) << VIRTUAL_ACC_START_BIT_POSITION); } @@ -568,7 +568,7 @@ library ReserveConfiguration { function getIsVirtualAccActive( DataTypes.ReserveConfigurationMap memory self ) internal pure returns (bool) { - return (self.data & ~VIRTUAL_ACC_ACTIVE) != 0; + return (self.data & ~VIRTUAL_ACC_ACTIVE_MASK) != 0; } /** From be0d5008364676d7cc548ab36949241d06fa7b6c Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 18:00:09 +0530 Subject: [PATCH 04/13] fix: disableLiquidationGracePeriod (8) --- .../interfaces/IPoolConfigurator.sol | 13 +++++ .../protocol/pool/PoolConfigurator.sol | 9 ++++ tests/core/Pool.Liquidations.t.sol | 51 +++++++++++++++++++ .../core/PoolConfigurator.ACLModifiers.t.sol | 16 ++++++ .../PoolConfigurator.reserveRiskConfig.t.sol | 16 ++++++ 5 files changed, 105 insertions(+) diff --git a/src/core/contracts/interfaces/IPoolConfigurator.sol b/src/core/contracts/interfaces/IPoolConfigurator.sol index beab809a..420ada68 100644 --- a/src/core/contracts/interfaces/IPoolConfigurator.sol +++ b/src/core/contracts/interfaces/IPoolConfigurator.sol @@ -144,6 +144,12 @@ interface IPoolConfigurator { */ event LiquidationGracePeriodChanged(address indexed asset, uint40 gracePeriodUntil); + /** + * @dev Emitted when the liquidation grace period is disabled. + * @param asset The address of the underlying asset of the reserve + */ + event LiquidationGracePeriodDisabled(address indexed asset); + /** * @dev Emitted when the unbacked mint cap of a reserve is updated. * @param asset The address of the underlying asset of the reserve @@ -401,6 +407,13 @@ interface IPoolConfigurator { */ function setReservePause(address asset, bool paused) external; + /** + * @notice Disables liquidation grace period for the asset. The liquidation grace period is set in the past + * so that liquidations are allowed for the asset. + * @param asset The address of the underlying asset of the reserve + */ + function disableLiquidationGracePeriod(address asset) external; + /** * @notice Updates the reserve factor of a reserve. * @param asset The address of the underlying asset of the reserve diff --git a/src/core/contracts/protocol/pool/PoolConfigurator.sol b/src/core/contracts/protocol/pool/PoolConfigurator.sol index e023dc6d..a5bc2621 100644 --- a/src/core/contracts/protocol/pool/PoolConfigurator.sol +++ b/src/core/contracts/protocol/pool/PoolConfigurator.sol @@ -280,6 +280,15 @@ abstract contract PoolConfigurator is VersionedInitializable, IPoolConfigurator setReservePause(asset, paused, 0); } + /// @inheritdoc IPoolConfigurator + function disableLiquidationGracePeriod(address asset) external override onlyEmergencyOrPoolAdmin { + // set the liquidation grace period in the past to disable liquidation grace period + uint40 until = uint40(block.timestamp) - 1; + _pool.setLiquidationGracePeriod(asset, until); + + emit LiquidationGracePeriodDisabled(asset); + } + /// @inheritdoc IPoolConfigurator function setReserveFactor( address asset, diff --git a/tests/core/Pool.Liquidations.t.sol b/tests/core/Pool.Liquidations.t.sol index 12c332da..a0c1c70d 100644 --- a/tests/core/Pool.Liquidations.t.sol +++ b/tests/core/Pool.Liquidations.t.sol @@ -930,6 +930,57 @@ contract PoolLiquidationTests is TestnetProcedures { contracts.poolProxy.liquidationCall(tokenList.usdx, tokenList.wbtc, bob, 100e6, false); } + function test_liquidation_when_grace_period_disabled( + uint40 liquidationGracePeriod + ) public { + vm.assume(liquidationGracePeriod <= contracts.poolConfiguratorProxy.MAX_GRACE_PERIOD() && liquidationGracePeriod != 0); + address[] memory assetsInGrace = new address[](1); + assetsInGrace[0] = tokenList.usdx; + + _setLiquidationGracePeriod(assetsInGrace, liquidationGracePeriod); + + vm.startPrank(alice); + contracts.poolProxy.supply(tokenList.wbtc, 1.25e8, alice, 0); + contracts.poolProxy.borrow(tokenList.usdx, 22_500e6, 2, 0, alice); + vm.stopPrank(); + + LiquidationInput memory params = _loadLiquidationInput( + alice, + tokenList.wbtc, // collateral + tokenList.usdx, // debt + 5_000e6, + tokenList.wbtc, + 25_00 + ); + + vm.startPrank(bob); + // check that liquidations are not allowed after grace period activation + vm.expectRevert(bytes(Errors.LIQUIDATION_GRACE_SENTINEL_CHECK_FAILED)); + contracts.poolProxy.liquidationCall( + params.collateralAsset, + params.debtAsset, + params.user, + params.liquidationAmountInput, + params.receiveAToken + ); + vm.stopPrank(); + + vm.startPrank(poolAdmin); + contracts.poolConfiguratorProxy.disableLiquidationGracePeriod(assetsInGrace[0]); + vm.stopPrank(); + + vm.startPrank(bob); + // check that liquidations are allowed after grace period disabled + contracts.poolProxy.liquidationCall( + params.collateralAsset, + params.debtAsset, + params.user, + params.liquidationAmountInput, + params.receiveAToken + ); + vm.stopPrank(); + } + function test_liquidation_with_liquidation_grace_period_collateral_active( uint40 liquidationGracePeriod ) public { diff --git a/tests/core/PoolConfigurator.ACLModifiers.t.sol b/tests/core/PoolConfigurator.ACLModifiers.t.sol index aad612d2..4a20bb75 100644 --- a/tests/core/PoolConfigurator.ACLModifiers.t.sol +++ b/tests/core/PoolConfigurator.ACLModifiers.t.sol @@ -328,6 +328,22 @@ contract PoolConfiguratorACLModifiersTest is TestnetProcedures { contracts.poolConfiguratorProxy.setReservePause(asset, paused); } + function test_reverts_disableLiquidationGracePeriod_on_unauth( + address caller, + address asset + ) public { + vm.assume( + !contracts.aclManager.isPoolAdmin(caller) && + !contracts.aclManager.isEmergencyAdmin(caller) && + caller != address(contracts.poolAddressesProvider) + ); + + vm.prank(caller); + + vm.expectRevert(bytes(Errors.CALLER_NOT_POOL_OR_EMERGENCY_ADMIN)); + contracts.poolConfiguratorProxy.disableLiquidationGracePeriod(asset); + } + function test_reverts_setPoolPause_unauth( address caller, bool paused, diff --git a/tests/core/PoolConfigurator.reserveRiskConfig.t.sol b/tests/core/PoolConfigurator.reserveRiskConfig.t.sol index c6f5fc1b..d589d025 100644 --- a/tests/core/PoolConfigurator.reserveRiskConfig.t.sol +++ b/tests/core/PoolConfigurator.reserveRiskConfig.t.sol @@ -766,6 +766,22 @@ contract PoolConfiguratorReserveRiskConfigs is TestnetProcedures { vm.stopPrank(); } + function test_disableLiquidationGracePeriod() public { + uint40 gracePeriod = 2 hours; + address asset = tokenList.usdx; + uint40 until = uint40(block.timestamp) + 2 hours; + + vm.startPrank(poolAdmin); + + contracts.poolConfiguratorProxy.setReservePause(asset, false, gracePeriod); + assertEq(contracts.poolProxy.getLiquidationGracePeriod(asset), until); + + contracts.poolConfiguratorProxy.disableLiquidationGracePeriod(asset); + assertEq(contracts.poolProxy.getLiquidationGracePeriod(asset), block.timestamp - 1); + + vm.stopPrank(); + } + function test_setLiquidationGracePeriodPool(uint40 gracePeriod) public { vm.assume(gracePeriod <= contracts.poolConfiguratorProxy.MAX_GRACE_PERIOD()); From 55d477987b2116585c3e68df89429f1293593ea3 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 18:28:57 +0530 Subject: [PATCH 05/13] docs: fix comment of liquidationGracePeriodUntil (10) --- src/core/contracts/interfaces/IPool.sol | 2 +- src/core/contracts/protocol/libraries/types/DataTypes.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/contracts/interfaces/IPool.sol b/src/core/contracts/interfaces/IPool.sol index 4e49aa40..c9845d2c 100644 --- a/src/core/contracts/interfaces/IPool.sol +++ b/src/core/contracts/interfaces/IPool.sol @@ -727,7 +727,7 @@ interface IPool { /** * @notice Sets the liquidation grace period of the given asset * @dev To enable a liquidation grace period, a timestamp in the future should be set, - * To disable a liquidation grace period, any timestamp in the past works, like 0 + * To disable a liquidation grace period, any timestamp in the past works, like block.timestamp - 1 * @param asset The address of the underlying asset to set the liquidationGracePeriod * @param until Timestamp when the liquidation grace period will end **/ diff --git a/src/core/contracts/protocol/libraries/types/DataTypes.sol b/src/core/contracts/protocol/libraries/types/DataTypes.sol index 22920a32..64f3e891 100644 --- a/src/core/contracts/protocol/libraries/types/DataTypes.sol +++ b/src/core/contracts/protocol/libraries/types/DataTypes.sol @@ -56,7 +56,7 @@ library DataTypes { uint40 lastUpdateTimestamp; //the id of the reserve. Represents the position in the list of the active reserves uint16 id; - //timestamp in the future, until when liquidations are not allowed on the reserve + //timestamp until when liquidations are not allowed on the reserve, if set to past liquidations will be allowed uint40 liquidationGracePeriodUntil; //aToken address address aTokenAddress; From 68c2ed0f00cbce97ee8edc9f460f7f44a8e58b32 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 19:13:29 +0530 Subject: [PATCH 06/13] fix: remove unused imports in logic libraries --- src/core/contracts/protocol/libraries/logic/EModeLogic.sol | 1 - src/core/contracts/protocol/libraries/logic/FlashLoanLogic.sol | 1 - src/core/contracts/protocol/libraries/logic/ValidationLogic.sol | 2 -- 3 files changed, 4 deletions(-) diff --git a/src/core/contracts/protocol/libraries/logic/EModeLogic.sol b/src/core/contracts/protocol/libraries/logic/EModeLogic.sol index 82b08a15..b61e440c 100644 --- a/src/core/contracts/protocol/libraries/logic/EModeLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/EModeLogic.sol @@ -5,7 +5,6 @@ import {GPv2SafeERC20} from '../../../dependencies/gnosis/contracts/GPv2SafeERC2 import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol'; import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol'; import {UserConfiguration} from '../configuration/UserConfiguration.sol'; -import {Errors} from '../helpers/Errors.sol'; import {WadRayMath} from '../math/WadRayMath.sol'; import {PercentageMath} from '../math/PercentageMath.sol'; import {DataTypes} from '../types/DataTypes.sol'; diff --git a/src/core/contracts/protocol/libraries/logic/FlashLoanLogic.sol b/src/core/contracts/protocol/libraries/logic/FlashLoanLogic.sol index 615b2fdd..f6edf532 100644 --- a/src/core/contracts/protocol/libraries/logic/FlashLoanLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/FlashLoanLogic.sol @@ -9,7 +9,6 @@ import {IPool} from '../../../interfaces/IPool.sol'; import {IFlashLoanReceiver} from '../../../flashloan/interfaces/IFlashLoanReceiver.sol'; import {IFlashLoanSimpleReceiver} from '../../../flashloan/interfaces/IFlashLoanSimpleReceiver.sol'; import {IPoolAddressesProvider} from '../../../interfaces/IPoolAddressesProvider.sol'; -import {UserConfiguration} from '../configuration/UserConfiguration.sol'; import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol'; import {Errors} from '../helpers/Errors.sol'; import {WadRayMath} from '../math/WadRayMath.sol'; diff --git a/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol b/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol index 2486db31..5976572d 100644 --- a/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -5,8 +5,6 @@ import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol'; import {Address} from '../../../dependencies/openzeppelin/contracts/Address.sol'; import {GPv2SafeERC20} from '../../../dependencies/gnosis/contracts/GPv2SafeERC20.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; -import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol'; -import {IScaledBalanceToken} from '../../../interfaces/IScaledBalanceToken.sol'; import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol'; import {IAToken} from '../../../interfaces/IAToken.sol'; import {IPriceOracleSentinel} from '../../../interfaces/IPriceOracleSentinel.sol'; From ab833723022fdfa6a39f1c1b3579ae42847090dd Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 19:16:03 +0530 Subject: [PATCH 07/13] fix: remove decimals input for asset listing (12) --- .../protocol/libraries/logic/ConfiguratorLogic.sol | 13 +++++++++---- .../libraries/types/ConfiguratorInputTypes.sol | 1 - .../contracts/protocol/pool/PoolConfigurator.sol | 3 +-- .../v3-config-engine/libraries/ListingEngine.sol | 5 ----- tests/core/PoolConfigurator.initReserves.t.sol | 10 ++++------ tests/utils/BatchTestProcedures.sol | 1 - tests/utils/TestnetProcedures.sol | 1 - 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol b/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol index 39a448b4..41d9e1c3 100644 --- a/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol @@ -8,7 +8,9 @@ import {InitializableImmutableAdminUpgradeabilityProxy} from '../aave-upgradeabi import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol'; import {DataTypes} from '../types/DataTypes.sol'; +import {Errors} from '../helpers/Errors.sol'; import {ConfiguratorInputTypes} from '../types/ConfiguratorInputTypes.sol'; +import {IERC20Detailed} from '../../../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; /** * @title ConfiguratorLogic library @@ -52,6 +54,9 @@ library ConfiguratorLogic { IPool pool, ConfiguratorInputTypes.InitReserveInput calldata input ) external { + uint8 underlyingAssetDecimals = IERC20Detailed(input.underlyingAsset).decimals(); + require(underlyingAssetDecimals > 5, Errors.INVALID_DECIMALS); + address aTokenProxyAddress = _initTokenWithProxy( input.aTokenImpl, abi.encodeWithSelector( @@ -60,7 +65,7 @@ library ConfiguratorLogic { input.treasury, input.underlyingAsset, input.incentivesController, - input.underlyingAssetDecimals, + underlyingAssetDecimals, input.aTokenName, input.aTokenSymbol, input.params @@ -74,7 +79,7 @@ library ConfiguratorLogic { pool, input.underlyingAsset, input.incentivesController, - input.underlyingAssetDecimals, + underlyingAssetDecimals, input.stableDebtTokenName, input.stableDebtTokenSymbol, input.params @@ -88,7 +93,7 @@ library ConfiguratorLogic { pool, input.underlyingAsset, input.incentivesController, - input.underlyingAssetDecimals, + underlyingAssetDecimals, input.variableDebtTokenName, input.variableDebtTokenSymbol, input.params @@ -105,7 +110,7 @@ library ConfiguratorLogic { DataTypes.ReserveConfigurationMap memory currentConfig = DataTypes.ReserveConfigurationMap(0); - currentConfig.setDecimals(input.underlyingAssetDecimals); + currentConfig.setDecimals(underlyingAssetDecimals); currentConfig.setActive(true); currentConfig.setPaused(false); diff --git a/src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol b/src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol index ad297064..7a80594e 100644 --- a/src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol +++ b/src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol @@ -6,7 +6,6 @@ library ConfiguratorInputTypes { address aTokenImpl; address stableDebtTokenImpl; address variableDebtTokenImpl; - uint8 underlyingAssetDecimals; bool useVirtualBalance; address interestRateStrategyAddress; address underlyingAsset; diff --git a/src/core/contracts/protocol/pool/PoolConfigurator.sol b/src/core/contracts/protocol/pool/PoolConfigurator.sol index a5bc2621..8ad0591d 100644 --- a/src/core/contracts/protocol/pool/PoolConfigurator.sol +++ b/src/core/contracts/protocol/pool/PoolConfigurator.sol @@ -81,9 +81,8 @@ abstract contract PoolConfigurator is VersionedInitializable, IPoolConfigurator ConfiguratorInputTypes.InitReserveInput[] calldata input ) external override onlyAssetListingOrPoolAdmins { IPool cachedPool = _pool; - for (uint256 i = 0; i < input.length; i++) { - require(IERC20Detailed(input[i].underlyingAsset).decimals() > 5, Errors.INVALID_DECIMALS); + for (uint256 i = 0; i < input.length; i++) { ConfiguratorLogic.executeInitReserve(cachedPool, input[i]); emit ReserveInterestRateDataChanged( input[i].underlyingAsset, diff --git a/src/periphery/contracts/v3-config-engine/libraries/ListingEngine.sol b/src/periphery/contracts/v3-config-engine/libraries/ListingEngine.sol index 15550697..4e1e8a7f 100644 --- a/src/periphery/contracts/v3-config-engine/libraries/ListingEngine.sol +++ b/src/periphery/contracts/v3-config-engine/libraries/ListingEngine.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC20Metadata.sol'; import {IAaveV3ConfigEngine as IEngine, IPoolConfigurator, IPool, IDefaultInterestRateStrategyV2} from '../IAaveV3ConfigEngine.sol'; import {PriceFeedEngine} from './PriceFeedEngine.sol'; import {CapsEngine} from './CapsEngine.sol'; @@ -177,14 +176,10 @@ library ListingEngine { memory initReserveInputs = new ConfiguratorInputTypes.InitReserveInput[](ids.length); for (uint256 i = 0; i < ids.length; i++) { - uint8 decimals = IERC20Metadata(ids[i]).decimals(); - require(decimals > 0, 'INVALID_ASSET_DECIMALS'); - initReserveInputs[i] = ConfiguratorInputTypes.InitReserveInput({ aTokenImpl: basics[i].implementations.aToken, stableDebtTokenImpl: basics[i].implementations.sToken, variableDebtTokenImpl: basics[i].implementations.vToken, - underlyingAssetDecimals: decimals, interestRateStrategyAddress: rateStrategy, interestRateData: abi.encode(rates[i]), underlyingAsset: ids[i], diff --git a/tests/core/PoolConfigurator.initReserves.t.sol b/tests/core/PoolConfigurator.initReserves.t.sol index a6159b64..77cb5cbc 100644 --- a/tests/core/PoolConfigurator.initReserves.t.sol +++ b/tests/core/PoolConfigurator.initReserves.t.sol @@ -51,7 +51,6 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { report.aToken, report.stableDebtToken, report.variableDebtToken, - newToken.decimals(), isVirtualAccActive, t.rateStrategy, address(newToken), @@ -167,7 +166,7 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(aTokenProxy).name(), reserveInput.aTokenName); assertEq(AToken(aTokenProxy).symbol(), reserveInput.aTokenSymbol); - assertEq(AToken(aTokenProxy).decimals(), reserveInput.underlyingAssetDecimals); + assertEq(AToken(aTokenProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); assertEq(AToken(aTokenProxy).RESERVE_TREASURY_ADDRESS(), reserveInput.treasury); assertEq(AToken(aTokenProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset); assertEq( @@ -177,7 +176,7 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(stableDebtProxy).name(), reserveInput.stableDebtTokenName); assertEq(AToken(stableDebtProxy).symbol(), reserveInput.stableDebtTokenSymbol); - assertEq(AToken(stableDebtProxy).decimals(), reserveInput.underlyingAssetDecimals); + assertEq(AToken(stableDebtProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); assertEq(AToken(stableDebtProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset); assertEq( address(AToken(stableDebtProxy).getIncentivesController()), @@ -186,7 +185,7 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(variableDebtProxy).name(), reserveInput.variableDebtTokenName); assertEq(AToken(variableDebtProxy).symbol(), reserveInput.variableDebtTokenSymbol); - assertEq(AToken(variableDebtProxy).decimals(), reserveInput.underlyingAssetDecimals); + assertEq(AToken(variableDebtProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); assertEq( AToken(variableDebtProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset @@ -205,7 +204,7 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(c.isActive, true); assertEq(c.isFrozen, false); assertEq(c.isPaused, false); - assertEq(c.decimals, reserveInput.underlyingAssetDecimals); + assertEq(c.decimals, TestnetERC20(reserveInput.underlyingAsset).decimals()); assertEq(c.ltv, 0); assertEq(c.liquidationThreshold, 0); @@ -274,7 +273,6 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { report.aToken, report.stableDebtToken, report.variableDebtToken, - newToken.decimals(), true, t.rateStrategy, address(newToken), diff --git a/tests/utils/BatchTestProcedures.sol b/tests/utils/BatchTestProcedures.sol index 00b9efa3..b91f0e96 100644 --- a/tests/utils/BatchTestProcedures.sol +++ b/tests/utils/BatchTestProcedures.sol @@ -280,7 +280,6 @@ contract BatchTestProcedures is Test, DeployUtils, FfiUtils, DefaultMarketInput r.aToken, r.stableDebtToken, r.variableDebtToken, - listingToken.decimals(), true, t.rateStrategy, address(listingToken), diff --git a/tests/utils/TestnetProcedures.sol b/tests/utils/TestnetProcedures.sol index 5d6f39c2..ab6ee5e3 100644 --- a/tests/utils/TestnetProcedures.sol +++ b/tests/utils/TestnetProcedures.sol @@ -312,7 +312,6 @@ contract TestnetProcedures is Test, DeployUtils, FfiUtils, DefaultMarketInput { r.aToken, r.stableDebtToken, r.variableDebtToken, - listingToken.decimals(), true, t.rateStrategy, address(listingToken), From 93e9c8d4424f35ae766486287febddb358efe50a Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 20:14:41 +0530 Subject: [PATCH 08/13] docs: improve virtual accounting docs (14) --- src/core/contracts/interfaces/IPoolConfigurator.sol | 2 ++ .../protocol/libraries/configuration/ReserveConfiguration.sol | 2 ++ .../protocol/pool/DefaultReserveInterestRateStrategyV2.sol | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/contracts/interfaces/IPoolConfigurator.sol b/src/core/contracts/interfaces/IPoolConfigurator.sol index 420ada68..8acdb6fd 100644 --- a/src/core/contracts/interfaces/IPoolConfigurator.sol +++ b/src/core/contracts/interfaces/IPoolConfigurator.sol @@ -295,6 +295,8 @@ interface IPoolConfigurator { /** * @notice Initializes multiple reserves. + * @dev param useVirtualBalance of the input struct should be true for all normal assets and should be false + * only in special cases (ex. GHO) where an asset is minted instead of supplied. * @param input The array of initialization parameters */ function initReserves(ConfiguratorInputTypes.InitReserveInput[] calldata input) external; diff --git a/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 2b04a0f3..0408f3ce 100644 --- a/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -562,6 +562,8 @@ library ReserveConfiguration { /** * @notice Gets the virtual account active/not state of the reserve + * @dev The state should be true for all normal assets and should be false + * only in special cases (ex. GHO) where an asset is minted instead of supplied. * @param self The reserve configuration * @return The active state */ diff --git a/src/core/contracts/protocol/pool/DefaultReserveInterestRateStrategyV2.sol b/src/core/contracts/protocol/pool/DefaultReserveInterestRateStrategyV2.sol index 5620eef0..cd7dcf64 100644 --- a/src/core/contracts/protocol/pool/DefaultReserveInterestRateStrategyV2.sol +++ b/src/core/contracts/protocol/pool/DefaultReserveInterestRateStrategyV2.sol @@ -117,7 +117,7 @@ contract DefaultReserveInterestRateStrategyV2 is IDefaultInterestRateStrategyV2 ) external view virtual override returns (uint256, uint256, uint256) { InterestRateDataRay memory rateData = _rayifyRateData(_interestRateData[params.reserve]); - // @note This is a short circuit to allow mintable assets, which by definition cannot be supplied + // @note This is a short circuit to allow mintable assets (ex. GHO), which by definition cannot be supplied // and thus do not use virtual underlying balances. if (!params.usingVirtualBalance) { return (0, 0, rateData.baseVariableBorrowRate); From dc969f867ed49e612fc72758ace5d04d3918f6ff Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Wed, 22 May 2024 20:20:17 +0530 Subject: [PATCH 09/13] chore: fix lint --- tests/core/Pool.Liquidations.t.sol | 9 +++++---- tests/core/PoolConfigurator.initReserves.t.sol | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/core/Pool.Liquidations.t.sol b/tests/core/Pool.Liquidations.t.sol index a0c1c70d..65391f74 100644 --- a/tests/core/Pool.Liquidations.t.sol +++ b/tests/core/Pool.Liquidations.t.sol @@ -930,10 +930,11 @@ contract PoolLiquidationTests is TestnetProcedures { contracts.poolProxy.liquidationCall(tokenList.usdx, tokenList.wbtc, bob, 100e6, false); } - function test_liquidation_when_grace_period_disabled( - uint40 liquidationGracePeriod - ) public { - vm.assume(liquidationGracePeriod <= contracts.poolConfiguratorProxy.MAX_GRACE_PERIOD() && liquidationGracePeriod != 0); + function test_liquidation_when_grace_period_disabled(uint40 liquidationGracePeriod) public { + vm.assume( + liquidationGracePeriod <= contracts.poolConfiguratorProxy.MAX_GRACE_PERIOD() && + liquidationGracePeriod != 0 + ); address[] memory assetsInGrace = new address[](1); assetsInGrace[0] = tokenList.usdx; diff --git a/tests/core/PoolConfigurator.initReserves.t.sol b/tests/core/PoolConfigurator.initReserves.t.sol index 77cb5cbc..6b859094 100644 --- a/tests/core/PoolConfigurator.initReserves.t.sol +++ b/tests/core/PoolConfigurator.initReserves.t.sol @@ -166,7 +166,10 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(aTokenProxy).name(), reserveInput.aTokenName); assertEq(AToken(aTokenProxy).symbol(), reserveInput.aTokenSymbol); - assertEq(AToken(aTokenProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); + assertEq( + AToken(aTokenProxy).decimals(), + TestnetERC20(reserveInput.underlyingAsset).decimals() + ); assertEq(AToken(aTokenProxy).RESERVE_TREASURY_ADDRESS(), reserveInput.treasury); assertEq(AToken(aTokenProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset); assertEq( @@ -176,7 +179,10 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(stableDebtProxy).name(), reserveInput.stableDebtTokenName); assertEq(AToken(stableDebtProxy).symbol(), reserveInput.stableDebtTokenSymbol); - assertEq(AToken(stableDebtProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); + assertEq( + AToken(stableDebtProxy).decimals(), + TestnetERC20(reserveInput.underlyingAsset).decimals() + ); assertEq(AToken(stableDebtProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset); assertEq( address(AToken(stableDebtProxy).getIncentivesController()), @@ -185,7 +191,10 @@ contract PoolConfiguratorInitReservesTest is TestnetProcedures { assertEq(AToken(variableDebtProxy).name(), reserveInput.variableDebtTokenName); assertEq(AToken(variableDebtProxy).symbol(), reserveInput.variableDebtTokenSymbol); - assertEq(AToken(variableDebtProxy).decimals(), TestnetERC20(reserveInput.underlyingAsset).decimals()); + assertEq( + AToken(variableDebtProxy).decimals(), + TestnetERC20(reserveInput.underlyingAsset).decimals() + ); assertEq( AToken(variableDebtProxy).UNDERLYING_ASSET_ADDRESS(), reserveInput.underlyingAsset From dcf70f5d057dc0d76a8306131ac2d620afd11b73 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Thu, 23 May 2024 15:51:56 +0530 Subject: [PATCH 10/13] Update src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol Co-authored-by: Ernesto Boado --- .../contracts/protocol/libraries/logic/ConfiguratorLogic.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol b/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol index 41d9e1c3..01580d9e 100644 --- a/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/ConfiguratorLogic.sol @@ -54,6 +54,7 @@ library ConfiguratorLogic { IPool pool, ConfiguratorInputTypes.InitReserveInput calldata input ) external { + // It is an assumption that the asset listed is non-malicious, and the external call doesn't create re-entrancies uint8 underlyingAssetDecimals = IERC20Detailed(input.underlyingAsset).decimals(); require(underlyingAssetDecimals > 5, Errors.INVALID_DECIMALS); From fc68ee7b5b20591551693c29f20f65dd59b44c2d Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Thu, 23 May 2024 15:52:10 +0530 Subject: [PATCH 11/13] Update docs/Aave-v3.1-features.md Co-authored-by: Ernesto Boado --- docs/Aave-v3.1-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Aave-v3.1-features.md b/docs/Aave-v3.1-features.md index 27dfe34d..bbb7bb98 100644 --- a/docs/Aave-v3.1-features.md +++ b/docs/Aave-v3.1-features.md @@ -72,7 +72,7 @@ Given its implications and criticality, virtual accounting can be considered the - [ConfigurationInputTypes](../src/core/contracts/protocol/libraries/types/ConfiguratorInputTypes.sol) - Added flag `useVirtualBalance` for a new listing to use or not virtual balance. - [ReserveConfiguration](../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol) - - Added logic to store and set/get the new `VIRTUAL_ACC_ACTIVE_MASK` flag. + - Added logic to set/get the new configuration flag for if a reserve has virtual account active. - [Errors](../src/core/contracts/protocol/libraries/helpers/Errors.sol) - In relation with this feature, added the `WITHDRAW_TO_ATOKEN` and `SUPPLY_TO_ATOKEN` errors. - [Pool](../src/core/contracts/protocol/pool/Pool.sol) From 4a2d4cc767fd72c3b90f7c0c811102ecfe5ec328 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Thu, 23 May 2024 16:14:10 +0530 Subject: [PATCH 12/13] fix: timestamp of disableLiquidationGracePeriod --- src/core/contracts/interfaces/IPool.sol | 2 +- src/core/contracts/protocol/pool/PoolConfigurator.sol | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/contracts/interfaces/IPool.sol b/src/core/contracts/interfaces/IPool.sol index c9845d2c..4e49aa40 100644 --- a/src/core/contracts/interfaces/IPool.sol +++ b/src/core/contracts/interfaces/IPool.sol @@ -727,7 +727,7 @@ interface IPool { /** * @notice Sets the liquidation grace period of the given asset * @dev To enable a liquidation grace period, a timestamp in the future should be set, - * To disable a liquidation grace period, any timestamp in the past works, like block.timestamp - 1 + * To disable a liquidation grace period, any timestamp in the past works, like 0 * @param asset The address of the underlying asset to set the liquidationGracePeriod * @param until Timestamp when the liquidation grace period will end **/ diff --git a/src/core/contracts/protocol/pool/PoolConfigurator.sol b/src/core/contracts/protocol/pool/PoolConfigurator.sol index 8ad0591d..4606746a 100644 --- a/src/core/contracts/protocol/pool/PoolConfigurator.sol +++ b/src/core/contracts/protocol/pool/PoolConfigurator.sol @@ -282,8 +282,7 @@ abstract contract PoolConfigurator is VersionedInitializable, IPoolConfigurator /// @inheritdoc IPoolConfigurator function disableLiquidationGracePeriod(address asset) external override onlyEmergencyOrPoolAdmin { // set the liquidation grace period in the past to disable liquidation grace period - uint40 until = uint40(block.timestamp) - 1; - _pool.setLiquidationGracePeriod(asset, until); + _pool.setLiquidationGracePeriod(asset, 0); emit LiquidationGracePeriodDisabled(asset); } From 1ff026271a8ffa0defbe870df67dfa6e7ab5ffa8 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Thu, 23 May 2024 20:11:42 +0530 Subject: [PATCH 13/13] Update BorrowLogic.sol Co-authored-by: Andrey --- src/core/contracts/protocol/libraries/logic/BorrowLogic.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol b/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol index 5364da4f..cdcf0101 100644 --- a/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol +++ b/src/core/contracts/protocol/libraries/logic/BorrowLogic.sol @@ -308,8 +308,8 @@ library BorrowLogic { * @param reserve The of the reserve of the asset being repaid * @param userConfig The user configuration mapping that tracks the supplied/borrowed assets * @param asset The asset of the position being swapped - * @param interestRateMode The current interest rate mode of the position being swapped * @param user The user whose debt position is being swapped + * @param interestRateMode The current interest rate mode of the position being swapped */ function executeSwapBorrowRateMode( DataTypes.ReserveData storage reserve,