mirror of
				https://github.com/Instadapp/aave-protocol-v2.git
				synced 2024-07-29 21:47:30 +00:00 
			
		
		
		
	fix: Revert reserves cap change due breaking change at ILendingPool interface with current deployed markets
This commit is contained in:
		
							parent
							
								
									d998c2f4c7
								
							
						
					
					
						commit
						138446bb51
					
				| 
						 | 
				
			
			@ -87,7 +87,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
 | 
			
		|||
    _addressesProvider = provider;
 | 
			
		||||
    _maxStableRateBorrowSizePercent = 2500;
 | 
			
		||||
    _flashLoanPremiumTotal = 9;
 | 
			
		||||
    _maxNumberOfReserves = UserConfiguration._maxReserves;
 | 
			
		||||
    _maxNumberOfReserves = 128;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -713,7 +713,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @dev Returns the fee on flash loans
 | 
			
		||||
   * @dev Returns the fee on flash loans 
 | 
			
		||||
   */
 | 
			
		||||
  function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) {
 | 
			
		||||
    return _flashLoanPremiumTotal;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,9 +13,6 @@ library UserConfiguration {
 | 
			
		|||
  uint256 internal constant BORROWING_MASK =
 | 
			
		||||
    0x5555555555555555555555555555555555555555555555555555555555555555;
 | 
			
		||||
 | 
			
		||||
  uint256 internal constant _maxReserves = 256;
 | 
			
		||||
  uint256 internal constant _indexCount = _maxReserves / 128 + ((_maxReserves % 128 > 0) ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @dev Sets if the user is borrowing the reserve identified by reserveIndex
 | 
			
		||||
   * @param self The configuration object
 | 
			
		||||
| 
						 | 
				
			
			@ -27,11 +24,9 @@ library UserConfiguration {
 | 
			
		|||
    uint256 reserveIndex,
 | 
			
		||||
    bool borrowing
 | 
			
		||||
  ) internal {
 | 
			
		||||
    require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    uint256 index = reserveIndex / 128;
 | 
			
		||||
    reserveIndex = reserveIndex % 128;
 | 
			
		||||
    self.data[index] =
 | 
			
		||||
      (self.data[index] & ~(1 << (reserveIndex * 2))) |
 | 
			
		||||
    require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    self.data =
 | 
			
		||||
      (self.data & ~(1 << (reserveIndex * 2))) |
 | 
			
		||||
      (uint256(borrowing ? 1 : 0) << (reserveIndex * 2));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,11 +41,9 @@ library UserConfiguration {
 | 
			
		|||
    uint256 reserveIndex,
 | 
			
		||||
    bool usingAsCollateral
 | 
			
		||||
  ) internal {
 | 
			
		||||
    require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    uint256 index = reserveIndex / 128;
 | 
			
		||||
    reserveIndex = reserveIndex % 128;
 | 
			
		||||
    self.data[index] =
 | 
			
		||||
      (self.data[index] & ~(1 << (reserveIndex * 2 + 1))) |
 | 
			
		||||
    require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    self.data =
 | 
			
		||||
      (self.data & ~(1 << (reserveIndex * 2 + 1))) |
 | 
			
		||||
      (uint256(usingAsCollateral ? 1 : 0) << (reserveIndex * 2 + 1));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,10 +57,8 @@ library UserConfiguration {
 | 
			
		|||
    DataTypes.UserConfigurationMap memory self,
 | 
			
		||||
    uint256 reserveIndex
 | 
			
		||||
  ) internal pure returns (bool) {
 | 
			
		||||
    require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    uint256 index = reserveIndex / 128;
 | 
			
		||||
    reserveIndex = reserveIndex % 128;
 | 
			
		||||
    return (self.data[index] >> (reserveIndex * 2)) & 3 != 0;
 | 
			
		||||
    require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    return (self.data >> (reserveIndex * 2)) & 3 != 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -81,10 +72,8 @@ library UserConfiguration {
 | 
			
		|||
    pure
 | 
			
		||||
    returns (bool)
 | 
			
		||||
  {
 | 
			
		||||
    require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    uint256 index = reserveIndex / 128;
 | 
			
		||||
    reserveIndex = reserveIndex % 128;
 | 
			
		||||
    return (self.data[index] >> (reserveIndex * 2)) & 1 != 0;
 | 
			
		||||
    require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    return (self.data >> (reserveIndex * 2)) & 1 != 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -98,10 +87,8 @@ library UserConfiguration {
 | 
			
		|||
    pure
 | 
			
		||||
    returns (bool)
 | 
			
		||||
  {
 | 
			
		||||
    require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    uint256 index = reserveIndex / 128;
 | 
			
		||||
    reserveIndex = reserveIndex % 128;
 | 
			
		||||
    return (self.data[index] >> (reserveIndex * 2 + 1)) & 1 != 0;
 | 
			
		||||
    require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
 | 
			
		||||
    return (self.data >> (reserveIndex * 2 + 1)) & 1 != 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -110,12 +97,7 @@ library UserConfiguration {
 | 
			
		|||
   * @return True if the user has been borrowing any reserve, false otherwise
 | 
			
		||||
   **/
 | 
			
		||||
  function isBorrowingAny(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) {
 | 
			
		||||
    for (uint8 i = 0; i < _indexCount; i++) {
 | 
			
		||||
      if (self.data[i] & BORROWING_MASK != 0) {
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
    return self.data & BORROWING_MASK != 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -124,11 +106,6 @@ library UserConfiguration {
 | 
			
		|||
   * @return True if the user has been borrowing any reserve, false otherwise
 | 
			
		||||
   **/
 | 
			
		||||
  function isEmpty(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) {
 | 
			
		||||
    for (uint8 i = 0; i < _indexCount; i++) {
 | 
			
		||||
      if (self.data[i] != 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
    return self.data == 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ library DataTypes {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  struct UserConfigurationMap {
 | 
			
		||||
    uint256[2] data; // size is _maxReserves / 128 + ((_maxReserves % 128 > 0) ? 1 : 0), but need to be literal
 | 
			
		||||
    uint256 data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  enum InterestRateMode {NONE, STABLE, VARIABLE}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,164 +0,0 @@
 | 
			
		|||
import { TestEnv, makeSuite } from './helpers/make-suite';
 | 
			
		||||
import {
 | 
			
		||||
  APPROVAL_AMOUNT_LENDING_POOL,
 | 
			
		||||
  MAX_UINT_AMOUNT,
 | 
			
		||||
  RAY,
 | 
			
		||||
  ZERO_ADDRESS,
 | 
			
		||||
} from '../../helpers/constants';
 | 
			
		||||
import {
 | 
			
		||||
  convertToCurrencyDecimals,
 | 
			
		||||
  getContractAddressWithJsonFallback,
 | 
			
		||||
} from '../../helpers/contracts-helpers';
 | 
			
		||||
import { eContractid, ProtocolErrors, RateMode } from '../../helpers/types';
 | 
			
		||||
import { strategyWETH } from '../../markets/aave/reservesConfigs';
 | 
			
		||||
import {
 | 
			
		||||
  deployATokenImplementations,
 | 
			
		||||
  deployMintableERC20,
 | 
			
		||||
  deployValidationLogic,
 | 
			
		||||
} from '../../helpers/contracts-deployments';
 | 
			
		||||
import { getATokenExtraParams } from '../../helpers/init-helpers';
 | 
			
		||||
import { ConfigNames } from '../../helpers/configuration';
 | 
			
		||||
import { zeroAddress } from 'hardhat/node_modules/ethereumjs-util';
 | 
			
		||||
import AaveConfig from '../../markets/aave';
 | 
			
		||||
import { getATokensAndRatesHelper } from '../../helpers/contracts-getters';
 | 
			
		||||
import { config } from 'process';
 | 
			
		||||
import { parseEther } from '@ethersproject/units';
 | 
			
		||||
import exp from 'constants';
 | 
			
		||||
 | 
			
		||||
const { expect } = require('chai');
 | 
			
		||||
 | 
			
		||||
makeSuite('Adding > 128 asset to many-asset configured pool', (testEnv: TestEnv) => {
 | 
			
		||||
  const tokens = {};
 | 
			
		||||
 | 
			
		||||
  before('setup', async () => {
 | 
			
		||||
    const { pool, dai, configurator, deployer, oracle } = testEnv;
 | 
			
		||||
    const atokenAndRatesDeployer = await getATokensAndRatesHelper();
 | 
			
		||||
 | 
			
		||||
    const reservesCount = await pool.getReservesList();
 | 
			
		||||
 | 
			
		||||
    const daiData = await pool.getReserveData(dai.address);
 | 
			
		||||
    const poolName = ConfigNames.Aave;
 | 
			
		||||
 | 
			
		||||
    const {
 | 
			
		||||
      ATokenNamePrefix,
 | 
			
		||||
      StableDebtTokenNamePrefix,
 | 
			
		||||
      VariableDebtTokenNamePrefix,
 | 
			
		||||
      SymbolPrefix,
 | 
			
		||||
    } = AaveConfig;
 | 
			
		||||
 | 
			
		||||
    // Create tokens
 | 
			
		||||
    let tokenInitParams = [];
 | 
			
		||||
    let reserveInitParams = [];
 | 
			
		||||
 | 
			
		||||
    const aTokenImplAddress = await getContractAddressWithJsonFallback(
 | 
			
		||||
      eContractid.AToken,
 | 
			
		||||
      poolName
 | 
			
		||||
    );
 | 
			
		||||
    const stableDebtImplAddress = await getContractAddressWithJsonFallback(
 | 
			
		||||
      eContractid.StableDebtToken,
 | 
			
		||||
      poolName
 | 
			
		||||
    );
 | 
			
		||||
    const variableDebtImplAddress = await getContractAddressWithJsonFallback(
 | 
			
		||||
      eContractid.VariableDebtToken,
 | 
			
		||||
      poolName
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const daiPrice = await oracle.getAssetPrice(dai.address);
 | 
			
		||||
 | 
			
		||||
    // All assets will be initialized with the same price as Dai.
 | 
			
		||||
    for (let i = reservesCount.length; i < 140; i++) {
 | 
			
		||||
      const tokenName = `RealT-${i}`;
 | 
			
		||||
      const token = await deployMintableERC20([tokenName, tokenName, '18']);
 | 
			
		||||
      tokens[tokenName] = token;
 | 
			
		||||
 | 
			
		||||
      tokenInitParams.push({
 | 
			
		||||
        aTokenImpl: aTokenImplAddress,
 | 
			
		||||
        stableDebtTokenImpl: stableDebtImplAddress,
 | 
			
		||||
        variableDebtTokenImpl: variableDebtImplAddress,
 | 
			
		||||
        underlyingAssetDecimals: 18,
 | 
			
		||||
        interestRateStrategyAddress: daiData.interestRateStrategyAddress,
 | 
			
		||||
        underlyingAsset: token.address,
 | 
			
		||||
        treasury: ZERO_ADDRESS,
 | 
			
		||||
        incentivesController: ZERO_ADDRESS,
 | 
			
		||||
        underlyingAssetName: tokenName,
 | 
			
		||||
        aTokenName: `${ATokenNamePrefix} ${tokenName}`,
 | 
			
		||||
        aTokenSymbol: `a${SymbolPrefix}${tokenName}`,
 | 
			
		||||
        variableDebtTokenName: `${VariableDebtTokenNamePrefix} ${SymbolPrefix}${tokenName}`,
 | 
			
		||||
        variableDebtTokenSymbol: `variableDebt${SymbolPrefix}${tokenName}`,
 | 
			
		||||
        stableDebtTokenName: `${StableDebtTokenNamePrefix} ${tokenName}`,
 | 
			
		||||
        stableDebtTokenSymbol: `stableDebt${SymbolPrefix}${tokenName}`,
 | 
			
		||||
        params: '0x10',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      reserveInitParams.push({
 | 
			
		||||
        asset: token.address,
 | 
			
		||||
        baseLTV: 5000,
 | 
			
		||||
        liquidationThreshold: 8000,
 | 
			
		||||
        liquidationBonus: 10500,
 | 
			
		||||
        reserveFactor: 1000,
 | 
			
		||||
        stableBorrowingEnabled: false,
 | 
			
		||||
        borrowingEnabled: true,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (tokenInitParams.length == 2 || i == 139) {
 | 
			
		||||
        await configurator.batchInitReserve(tokenInitParams);
 | 
			
		||||
 | 
			
		||||
        for (let j = 0; j < reserveInitParams.length; j++) {
 | 
			
		||||
          let params = reserveInitParams[j];
 | 
			
		||||
          await configurator
 | 
			
		||||
            .connect(deployer.signer)
 | 
			
		||||
            .configureReserveAsCollateral(
 | 
			
		||||
              params.asset,
 | 
			
		||||
              params.baseLTV,
 | 
			
		||||
              params.liquidationThreshold,
 | 
			
		||||
              params.liquidationBonus
 | 
			
		||||
            );
 | 
			
		||||
          await configurator.enableBorrowingOnReserve(params.asset, false);
 | 
			
		||||
          await oracle.setAssetPrice(params.asset, daiPrice);
 | 
			
		||||
        }
 | 
			
		||||
        tokenInitParams = [];
 | 
			
		||||
        reserveInitParams = [];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('Check that pool contains >128 assets', async () => {
 | 
			
		||||
    const { pool } = testEnv;
 | 
			
		||||
    const reservesCount = await pool.getReservesList();
 | 
			
		||||
    expect(reservesCount.length).to.be.gt(128);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('Add collateral and borrow asset 130', async () => {
 | 
			
		||||
    const {
 | 
			
		||||
      users: [, user, funder],
 | 
			
		||||
      weth,
 | 
			
		||||
      pool,
 | 
			
		||||
    } = testEnv;
 | 
			
		||||
 | 
			
		||||
    const realT130 = tokens[`RealT-${130}`];
 | 
			
		||||
 | 
			
		||||
    const assetdata = await pool.getReserveData(realT130.address);
 | 
			
		||||
    expect(assetdata.id).to.be.gt(128);
 | 
			
		||||
 | 
			
		||||
    await realT130.connect(funder.signer).mint(parseEther('100'));
 | 
			
		||||
    await realT130.connect(funder.signer).approve(pool.address, MAX_UINT_AMOUNT);
 | 
			
		||||
    await pool
 | 
			
		||||
      .connect(funder.signer)
 | 
			
		||||
      .deposit(realT130.address, parseEther('100'), funder.address, 0);
 | 
			
		||||
 | 
			
		||||
    await weth.connect(user.signer).mint(parseEther('1'));
 | 
			
		||||
    await weth.connect(user.signer).approve(pool.address, MAX_UINT_AMOUNT);
 | 
			
		||||
    await pool.connect(user.signer).deposit(weth.address, parseEther('1'), user.address, 0);
 | 
			
		||||
 | 
			
		||||
    const userDataBefore = await pool.getUserAccountData(user.address);
 | 
			
		||||
    await pool
 | 
			
		||||
      .connect(user.signer)
 | 
			
		||||
      .borrow(realT130.address, parseEther('1'), RateMode.Variable, 0, user.address);
 | 
			
		||||
    const userDataAfter = await pool.getUserAccountData(user.address);
 | 
			
		||||
 | 
			
		||||
    expect(userDataAfter.totalCollateralETH).to.be.eq(userDataBefore.totalCollateralETH);
 | 
			
		||||
    expect(userDataBefore.totalDebtETH).to.be.eq(0);
 | 
			
		||||
    expect(userDataAfter.totalDebtETH).to.be.gt(userDataBefore.totalDebtETH);
 | 
			
		||||
    expect(userDataAfter.healthFactor).to.be.lt(userDataBefore.healthFactor);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user