feat: added drop reserve main capability

This commit is contained in:
Hadrien Charlanes 2021-05-26 20:11:48 +02:00
parent 8926371a37
commit e2edf016eb
6 changed files with 80 additions and 21 deletions

View File

@ -168,14 +168,11 @@ interface ILendingPool {
); );
/** /**
* @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
* @param reserve the address of the reserve * @param reserve the address of the reserve
* @param amountMinted the amount minted to the treasury * @param amountMinted the amount minted to the treasury
**/ **/
event MintedToTreasury( event MintedToTreasury(address indexed reserve, uint256 amountMinted);
address indexed reserve,
uint256 amountMinted
);
/** /**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
@ -406,6 +403,8 @@ interface ILendingPool {
address interestRateStrategyAddress address interestRateStrategyAddress
) external; ) external;
function dropReserve(address reserve) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external; external;

View File

@ -545,11 +545,11 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
function mintToTreasury(address[] calldata reserves) public { function mintToTreasury(address[] calldata reserves) public {
for (uint256 i = 0; i < reserves.length; i++) { for (uint256 i = 0; i < reserves.length; i++) {
address reserveAddress = reserves[i]; address reserveAddress = reserves[i];
DataTypes.ReserveData storage reserve = _reserves[reserveAddress]; DataTypes.ReserveData storage reserve = _reserves[reserveAddress];
// this cover both inactive reserves and invalid reserves since the flag will be 0 for both // this cover both inactive reserves and invalid reserves since the flag will be 0 for both
if(!reserve.configuration.getActive()){ if (!reserve.configuration.getActive()) {
continue; continue;
} }
@ -690,15 +690,29 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
} }
/** /**
* @dev Returns the list of the initialized reserves * @dev Returns the list of the initialized reserves, does not contain dropped reserves
**/ **/
function getReservesList() external view override returns (address[] memory) { function getReservesList() external view override returns (address[] memory) {
address[] memory _activeReserves = new address[](_reservesCount); uint256 reserveListCount = _reservesCount;
uint256 droppedReservesCount = 0;
address[] memory reserves = new address[](reserveListCount);
for (uint256 i = 0; i < _reservesCount; i++) { for (uint256 i = 0; i < reserveListCount; i++) {
_activeReserves[i] = _reservesList[i]; if (_reservesList[i] != address(0)) {
reserves[i - droppedReservesCount] = _reservesList[i];
} else {
droppedReservesCount++;
}
} }
return _activeReserves;
if (droppedReservesCount == 0) return reserves;
address[] memory undroppedReserves = new address[](reserveListCount - droppedReservesCount);
for (uint256 i = 0; i < reserveListCount - droppedReservesCount; i++) {
undroppedReserves[i] = reserves[i];
}
return undroppedReserves;
} }
/** /**
@ -808,6 +822,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
_addReserveToList(asset); _addReserveToList(asset);
} }
/**
* @dev Drop a reserve
* - Only callable by the LendingPoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
**/
function dropReserve(address asset) external override onlyLendingPoolConfigurator {
_reserves[asset].dropReserve();
_removeReserveFromList(asset);
}
/** /**
* @dev Updates the address of the interest rate strategy contract * @dev Updates the address of the interest rate strategy contract
* - Only callable by the LendingPoolConfigurator contract * - Only callable by the LendingPoolConfigurator contract
@ -1084,7 +1108,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
return paybackAmount; return paybackAmount;
} }
function _addReserveToList(address asset) internal { function _addReserveToList(address asset) internal returns (uint8) {
uint256 reservesCount = _reservesCount; uint256 reservesCount = _reservesCount;
require(reservesCount < _maxNumberOfReserves, Errors.LP_NO_MORE_RESERVES_ALLOWED); require(reservesCount < _maxNumberOfReserves, Errors.LP_NO_MORE_RESERVES_ALLOWED);
@ -1092,10 +1116,18 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset; bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset;
if (!reserveAlreadyAdded) { if (!reserveAlreadyAdded) {
_reserves[asset].id = uint8(reservesCount); for (uint8 i = 0; i <= reservesCount; i++) {
_reservesList[reservesCount] = asset; if (_reservesList[i] == address(0)) {
_reserves[asset].id = i;
_reservesCount = reservesCount + 1; _reservesList[i] = asset;
_reservesCount = reservesCount + 1;
return i;
}
}
} }
} }
function _removeReserveFromList(address asset) internal {
_reservesList[_reserves[asset].id] = address(0);
}
} }

View File

@ -159,6 +159,11 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
); );
} }
/// @inheritdoc ILendingPoolConfigurator
function dropReserve(address asset) external onlyPoolAdmin {
_pool.dropReserve(asset);
}
/// @inheritdoc ILendingPoolConfigurator /// @inheritdoc ILendingPoolConfigurator
function updateAToken(UpdateATokenInput calldata input) external override onlyPoolAdmin { function updateAToken(UpdateATokenInput calldata input) external override onlyPoolAdmin {
ILendingPool cachedPool = _pool; ILendingPool cachedPool = _pool;

View File

@ -109,6 +109,9 @@ library Errors {
string public constant LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN = '85'; string public constant LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN = '85';
string public constant VL_RESERVE_PAUSED = '86'; string public constant VL_RESERVE_PAUSED = '86';
string public constant LPC_CALLER_NOT_RISK_OR_POOL_ADMIN = '87'; string public constant LPC_CALLER_NOT_RISK_OR_POOL_ADMIN = '87';
string public constant RL_ATOKEN_SUPPLY_NOT_NULL = '88';
string public constant RL_STABLE_DEBT_NOT_NULL = '89';
string public constant RL_VARIABLE_DEBT_SUPPLY_NOT_NULL = '90';
enum CollateralManagerErrors { enum CollateralManagerErrors {
NO_ERROR, NO_ERROR,

View File

@ -178,6 +178,23 @@ library ReserveLogic {
reserve.interestRateStrategyAddress = interestRateStrategyAddress; reserve.interestRateStrategyAddress = interestRateStrategyAddress;
} }
/**
* @dev drop a reserve
* @param reserve The reserve object
**/
function dropReserve(DataTypes.ReserveData storage reserve) external {
require(IERC20(reserve.aTokenAddress).totalSupply() == 0, Errors.RL_ATOKEN_SUPPLY_NOT_NULL);
require(
IERC20(reserve.stableDebtTokenAddress).totalSupply() == 0,
Errors.RL_STABLE_DEBT_NOT_NULL
);
require(
IERC20(reserve.variableDebtTokenAddress).totalSupply() == 0,
Errors.RL_VARIABLE_DEBT_SUPPLY_NOT_NULL
);
reserve.id = type(uint8).max;
}
struct UpdateInterestRatesLocalVars { struct UpdateInterestRatesLocalVars {
address stableDebtTokenAddress; address stableDebtTokenAddress;
uint256 availableLiquidity; uint256 availableLiquidity;
@ -320,7 +337,9 @@ library ReserveLogic {
vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor); vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor);
if (vars.amountToMint != 0) { if (vars.amountToMint != 0) {
reserve.accruedToTreasury = reserve.accruedToTreasury.add(vars.amountToMint.rayDiv(newLiquidityIndex)); reserve.accruedToTreasury = reserve.accruedToTreasury.add(
vars.amountToMint.rayDiv(newLiquidityIndex)
);
} }
} }

View File

@ -265,6 +265,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
); );
await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin); await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin);
lendingPoolConfiguratorProxy.dropReserve(mockTokens.KNC.address);
const collateralManager = await deployLendingPoolCollateralManager(); const collateralManager = await deployLendingPoolCollateralManager();
await waitForTx( await waitForTx(