From 1eb2d11a3d948d35ea45ca4ced4fa45c4172c983 Mon Sep 17 00:00:00 2001
From: emilio <emilio@ethlend.io>
Date: Wed, 5 Aug 2020 12:40:24 +0200
Subject: [PATCH 1/5] initial commit

---
 buidler.config.ts                             |  1 +
 contracts/lendingpool/LendingPool.sol         | 32 ++++++--
 .../LendingPoolLiquidationManager.sol         |  5 +-
 contracts/libraries/GenericLogic.sol          | 26 ++++--
 contracts/libraries/ReserveLogic.sol          |  2 +
 contracts/libraries/UserConfiguration.sol     | 49 +++++++++++
 contracts/libraries/UserLogic.sol             |  3 +
 contracts/libraries/ValidationLogic.sol       | 13 +--
 deployed-contracts.json                       | 82 +++++++++----------
 test/scenario.spec.ts                         |  2 +-
 10 files changed, 154 insertions(+), 61 deletions(-)
 create mode 100644 contracts/libraries/UserConfiguration.sol

diff --git a/buidler.config.ts b/buidler.config.ts
index 5b804bab..afd7b493 100644
--- a/buidler.config.ts
+++ b/buidler.config.ts
@@ -10,6 +10,7 @@ usePlugin('buidler-typechain');
 usePlugin('solidity-coverage');
 usePlugin('@nomiclabs/buidler-waffle');
 usePlugin('@nomiclabs/buidler-etherscan');
+usePlugin('buidler-gas-reporter');
 
 ['misc'].forEach((folder) => {
   const tasksPath = path.join(__dirname, 'tasks', folder);
diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol
index 74d1d89a..ed2d596a 100644
--- a/contracts/lendingpool/LendingPool.sol
+++ b/contracts/lendingpool/LendingPool.sol
@@ -16,6 +16,7 @@ import '../libraries/UserLogic.sol';
 import '../libraries/GenericLogic.sol';
 import '../libraries/ValidationLogic.sol';
 import '../libraries/ReserveConfiguration.sol';
+import '../libraries/UserConfiguration.sol';
 import '../libraries/UniversalERC20.sol';
 import '../tokenization/interfaces/IStableDebtToken.sol';
 import '../tokenization/interfaces/IVariableDebtToken.sol';
@@ -39,6 +40,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   using ReserveLogic for ReserveLogic.ReserveData;
   using UserLogic for UserLogic.UserReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
+  using UserConfiguration for UserConfiguration.Map;
 
   //main configuration parameters
   uint256 private constant REBALANCE_DOWN_RATE_DELTA = (1e27) / 5;
@@ -52,6 +54,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
   mapping(address => ReserveLogic.ReserveData) internal reserves;
   mapping(address => mapping(address => UserLogic.UserReserveData)) internal usersReserveData;
+  mapping(address => UserConfiguration.Map) internal usersConfig;
 
   address[] public reservesList;
 
@@ -274,6 +277,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     if (isFirstDeposit) {
       user.useAsCollateral = true;
+      usersConfig[msg.sender].setLending(reserve.index, true);
+      console.log("User %s configuration %s", msg.sender, usersConfig[msg.sender].data);
     }
 
     //minting AToken to user 1:1 with the specific exchange rate
@@ -312,6 +317,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     if (_aTokenBalanceAfterRedeem == 0) {
       user.useAsCollateral = false;
+      usersConfig[_user].setLending(reserve.index, false);
     }
 
     AToken(reserve.aTokenAddress).transferUnderlyingTo(_user, _amount);
@@ -335,6 +341,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   ) external nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
     UserLogic.UserReserveData storage user = usersReserveData[msg.sender][_reserve];
+    UserConfiguration.Map storage userConfig = usersConfig[msg.sender];
 
     uint256 amountInETH = IPriceOracleGetter(addressesProvider.getPriceOracle())
       .getAssetPrice(_reserve)
@@ -350,7 +357,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
       _interestRateMode,
       MAX_STABLE_RATE_BORROW_SIZE_PERCENT,
       reserves,
-      usersReserveData,
+      usersConfig[msg.sender],
       reservesList,
       addressesProvider.getPriceOracle()
     );
@@ -373,6 +380,11 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     reserve.updateInterestRates(_reserve, 0, _amount);
 
+    if(!userConfig.isBorrowing(reserve.index)){
+      userConfig.setBorrowing(reserve.index, true);
+      console.log("User %s configuration %s", msg.sender, userConfig.data);
+    }
+
     //if we reached this point, we can transfer
     AToken(reserve.aTokenAddress).transferUnderlyingTo(msg.sender, _amount);
 
@@ -404,6 +416,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     uint256 variableDebt;
     uint256 paybackAmount;
     uint256 currentStableRate;
+    uint256 totalDebt;
   }
 
   function repay(
@@ -418,6 +431,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     (vars.stableDebt, vars.variableDebt) = UserLogic.getUserCurrentDebt(_onBehalfOf, reserve);
 
+    vars.totalDebt = vars.stableDebt.add(vars.variableDebt);
+
     ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode);
 
     //default to max amount
@@ -451,6 +466,10 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     }
 
     reserve.updateInterestRates(_reserve, vars.paybackAmount, 0);
+    
+    if(vars.totalDebt.sub(vars.paybackAmount) == 0){
+      usersConfig[_onBehalfOf].setBorrowing(reserve.index, false);
+    }
 
     IERC20(_reserve).universalTransferFrom(
       msg.sender,
@@ -587,7 +606,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
       reserve,
       _reserve,
       reserves,
-      usersReserveData,
+      usersConfig[msg.sender],
       reservesList,
       addressesProvider.getPriceOracle()
     );
@@ -829,7 +848,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     ) = GenericLogic.calculateUserAccountData(
       _user,
       reserves,
-      usersReserveData,
+      usersConfig[_user],
       reservesList,
       addressesProvider.getPriceOracle()
     );
@@ -943,7 +962,10 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
       if (reservesList[i] == _reserve) {
         reserveAlreadyAdded = true;
       }
-    if (!reserveAlreadyAdded) reservesList.push(_reserve);
+    if (!reserveAlreadyAdded) {
+      reserves[_reserve].index = uint8(reservesList.length);
+      reservesList.push(_reserve);
+    }
   }
 
   function getReserveNormalizedIncome(address _reserve) external view returns (uint256) {
@@ -965,7 +987,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
         _user,
         _amount,
         reserves,
-        usersReserveData,
+        usersConfig[_user],
         reservesList,
         addressesProvider.getPriceOracle()
       );
diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol
index e6b4e50a..1fa5a3cd 100644
--- a/contracts/lendingpool/LendingPoolLiquidationManager.sol
+++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol
@@ -20,6 +20,7 @@ import '../libraries/UserLogic.sol';
 import '../libraries/ReserveLogic.sol';
 import '../libraries/UniversalERC20.sol';
 import '../libraries/ReserveConfiguration.sol';
+import '../libraries/UserConfiguration.sol';
 import {PercentageMath} from '../libraries/PercentageMath.sol';
 
 /**
@@ -36,12 +37,14 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
   using ReserveLogic for ReserveLogic.ReserveData;
   using UserLogic for UserLogic.UserReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
+  using UserConfiguration for UserConfiguration.Map;
 
   LendingPoolAddressesProvider public addressesProvider;
   IFeeProvider feeProvider;
 
   mapping(address => ReserveLogic.ReserveData) internal reserves;
   mapping(address => mapping(address => UserLogic.UserReserveData)) internal usersReserveData;
+  mapping(address => UserConfiguration.Map) usersConfig;
 
   address[] public reservesList;
 
@@ -131,7 +134,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
     (, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
       _user,
       reserves,
-      usersReserveData,
+      usersConfig[_user],
       reservesList,
       addressesProvider.getPriceOracle()
     );
diff --git a/contracts/libraries/GenericLogic.sol b/contracts/libraries/GenericLogic.sol
index 927670bd..757bf97b 100644
--- a/contracts/libraries/GenericLogic.sol
+++ b/contracts/libraries/GenericLogic.sol
@@ -1,11 +1,13 @@
 // SPDX-License-Identifier: agpl-3.0
 pragma solidity ^0.6.8;
+pragma experimental ABIEncoderV2;
 
 import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 
 import {ReserveLogic} from './ReserveLogic.sol';
 import {ReserveConfiguration} from './ReserveConfiguration.sol';
+import {UserConfiguration} from './UserConfiguration.sol';
 import {UserLogic} from './UserLogic.sol';
 import {WadRayMath} from './WadRayMath.sol';
 import {PercentageMath} from './PercentageMath.sol';
@@ -25,6 +27,7 @@ library GenericLogic {
   using WadRayMath for uint256;
   using PercentageMath for uint256;
   using ReserveConfiguration for ReserveConfiguration.Map;
+  using UserConfiguration for UserConfiguration.Map;
 
   uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18;
 
@@ -55,16 +58,21 @@ library GenericLogic {
     address _user,
     uint256 _amount,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    mapping(address => mapping(address => UserLogic.UserReserveData)) storage _usersData,
+    UserConfiguration.Map calldata _userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view returns (bool) {
+
+    if(!_userConfig.isBorrowingAny()){
+      return true;
+    }
+    
     // Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
     balanceDecreaseAllowedLocalVars memory vars;
 
     (vars.ltv, , , vars.decimals) = _reservesData[_reserve].configuration.getParams();
 
-    if (vars.ltv == 0 || !_usersData[_user][_reserve].useAsCollateral) {
+    if (vars.ltv == 0 || !_userConfig.isLending(_reservesData[_reserve].index)) {
       return true; //if reserve is not used as collateral, no reasons to block the transfer
     }
 
@@ -74,7 +82,7 @@ library GenericLogic {
       ,
       vars.currentLiquidationThreshold,
 
-    ) = calculateUserAccountData(_user, _reservesData, _usersData, _reserves, _oracle);
+    ) = calculateUserAccountData(_user, _reservesData, _userConfig, _reserves, _oracle);
 
     if (vars.borrowBalanceETH == 0) {
       return true; //no borrows - no reasons to block the transfer
@@ -134,18 +142,17 @@ library GenericLogic {
    * the average Loan To Value, the average Liquidation Ratio, and the Health factor.
    * @param _user the address of the user
    * @param _reservesData data of all the reserves
-   * @param _usersReserveData data
    * @return the total liquidity, total collateral, total borrow balances of the user in ETH.
    * also the average Ltv, liquidation threshold, and the health factor
    **/
   function calculateUserAccountData(
     address _user,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    mapping(address => mapping(address => UserLogic.UserReserveData)) storage _usersReserveData,
+    UserConfiguration.Map memory userConfig,
     address[] memory _reserves,
     address _oracle
   )
-    public
+    internal
     view
     returns (
       uint256,
@@ -158,6 +165,11 @@ library GenericLogic {
     CalculateUserAccountDataVars memory vars;
 
     for (vars.i = 0; vars.i < _reserves.length; vars.i++) {
+
+      if(!userConfig.isLendingOrBorrowing(vars.i)){
+        continue;
+      }
+
       vars.currentReserveAddress = _reserves[vars.i];
 
       ReserveLogic.ReserveData storage currentReserve = _reservesData[vars.currentReserveAddress];
@@ -186,7 +198,7 @@ library GenericLogic {
           .mul(vars.compoundedLiquidityBalance)
           .div(vars.tokenUnit);
 
-        if (vars.ltv != 0 && _usersReserveData[_user][_reserves[vars.i]].useAsCollateral) {
+        if (vars.ltv != 0 && userConfig.isLending(vars.i)) {
           vars.totalCollateralBalanceETH = vars.totalCollateralBalanceETH.add(liquidityBalanceETH);
 
           vars.avgLtv = vars.avgLtv.add(liquidityBalanceETH.mul(vars.ltv));
diff --git a/contracts/libraries/ReserveLogic.sol b/contracts/libraries/ReserveLogic.sol
index e0823337..082b9151 100644
--- a/contracts/libraries/ReserveLogic.sol
+++ b/contracts/libraries/ReserveLogic.sol
@@ -62,6 +62,8 @@ library ReserveLogic {
     uint40 lastUpdateTimestamp;
     // isStableBorrowRateEnabled = true means users can borrow at a stable rate
     bool isStableBorrowRateEnabled;
+
+    uint8 index;
   }
 
   /**
diff --git a/contracts/libraries/UserConfiguration.sol b/contracts/libraries/UserConfiguration.sol
new file mode 100644
index 00000000..2314318f
--- /dev/null
+++ b/contracts/libraries/UserConfiguration.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: agpl-3.0
+pragma solidity ^0.6.8;
+
+import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
+import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
+
+import {UserLogic} from './UserLogic.sol';
+import {WadRayMath} from './WadRayMath.sol';
+
+import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
+import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
+
+/**
+ * @title UserConfiguration library
+ * @author Aave
+ * @notice Implements the bitmap logic to handle the user configuration
+ */
+library UserConfiguration {
+
+  uint256 internal constant BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555;
+
+  struct Map {
+    uint256 data;
+  }
+
+  function setBorrowing(UserConfiguration.Map storage _self, uint256 _reserveIndex, bool _borrowing) internal {
+    _self.data |= uint256(_borrowing ? 1 : 0) << _reserveIndex*2;
+  }
+
+  function setLending(UserConfiguration.Map storage _self, uint256 _reserveIndex, bool _lending) internal {
+    _self.data |= uint256(_lending ? 1 : 0) << _reserveIndex*2+1;
+  }
+
+  function isLendingOrBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
+     return _self.data >> _reserveIndex*2 & 2 != 0;
+  }
+
+  function isBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
+    return _self.data >> _reserveIndex*2 & 1 != 0 ;
+  }
+
+  function isLending(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
+    return _self.data >> (_reserveIndex*2+1) & 1 != 0;
+  }
+
+  function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns(bool) {
+    return _self.data & BORROWING_MASK != 0;
+  }
+}
diff --git a/contracts/libraries/UserLogic.sol b/contracts/libraries/UserLogic.sol
index d5a904e4..5764bd1c 100644
--- a/contracts/libraries/UserLogic.sol
+++ b/contracts/libraries/UserLogic.sol
@@ -8,6 +8,8 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 import '../tokenization/base/DebtTokenBase.sol';
 import './ReserveLogic.sol';
 import './ReserveConfiguration.sol';
+import './UserConfiguration.sol';
+
 
 /**
  * @title UserLogic library
@@ -20,6 +22,7 @@ library UserLogic {
 
   struct UserReserveData {
     //defines if a specific deposit should or not be used as a collateral in borrows
+    UserConfiguration.Map configuration;
     bool useAsCollateral;
   }
 
diff --git a/contracts/libraries/ValidationLogic.sol b/contracts/libraries/ValidationLogic.sol
index 8f299ca6..7f3e79d7 100644
--- a/contracts/libraries/ValidationLogic.sol
+++ b/contracts/libraries/ValidationLogic.sol
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: agpl-3.0
 pragma solidity ^0.6.8;
+pragma experimental ABIEncoderV2;
 
 import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
@@ -11,6 +12,7 @@ import {WadRayMath} from './WadRayMath.sol';
 import {PercentageMath} from './PercentageMath.sol';
 import {UniversalERC20} from './UniversalERC20.sol';
 import {ReserveConfiguration} from './ReserveConfiguration.sol';
+import {UserConfiguration} from './UserConfiguration.sol';
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
 import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
 import '@nomiclabs/buidler/console.sol';
@@ -28,6 +30,7 @@ library ValidationLogic {
   using PercentageMath for uint256;
   using UniversalERC20 for IERC20;
   using ReserveConfiguration for ReserveConfiguration.Map;
+  using UserConfiguration for UserConfiguration.Map;
 
   /**
    * @dev validates a deposit.
@@ -96,7 +99,6 @@ library ValidationLogic {
    * @param _interestRateMode the interest rate mode at which the user is borrowing
    * @param _maxStableLoanPercent the max amount of the liquidity that can be borrowed at stable rate, in percentage
    * @param _reservesData the state of all the reserves
-   * @param _usersData the state of all the users for all the reserves
    * @param _reserves the addresses of all the active reserves
    * @param _oracle the price oracle
    */
@@ -110,7 +112,7 @@ library ValidationLogic {
     uint256 _interestRateMode,
     uint256 _maxStableLoanPercent,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    mapping(address => mapping(address => UserLogic.UserReserveData)) storage _usersData,
+    UserConfiguration.Map calldata userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view {
@@ -153,7 +155,7 @@ library ValidationLogic {
     ) = GenericLogic.calculateUserAccountData(
       msg.sender,
       _reservesData,
-      _usersData,
+      userConfig,
       _reserves,
       _oracle
     );
@@ -304,13 +306,12 @@ library ValidationLogic {
    * @param _reserve the state of the reserve that the user is enabling or disabling as collateral
    * @param _reserveAddress the address of the reserve
    * @param _reservesData the data of all the reserves
-   * @param _usersData the data of all the users
    */
   function validateSetUseReserveAsCollateral(
     ReserveLogic.ReserveData storage _reserve,
     address _reserveAddress,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    mapping(address => mapping(address => UserLogic.UserReserveData)) storage _usersData,
+    UserConfiguration.Map calldata userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view {
@@ -324,7 +325,7 @@ library ValidationLogic {
         msg.sender,
         underlyingBalance,
         _reservesData,
-        _usersData,
+        userConfig,
         _reserves,
         _oracle
       ),
diff --git a/deployed-contracts.json b/deployed-contracts.json
index e6b20b9a..a7314419 100644
--- a/deployed-contracts.json
+++ b/deployed-contracts.json
@@ -5,7 +5,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x613b8Aa5BAFB5c903B8AFF84307C3D8eb6a09C9D",
+      "address": "0xb0f645D86C1436502f45229292b117e45e1a2bC4",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -15,7 +15,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x832517B00deEa0cD9780C94837D92b2b282C75F5",
+      "address": "0x12c2160C86B21FFF1c708F77d5263CF192f2B661",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -25,7 +25,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x05D70e69C53E9A097E741976096ca16A4ec44Bdd",
+      "address": "0x94Bc72DCbdc296991dc61555e996C447cAD60369",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -34,7 +34,7 @@
       "address": "0x852e3718A320aD93Ad8692E8D663d247e4c1b400"
     },
     "localhost": {
-      "address": "0x7Ca3264502Ae135bc346Ddde379D11f72a210Df2"
+      "address": "0xcD1440EB52c2dD054a04a7E5E37412532D5173d4"
     }
   },
   "LendingPoolParametersProvider": {
@@ -52,7 +52,7 @@
       "address": "0xA10958a24032283FbE2D23cedf264d6eC9411CBA"
     },
     "localhost": {
-      "address": "0x1c9aA18db4804bD3E9788735Ac12c930a4cFAF29"
+      "address": "0x300e90Cf6EC17Fc047f63180122c33bB5e106586"
     }
   },
   "LendingPoolDataProvider": {
@@ -65,7 +65,7 @@
       "address": "0x2C4603396dE2F08642354A3A102760827FfFe113"
     },
     "localhost": {
-      "address": "0x2C29ed4a90805792c56B99EFf249e28b8b3a5d36"
+      "address": "0xCD980f1801Fac5999168c590879779Fb1539b484"
     }
   },
   "PriceOracle": {
@@ -74,7 +74,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xE825E4621E95a5AE37119617bfC0165724c51762",
+      "address": "0x0f611985C3dd0C3B6655b4216A2CB5988C5635f9",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -84,7 +84,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xF1d2bdD7CFc305eb550895DdADb55b7fBA2af1E5",
+      "address": "0x049F2C09e1d8C2ba59BE6A7Ff069B3632171a4dc",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -94,7 +94,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x84daCdA0B4802B6Aa8661F266A48BE4F54817119",
+      "address": "0x8330f3ab4680A70C76Fa55D886155f39c6800aE4",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -104,7 +104,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x70a259a0efDF51B073497d3723630ea8ae11B32a",
+      "address": "0x1b12f84d85e5EFdF07F992ACe35E832F630Ed4b7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -114,7 +114,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x5737D6Be516831d7E9596e4458583c17B2662b25",
+      "address": "0x689Bda5742bAD2249D3D96eAF7095B86F14FD397",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -149,7 +149,7 @@
       "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB"
     },
     "localhost": {
-      "address": "0x07C1cd8182AAda58009D3b547295A64046679666"
+      "address": "0xd0F297f35CD4357d2015F28Ac04CD2818f1df96c"
     }
   },
   "InitializableAdminUpgradeabilityProxy": {
@@ -158,7 +158,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x07C1cd8182AAda58009D3b547295A64046679666",
+      "address": "0xd0F297f35CD4357d2015F28Ac04CD2818f1df96c",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -167,7 +167,7 @@
       "address": "0x24E420B42971372F060a93129846761F354Bc50B"
     },
     "localhost": {
-      "address": "0xbCC0e6a5385C3a8A2d40Aa079F3E8d40f09Ae48d"
+      "address": "0x151c4FeF6A0421EF1f1e573003a075C363321036"
     }
   },
   "WalletBalanceProvider": {
@@ -176,7 +176,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x04297834784DcB98Df9fE232DE5a97D2569c8aDd",
+      "address": "0xf1d54dd9a27843B16F4e4b63f8f06A9E83074bA1",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -186,7 +186,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x352BD2c9A3a019aC10F7fc81dB119D4a325117DE",
+      "address": "0xf839CeF3895cb50756430290080b503b3B4e852f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -196,7 +196,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x5Cccb7f34cB05938c29442815Cc331AA6492B723",
+      "address": "0x5d7A000000200Fd161d3C35026E5e7e976dD3BAA",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -206,7 +206,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x7457b9406832EEa09864dcaAB82Ae3c134f9A975",
+      "address": "0xc93e68A8478fAc486BA9190FFE95138be2Bf8Ce7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -216,7 +216,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xdB97f0f4a431B70Ec854b270d56e1ECa25f3113b",
+      "address": "0xc6f1Fc4ab562c141cc836335F0Bb50e429c907c1",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -226,7 +226,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x8A8dC28F6C1874f573FCBd921f1fb24301caB913",
+      "address": "0x17e1cB8daCeee46Afc60934D94f5860341ddDdf6",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -236,7 +236,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x8bAE0F999E4A82191F7536E8a5e2De0412588d86",
+      "address": "0xb85CCdA348896399b6538C58A33c772097e4079f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -246,7 +246,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xa61F8cfACa566F8F4303cE283e9535934A8CDdD5",
+      "address": "0xe922A043Bb653355d788Fc872b3BA7c55dE20275",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -256,7 +256,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xb0f645D86C1436502f45229292b117e45e1a2bC4",
+      "address": "0x1144E5f1687e711dA0Ece078e8C2dbEa96d013f9",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -266,7 +266,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x12c2160C86B21FFF1c708F77d5263CF192f2B661",
+      "address": "0x816b8DFbC98bBA158dA7791DEacBA4EA63B1DF8f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -276,7 +276,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x155a2e68CB8Db7B1cB9066E717aE93e65A2f93EF",
+      "address": "0xde7a19b06E13642Fa63029BcE99A3dC64Ae50fa2",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -286,7 +286,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x94Bc72DCbdc296991dc61555e996C447cAD60369",
+      "address": "0x95FcA33A67122BD7B3c53533102A07F0185Aa153",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -296,7 +296,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x346fdD507f157a74e63a73ACf371B5bDf562De67",
+      "address": "0x1F16D1e96161578D78581874Bc7d39fDbCBCdf7A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -306,7 +306,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xCF8eF26FE68C88Fc899B1F40E48688F6C6FFf9E1",
+      "address": "0x2f0712dCe236E6e9f5C3d5226dA2D7De7b6D3bf5",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -316,7 +316,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x90C17f3141263b2942E843c83102ba8cD18956B7",
+      "address": "0xdd499FEeED70d925F905fa882E0946002505fb8a",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -326,7 +326,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x58C7b3Aa19a4EEb3505564ab45c6fd16442A85ec",
+      "address": "0x62B2aD4feA8DBe859f522e3cD6C1a958Da7ba370",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -336,7 +336,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xa25fA46698beE81E33e0Dd691849945B0B417ea4",
+      "address": "0x352BD2c9A3a019aC10F7fc81dB119D4a325117DE",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -346,7 +346,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xEec014eff3DBeE5a3100fb6a9128cF7c40c3e782",
+      "address": "0x5Cccb7f34cB05938c29442815Cc331AA6492B723",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -356,7 +356,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x4BD61457B65687B555fb86B8038Ffb5779970A3C",
+      "address": "0x7457b9406832EEa09864dcaAB82Ae3c134f9A975",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -366,7 +366,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x2114d96A6eC73Be7151938D0e7c74ec566cF0153",
+      "address": "0xdB97f0f4a431B70Ec854b270d56e1ECa25f3113b",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -376,7 +376,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x294c3d68F340883C44d50daD4Ec6737327f2f993",
+      "address": "0x8A8dC28F6C1874f573FCBd921f1fb24301caB913",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -386,7 +386,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x22e57AEFA0f0f5aF3f0933EBB08B2FD5E1f52389",
+      "address": "0x8bAE0F999E4A82191F7536E8a5e2De0412588d86",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -396,7 +396,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xbc80b4b4D77Df85898DCA2AbB615edC353039d2b",
+      "address": "0xa61F8cfACa566F8F4303cE283e9535934A8CDdD5",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -406,7 +406,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x613b8Aa5BAFB5c903B8AFF84307C3D8eb6a09C9D",
+      "address": "0xb0f645D86C1436502f45229292b117e45e1a2bC4",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -415,7 +415,7 @@
       "address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d"
     },
     "localhost": {
-      "address": "0x40Bf3Ca3a1EFdCDFf6BaE86Cf92EC5a46E629556"
+      "address": "0x580FE93f9caA2D590012f23a0F0893D558ceBBcc"
     }
   },
   "StableDebtToken": {
@@ -424,7 +424,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x9088A0A8f3e0906Fc7b1872407C8aB3EDF6D8F11",
+      "address": "0x9407cCBA4F79a7330244b2Bc20089A32259E789c",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -434,7 +434,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x078fd0F0A179084DB4FF90399518Fd14DD006b6c",
+      "address": "0x43C61876f933Bc11491764A750C6167bC05d8E7A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   }
diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts
index 10db45fb..21150450 100644
--- a/test/scenario.spec.ts
+++ b/test/scenario.spec.ts
@@ -12,7 +12,7 @@ BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN});
 
 const scenarioFolder = './test/helpers/scenarios/';
 
-const selectedScenarios: string[] = [];
+const selectedScenarios: string[] = ['borrow-repay-variable.json'];
 
 fs.readdirSync(scenarioFolder).forEach((file) => {
   if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return;

From 8df5182c59cd30cacb9e5828a5ecb4c65febba3c Mon Sep 17 00:00:00 2001
From: emilio <emilio@ethlend.io>
Date: Thu, 6 Aug 2020 00:46:22 +0200
Subject: [PATCH 2/5] Fixed bugs in user configuration

---
 contracts/lendingpool/LendingPool.sol         | 22 ++---
 .../LendingPoolLiquidationManager.sol         | 14 +---
 contracts/libraries/GenericLogic.sol          | 54 ++++++------
 contracts/libraries/UserConfiguration.sol     | 47 ++++++++---
 contracts/libraries/ValidationLogic.sol       | 19 ++---
 deployed-contracts.json                       | 82 +++++++++----------
 helpers/types.ts                              |  2 +-
 test/liquidation-atoken.spec.ts               |  4 +-
 test/liquidation-underlying.spec.ts           |  2 +-
 test/scenario.spec.ts                         |  2 +-
 10 files changed, 123 insertions(+), 125 deletions(-)

diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol
index ed2d596a..5f55fcd1 100644
--- a/contracts/lendingpool/LendingPool.sol
+++ b/contracts/lendingpool/LendingPool.sol
@@ -53,7 +53,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   using UniversalERC20 for IERC20;
 
   mapping(address => ReserveLogic.ReserveData) internal reserves;
-  mapping(address => mapping(address => UserLogic.UserReserveData)) internal usersReserveData;
   mapping(address => UserConfiguration.Map) internal usersConfig;
 
   address[] public reservesList;
@@ -264,7 +263,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     uint16 _referralCode
   ) external payable nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[msg.sender][_reserve];
 
     ValidationLogic.validateDeposit(reserve, _amount);
 
@@ -276,9 +274,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     reserve.updateInterestRates(_reserve, _amount, 0);
 
     if (isFirstDeposit) {
-      user.useAsCollateral = true;
-      usersConfig[msg.sender].setLending(reserve.index, true);
-      console.log("User %s configuration %s", msg.sender, usersConfig[msg.sender].data);
+      usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true);
     }
 
     //minting AToken to user 1:1 with the specific exchange rate
@@ -305,7 +301,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     uint256 _aTokenBalanceAfterRedeem
   ) external nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[_user][_reserve];
 
     AToken aToken = AToken(payable(reserve.aTokenAddress));
 
@@ -316,8 +311,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     reserve.updateInterestRates(_reserve, 0, _amount);
 
     if (_aTokenBalanceAfterRedeem == 0) {
-      user.useAsCollateral = false;
-      usersConfig[_user].setLending(reserve.index, false);
+      usersConfig[_user].setUsingAsCollateral(reserve.index, false);
     }
 
     AToken(reserve.aTokenAddress).transferUnderlyingTo(_user, _amount);
@@ -340,7 +334,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     uint16 _referralCode
   ) external nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[msg.sender][_reserve];
     UserConfiguration.Map storage userConfig = usersConfig[msg.sender];
 
     uint256 amountInETH = IPriceOracleGetter(addressesProvider.getPriceOracle())
@@ -350,7 +343,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     ValidationLogic.validateBorrow(
       reserve,
-      user,
       _reserve,
       _amount,
       amountInETH,
@@ -382,7 +374,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
 
     if(!userConfig.isBorrowing(reserve.index)){
       userConfig.setBorrowing(reserve.index, true);
-      console.log("User %s configuration %s", msg.sender, userConfig.data);
     }
 
     //if we reached this point, we can transfer
@@ -427,7 +418,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   ) external payable nonReentrant {
     RepayLocalVars memory vars;
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[_onBehalfOf][_reserve];
 
     (vars.stableDebt, vars.variableDebt) = UserLogic.getUserCurrentDebt(_onBehalfOf, reserve);
 
@@ -504,13 +494,12 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
    **/
   function swapBorrowRateMode(address _reserve, uint256 _rateMode) external nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[msg.sender][_reserve];
 
     (uint256 stableDebt, uint256 variableDebt) = UserLogic.getUserCurrentDebt(msg.sender, reserve);
 
     ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode);
 
-    ValidationLogic.validateSwapRateMode(reserve, user, stableDebt, variableDebt, rateMode);
+    ValidationLogic.validateSwapRateMode(reserve, usersConfig[msg.sender], stableDebt, variableDebt, rateMode);
 
     reserve.updateCumulativeIndexesAndTimestamp();
 
@@ -600,7 +589,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     nonReentrant
   {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
-    UserLogic.UserReserveData storage user = usersReserveData[msg.sender][_reserve];
 
     ValidationLogic.validateSetUseReserveAsCollateral(
       reserve,
@@ -611,7 +599,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
       addressesProvider.getPriceOracle()
     );
 
-    user.useAsCollateral = _useAsCollateral;
+    usersConfig[msg.sender].setUsingAsCollateral(reserve.index, _useAsCollateral);
 
     if (_useAsCollateral) {
       emit ReserveUsedAsCollateralEnabled(_reserve, msg.sender);
@@ -886,7 +874,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated(
       _user
     );
-    usageAsCollateralEnabled = usersReserveData[_user][_reserve].useAsCollateral;
+    usageAsCollateralEnabled = usersConfig[_user].isUsingAsCollateral(reserve.index);
     variableBorrowIndex = IVariableDebtToken(reserve.variableDebtTokenAddress).getUserIndex(_user);
   }
 
diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol
index 1fa5a3cd..1744fc1c 100644
--- a/contracts/lendingpool/LendingPoolLiquidationManager.sol
+++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol
@@ -43,8 +43,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
   IFeeProvider feeProvider;
 
   mapping(address => ReserveLogic.ReserveData) internal reserves;
-  mapping(address => mapping(address => UserLogic.UserReserveData)) internal usersReserveData;
-  mapping(address => UserConfiguration.Map) usersConfig;
+  mapping(address => UserConfiguration.Map) internal usersConfig;
 
   address[] public reservesList;
 
@@ -127,7 +126,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
   ) external payable returns (uint256, string memory) {
     ReserveLogic.ReserveData storage principalReserve = reserves[_reserve];
     ReserveLogic.ReserveData storage collateralReserve = reserves[_collateral];
-    UserLogic.UserReserveData storage userCollateral = usersReserveData[_user][_collateral];
+    UserConfiguration.Map storage userConfig = usersConfig[_user];
 
     LiquidationCallLocalVars memory vars;
 
@@ -148,17 +147,10 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
 
     vars.userCollateralBalance = IERC20(collateralReserve.aTokenAddress).balanceOf(_user);
 
-    //if _user hasn't deposited this specific collateral, nothing can be liquidated
-    if (vars.userCollateralBalance == 0) {
-      return (
-        uint256(LiquidationErrors.NO_COLLATERAL_AVAILABLE),
-        'Invalid collateral to liquidate'
-      );
-    }
 
     vars.isCollateralEnabled =
       collateralReserve.configuration.getLiquidationThreshold() > 0 &&
-      userCollateral.useAsCollateral;
+      userConfig.isUsingAsCollateral(collateralReserve.index);
 
     //if _collateral isn't enabled as collateral by _user, it cannot be liquidated
     if (!vars.isCollateralEnabled) {
diff --git a/contracts/libraries/GenericLogic.sol b/contracts/libraries/GenericLogic.sol
index 757bf97b..a7c80a02 100644
--- a/contracts/libraries/GenericLogic.sol
+++ b/contracts/libraries/GenericLogic.sol
@@ -63,16 +63,16 @@ library GenericLogic {
     address _oracle
   ) external view returns (bool) {
 
-    if(!_userConfig.isBorrowingAny()){
+    if (!_userConfig.isBorrowingAny() || !_userConfig.isUsingAsCollateral(_reservesData[_reserve].index)) {
       return true;
     }
-    
+
     // Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
     balanceDecreaseAllowedLocalVars memory vars;
 
     (vars.ltv, , , vars.decimals) = _reservesData[_reserve].configuration.getParams();
 
-    if (vars.ltv == 0 || !_userConfig.isLending(_reservesData[_reserve].index)) {
+    if (vars.ltv == 0) {
       return true; //if reserve is not used as collateral, no reasons to block the transfer
     }
 
@@ -130,6 +130,7 @@ library GenericLogic {
     uint256 avgLtv;
     uint256 avgLiquidationThreshold;
     uint256 reservesLength;
+    UserConfiguration.Map userConfig;
     bool healthFactorBelowThreshold;
     address currentReserveAddress;
     bool usageAsCollateralEnabled;
@@ -148,7 +149,7 @@ library GenericLogic {
   function calculateUserAccountData(
     address _user,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    UserConfiguration.Map memory userConfig,
+    UserConfiguration.Map memory _userConfig,
     address[] memory _reserves,
     address _oracle
   )
@@ -164,51 +165,48 @@ library GenericLogic {
   {
     CalculateUserAccountDataVars memory vars;
 
+    if (_userConfig.isEmpty()) {
+      return (0, 0, 0, 0, uint256(-1));
+    }
     for (vars.i = 0; vars.i < _reserves.length; vars.i++) {
-
-      if(!userConfig.isLendingOrBorrowing(vars.i)){
+      if (!_userConfig.isUsingAsCollateralOrBorrowing(vars.i)) {
         continue;
       }
 
       vars.currentReserveAddress = _reserves[vars.i];
-
       ReserveLogic.ReserveData storage currentReserve = _reservesData[vars.currentReserveAddress];
 
-      vars.compoundedLiquidityBalance = IERC20(currentReserve.aTokenAddress).balanceOf(_user);
-      vars.compoundedBorrowBalance = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(_user);
-      vars.compoundedBorrowBalance = vars.compoundedBorrowBalance.add(
-        IERC20(currentReserve.variableDebtTokenAddress).balanceOf(_user)
-      );
-
-      if (vars.compoundedLiquidityBalance == 0 && vars.compoundedBorrowBalance == 0) {
-        continue;
-      }
-
       (vars.ltv, vars.liquidationThreshold, , vars.decimals) = currentReserve
         .configuration
         .getParams();
 
       vars.tokenUnit = 10**vars.decimals;
-      vars.reserveUnitPrice = IPriceOracleGetter(_oracle).getAssetPrice(_reserves[vars.i]);
+      vars.reserveUnitPrice = IPriceOracleGetter(_oracle).getAssetPrice(vars.currentReserveAddress);
+
+      if (vars.ltv != 0 && _userConfig.isUsingAsCollateral(vars.i)) {
+        vars.compoundedLiquidityBalance = IERC20(currentReserve.aTokenAddress).balanceOf(_user);
 
-      //liquidity and collateral balance
-      if (vars.compoundedLiquidityBalance > 0) {
         uint256 liquidityBalanceETH = vars
           .reserveUnitPrice
           .mul(vars.compoundedLiquidityBalance)
           .div(vars.tokenUnit);
 
-        if (vars.ltv != 0 && userConfig.isLending(vars.i)) {
-          vars.totalCollateralBalanceETH = vars.totalCollateralBalanceETH.add(liquidityBalanceETH);
+        vars.totalCollateralBalanceETH = vars.totalCollateralBalanceETH.add(liquidityBalanceETH);
 
-          vars.avgLtv = vars.avgLtv.add(liquidityBalanceETH.mul(vars.ltv));
-          vars.avgLiquidationThreshold = vars.avgLiquidationThreshold.add(
-            liquidityBalanceETH.mul(vars.liquidationThreshold)
-          );
-        }
+        vars.avgLtv = vars.avgLtv.add(liquidityBalanceETH.mul(vars.ltv));
+        vars.avgLiquidationThreshold = vars.avgLiquidationThreshold.add(
+          liquidityBalanceETH.mul(vars.liquidationThreshold)
+        );
       }
 
-      if (vars.compoundedBorrowBalance > 0) {
+      if (_userConfig.isBorrowing(vars.i)) {
+        vars.compoundedBorrowBalance = IERC20(currentReserve.stableDebtTokenAddress).balanceOf(
+          _user
+        );
+        vars.compoundedBorrowBalance = vars.compoundedBorrowBalance.add(
+          IERC20(currentReserve.variableDebtTokenAddress).balanceOf(_user)
+        );
+
         vars.totalBorrowBalanceETH = vars.totalBorrowBalanceETH.add(
           vars.reserveUnitPrice.mul(vars.compoundedBorrowBalance).div(vars.tokenUnit)
         );
diff --git a/contracts/libraries/UserConfiguration.sol b/contracts/libraries/UserConfiguration.sol
index 2314318f..bad438ad 100644
--- a/contracts/libraries/UserConfiguration.sol
+++ b/contracts/libraries/UserConfiguration.sol
@@ -16,34 +16,57 @@ import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
  * @notice Implements the bitmap logic to handle the user configuration
  */
 library UserConfiguration {
-
   uint256 internal constant BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555;
 
   struct Map {
     uint256 data;
   }
 
-  function setBorrowing(UserConfiguration.Map storage _self, uint256 _reserveIndex, bool _borrowing) internal {
-    _self.data |= uint256(_borrowing ? 1 : 0) << _reserveIndex*2;
+  function setBorrowing(
+    UserConfiguration.Map storage _self,
+    uint256 _reserveIndex,
+    bool _borrowing
+  ) internal {
+    _self.data = (_self.data & ~(1 << _reserveIndex*2)) | uint256(_borrowing ? 1 : 0) << (_reserveIndex * 2);
   }
 
-  function setLending(UserConfiguration.Map storage _self, uint256 _reserveIndex, bool _lending) internal {
-    _self.data |= uint256(_lending ? 1 : 0) << _reserveIndex*2+1;
+  function setUsingAsCollateral(
+    UserConfiguration.Map storage _self,
+    uint256 _reserveIndex,
+    bool _usingAsCollateral
+  ) internal {
+    _self.data = (_self.data & ~(1 << _reserveIndex*2+1)) | uint256(_usingAsCollateral ? 1 : 0) << (_reserveIndex * 2 + 1);
   }
 
-  function isLendingOrBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
-     return _self.data >> _reserveIndex*2 & 2 != 0;
+  function isUsingAsCollateralOrBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
+    internal
+    view
+    returns (bool)
+  {
+    return (_self.data >> (_reserveIndex * 2)) & 3 != 0;
   }
 
-  function isBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
-    return _self.data >> _reserveIndex*2 & 1 != 0 ;
+  function isBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
+    internal
+    view
+    returns (bool)
+  {
+    return (_self.data >> (_reserveIndex * 2)) & 1 != 0;
   }
 
-  function isLending(UserConfiguration.Map memory _self, uint256 _reserveIndex) internal view returns(bool) {
-    return _self.data >> (_reserveIndex*2+1) & 1 != 0;
+  function isUsingAsCollateral(UserConfiguration.Map memory _self, uint256 _reserveIndex)
+    internal
+    view
+    returns (bool)
+  {
+    return (_self.data >> (_reserveIndex * 2 + 1)) & 1 != 0;
   }
 
-  function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns(bool) {
+  function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns (bool) {
     return _self.data & BORROWING_MASK != 0;
   }
+
+  function isEmpty(UserConfiguration.Map memory _self) internal view returns(bool) {
+    return _self.data == 0;
+  }
 }
diff --git a/contracts/libraries/ValidationLogic.sol b/contracts/libraries/ValidationLogic.sol
index 7f3e79d7..dc2a2aed 100644
--- a/contracts/libraries/ValidationLogic.sol
+++ b/contracts/libraries/ValidationLogic.sol
@@ -92,34 +92,31 @@ library ValidationLogic {
   /**
    * @dev validates a borrow.
    * @param _reserve the reserve state from which the user is borrowing
-   * @param _user the state of the user for the specific reserve
    * @param _reserveAddress the address of the reserve
    * @param _amount the amount to be borrowed
    * @param _amountInETH the amount to be borrowed, in ETH
    * @param _interestRateMode the interest rate mode at which the user is borrowing
    * @param _maxStableLoanPercent the max amount of the liquidity that can be borrowed at stable rate, in percentage
    * @param _reservesData the state of all the reserves
+   * @param _userConfig the state of the user for the specific reserve
    * @param _reserves the addresses of all the active reserves
    * @param _oracle the price oracle
    */
 
   function validateBorrow(
     ReserveLogic.ReserveData storage _reserve,
-    UserLogic.UserReserveData storage _user,
     address _reserveAddress,
     uint256 _amount,
     uint256 _amountInETH,
     uint256 _interestRateMode,
     uint256 _maxStableLoanPercent,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    UserConfiguration.Map calldata userConfig,
+    UserConfiguration.Map storage _userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view {
     ValidateBorrowLocalVars memory vars;
 
-    //internalValidateReserveStateAndAmount(_reserve, _amount);
-
     (
       vars.isActive,
       vars.isFreezed,
@@ -155,7 +152,7 @@ library ValidationLogic {
     ) = GenericLogic.calculateUserAccountData(
       msg.sender,
       _reservesData,
-      userConfig,
+      _userConfig,
       _reserves,
       _oracle
     );
@@ -189,7 +186,7 @@ library ValidationLogic {
       require(vars.stableRateBorrowingEnabled, '11');
 
       require(
-        !_user.useAsCollateral ||
+        !_userConfig.isUsingAsCollateral(_reserve.index) ||
           _reserve.configuration.getLtv() == 0 ||
           _amount > IERC20(_reserve.aTokenAddress).balanceOf(msg.sender),
         '12'
@@ -253,14 +250,14 @@ library ValidationLogic {
   /**
    * @dev validates a swap of borrow rate mode.
    * @param _reserve the reserve state on which the user is swapping the rate
-   * @param _user the user state for the reserve on which user is swapping the rate
+   * @param _userConfig the user reserves configuration
    * @param _stableBorrowBalance the stable borrow balance of the user
    * @param _variableBorrowBalance the stable borrow balance of the user
    * @param _currentRateMode the rate mode of the borrow
    */
   function validateSwapRateMode(
     ReserveLogic.ReserveData storage _reserve,
-    UserLogic.UserReserveData storage _user,
+    UserConfiguration.Map storage _userConfig,
     uint256 _stableBorrowBalance,
     uint256 _variableBorrowBalance,
     ReserveLogic.InterestRateMode _currentRateMode
@@ -290,7 +287,7 @@ library ValidationLogic {
       require(stableRateEnabled, '11');
 
       require(
-        !_user.useAsCollateral ||
+        !_userConfig.isUsingAsCollateral(_reserve.index) ||
           _reserve.configuration.getLtv() == 0 ||
           _stableBorrowBalance.add(_variableBorrowBalance) >
           IERC20(_reserve.aTokenAddress).balanceOf(msg.sender),
@@ -311,7 +308,7 @@ library ValidationLogic {
     ReserveLogic.ReserveData storage _reserve,
     address _reserveAddress,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    UserConfiguration.Map calldata userConfig,
+    UserConfiguration.Map storage userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view {
diff --git a/deployed-contracts.json b/deployed-contracts.json
index a7314419..099f63e8 100644
--- a/deployed-contracts.json
+++ b/deployed-contracts.json
@@ -5,7 +5,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xb0f645D86C1436502f45229292b117e45e1a2bC4",
+      "address": "0x7AC94fC704557bFBB6E743c797C45b3384b95bB6",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -15,7 +15,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x12c2160C86B21FFF1c708F77d5263CF192f2B661",
+      "address": "0x9e3C887092123acf59a1819e78a95B37e46BC886",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -25,7 +25,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x94Bc72DCbdc296991dc61555e996C447cAD60369",
+      "address": "0xe9ECaCA2FAe7ecCB11242B393E545F293E33096f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -34,7 +34,7 @@
       "address": "0x852e3718A320aD93Ad8692E8D663d247e4c1b400"
     },
     "localhost": {
-      "address": "0xcD1440EB52c2dD054a04a7E5E37412532D5173d4"
+      "address": "0xFC16126DBD017331464103385809E4113A61Fe3A"
     }
   },
   "LendingPoolParametersProvider": {
@@ -52,7 +52,7 @@
       "address": "0xA10958a24032283FbE2D23cedf264d6eC9411CBA"
     },
     "localhost": {
-      "address": "0x300e90Cf6EC17Fc047f63180122c33bB5e106586"
+      "address": "0xC6627778273999AeF86ab786d3f6088e9C60F535"
     }
   },
   "LendingPoolDataProvider": {
@@ -65,7 +65,7 @@
       "address": "0x2C4603396dE2F08642354A3A102760827FfFe113"
     },
     "localhost": {
-      "address": "0xCD980f1801Fac5999168c590879779Fb1539b484"
+      "address": "0x6Ad44DDbF6564F0abc078340e11100d44406dD12"
     }
   },
   "PriceOracle": {
@@ -74,7 +74,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x0f611985C3dd0C3B6655b4216A2CB5988C5635f9",
+      "address": "0x372AED51F78c3CaB8b632986b689888caf25Ffa5",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -84,7 +84,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x049F2C09e1d8C2ba59BE6A7Ff069B3632171a4dc",
+      "address": "0xea0ddFACb2c3392b8DCD3B827534496b585aAcc7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -94,7 +94,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x8330f3ab4680A70C76Fa55D886155f39c6800aE4",
+      "address": "0xD859214080050ddC8745c2A6dF41439Bb851D5Bc",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -104,7 +104,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x1b12f84d85e5EFdF07F992ACe35E832F630Ed4b7",
+      "address": "0x4a8527a3657a358B956571EEf857Fe5A8567A378",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -114,7 +114,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x689Bda5742bAD2249D3D96eAF7095B86F14FD397",
+      "address": "0x52EF9F7d7dc2EFF6D691080204Adae9002b9AE67",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -149,7 +149,7 @@
       "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB"
     },
     "localhost": {
-      "address": "0xd0F297f35CD4357d2015F28Ac04CD2818f1df96c"
+      "address": "0xf2923EBa2C4AF250D93e8201Bc20a0096B3A8f89"
     }
   },
   "InitializableAdminUpgradeabilityProxy": {
@@ -158,7 +158,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xd0F297f35CD4357d2015F28Ac04CD2818f1df96c",
+      "address": "0xf2923EBa2C4AF250D93e8201Bc20a0096B3A8f89",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -167,7 +167,7 @@
       "address": "0x24E420B42971372F060a93129846761F354Bc50B"
     },
     "localhost": {
-      "address": "0x151c4FeF6A0421EF1f1e573003a075C363321036"
+      "address": "0x9D72c382e918491A463157Ea3e7633FE0F26F83d"
     }
   },
   "WalletBalanceProvider": {
@@ -176,7 +176,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xf1d54dd9a27843B16F4e4b63f8f06A9E83074bA1",
+      "address": "0xF1BbafE2063F81038079cCdC2E8e5100693B109b",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -186,7 +186,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xf839CeF3895cb50756430290080b503b3B4e852f",
+      "address": "0x07FcFF7B7953ff64969B3c4C8E7c386fC7Efaa55",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -196,7 +196,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x5d7A000000200Fd161d3C35026E5e7e976dD3BAA",
+      "address": "0x921d5f671e5892e43a292Fa1A5BCA3B4F6E62aE9",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -206,7 +206,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xc93e68A8478fAc486BA9190FFE95138be2Bf8Ce7",
+      "address": "0x30d4f0D334822B2887C280A9540959e1dBdD340c",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -216,7 +216,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xc6f1Fc4ab562c141cc836335F0Bb50e429c907c1",
+      "address": "0x62b9F2345e060F6B81bA677Eb1cCC39Ec47d162f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -226,7 +226,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x17e1cB8daCeee46Afc60934D94f5860341ddDdf6",
+      "address": "0x18287eAe938cf3C2024A460C4759E9E081729FB2",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -236,7 +236,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xb85CCdA348896399b6538C58A33c772097e4079f",
+      "address": "0x6C12CB1315d28904AE67aaf4d21F1247e0Caf1E7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -246,7 +246,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xe922A043Bb653355d788Fc872b3BA7c55dE20275",
+      "address": "0xf400aDA5C432462a380ae49ee9A84FE3F21B188d",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -256,7 +256,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x1144E5f1687e711dA0Ece078e8C2dbEa96d013f9",
+      "address": "0x1e3b37AA176ec7d5ae1A36e093A9f849742563F4",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -266,7 +266,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x816b8DFbC98bBA158dA7791DEacBA4EA63B1DF8f",
+      "address": "0xfDdff7952ab54f34FBE3E421b4DB1E8B0cf673Df",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -276,7 +276,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xde7a19b06E13642Fa63029BcE99A3dC64Ae50fa2",
+      "address": "0x378a425415BC1099820005E93448D877A5e02793",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -286,7 +286,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x95FcA33A67122BD7B3c53533102A07F0185Aa153",
+      "address": "0x2361fAEcc05E4e50D85c22E253bafD6B62f91F7A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -296,7 +296,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x1F16D1e96161578D78581874Bc7d39fDbCBCdf7A",
+      "address": "0x1Bf05105664fA2eA4af77E88e637189d76e6283f",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -306,7 +306,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x2f0712dCe236E6e9f5C3d5226dA2D7De7b6D3bf5",
+      "address": "0x529D91657646F22e348c1B9870d0C0D88ED1151A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -316,7 +316,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xdd499FEeED70d925F905fa882E0946002505fb8a",
+      "address": "0x21a26892Ad0ee4b429BB768BaAF4A7fB623d91C7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -326,7 +326,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x62B2aD4feA8DBe859f522e3cD6C1a958Da7ba370",
+      "address": "0x269615E7bA0C64666F8d7586dE868aD55EDD8577",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -336,7 +336,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x352BD2c9A3a019aC10F7fc81dB119D4a325117DE",
+      "address": "0xc9b9B169eA13aB77079F62c5D2f038f50746A4cD",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -346,7 +346,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x5Cccb7f34cB05938c29442815Cc331AA6492B723",
+      "address": "0x2102f3e30ab514e35561C9499f49c3079957f407",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -356,7 +356,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x7457b9406832EEa09864dcaAB82Ae3c134f9A975",
+      "address": "0x87985DF0bf4c392F4114554fcCfC9Ef713463965",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -366,7 +366,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xdB97f0f4a431B70Ec854b270d56e1ECa25f3113b",
+      "address": "0xf20d0172C4F801762a1Fed1F969fF143BAf6740A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -376,7 +376,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x8A8dC28F6C1874f573FCBd921f1fb24301caB913",
+      "address": "0x9707728C9D0C48a83fDA8eEaF39b104EDcFC4f4A",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -386,7 +386,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x8bAE0F999E4A82191F7536E8a5e2De0412588d86",
+      "address": "0x078522E6413f005DA503EA2c72e161C54D27a5ec",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -396,7 +396,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xa61F8cfACa566F8F4303cE283e9535934A8CDdD5",
+      "address": "0xFF8862c67087C7474e44693a017411E1783A6b50",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -406,7 +406,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0xb0f645D86C1436502f45229292b117e45e1a2bC4",
+      "address": "0x7AC94fC704557bFBB6E743c797C45b3384b95bB6",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -415,7 +415,7 @@
       "address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d"
     },
     "localhost": {
-      "address": "0x580FE93f9caA2D590012f23a0F0893D558ceBBcc"
+      "address": "0x49CC1e6749f45e3BaB945B96c0d6723a606BDcDa"
     }
   },
   "StableDebtToken": {
@@ -424,7 +424,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x9407cCBA4F79a7330244b2Bc20089A32259E789c",
+      "address": "0x34dB38AC79A5e23F6Ff6711098979Ca3159b80d7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   },
@@ -434,7 +434,7 @@
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
-      "address": "0x43C61876f933Bc11491764A750C6167bC05d8E7A",
+      "address": "0x7BCb706a6C9cA7F9e51199d3d87A6A92b9cc05b4",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     }
   }
diff --git a/helpers/types.ts b/helpers/types.ts
index 427b25b6..e3616e29 100644
--- a/helpers/types.ts
+++ b/helpers/types.ts
@@ -62,7 +62,7 @@ export enum ProtocolErrors {
   HF_IS_NOT_BELLOW_THRESHOLD = 'Health factor is not below the threshold',
   INVALID_HF = 'Invalid health factor',
   USER_DID_NOT_BORROW_SPECIFIED = 'User did not borrow the specified currency',
-  INVALID_COLLATERAL_TO_LIQUIDATE = 'Invalid collateral to liquidate',
+  THE_COLLATERAL_CHOSEN_CANNOT_BE_LIQUIDATED = 'The collateral chosen cannot be liquidated',
 }
 
 export type tEthereumAddress = string;
diff --git a/test/liquidation-atoken.spec.ts b/test/liquidation-atoken.spec.ts
index 8ea7f260..2a15e9a9 100644
--- a/test/liquidation-atoken.spec.ts
+++ b/test/liquidation-atoken.spec.ts
@@ -17,7 +17,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
     HF_IS_NOT_BELLOW_THRESHOLD,
     INVALID_HF,
     USER_DID_NOT_BORROW_SPECIFIED,
-    INVALID_COLLATERAL_TO_LIQUIDATE,
+    THE_COLLATERAL_CHOSEN_CANNOT_BE_LIQUIDATED,
   } = ProtocolErrors;
 
   it('LIQUIDATION - Deposits ETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => {
@@ -111,7 +111,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
 
     await expect(
       pool.liquidationCall(dai.address, dai.address, borrower.address, oneEther.toString(), true)
-    ).revertedWith(INVALID_COLLATERAL_TO_LIQUIDATE);
+    ).revertedWith(THE_COLLATERAL_CHOSEN_CANNOT_BE_LIQUIDATED);
   });
 
   it('LIQUIDATION - Liquidates the borrow', async () => {
diff --git a/test/liquidation-underlying.spec.ts b/test/liquidation-underlying.spec.ts
index 5a62d680..83227438 100644
--- a/test/liquidation-underlying.spec.ts
+++ b/test/liquidation-underlying.spec.ts
@@ -47,7 +47,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
     HF_IS_NOT_BELLOW_THRESHOLD,
     INVALID_HF,
     USER_DID_NOT_BORROW_SPECIFIED,
-    INVALID_COLLATERAL_TO_LIQUIDATE,
+    THE_COLLATERAL_CHOSEN_CANNOT_BE_LIQUIDATED,
   } = ProtocolErrors;
 
   it('LIQUIDATION - Deposits ETH, borrows DAI', async () => {
diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts
index 21150450..9722f5a5 100644
--- a/test/scenario.spec.ts
+++ b/test/scenario.spec.ts
@@ -12,7 +12,7 @@ BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN});
 
 const scenarioFolder = './test/helpers/scenarios/';
 
-const selectedScenarios: string[] = ['borrow-repay-variable.json'];
+const selectedScenarios: string[] = ['deposit.json','redeem.json','borrow-repay-stable.json', 'borrow-repay-variable.json'];
 
 fs.readdirSync(scenarioFolder).forEach((file) => {
   if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return;

From f9115b703027d5330fe9a44b80eea014a3ebeb9f Mon Sep 17 00:00:00 2001
From: emilio <emilio@ethlend.io>
Date: Thu, 6 Aug 2020 09:52:15 +0200
Subject: [PATCH 3/5] refactored UserLogic

---
 buidler.config.ts                             |  2 +-
 contracts/lendingpool/LendingPool.sol         | 11 ++-
 .../LendingPoolLiquidationManager.sol         |  5 +-
 contracts/libraries/GenericLogic.sol          |  2 -
 contracts/libraries/Helpers.sol               | 49 +++++++++++
 contracts/libraries/ReserveConfiguration.sol  |  1 -
 contracts/libraries/ReserveLogic.sol          |  3 -
 contracts/libraries/UserConfiguration.sol     |  3 -
 contracts/libraries/UserLogic.sol             | 84 -------------------
 contracts/libraries/ValidationLogic.sol       |  2 -
 deployed-contracts.json                       | 24 +++---
 helpers/contracts-helpers.ts                  |  4 -
 test/scenario.spec.ts                         |  2 +-
 13 files changed, 70 insertions(+), 122 deletions(-)
 create mode 100644 contracts/libraries/Helpers.sol
 delete mode 100644 contracts/libraries/UserLogic.sol

diff --git a/buidler.config.ts b/buidler.config.ts
index afd7b493..2e60fb18 100644
--- a/buidler.config.ts
+++ b/buidler.config.ts
@@ -10,7 +10,7 @@ usePlugin('buidler-typechain');
 usePlugin('solidity-coverage');
 usePlugin('@nomiclabs/buidler-waffle');
 usePlugin('@nomiclabs/buidler-etherscan');
-usePlugin('buidler-gas-reporter');
+//usePlugin('buidler-gas-reporter');
 
 ['misc'].forEach((folder) => {
   const tasksPath = path.join(__dirname, 'tasks', folder);
diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol
index 5f55fcd1..53012be8 100644
--- a/contracts/lendingpool/LendingPool.sol
+++ b/contracts/lendingpool/LendingPool.sol
@@ -12,7 +12,7 @@ import '../configuration/LendingPoolAddressesProvider.sol';
 import '../tokenization/AToken.sol';
 import '../libraries/WadRayMath.sol';
 import '../libraries/ReserveLogic.sol';
-import '../libraries/UserLogic.sol';
+import '../libraries/Helpers.sol';
 import '../libraries/GenericLogic.sol';
 import '../libraries/ValidationLogic.sol';
 import '../libraries/ReserveConfiguration.sol';
@@ -38,7 +38,6 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   using WadRayMath for uint256;
   using Address for address payable;
   using ReserveLogic for ReserveLogic.ReserveData;
-  using UserLogic for UserLogic.UserReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
   using UserConfiguration for UserConfiguration.Map;
 
@@ -419,7 +418,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     RepayLocalVars memory vars;
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
 
-    (vars.stableDebt, vars.variableDebt) = UserLogic.getUserCurrentDebt(_onBehalfOf, reserve);
+    (vars.stableDebt, vars.variableDebt) = Helpers.getUserCurrentDebt(_onBehalfOf, reserve);
 
     vars.totalDebt = vars.stableDebt.add(vars.variableDebt);
 
@@ -495,7 +494,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
   function swapBorrowRateMode(address _reserve, uint256 _rateMode) external nonReentrant {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
 
-    (uint256 stableDebt, uint256 variableDebt) = UserLogic.getUserCurrentDebt(msg.sender, reserve);
+    (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
 
     ReserveLogic.InterestRateMode rateMode = ReserveLogic.InterestRateMode(_rateMode);
 
@@ -867,8 +866,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
     ReserveLogic.ReserveData storage reserve = reserves[_reserve];
 
     currentATokenBalance = IERC20(reserve.aTokenAddress).balanceOf(_user);
-    (currentStableDebt, currentVariableDebt) = UserLogic.getUserCurrentDebt(_user, reserve);
-    (principalStableDebt, principalVariableDebt) = UserLogic.getUserPrincipalDebt(_user, reserve);
+    (currentStableDebt, currentVariableDebt) = Helpers.getUserCurrentDebt(_user, reserve);
+    (principalStableDebt, principalVariableDebt) = Helpers.getUserPrincipalDebt(_user, reserve);
     liquidityRate = reserve.currentLiquidityRate;
     stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(_user);
     stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated(
diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol
index 1744fc1c..2e22ddba 100644
--- a/contracts/lendingpool/LendingPoolLiquidationManager.sol
+++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol
@@ -16,7 +16,7 @@ import '../tokenization/interfaces/IVariableDebtToken.sol';
 import '../libraries/WadRayMath.sol';
 import '../interfaces/IPriceOracleGetter.sol';
 import '../libraries/GenericLogic.sol';
-import '../libraries/UserLogic.sol';
+import '../libraries/Helpers.sol';
 import '../libraries/ReserveLogic.sol';
 import '../libraries/UniversalERC20.sol';
 import '../libraries/ReserveConfiguration.sol';
@@ -35,7 +35,6 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
   using PercentageMath for uint256;
   using Address for address;
   using ReserveLogic for ReserveLogic.ReserveData;
-  using UserLogic for UserLogic.UserReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
   using UserConfiguration for UserConfiguration.Map;
 
@@ -161,7 +160,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
     }
 
     //if the user hasn't borrowed the specific currency defined by _reserve, it cannot be liquidated
-    (vars.userStableDebt, vars.userVariableDebt) = UserLogic.getUserCurrentDebt(
+    (vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(
       _user,
       principalReserve
     );
diff --git a/contracts/libraries/GenericLogic.sol b/contracts/libraries/GenericLogic.sol
index a7c80a02..db18ddda 100644
--- a/contracts/libraries/GenericLogic.sol
+++ b/contracts/libraries/GenericLogic.sol
@@ -8,7 +8,6 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 import {ReserveLogic} from './ReserveLogic.sol';
 import {ReserveConfiguration} from './ReserveConfiguration.sol';
 import {UserConfiguration} from './UserConfiguration.sol';
-import {UserLogic} from './UserLogic.sol';
 import {WadRayMath} from './WadRayMath.sol';
 import {PercentageMath} from './PercentageMath.sol';
 import '../interfaces/IPriceOracleGetter.sol';
@@ -22,7 +21,6 @@ import '@nomiclabs/buidler/console.sol';
  */
 library GenericLogic {
   using ReserveLogic for ReserveLogic.ReserveData;
-  using UserLogic for UserLogic.UserReserveData;
   using SafeMath for uint256;
   using WadRayMath for uint256;
   using PercentageMath for uint256;
diff --git a/contracts/libraries/Helpers.sol b/contracts/libraries/Helpers.sol
new file mode 100644
index 00000000..de71cfa1
--- /dev/null
+++ b/contracts/libraries/Helpers.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: agpl-3.0
+pragma solidity ^0.6.8;
+
+import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
+import '../tokenization/base/DebtTokenBase.sol';
+import './ReserveLogic.sol';
+
+
+/**
+ * @title Helpers library
+ * @author Aave
+ * @notice Implements calculation helpers.
+ */
+library Helpers {
+
+  /**
+   * @dev fetches the user current stable and variable debt balances
+   * @param _user the user
+   * @param _reserve the reserve object
+   * @return the stable and variable debt balance
+   **/
+  function getUserCurrentDebt(address _user, ReserveLogic.ReserveData storage _reserve)
+    internal
+    view
+    returns (uint256, uint256)
+  {
+    return (
+      IERC20(_reserve.stableDebtTokenAddress).balanceOf(_user),
+      IERC20(_reserve.variableDebtTokenAddress).balanceOf(_user)
+    );
+  }
+
+  /**
+   * @dev fetches the user principal stable and variable debt balances
+   * @param _user the user
+   * @param _reserve the reserve object
+   * @return the stable and variable debt balance
+   **/
+  function getUserPrincipalDebt(address _user, ReserveLogic.ReserveData storage _reserve)
+    internal
+    view
+    returns (uint256, uint256)
+  {
+    return (
+      DebtTokenBase(_reserve.stableDebtTokenAddress).principalBalanceOf(_user),
+      DebtTokenBase(_reserve.variableDebtTokenAddress).principalBalanceOf(_user)
+    );
+  }
+}
diff --git a/contracts/libraries/ReserveConfiguration.sol b/contracts/libraries/ReserveConfiguration.sol
index 1855a859..92811fa9 100644
--- a/contracts/libraries/ReserveConfiguration.sol
+++ b/contracts/libraries/ReserveConfiguration.sol
@@ -5,7 +5,6 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 
 import {ReserveLogic} from './ReserveLogic.sol';
-import {UserLogic} from './UserLogic.sol';
 import {WadRayMath} from './WadRayMath.sol';
 
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
diff --git a/contracts/libraries/ReserveLogic.sol b/contracts/libraries/ReserveLogic.sol
index 082b9151..3645c1d9 100644
--- a/contracts/libraries/ReserveLogic.sol
+++ b/contracts/libraries/ReserveLogic.sol
@@ -3,8 +3,6 @@ pragma solidity ^0.6.8;
 
 import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
-
-import {UserLogic} from './UserLogic.sol';
 import {MathUtils} from './MathUtils.sol';
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
 import {UniversalERC20} from './UniversalERC20.sol';
@@ -28,7 +26,6 @@ library ReserveLogic {
   using WadRayMath for uint256;
   using UniversalERC20 for IERC20;
   using Address for address;
-  using UserLogic for UserLogic.UserReserveData;
   using ReserveLogic for ReserveLogic.ReserveData;
   using ReserveConfiguration for ReserveConfiguration.Map;
 
diff --git a/contracts/libraries/UserConfiguration.sol b/contracts/libraries/UserConfiguration.sol
index bad438ad..21df0981 100644
--- a/contracts/libraries/UserConfiguration.sol
+++ b/contracts/libraries/UserConfiguration.sol
@@ -3,10 +3,7 @@ pragma solidity ^0.6.8;
 
 import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
-
-import {UserLogic} from './UserLogic.sol';
 import {WadRayMath} from './WadRayMath.sol';
-
 import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
 import {IFeeProvider} from '../interfaces/IFeeProvider.sol';
 
diff --git a/contracts/libraries/UserLogic.sol b/contracts/libraries/UserLogic.sol
deleted file mode 100644
index 5764bd1c..00000000
--- a/contracts/libraries/UserLogic.sol
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-License-Identifier: agpl-3.0
-pragma solidity ^0.6.8;
-
-import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
-
-import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
-import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
-import '../tokenization/base/DebtTokenBase.sol';
-import './ReserveLogic.sol';
-import './ReserveConfiguration.sol';
-import './UserConfiguration.sol';
-
-
-/**
- * @title UserLogic library
- * @author Aave
- * @notice Implements user specific logic.
- */
-library UserLogic {
-  using SafeMath for uint256;
-  using ReserveConfiguration for ReserveConfiguration.Map;
-
-  struct UserReserveData {
-    //defines if a specific deposit should or not be used as a collateral in borrows
-    UserConfiguration.Map configuration;
-    bool useAsCollateral;
-  }
-
-  /**
-   * @dev checks if a user is allowed to borrow at a stable rate
-   * @param _reserve the reserve address
-   * @param _user the user
-   * @param _amount the amount the the user wants to borrow
-   * @return true if the user is allowed to borrow at a stable rate, false otherwise
-   **/
-
-  function isAllowedToBorrowAtStable(
-    UserReserveData storage _user,
-    ReserveLogic.ReserveData storage _reserve,
-    address _userAddress,
-    uint256 _amount
-  ) external view returns (bool) {
-    if (!_reserve.isStableBorrowRateEnabled) return false;
-
-    return
-      !_user.useAsCollateral ||
-      _reserve.configuration.getLtv() == 0 ||
-      _amount > IERC20(_reserve.aTokenAddress).balanceOf(_userAddress);
-  }
-
-  /**
-   * @dev fetches the user current stable and variable debt balances
-   * @param _user the user
-   * @param _reserve the reserve object
-   * @return the stable and variable debt balance
-   **/
-  function getUserCurrentDebt(address _user, ReserveLogic.ReserveData storage _reserve)
-    internal
-    view
-    returns (uint256, uint256)
-  {
-    return (
-      IERC20(_reserve.stableDebtTokenAddress).balanceOf(_user),
-      IERC20(_reserve.variableDebtTokenAddress).balanceOf(_user)
-    );
-  }
-
-  /**
-   * @dev fetches the user principal stable and variable debt balances
-   * @param _user the user
-   * @param _reserve the reserve object
-   * @return the stable and variable debt balance
-   **/
-  function getUserPrincipalDebt(address _user, ReserveLogic.ReserveData storage _reserve)
-    internal
-    view
-    returns (uint256, uint256)
-  {
-    return (
-      DebtTokenBase(_reserve.stableDebtTokenAddress).principalBalanceOf(_user),
-      DebtTokenBase(_reserve.variableDebtTokenAddress).principalBalanceOf(_user)
-    );
-  }
-}
diff --git a/contracts/libraries/ValidationLogic.sol b/contracts/libraries/ValidationLogic.sol
index dc2a2aed..5710fb77 100644
--- a/contracts/libraries/ValidationLogic.sol
+++ b/contracts/libraries/ValidationLogic.sol
@@ -6,7 +6,6 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 
 import {ReserveLogic} from './ReserveLogic.sol';
-import {UserLogic} from './UserLogic.sol';
 import {GenericLogic} from './GenericLogic.sol';
 import {WadRayMath} from './WadRayMath.sol';
 import {PercentageMath} from './PercentageMath.sol';
@@ -24,7 +23,6 @@ import '@nomiclabs/buidler/console.sol';
  */
 library ValidationLogic {
   using ReserveLogic for ReserveLogic.ReserveData;
-  using UserLogic for UserLogic.UserReserveData;
   using SafeMath for uint256;
   using WadRayMath for uint256;
   using PercentageMath for uint256;
diff --git a/deployed-contracts.json b/deployed-contracts.json
index 099f63e8..4a39626a 100644
--- a/deployed-contracts.json
+++ b/deployed-contracts.json
@@ -70,7 +70,7 @@
   },
   "PriceOracle": {
     "buidlerevm": {
-      "address": "0x85bdE212E66e2BAE510E44Ed59116c1eC712795b",
+      "address": "0xE4C10Db67595aF2Cb4166c8C274e0140f7E43059",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -80,7 +80,7 @@
   },
   "MockAggregator": {
     "buidlerevm": {
-      "address": "0xAF6BA11790D1942625C0c2dA07da19AB63845cfF",
+      "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -90,7 +90,7 @@
   },
   "ChainlinkProxyPriceProvider": {
     "buidlerevm": {
-      "address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
+      "address": "0x7B6C3e5486D9e6959441ab554A889099eed76290",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -100,7 +100,7 @@
   },
   "LendingRateOracle": {
     "buidlerevm": {
-      "address": "0xf91aC1098F3b154671Ce83290114aaE45ac0225f",
+      "address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -110,7 +110,7 @@
   },
   "DefaultReserveInterestRateStrategy": {
     "buidlerevm": {
-      "address": "0x2dD8146Ad2138ac61F93E549f8F917927B47E28a",
+      "address": "0x63b9792E7A95e3aa037255E8cAa0Dfd76f7383e7",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -146,7 +146,7 @@
   },
   "TokenDistributor": {
     "buidlerevm": {
-      "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB"
+      "address": "0x1bb3d8FA7bDa74Af0D64d348a2545E7570863fA8"
     },
     "localhost": {
       "address": "0xf2923EBa2C4AF250D93e8201Bc20a0096B3A8f89"
@@ -154,7 +154,7 @@
   },
   "InitializableAdminUpgradeabilityProxy": {
     "buidlerevm": {
-      "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB",
+      "address": "0x1bb3d8FA7bDa74Af0D64d348a2545E7570863fA8",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -164,7 +164,7 @@
   },
   "MockFlashLoanReceiver": {
     "buidlerevm": {
-      "address": "0x24E420B42971372F060a93129846761F354Bc50B"
+      "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB"
     },
     "localhost": {
       "address": "0x9D72c382e918491A463157Ea3e7633FE0F26F83d"
@@ -172,7 +172,7 @@
   },
   "WalletBalanceProvider": {
     "buidlerevm": {
-      "address": "0x285671fF5C8172dE63cF5eA264B2e827aDBC6740",
+      "address": "0x51fa472EB89c046484B037B6125CF843C9d41b44",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -412,7 +412,7 @@
   },
   "AaveProtocolTestHelpers": {
     "buidlerevm": {
-      "address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d"
+      "address": "0x4b2c297ba5be42610994974b9543D56B864CA011"
     },
     "localhost": {
       "address": "0x49CC1e6749f45e3BaB945B96c0d6723a606BDcDa"
@@ -420,7 +420,7 @@
   },
   "StableDebtToken": {
     "buidlerevm": {
-      "address": "0xBdFE372Bb5a0db801A1a17796EC5cfF2F30A714C",
+      "address": "0xc783bfC59158E888dA3E9c7768aaDC7a58ee7809",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
@@ -430,7 +430,7 @@
   },
   "VariableDebtToken": {
     "buidlerevm": {
-      "address": "0xD325d114a728C2114Bd33Ad47152f790f2a29c5c",
+      "address": "0xBdFE372Bb5a0db801A1a17796EC5cfF2F30A714C",
       "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
     },
     "localhost": {
diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts
index 0967e0c2..ac5dfb1b 100644
--- a/helpers/contracts-helpers.ts
+++ b/helpers/contracts-helpers.ts
@@ -118,7 +118,6 @@ const deployLibrary = async (libraryId: eContractid) => {
 };
 
 export const linkLibrariesToArtifact = async (artifact: Artifact) => {
-  const userLogic = await deployLibrary(eContractid.UserLogic);
   const reserveLogic = await deployLibrary(eContractid.ReserveLogic);
 
   const genericLogicArtifact = await readArtifact(
@@ -127,7 +126,6 @@ export const linkLibrariesToArtifact = async (artifact: Artifact) => {
   );
 
   const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, {
-    [eContractid.UserLogic]: userLogic.address,
     [eContractid.ReserveLogic]: reserveLogic.address,
   });
 
@@ -144,7 +142,6 @@ export const linkLibrariesToArtifact = async (artifact: Artifact) => {
   );
 
   const linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, {
-    [eContractid.UserLogic]: userLogic.address,
     [eContractid.ReserveLogic]: reserveLogic.address,
     [eContractid.GenericLogic]: genericLogic.address,
   });
@@ -157,7 +154,6 @@ export const linkLibrariesToArtifact = async (artifact: Artifact) => {
   const validationLogic = await (await validationLogicFactory.deploy()).deployed();
 
   const linkedBytecode = linkBytecode(artifact, {
-    [eContractid.UserLogic]: userLogic.address,
     [eContractid.ReserveLogic]: reserveLogic.address,
     [eContractid.GenericLogic]: genericLogic.address,
     [eContractid.ValidationLogic]: validationLogic.address,
diff --git a/test/scenario.spec.ts b/test/scenario.spec.ts
index 9722f5a5..10db45fb 100644
--- a/test/scenario.spec.ts
+++ b/test/scenario.spec.ts
@@ -12,7 +12,7 @@ BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN});
 
 const scenarioFolder = './test/helpers/scenarios/';
 
-const selectedScenarios: string[] = ['deposit.json','redeem.json','borrow-repay-stable.json', 'borrow-repay-variable.json'];
+const selectedScenarios: string[] = [];
 
 fs.readdirSync(scenarioFolder).forEach((file) => {
   if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return;

From 5c4df95b87c710816ccf4b50829345a030b2c7b4 Mon Sep 17 00:00:00 2001
From: emilio <emilio@ethlend.io>
Date: Thu, 6 Aug 2020 09:57:12 +0200
Subject: [PATCH 4/5] Added comments to UserConfiguration

---
 contracts/libraries/UserConfiguration.sol | 40 +++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/contracts/libraries/UserConfiguration.sol b/contracts/libraries/UserConfiguration.sol
index 21df0981..9f7c1531 100644
--- a/contracts/libraries/UserConfiguration.sol
+++ b/contracts/libraries/UserConfiguration.sol
@@ -19,6 +19,12 @@ library UserConfiguration {
     uint256 data;
   }
 
+  /**
+  * @dev sets if the user is borrowing the reserve identified by _reserveIndex
+  * @param _self the configuration object
+  * @param _reserveIndex the index of the reserve in the bitmap
+  * @param _borrowing true if the user is borrowing the reserve, false otherwise
+  **/
   function setBorrowing(
     UserConfiguration.Map storage _self,
     uint256 _reserveIndex,
@@ -27,6 +33,12 @@ library UserConfiguration {
     _self.data = (_self.data & ~(1 << _reserveIndex*2)) | uint256(_borrowing ? 1 : 0) << (_reserveIndex * 2);
   }
 
+  /**
+  * @dev sets if the user is using as collateral the reserve identified by _reserveIndex
+  * @param _self the configuration object
+  * @param _reserveIndex the index of the reserve in the bitmap
+  * @param _usingAsCollateral true if the user is usin the reserve as collateral, false otherwise
+  **/
   function setUsingAsCollateral(
     UserConfiguration.Map storage _self,
     uint256 _reserveIndex,
@@ -35,6 +47,12 @@ library UserConfiguration {
     _self.data = (_self.data & ~(1 << _reserveIndex*2+1)) | uint256(_usingAsCollateral ? 1 : 0) << (_reserveIndex * 2 + 1);
   }
 
+  /**
+  * @dev used to validate if a user has been using the reserve for borrowing or as collateral
+  * @param _self the configuration object
+  * @param _reserveIndex the index of the reserve in the bitmap
+  * @return true if the user has been using a reserve for borrowing or as collateral, false otherwise
+  **/
   function isUsingAsCollateralOrBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
     internal
     view
@@ -43,6 +61,12 @@ library UserConfiguration {
     return (_self.data >> (_reserveIndex * 2)) & 3 != 0;
   }
 
+  /**
+  * @dev used to validate if a user has been using the reserve for borrowing
+  * @param _self the configuration object
+  * @param _reserveIndex the index of the reserve in the bitmap
+  * @return true if the user has been using a reserve for borrowing, false otherwise
+  **/
   function isBorrowing(UserConfiguration.Map memory _self, uint256 _reserveIndex)
     internal
     view
@@ -51,6 +75,12 @@ library UserConfiguration {
     return (_self.data >> (_reserveIndex * 2)) & 1 != 0;
   }
 
+  /**
+  * @dev used to validate if a user has been using the reserve as collateral
+  * @param _self the configuration object
+  * @param _reserveIndex the index of the reserve in the bitmap
+  * @return true if the user has been using a reserve as collateral, false otherwise
+  **/
   function isUsingAsCollateral(UserConfiguration.Map memory _self, uint256 _reserveIndex)
     internal
     view
@@ -59,10 +89,20 @@ library UserConfiguration {
     return (_self.data >> (_reserveIndex * 2 + 1)) & 1 != 0;
   }
 
+  /**
+  * @dev used to validate if a user has been borrowing from any reserve
+  * @param _self the configuration object
+  * @return true if the user has been borrowing any reserve, false otherwise
+  **/
   function isBorrowingAny(UserConfiguration.Map memory _self) internal view returns (bool) {
     return _self.data & BORROWING_MASK != 0;
   }
 
+  /**
+  * @dev used to validate if a user has not been using any reserve
+  * @param _self the configuration object
+  * @return true if the user has been borrowing any reserve, false otherwise
+  **/
   function isEmpty(UserConfiguration.Map memory _self) internal view returns(bool) {
     return _self.data == 0;
   }

From 1015a7ca137360da57e5bec0f420ac70cc4e76e3 Mon Sep 17 00:00:00 2001
From: emilio <emilio@ethlend.io>
Date: Thu, 6 Aug 2020 19:49:41 +0200
Subject: [PATCH 5/5] Fixes comments

---
 contracts/libraries/GenericLogic.sol    | 6 ++++--
 contracts/libraries/ValidationLogic.sol | 7 +++++--
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/contracts/libraries/GenericLogic.sol b/contracts/libraries/GenericLogic.sol
index db18ddda..a25d7805 100644
--- a/contracts/libraries/GenericLogic.sol
+++ b/contracts/libraries/GenericLogic.sol
@@ -128,7 +128,6 @@ library GenericLogic {
     uint256 avgLtv;
     uint256 avgLiquidationThreshold;
     uint256 reservesLength;
-    UserConfiguration.Map userConfig;
     bool healthFactorBelowThreshold;
     address currentReserveAddress;
     bool usageAsCollateralEnabled;
@@ -141,7 +140,10 @@ library GenericLogic {
    * the average Loan To Value, the average Liquidation Ratio, and the Health factor.
    * @param _user the address of the user
    * @param _reservesData data of all the reserves
-   * @return the total liquidity, total collateral, total borrow balances of the user in ETH.
+   * @param _userConfig the configuration of the user
+   * @param _reserves the list of the available reserves
+   * @param _oracle the price oracle address
+   * @return the total collateral and total borrow balance of the user in ETH, the avg ltv and liquidation threshold and the HF
    * also the average Ltv, liquidation threshold, and the health factor
    **/
   function calculateUserAccountData(
diff --git a/contracts/libraries/ValidationLogic.sol b/contracts/libraries/ValidationLogic.sol
index 5710fb77..acc109e6 100644
--- a/contracts/libraries/ValidationLogic.sol
+++ b/contracts/libraries/ValidationLogic.sol
@@ -301,12 +301,15 @@ library ValidationLogic {
    * @param _reserve the state of the reserve that the user is enabling or disabling as collateral
    * @param _reserveAddress the address of the reserve
    * @param _reservesData the data of all the reserves
+   * @param _userConfig the state of the user for the specific reserve
+   * @param _reserves the addresses of all the active reserves
+   * @param _oracle the price oracle
    */
   function validateSetUseReserveAsCollateral(
     ReserveLogic.ReserveData storage _reserve,
     address _reserveAddress,
     mapping(address => ReserveLogic.ReserveData) storage _reservesData,
-    UserConfiguration.Map storage userConfig,
+    UserConfiguration.Map storage _userConfig,
     address[] calldata _reserves,
     address _oracle
   ) external view {
@@ -320,7 +323,7 @@ library ValidationLogic {
         msg.sender,
         underlyingBalance,
         _reservesData,
-        userConfig,
+        _userConfig,
         _reserves,
         _oracle
       ),