From 4a1e1156f48447526e38d194d8a217a8cdb626ca Mon Sep 17 00:00:00 2001
From: The3D <frangellaemilio@gmail.com>
Date: Thu, 10 Sep 2020 12:51:52 +0200
Subject: [PATCH] Merge local branch

---
 contracts/interfaces/ILendingPool.sol         |  1 -
 .../IReserveInterestRateStrategy.sol          |  3 +-
 .../DefaultReserveInterestRateStrategy.sol    | 48 ++++++++++++-------
 contracts/lendingpool/LendingPool.sol         | 44 +++++++++++++++--
 .../LendingPoolLiquidationManager.sol         | 38 +++++++++++++--
 .../configuration/ReserveConfiguration.sol    | 19 ++++++++
 contracts/libraries/logic/ReserveLogic.sol    |  3 +-
 contracts/mocks/upgradeability/MockAToken.sol |  2 +-
 contracts/tokenization/AToken.sol             |  8 ++++
 contracts/tokenization/VariableDebtToken.sol  | 12 ++++-
 contracts/tokenization/base/DebtTokenBase.sol |  2 +-
 contracts/tokenization/interfaces/IAToken.sol |  8 ++++
 .../interfaces/IVariableDebtToken.sol         |  5 --
 13 files changed, 158 insertions(+), 35 deletions(-)

diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol
index a7a5e1ca..12119a3a 100644
--- a/contracts/interfaces/ILendingPool.sol
+++ b/contracts/interfaces/ILendingPool.sol
@@ -305,7 +305,6 @@ interface ILendingPool {
       uint256 principalVariableDebt,
       uint256 stableBorrowRate,
       uint256 liquidityRate,
-      uint256 variableBorrowIndex,
       uint40 stableRateLastUpdated,
       bool usageAsCollateralEnabled
     );
diff --git a/contracts/interfaces/IReserveInterestRateStrategy.sol b/contracts/interfaces/IReserveInterestRateStrategy.sol
index 48311e70..acc097bf 100644
--- a/contracts/interfaces/IReserveInterestRateStrategy.sol
+++ b/contracts/interfaces/IReserveInterestRateStrategy.sol
@@ -23,7 +23,8 @@ interface IReserveInterestRateStrategy {
     uint256 utilizationRate,
     uint256 totalBorrowsStable,
     uint256 totalBorrowsVariable,
-    uint256 averageStableBorrowRate
+    uint256 averageStableBorrowRate,
+    uint256 reserveFactor
   )
     external
     view
diff --git a/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol
index c2303254..c93e6c38 100644
--- a/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol
+++ b/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol
@@ -49,6 +49,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
   //slope of the stable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
   uint256 internal immutable _stableRateSlope2;
 
+ 
   constructor(
     LendingPoolAddressesProvider provider,
     uint256 baseVariableBorrowRate,
@@ -89,6 +90,15 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
     return _baseVariableBorrowRate;
   }
 
+  struct CalcInterestRatesLocalVars {
+
+    uint256 totalBorrows;
+    uint256 currentVariableBorrowRate;
+    uint256 currentStableBorrowRate;
+    uint256 currentLiquidityRate;
+    uint256 utilizationRate;
+  }
+
   /**
    * @dev calculates the interest rates depending on the available liquidity and the total borrowed.
    * @param reserve the address of the reserve
@@ -96,6 +106,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
    * @param totalBorrowsStable the total borrowed from the reserve a stable rate
    * @param totalBorrowsVariable the total borrowed from the reserve at a variable rate
    * @param averageStableBorrowRate the weighted average of all the stable rate borrows
+   * @param reserveFactor the reserve portion of the interest to redirect to the reserve treasury
    * @return currentLiquidityRate the liquidity rate
    * @return currentStableBorrowRate stable borrow rate
    * @return currentVariableBorrowRate variable borrow rate
@@ -105,7 +116,8 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
     uint256 availableLiquidity,
     uint256 totalBorrowsStable,
     uint256 totalBorrowsVariable,
-    uint256 averageStableBorrowRate
+    uint256 averageStableBorrowRate,
+    uint256 reserveFactor
   )
     external
     override
@@ -116,16 +128,19 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
       uint256
     )
   {
-    uint256 totalBorrows = totalBorrowsStable.add(totalBorrowsVariable);
-    uint256 currentVariableBorrowRate = 0;
-    uint256 currentStableBorrowRate = 0;
-    uint256 currentLiquidityRate = 0;
 
-    uint256 utilizationRate = totalBorrows == 0
+    CalcInterestRatesLocalVars memory vars;
+
+    vars.totalBorrows = totalBorrowsStable.add(totalBorrowsVariable);
+    vars.currentVariableBorrowRate = 0;
+    vars.currentStableBorrowRate = 0;
+    vars.currentLiquidityRate = 0;
+
+    uint256 utilizationRate = vars.totalBorrows == 0
       ? 0
-      : totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
+      : vars.totalBorrows.rayDiv(availableLiquidity.add(vars.totalBorrows));
 
-    currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
+    vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
       .getMarketBorrowRate(reserve);
 
     if (utilizationRate > OPTIMAL_UTILIZATION_RATE) {
@@ -133,31 +148,32 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
         EXCESS_UTILIZATION_RATE
       );
 
-      currentStableBorrowRate = currentStableBorrowRate.add(_stableRateSlope1).add(
+      vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(_stableRateSlope1).add(
         _stableRateSlope2.rayMul(excessUtilizationRateRatio)
       );
 
-      currentVariableBorrowRate = _baseVariableBorrowRate.add(_variableRateSlope1).add(
+      vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(_variableRateSlope1).add(
         _variableRateSlope2.rayMul(excessUtilizationRateRatio)
       );
     } else {
-      currentStableBorrowRate = currentStableBorrowRate.add(
+      vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(
         _stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
       );
-      currentVariableBorrowRate = _baseVariableBorrowRate.add(
+      vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
         utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(_variableRateSlope1)
       );
     }
 
-    currentLiquidityRate = _getOverallBorrowRate(
+    vars.currentLiquidityRate = _getOverallBorrowRate(
       totalBorrowsStable,
       totalBorrowsVariable,
-      currentVariableBorrowRate,
+      vars.currentVariableBorrowRate,
       averageStableBorrowRate
     )
-      .rayMul(utilizationRate);
+      .rayMul(utilizationRate)
+      .rayMul(WadRayMath.ray().sub(reserveFactor));
 
-    return (currentLiquidityRate, currentStableBorrowRate, currentVariableBorrowRate);
+    return (vars.currentLiquidityRate, vars.currentStableBorrowRate, vars.currentVariableBorrowRate);
   }
 
   /**
diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol
index 9e4e6707..50944f9f 100644
--- a/contracts/lendingpool/LendingPool.sol
+++ b/contracts/lendingpool/LendingPool.sol
@@ -12,6 +12,7 @@ import {IAToken} from '../tokenization/interfaces/IAToken.sol';
 import {Helpers} from '../libraries/helpers/Helpers.sol';
 import {Errors} from '../libraries/helpers/Errors.sol';
 import {WadRayMath} from '../libraries/math/WadRayMath.sol';
+import {PercentageMath} from '../libraries/math/PercentageMath.sol';
 import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
 import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
 import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
@@ -19,12 +20,12 @@ import {ReserveConfiguration} from '../libraries/configuration/ReserveConfigurat
 import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
 import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
 import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
+import {DebtTokenBase} from '../tokenization/base/DebtTokenBase.sol';
 import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
 import {LendingPoolLiquidationManager} from './LendingPoolLiquidationManager.sol';
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
 import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
 import {ILendingPool} from '../interfaces/ILendingPool.sol';
-
 /**
  * @title LendingPool contract
  * @notice Implements the actions of the LendingPool, and exposes accessory methods to fetch the users and reserve data
@@ -34,6 +35,7 @@ import {ILendingPool} from '../interfaces/ILendingPool.sol';
 contract LendingPool is VersionedInitializable, ILendingPool {
   using SafeMath for uint256;
   using WadRayMath for uint256;
+  using PercentageMath for uint256;
   using ReserveLogic for ReserveLogic.ReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
   using UserConfiguration for UserConfiguration.Map;
@@ -224,6 +226,9 @@ contract LendingPool is VersionedInitializable, ILendingPool {
 
     reserve.updateCumulativeIndexesAndTimestamp();
 
+    address debtTokenAddress = interestRateMode == ReserveLogic.InterestRateMode.STABLE ? reserve.stableDebtTokenAddress : reserve.variableDebtTokenAddress;
+    _mintToReserveTreasury(reserve, onBehalfOf, debtTokenAddress);
+
     //burns an equivalent amount of debt tokens
     if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
       IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
@@ -265,6 +270,10 @@ contract LendingPool is VersionedInitializable, ILendingPool {
 
     reserve.updateCumulativeIndexesAndTimestamp();
 
+    address debtTokenAddress = interestRateMode == ReserveLogic.InterestRateMode.STABLE ? reserve.stableDebtTokenAddress : reserve.variableDebtTokenAddress;
+    _mintToReserveTreasury(reserve, msg.sender, debtTokenAddress);
+
+
     if (interestRateMode == ReserveLogic.InterestRateMode.STABLE) {
       //burn stable rate tokens, mint variable rate tokens
       IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt);
@@ -321,6 +330,9 @@ contract LendingPool is VersionedInitializable, ILendingPool {
 
     reserve.updateCumulativeIndexesAndTimestamp();
 
+    _mintToReserveTreasury(reserve, user, address(stableDebtToken));
+
+
     stableDebtToken.burn(user, stableBorrowBalance);
     stableDebtToken.mint(user, stableBorrowBalance, reserve.currentStableBorrowRate);
 
@@ -609,7 +621,6 @@ contract LendingPool is VersionedInitializable, ILendingPool {
       uint256 principalVariableDebt,
       uint256 stableBorrowRate,
       uint256 liquidityRate,
-      uint256 variableBorrowIndex,
       uint40 stableRateLastUpdated,
       bool usageAsCollateralEnabled
     )
@@ -625,7 +636,6 @@ contract LendingPool is VersionedInitializable, ILendingPool {
       user
     );
     usageAsCollateralEnabled = _usersConfig[user].isUsingAsCollateral(reserve.index);
-    variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(user);
   }
 
   function getReserves() external override view returns (address[] memory) {
@@ -706,6 +716,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
    * @param vars Input struct for the borrowing action, in order to avoid STD errors
    **/
   function _executeBorrow(ExecuteBorrowParams memory vars) internal {
+    
     ReserveLogic.ReserveData storage reserve = _reserves[vars.asset];
     UserConfiguration.Map storage userConfig = _usersConfig[msg.sender];
 
@@ -730,13 +741,21 @@ contract LendingPool is VersionedInitializable, ILendingPool {
 
 
     uint256 reserveIndex = reserve.index;
+
     if (!userConfig.isBorrowing(reserveIndex)) {
       userConfig.setBorrowing(reserveIndex, true);
     }
 
+    address debtTokenAddress = ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE ? 
+        reserve.stableDebtTokenAddress 
+        : 
+        reserve.variableDebtTokenAddress;
+
 
     reserve.updateCumulativeIndexesAndTimestamp();
 
+    _mintToReserveTreasury(reserve, vars.user, debtTokenAddress);
+
     //caching the current stable borrow rate
     uint256 currentStableRate = 0;
 
@@ -745,13 +764,13 @@ contract LendingPool is VersionedInitializable, ILendingPool {
     ) {
       currentStableRate = reserve.currentStableBorrowRate;
 
-      IStableDebtToken(reserve.stableDebtTokenAddress).mint(
+      IStableDebtToken(debtTokenAddress).mint(
         vars.user,
         vars.amount,
         currentStableRate
       );
     } else {
-      IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount);
+      IVariableDebtToken(debtTokenAddress).mint(vars.user, vars.amount);
     }
 
     reserve.updateInterestRates(vars.asset, vars.aTokenAddress, 0, vars.releaseUnderlying ?  vars.amount : 0);
@@ -848,4 +867,19 @@ contract LendingPool is VersionedInitializable, ILendingPool {
   function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) {
     return _addressesProvider;
   }
+
+  function _mintToReserveTreasury(ReserveLogic.ReserveData storage reserve, address user, address debtTokenAddress) internal {
+    
+    uint256 currentPrincipalBalance = DebtTokenBase(debtTokenAddress).principalBalanceOf(user);
+    //calculating the interest accrued since the last borrow and minting the equivalent amount to the reserve factor
+    if(currentPrincipalBalance > 0){
+
+      uint256 balanceIncrease = IERC20(debtTokenAddress).balanceOf(user).sub(currentPrincipalBalance);
+
+      uint256 amountForReserveFactor = balanceIncrease.percentMul(reserve.configuration.getReserveFactor());
+
+      IAToken(reserve.aTokenAddress).mintToReserve(amountForReserveFactor);      
+    }    
+
+  }
 }
diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol
index 12ecf777..dee6d90c 100644
--- a/contracts/lendingpool/LendingPoolLiquidationManager.sol
+++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol
@@ -10,6 +10,7 @@ import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddresse
 import {IAToken} from '../tokenization/interfaces/IAToken.sol';
 import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
 import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
+import {DebtTokenBase} from '../tokenization/base/DebtTokenBase.sol';
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
 import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
 import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
@@ -208,6 +209,9 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
 
     //update the principal reserve
     principalReserve.updateCumulativeIndexesAndTimestamp();
+
+
+
     principalReserve.updateInterestRates(
       principal,
       principalReserve.aTokenAddress,
@@ -216,16 +220,29 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
     );
 
     if (vars.userVariableDebt >= vars.actualAmountToLiquidate) {
-      IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
+
+      address tokenAddress = principalReserve.variableDebtTokenAddress;
+
+      _mintToReserveTreasury(principalReserve, user, tokenAddress);
+
+      IVariableDebtToken(tokenAddress).burn(
         user,
         vars.actualAmountToLiquidate
       );
     } else {
-      IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
+
+      address tokenAddress = principalReserve.variableDebtTokenAddress;
+
+      _mintToReserveTreasury(principalReserve, user, tokenAddress);
+
+      IVariableDebtToken(tokenAddress).burn(
         user,
         vars.userVariableDebt
       );
-      IStableDebtToken(principalReserve.stableDebtTokenAddress).burn(
+
+      tokenAddress = principalReserve.stableDebtTokenAddress;
+
+      IStableDebtToken(tokenAddress).burn(
         user,
         vars.actualAmountToLiquidate.sub(vars.userVariableDebt)
       );
@@ -337,4 +354,19 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
     }
     return (collateralAmount, principalAmountNeeded);
   }
+
+  function _mintToReserveTreasury(ReserveLogic.ReserveData storage reserve, address user, address debtTokenAddress) internal {
+    
+    uint256 currentPrincipalBalance = DebtTokenBase(debtTokenAddress).principalBalanceOf(user);
+    //calculating the interest accrued since the last borrow and minting the equivalent amount to the reserve factor
+    if(currentPrincipalBalance > 0){
+
+      uint256 balanceIncrease = IERC20(debtTokenAddress).balanceOf(user).sub(currentPrincipalBalance);
+
+      uint256 amountForReserveFactor = balanceIncrease.percentMul(reserve.configuration.getReserveFactor());
+
+      IAToken(reserve.aTokenAddress).mintToReserve(amountForReserveFactor);      
+    }    
+
+  }
 }
diff --git a/contracts/libraries/configuration/ReserveConfiguration.sol b/contracts/libraries/configuration/ReserveConfiguration.sol
index 46ad9ba9..96c0024c 100644
--- a/contracts/libraries/configuration/ReserveConfiguration.sol
+++ b/contracts/libraries/configuration/ReserveConfiguration.sol
@@ -21,6 +21,7 @@ library ReserveConfiguration {
   uint256 constant FROZEN_MASK = 0xDFFFFFFFFFFFFFF;
   uint256 constant BORROWING_MASK = 0xBFFFFFFFFFFFFFF;
   uint256 constant STABLE_BORROWING_MASK = 0x7FFFFFFFFFFFFFF;
+  uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFF;
 
   struct Map {
     //bit 0-15: LTV
@@ -31,9 +32,27 @@ library ReserveConfiguration {
     //bit 57: reserve is freezed
     //bit 58: borrowing is enabled
     //bit 59: stable rate borrowing enabled
+    //bit 64-79: reserve factor
     uint256 data;
   }
 
+  /**
+   * @dev sets the reserve factor of the reserve
+   * @param self the reserve configuration
+   * @param ltv the new ltv
+   **/
+  function setReserveFactor(ReserveConfiguration.Map memory self, uint256 ltv) internal pure {
+    self.data = (self.data & RESERVE_FACTOR_MASK) | ltv;
+  }
+
+  /**
+   * @dev gets the reserve factor of the reserve
+   * @param self the reserve configuration
+   * @return the reserve factor
+   **/
+  function getReserveFactor(ReserveConfiguration.Map storage self) internal view returns (uint256) {
+    return self.data & ~RESERVE_FACTOR_MASK;
+  }
   /**
    * @dev sets the Loan to Value of the reserve
    * @param self the reserve configuration
diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol
index 607c8c63..90ed10cf 100644
--- a/contracts/libraries/logic/ReserveLogic.sol
+++ b/contracts/libraries/logic/ReserveLogic.sol
@@ -246,7 +246,8 @@ library ReserveLogic {
       vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken),
       IERC20(vars.stableDebtTokenAddress).totalSupply(),
       IERC20(reserve.variableDebtTokenAddress).totalSupply(),
-      vars.currentAvgStableRate
+      vars.currentAvgStableRate,
+      reserve.configuration.getReserveFactor()
     );
     require(vars.newLiquidityRate < (1 << 128), "ReserveLogic: Liquidity rate overflow");
     require(vars.newStableRate < (1 << 128), "ReserveLogic: Stable borrow rate overflow");
diff --git a/contracts/mocks/upgradeability/MockAToken.sol b/contracts/mocks/upgradeability/MockAToken.sol
index 05f0db4e..a0368535 100644
--- a/contracts/mocks/upgradeability/MockAToken.sol
+++ b/contracts/mocks/upgradeability/MockAToken.sol
@@ -10,7 +10,7 @@ contract MockAToken is AToken {
     address _underlyingAssetAddress,
     string memory _tokenName,
     string memory _tokenSymbol
-  ) public AToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {}
+  ) public AToken(_pool, _underlyingAssetAddress,address(0), _tokenName, _tokenSymbol) {}
 
   function getRevision() internal override pure returns (uint256) {
     return 0x2;
diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol
index de178819..36ca5ecb 100644
--- a/contracts/tokenization/AToken.sol
+++ b/contracts/tokenization/AToken.sol
@@ -25,6 +25,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
   uint256 public constant UINT_MAX_VALUE = uint256(-1);
 
   address public immutable UNDERLYING_ASSET_ADDRESS;
+  address public immutable RESERVE_TREASURY_ADDRESS;
 
   mapping(address => uint256) private _userIndexes;
   mapping(address => address) private _interestRedirectionAddresses;
@@ -48,11 +49,13 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
   constructor(
     LendingPool pool,
     address underlyingAssetAddress,
+    address reserveTreasuryAddress,
     string memory tokenName,
     string memory tokenSymbol
   ) public ERC20(tokenName, tokenSymbol, 18) {
     _pool = pool;
     UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
+    RESERVE_TREASURY_ADDRESS = reserveTreasuryAddress;
   }
 
   function getRevision() internal virtual override pure returns (uint256) {
@@ -183,6 +186,11 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
     emit Mint(user, amount, balanceIncrease, index);
   }
 
+  function mintToReserve(uint256 amount) external override onlyLendingPool {
+      uint256 index = _pool.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
+      _mint(RESERVE_TREASURY_ADDRESS, amount.div(index));
+  }
+
   /**
    * @dev transfers tokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
    *      only lending pools can call this function
diff --git a/contracts/tokenization/VariableDebtToken.sol b/contracts/tokenization/VariableDebtToken.sol
index 1fcda07a..80f626f9 100644
--- a/contracts/tokenization/VariableDebtToken.sol
+++ b/contracts/tokenization/VariableDebtToken.sol
@@ -17,6 +17,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
   using WadRayMath for uint256;
 
   uint256 public constant DEBT_TOKEN_REVISION = 0x1;
+  mapping(address => uint256) _userIndexes;
 
   constructor(
     address pool,
@@ -59,6 +60,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
     uint256 index = POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET);
 
     _mint(user, amount.rayDiv(index));
+    _userIndexes[user] = index;
     emit MintDebt(user, amount, index);
   }
 
@@ -71,7 +73,15 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
 
     uint256 index = POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET);
     _burn(user, amount.rayDiv(index)); 
-
+    _userIndexes[user] = index;
     emit BurnDebt(user, amount, index);
   }
+
+  /**
+   * @dev Returns the principal debt balance of the user from
+   * @return The debt balance of the user since the last burn/mint action
+   **/
+  function principalBalanceOf(address user) public virtual override view returns (uint256) {
+    return super.balanceOf(user).rayMul(_userIndexes[user]);
+  }
 }
diff --git a/contracts/tokenization/base/DebtTokenBase.sol b/contracts/tokenization/base/DebtTokenBase.sol
index ec021951..21d4dcf6 100644
--- a/contracts/tokenization/base/DebtTokenBase.sol
+++ b/contracts/tokenization/base/DebtTokenBase.sol
@@ -67,7 +67,7 @@ abstract contract DebtTokenBase is ERC20, VersionedInitializable {
    * @dev Returns the principal debt balance of the user from
    * @return The debt balance of the user since the last burn/mint action
    **/
-  function principalBalanceOf(address user) public view returns (uint256) {
+  function principalBalanceOf(address user) public virtual view returns (uint256) {
     return super.balanceOf(user);
   }
 
diff --git a/contracts/tokenization/interfaces/IAToken.sol b/contracts/tokenization/interfaces/IAToken.sol
index 65ad0cfa..ec6898fe 100644
--- a/contracts/tokenization/interfaces/IAToken.sol
+++ b/contracts/tokenization/interfaces/IAToken.sol
@@ -127,6 +127,14 @@ interface IAToken is IERC20 {
    */
   function mint(address user, uint256 amount) external;
 
+  /**
+   * @dev mints aTokens to reserve, based on the reserveFactor value
+   * only lending pools can call this function
+   * @param amount the amount of tokens to mint
+   */
+  function mintToReserve(uint256 amount) external;
+
+
   /**
    * @dev transfers tokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
    *      only lending pools can call this function
diff --git a/contracts/tokenization/interfaces/IVariableDebtToken.sol b/contracts/tokenization/interfaces/IVariableDebtToken.sol
index e979b4a5..6f58e2d2 100644
--- a/contracts/tokenization/interfaces/IVariableDebtToken.sol
+++ b/contracts/tokenization/interfaces/IVariableDebtToken.sol
@@ -46,9 +46,4 @@ interface IVariableDebtToken {
    **/
   function burn(address user, uint256 amount) external;
 
-  /**
-   * @dev returns the last index of the user
-   * @return the index of the user
-   **/
-  function getUserIndex(address user) external view returns (uint256);
 }