From 611605eebf51a0be5fbd02f8a4fced68f0375072 Mon Sep 17 00:00:00 2001
From: David Racero <canillas.mail@gmail.com>
Date: Wed, 13 Jan 2021 15:11:39 +0100
Subject: [PATCH] Fix mockup base tests. Separate uniswap adapter tests into
 separate files.

---
 .../mocks/swap/MockUniswapV2Router02.sol      |   56 +-
 test/__setup.spec.ts                          |   24 +-
 test/uniswapAdapters.base.spec.ts             |  227 +++
 ... => uniswapAdapters.liquiditySwap.spec.ts} | 1591 +----------------
 test/uniswapAdapters.repay.spec.ts            | 1431 +++++++++++++++
 5 files changed, 1747 insertions(+), 1582 deletions(-)
 create mode 100644 test/uniswapAdapters.base.spec.ts
 rename test/{uniswapAdapters.spec.ts => uniswapAdapters.liquiditySwap.spec.ts} (53%)
 create mode 100644 test/uniswapAdapters.repay.spec.ts

diff --git a/contracts/mocks/swap/MockUniswapV2Router02.sol b/contracts/mocks/swap/MockUniswapV2Router02.sol
index 7f38bf92..b7fd3f80 100644
--- a/contracts/mocks/swap/MockUniswapV2Router02.sol
+++ b/contracts/mocks/swap/MockUniswapV2Router02.sol
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: agpl-3.0
 pragma solidity 0.6.12;
 
-import {IUniswapV2Router02} from "../../interfaces/IUniswapV2Router02.sol";
+import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol';
 import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
 import {MintableERC20} from '../tokens/MintableERC20.sol';
 
@@ -22,7 +22,7 @@ contract MockUniswapV2Router02 is IUniswapV2Router02 {
 
   function swapExactTokensForTokens(
     uint256 amountIn,
-    uint256 /* amountOutMin */,
+    uint256, /* amountOutMin */
     address[] calldata path,
     address to,
     uint256 /* deadline */
@@ -32,50 +32,74 @@ contract MockUniswapV2Router02 is IUniswapV2Router02 {
     MintableERC20(path[1]).mint(_amountToReturn[path[0]]);
     IERC20(path[1]).transfer(to, _amountToReturn[path[0]]);
 
-    amounts = new uint[](path.length);
+    amounts = new uint256[](path.length);
     amounts[0] = amountIn;
     amounts[1] = _amountToReturn[path[0]];
   }
 
   function swapTokensForExactTokens(
-    uint amountOut,
-    uint /* amountInMax */,
+    uint256 amountOut,
+    uint256, /* amountInMax */
     address[] calldata path,
     address to,
-    uint /* deadline */
+    uint256 /* deadline */
   ) external override returns (uint256[] memory amounts) {
     IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap[path[0]]);
 
     MintableERC20(path[1]).mint(amountOut);
     IERC20(path[1]).transfer(to, amountOut);
 
-    amounts = new uint[](path.length);
+    amounts = new uint256[](path.length);
     amounts[0] = _amountToSwap[path[0]];
     amounts[1] = amountOut;
   }
 
-  function setAmountOut(uint amountIn, address reserveIn, address reserveOut, uint amountOut) public {
+  function setAmountOut(
+    uint256 amountIn,
+    address reserveIn,
+    address reserveOut,
+    uint256 amountOut
+  ) public {
     _amountsOut[reserveIn][reserveOut][amountIn] = amountOut;
   }
 
-  function setAmountIn(uint amountOut, address reserveIn, address reserveOut, uint amountIn) public {
+  function setAmountIn(
+    uint256 amountOut,
+    address reserveIn,
+    address reserveOut,
+    uint256 amountIn
+  ) public {
     _amountsIn[reserveIn][reserveOut][amountOut] = amountIn;
   }
 
-  function setDefaultMockValue(uint value) public {
+  function setDefaultMockValue(uint256 value) public {
     defaultMockValue = value;
   }
 
-  function getAmountsOut(uint amountIn, address[] calldata path) external view override returns (uint[] memory) {
-    uint256[] memory amounts = new uint256[](2);
+  function getAmountsOut(uint256 amountIn, address[] calldata path)
+    external
+    view
+    override
+    returns (uint256[] memory)
+  {
+    uint256[] memory amounts = new uint256[](path.length);
     amounts[0] = amountIn;
-    amounts[1] = _amountsOut[path[0]][path[1]][amountIn] > 0 ? _amountsOut[path[0]][path[1]][amountIn] : defaultMockValue;
+    amounts[1] = _amountsOut[path[0]][path[1]][amountIn] > 0
+      ? _amountsOut[path[0]][path[1]][amountIn]
+      : defaultMockValue;
     return amounts;
   }
 
-  function getAmountsIn(uint amountOut, address[] calldata path) external view override returns (uint[] memory) {
-    uint256[] memory amounts = new uint256[](2);
-    amounts[0] = _amountsIn[path[0]][path[1]][amountOut] > 0 ? _amountsIn[path[0]][path[1]][amountOut] : defaultMockValue;
+  function getAmountsIn(uint256 amountOut, address[] calldata path)
+    external
+    view
+    override
+    returns (uint256[] memory)
+  {
+    uint256[] memory amounts = new uint256[](path.length);
+    amounts[0] = _amountsIn[path[0]][path[1]][amountOut] > 0
+      ? _amountsIn[path[0]][path[1]][amountOut]
+      : defaultMockValue;
     amounts[1] = amountOut;
     return amounts;
   }
diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts
index 89f535e4..de3478af 100644
--- a/test/__setup.spec.ts
+++ b/test/__setup.spec.ts
@@ -29,7 +29,12 @@ import {
 import { Signer } from 'ethers';
 import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../helpers/types';
 import { MintableERC20 } from '../types/MintableERC20';
-import { ConfigNames, getReservesConfigByPool, getTreasuryAddress, loadPoolConfig } from '../helpers/configuration';
+import {
+  ConfigNames,
+  getReservesConfigByPool,
+  getTreasuryAddress,
+  loadPoolConfig,
+} from '../helpers/configuration';
 import { initializeMakeSuite } from './helpers/make-suite';
 
 import {
@@ -38,10 +43,7 @@ import {
   setInitialMarketRatesInRatesOracleByHelper,
 } from '../helpers/oracles-helpers';
 import { DRE, waitForTx } from '../helpers/misc-utils';
-import {
-  initReservesByHelper,
-  configureReservesByHelper,
-} from '../helpers/init-helpers';
+import { initReservesByHelper, configureReservesByHelper } from '../helpers/init-helpers';
 import AaveConfig from '../markets/aave';
 import { ZERO_ADDRESS } from '../helpers/constants';
 import {
@@ -216,13 +218,15 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
 
   const treasuryAddress = await getTreasuryAddress(config);
 
-  await initReservesByHelper(reservesParams, allReservesAddresses, admin, treasuryAddress, ZERO_ADDRESS, false);
-  await configureReservesByHelper(
+  await initReservesByHelper(
     reservesParams,
     allReservesAddresses,
-    testHelpers,
-    admin
+    admin,
+    treasuryAddress,
+    ZERO_ADDRESS,
+    false
   );
+  await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin);
 
   const collateralManager = await deployLendingPoolCollateralManager();
   await waitForTx(
@@ -238,6 +242,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
   const UniswapLiquiditySwapAdapter = await deployUniswapLiquiditySwapAdapter([
     addressesProvider.address,
     mockUniswapRouter.address,
+    mockTokens.WETH.address,
   ]);
   await insertContractAddressInDb(
     eContractid.UniswapLiquiditySwapAdapter,
@@ -247,6 +252,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
   const UniswapRepayAdapter = await deployUniswapRepayAdapter([
     addressesProvider.address,
     mockUniswapRouter.address,
+    mockTokens.WETH.address,
   ]);
   await insertContractAddressInDb(eContractid.UniswapRepayAdapter, UniswapRepayAdapter.address);
 
diff --git a/test/uniswapAdapters.base.spec.ts b/test/uniswapAdapters.base.spec.ts
new file mode 100644
index 00000000..80f76725
--- /dev/null
+++ b/test/uniswapAdapters.base.spec.ts
@@ -0,0 +1,227 @@
+import { makeSuite, TestEnv } from './helpers/make-suite';
+import { convertToCurrencyDecimals } from '../helpers/contracts-helpers';
+import { getMockUniswapRouter } from '../helpers/contracts-getters';
+import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02';
+import BigNumber from 'bignumber.js';
+import { evmRevert, evmSnapshot } from '../helpers/misc-utils';
+import { ethers } from 'ethers';
+import { USD_ADDRESS } from '../helpers/constants';
+const { parseEther } = ethers.utils;
+
+const { expect } = require('chai');
+
+makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
+  let mockUniswapRouter: MockUniswapV2Router02;
+  let evmSnapshotId: string;
+
+  before(async () => {
+    mockUniswapRouter = await getMockUniswapRouter();
+  });
+
+  beforeEach(async () => {
+    evmSnapshotId = await evmSnapshot();
+  });
+
+  afterEach(async () => {
+    await evmRevert(evmSnapshotId);
+  });
+
+  describe('BaseUniswapAdapter', () => {
+    describe('getAmountsOut', () => {
+      it('should return the estimated amountOut and prices for the asset swap', async () => {
+        const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv;
+
+        const amountIn = parseEther('1');
+        const flashloanPremium = amountIn.mul(9).div(10000);
+        const amountToSwap = amountIn.sub(flashloanPremium);
+
+        const wethPrice = await oracle.getAssetPrice(weth.address);
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
+
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        const outPerInPrice = amountToSwap
+          .mul(parseEther('1'))
+          .mul(parseEther('1'))
+          .div(expectedDaiAmount.mul(parseEther('1')));
+        const ethUsdValue = amountIn
+          .mul(wethPrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+        const daiUsdValue = expectedDaiAmount
+          .mul(daiPrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        await mockUniswapRouter.setAmountOut(
+          amountToSwap,
+          weth.address,
+          dai.address,
+          expectedDaiAmount
+        );
+
+        const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
+          amountIn,
+          weth.address,
+          dai.address
+        );
+
+        expect(result['0']).to.be.eq(expectedDaiAmount);
+        expect(result['1']).to.be.eq(outPerInPrice);
+        expect(result['2']).to.be.eq(ethUsdValue);
+        expect(result['3']).to.be.eq(daiUsdValue);
+      });
+      it('should work correctly with different decimals', async () => {
+        const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv;
+
+        const amountIn = parseEther('10');
+        const flashloanPremium = amountIn.mul(9).div(10000);
+        const amountToSwap = amountIn.sub(flashloanPremium);
+
+        const aavePrice = await oracle.getAssetPrice(aave.address);
+        const usdcPrice = await oracle.getAssetPrice(usdc.address);
+        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
+
+        const expectedUSDCAmount = await convertToCurrencyDecimals(
+          usdc.address,
+          new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0)
+        );
+
+        const outPerInPrice = amountToSwap
+          .mul(parseEther('1'))
+          .mul('1000000') // usdc 6 decimals
+          .div(expectedUSDCAmount.mul(parseEther('1')));
+
+        const aaveUsdValue = amountIn
+          .mul(aavePrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        const usdcUsdValue = expectedUSDCAmount
+          .mul(usdcPrice)
+          .div('1000000') // usdc 6 decimals
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        await mockUniswapRouter.setAmountOut(
+          amountToSwap,
+          aave.address,
+          usdc.address,
+          expectedUSDCAmount
+        );
+
+        const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
+          amountIn,
+          aave.address,
+          usdc.address
+        );
+
+        expect(result['0']).to.be.eq(expectedUSDCAmount);
+        expect(result['1']).to.be.eq(outPerInPrice);
+        expect(result['2']).to.be.eq(aaveUsdValue);
+        expect(result['3']).to.be.eq(usdcUsdValue);
+      });
+    });
+
+    describe('getAmountsIn', () => {
+      it('should return the estimated required amountIn for the asset swap', async () => {
+        const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv;
+
+        const amountIn = parseEther('1');
+        const flashloanPremium = amountIn.mul(9).div(10000);
+        const amountToSwap = amountIn.add(flashloanPremium);
+
+        const wethPrice = await oracle.getAssetPrice(weth.address);
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
+
+        const amountOut = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountIn.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        const inPerOutPrice = amountOut
+          .mul(parseEther('1'))
+          .mul(parseEther('1'))
+          .div(amountToSwap.mul(parseEther('1')));
+
+        const ethUsdValue = amountToSwap
+          .mul(wethPrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+        const daiUsdValue = amountOut
+          .mul(daiPrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        await mockUniswapRouter.setAmountIn(amountOut, weth.address, dai.address, amountIn);
+
+        const result = await uniswapLiquiditySwapAdapter.getAmountsIn(
+          amountOut,
+          weth.address,
+          dai.address
+        );
+
+        expect(result['0']).to.be.eq(amountToSwap);
+        expect(result['1']).to.be.eq(inPerOutPrice);
+        expect(result['2']).to.be.eq(ethUsdValue);
+        expect(result['3']).to.be.eq(daiUsdValue);
+      });
+      it('should work correctly with different decimals', async () => {
+        const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv;
+
+        const amountIn = parseEther('10');
+        const flashloanPremium = amountIn.mul(9).div(10000);
+        const amountToSwap = amountIn.add(flashloanPremium);
+
+        const aavePrice = await oracle.getAssetPrice(aave.address);
+        const usdcPrice = await oracle.getAssetPrice(usdc.address);
+        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
+
+        const amountOut = await convertToCurrencyDecimals(
+          usdc.address,
+          new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0)
+        );
+
+        const inPerOutPrice = amountOut
+          .mul(parseEther('1'))
+          .mul(parseEther('1'))
+          .div(amountToSwap.mul('1000000')); // usdc 6 decimals
+
+        const aaveUsdValue = amountToSwap
+          .mul(aavePrice)
+          .div(parseEther('1'))
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        const usdcUsdValue = amountOut
+          .mul(usdcPrice)
+          .div('1000000') // usdc 6 decimals
+          .mul(usdPrice)
+          .div(parseEther('1'));
+
+        await mockUniswapRouter.setAmountIn(amountOut, aave.address, usdc.address, amountIn);
+
+        const result = await uniswapLiquiditySwapAdapter.getAmountsIn(
+          amountOut,
+          aave.address,
+          usdc.address
+        );
+
+        expect(result['0']).to.be.eq(amountToSwap);
+        expect(result['1']).to.be.eq(inPerOutPrice);
+        expect(result['2']).to.be.eq(aaveUsdValue);
+        expect(result['3']).to.be.eq(usdcUsdValue);
+      });
+    });
+  });
+});
diff --git a/test/uniswapAdapters.spec.ts b/test/uniswapAdapters.liquiditySwap.spec.ts
similarity index 53%
rename from test/uniswapAdapters.spec.ts
rename to test/uniswapAdapters.liquiditySwap.spec.ts
index e5dcb7f5..65882c0e 100644
--- a/test/uniswapAdapters.spec.ts
+++ b/test/uniswapAdapters.liquiditySwap.spec.ts
@@ -5,13 +5,9 @@ import {
   buildPermitParams,
   getSignatureFromTypedData,
   buildLiquiditySwapParams,
-  buildRepayAdapterParams,
 } from '../helpers/contracts-helpers';
 import { getMockUniswapRouter } from '../helpers/contracts-getters';
-import {
-  deployUniswapLiquiditySwapAdapter,
-  deployUniswapRepayAdapter,
-} from '../helpers/contracts-deployments';
+import { deployUniswapLiquiditySwapAdapter } from '../helpers/contracts-deployments';
 import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02';
 import { Zero } from '@ethersproject/constants';
 import BigNumber from 'bignumber.js';
@@ -19,9 +15,8 @@ import { DRE, evmRevert, evmSnapshot } from '../helpers/misc-utils';
 import { ethers } from 'ethers';
 import { eContractid } from '../helpers/types';
 import { AToken } from '../types/AToken';
-import { StableDebtToken } from '../types/StableDebtToken';
 import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants';
-import { MAX_UINT_AMOUNT, USD_ADDRESS } from '../helpers/constants';
+import { MAX_UINT_AMOUNT } from '../helpers/constants';
 const { parseEther } = ethers.utils;
 
 const { expect } = require('chai');
@@ -42,218 +37,25 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
     await evmRevert(evmSnapshotId);
   });
 
-  describe('BaseUniswapAdapter', () => {
-    describe('getAmountsOut', () => {
-      it('should return the estimated amountOut and prices for the asset swap', async () => {
-        const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv;
-
-        const amountIn = parseEther('1');
-        const flashloanPremium = amountIn.mul(9).div(10000);
-        const amountToSwap = amountIn.sub(flashloanPremium);
-
-        const wethPrice = await oracle.getAssetPrice(weth.address);
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
-
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountToSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        const outPerInPrice = amountToSwap
-          .mul(parseEther('1'))
-          .mul(parseEther('1'))
-          .div(expectedDaiAmount.mul(parseEther('1')));
-        const ethUsdValue = amountIn
-          .mul(wethPrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-        const daiUsdValue = expectedDaiAmount
-          .mul(daiPrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        await mockUniswapRouter.setAmountOut(
-          amountToSwap,
-          weth.address,
-          dai.address,
-          expectedDaiAmount
-        );
-
-        const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
-          amountIn,
-          weth.address,
-          dai.address
-        );
-
-        expect(result['0']).to.be.eq(expectedDaiAmount);
-        expect(result['1']).to.be.eq(outPerInPrice);
-        expect(result['2']).to.be.eq(ethUsdValue);
-        expect(result['3']).to.be.eq(daiUsdValue);
-      });
-      it('should work correctly with different decimals', async () => {
-        const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv;
-
-        const amountIn = parseEther('10');
-        const flashloanPremium = amountIn.mul(9).div(10000);
-        const amountToSwap = amountIn.sub(flashloanPremium);
-
-        const aavePrice = await oracle.getAssetPrice(aave.address);
-        const usdcPrice = await oracle.getAssetPrice(usdc.address);
-        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
-
-        const expectedUSDCAmount = await convertToCurrencyDecimals(
-          usdc.address,
-          new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0)
-        );
-
-        const outPerInPrice = amountToSwap
-          .mul(parseEther('1'))
-          .mul('1000000') // usdc 6 decimals
-          .div(expectedUSDCAmount.mul(parseEther('1')));
-
-        const aaveUsdValue = amountIn
-          .mul(aavePrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        const usdcUsdValue = expectedUSDCAmount
-          .mul(usdcPrice)
-          .div('1000000') // usdc 6 decimals
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        await mockUniswapRouter.setAmountOut(
-          amountToSwap,
-          aave.address,
-          usdc.address,
-          expectedUSDCAmount
-        );
-
-        const result = await uniswapLiquiditySwapAdapter.getAmountsOut(
-          amountIn,
-          aave.address,
-          usdc.address
-        );
-
-        expect(result['0']).to.be.eq(expectedUSDCAmount);
-        expect(result['1']).to.be.eq(outPerInPrice);
-        expect(result['2']).to.be.eq(aaveUsdValue);
-        expect(result['3']).to.be.eq(usdcUsdValue);
-      });
-    });
-
-    describe('getAmountsIn', () => {
-      it('should return the estimated required amountIn for the asset swap', async () => {
-        const { weth, dai, uniswapLiquiditySwapAdapter, oracle } = testEnv;
-
-        const amountIn = parseEther('1');
-        const flashloanPremium = amountIn.mul(9).div(10000);
-        const amountToSwap = amountIn.add(flashloanPremium);
-
-        const wethPrice = await oracle.getAssetPrice(weth.address);
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
-
-        const amountOut = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountIn.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        const inPerOutPrice = amountOut
-          .mul(parseEther('1'))
-          .mul(parseEther('1'))
-          .div(amountToSwap.mul(parseEther('1')));
-
-        const ethUsdValue = amountToSwap
-          .mul(wethPrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-        const daiUsdValue = amountOut
-          .mul(daiPrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        await mockUniswapRouter.setAmountIn(amountOut, weth.address, dai.address, amountIn);
-
-        const result = await uniswapLiquiditySwapAdapter.getAmountsIn(
-          amountOut,
-          weth.address,
-          dai.address
-        );
-
-        expect(result['0']).to.be.eq(amountToSwap);
-        expect(result['1']).to.be.eq(inPerOutPrice);
-        expect(result['2']).to.be.eq(ethUsdValue);
-        expect(result['3']).to.be.eq(daiUsdValue);
-      });
-      it('should work correctly with different decimals', async () => {
-        const { aave, usdc, uniswapLiquiditySwapAdapter, oracle } = testEnv;
-
-        const amountIn = parseEther('10');
-        const flashloanPremium = amountIn.mul(9).div(10000);
-        const amountToSwap = amountIn.add(flashloanPremium);
-
-        const aavePrice = await oracle.getAssetPrice(aave.address);
-        const usdcPrice = await oracle.getAssetPrice(usdc.address);
-        const usdPrice = await oracle.getAssetPrice(USD_ADDRESS);
-
-        const amountOut = await convertToCurrencyDecimals(
-          usdc.address,
-          new BigNumber(amountToSwap.toString()).div(usdcPrice.toString()).toFixed(0)
-        );
-
-        const inPerOutPrice = amountOut
-          .mul(parseEther('1'))
-          .mul(parseEther('1'))
-          .div(amountToSwap.mul('1000000')); // usdc 6 decimals
-
-        const aaveUsdValue = amountToSwap
-          .mul(aavePrice)
-          .div(parseEther('1'))
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        const usdcUsdValue = amountOut
-          .mul(usdcPrice)
-          .div('1000000') // usdc 6 decimals
-          .mul(usdPrice)
-          .div(parseEther('1'));
-
-        await mockUniswapRouter.setAmountIn(amountOut, aave.address, usdc.address, amountIn);
-
-        const result = await uniswapLiquiditySwapAdapter.getAmountsIn(
-          amountOut,
-          aave.address,
-          usdc.address
-        );
-
-        expect(result['0']).to.be.eq(amountToSwap);
-        expect(result['1']).to.be.eq(inPerOutPrice);
-        expect(result['2']).to.be.eq(aaveUsdValue);
-        expect(result['3']).to.be.eq(usdcUsdValue);
-      });
-    });
-  });
-
   describe('UniswapLiquiditySwapAdapter', () => {
     describe('constructor', () => {
       it('should deploy with correct parameters', async () => {
-        const { addressesProvider } = testEnv;
+        const { addressesProvider, weth } = testEnv;
         await deployUniswapLiquiditySwapAdapter([
           addressesProvider.address,
           mockUniswapRouter.address,
+          weth.address,
         ]);
       });
 
       it('should revert if not valid addresses provider', async () => {
+        const { weth } = testEnv;
         expect(
-          deployUniswapLiquiditySwapAdapter([mockUniswapRouter.address, mockUniswapRouter.address])
+          deployUniswapLiquiditySwapAdapter([
+            mockUniswapRouter.address,
+            mockUniswapRouter.address,
+            weth.address,
+          ])
         ).to.be.reverted;
       });
     });
@@ -1367,7 +1169,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         )
           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
@@ -1445,7 +1248,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r,
                 s,
               },
-            ]
+            ],
+            [false]
           )
         )
           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
@@ -1493,7 +1297,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         ).to.be.revertedWith('INCONSISTENT_PARAMS');
 
@@ -1511,7 +1316,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         ).to.be.revertedWith('INCONSISTENT_PARAMS');
 
@@ -1529,7 +1335,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         ).to.be.revertedWith('INCONSISTENT_PARAMS');
 
@@ -1541,7 +1348,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
               [dai.address],
               [amountWETHtoSwap],
               [expectedDaiAmount],
-              []
+              [],
+              [false]
             )
         ).to.be.revertedWith('INCONSISTENT_PARAMS');
 
@@ -1559,7 +1367,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         ).to.be.revertedWith('INCONSISTENT_PARAMS');
       });
@@ -1597,7 +1406,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         ).to.be.revertedWith('minAmountOut exceed max slippage');
       });
@@ -1679,7 +1489,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
               r: '0x0000000000000000000000000000000000000000000000000000000000000000',
               s: '0x0000000000000000000000000000000000000000000000000000000000000000',
             },
-          ]
+          ],
+          [false]
         );
 
         const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address);
@@ -1818,7 +1629,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
               r: aUsdcr,
               s: aUsdcs,
             },
-          ]
+          ],
+          [false]
         );
 
         const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address);
@@ -1884,7 +1696,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r: '0x0000000000000000000000000000000000000000000000000000000000000000',
                 s: '0x0000000000000000000000000000000000000000000000000000000000000000',
               },
-            ]
+            ],
+            [false]
           )
         )
           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
@@ -1969,7 +1782,8 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
                 r,
                 s,
               },
-            ]
+            ],
+            [false]
           )
         )
           .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
@@ -1994,1341 +1808,4 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
       });
     });
   });
-
-  describe('UniswapRepayAdapter', () => {
-    beforeEach(async () => {
-      const { users, weth, dai, usdc, aave, pool, deployer } = testEnv;
-      const userAddress = users[0].address;
-
-      // Provide liquidity
-      await dai.mint(parseEther('20000'));
-      await dai.approve(pool.address, parseEther('20000'));
-      await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
-
-      const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '2000000');
-      await usdc.mint(usdcLiquidity);
-      await usdc.approve(pool.address, usdcLiquidity);
-      await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0);
-
-      await weth.mint(parseEther('100'));
-      await weth.approve(pool.address, parseEther('100'));
-      await pool.deposit(weth.address, parseEther('100'), deployer.address, 0);
-
-      await aave.mint(parseEther('1000000'));
-      await aave.approve(pool.address, parseEther('1000000'));
-      await pool.deposit(aave.address, parseEther('1000000'), deployer.address, 0);
-
-      // Make a deposit for user
-      await weth.mint(parseEther('1000'));
-      await weth.approve(pool.address, parseEther('1000'));
-      await pool.deposit(weth.address, parseEther('1000'), userAddress, 0);
-
-      await aave.mint(parseEther('1000000'));
-      await aave.approve(pool.address, parseEther('1000000'));
-      await pool.deposit(aave.address, parseEther('1000000'), userAddress, 0);
-
-      await usdc.mint(usdcLiquidity);
-      await usdc.approve(pool.address, usdcLiquidity);
-      await pool.deposit(usdc.address, usdcLiquidity, userAddress, 0);
-    });
-
-    describe('constructor', () => {
-      it('should deploy with correct parameters', async () => {
-        const { addressesProvider } = testEnv;
-        await deployUniswapRepayAdapter([addressesProvider.address, mockUniswapRouter.address]);
-      });
-
-      it('should revert if not valid addresses provider', async () => {
-        expect(deployUniswapRepayAdapter([mockUniswapRouter.address, mockUniswapRouter.address])).to
-          .be.reverted;
-      });
-    });
-
-    describe('executeOperation', () => {
-      it('should correctly swap tokens and repay debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
-
-        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.0009)
-          .toFixed(0);
-
-        await mockUniswapRouter.setAmountIn(
-          flashLoanDebt,
-          weth.address,
-          dai.address,
-          liquidityToSwap
-        );
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        )
-          .to.emit(uniswapRepayAdapter, 'Swapped')
-          .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly swap tokens and repay debt with permit', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
-        const deadline = MAX_UINT_AMOUNT;
-        const nonce = (await aWETH._nonces(userAddress)).toNumber();
-        const msgParams = buildPermitParams(
-          chainId,
-          aWETH.address,
-          '1',
-          await aWETH.name(),
-          userAddress,
-          uniswapRepayAdapter.address,
-          nonce,
-          deadline,
-          liquidityToSwap.toString()
-        );
-
-        const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
-        if (!ownerPrivateKey) {
-          throw new Error('INVALID_OWNER_PK');
-        }
-
-        const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
-
-        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.0009)
-          .toFixed(0);
-
-        await mockUniswapRouter.setAmountIn(
-          flashLoanDebt,
-          weth.address,
-          dai.address,
-          liquidityToSwap
-        );
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          liquidityToSwap,
-          deadline,
-          v,
-          r,
-          s
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        )
-          .to.emit(uniswapRepayAdapter, 'Swapped')
-          .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should revert if caller not lending pool', async () => {
-        const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          uniswapRepayAdapter
-            .connect(user)
-            .executeOperation(
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params
-            )
-        ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL');
-      });
-
-      it('should revert if there is not debt to repay with the specified rate mode', async () => {
-        const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        await weth.connect(user).mint(amountWETHtoSwap);
-        await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap);
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        ).to.be.reverted;
-      });
-
-      it('should revert if there is not debt to repay', async () => {
-        const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        await weth.connect(user).mint(amountWETHtoSwap);
-        await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap);
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        ).to.be.reverted;
-      });
-
-      it('should revert when max amount allowed to swap is bigger than max slippage', async () => {
-        const { users, pool, weth, oracle, dai, aWETH, uniswapRepayAdapter } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap);
-
-        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.0009)
-          .toFixed(0);
-
-        await mockUniswapRouter.setAmountIn(
-          flashLoanDebt,
-          weth.address,
-          dai.address,
-          bigMaxAmountToSwap
-        );
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          bigMaxAmountToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        ).to.be.revertedWith('maxAmountToSwap exceed max slippage');
-      });
-
-      it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-        const userWethBalanceBefore = await weth.balanceOf(userAddress);
-
-        const actualWEthSwapped = new BigNumber(liquidityToSwap.toString())
-          .multipliedBy(0.995)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
-
-        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.0009)
-          .toFixed(0);
-
-        await mockUniswapRouter.setAmountIn(
-          flashLoanDebt,
-          weth.address,
-          dai.address,
-          actualWEthSwapped
-        );
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await expect(
-          pool
-            .connect(user)
-            .flashLoan(
-              uniswapRepayAdapter.address,
-              [dai.address],
-              [expectedDaiAmount.toString()],
-              [0],
-              userAddress,
-              params,
-              0
-            )
-        )
-          .to.emit(uniswapRepayAdapter, 'Swapped')
-          .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt);
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-        const userWethBalance = await weth.balanceOf(userAddress);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped));
-        expect(userWethBalance).to.be.eq(userWethBalanceBefore);
-      });
-
-      it('should correctly swap tokens and repay the whole stable debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
-        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await pool
-          .connect(user)
-          .flashLoan(
-            uniswapRepayAdapter.address,
-            [dai.address],
-            [amountToRepay.toString()],
-            [0],
-            userAddress,
-            params,
-            0
-          );
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.eq(Zero);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly swap tokens and repay the whole variable debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
-
-        const daiStableVariableTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).variableDebtTokenAddress;
-
-        const daiVariableDebtContract = await getContract<StableDebtToken>(
-          eContractid.VariableDebtToken,
-          daiStableVariableTokenAddress
-        );
-
-        const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf(
-          userAddress
-        );
-
-        // Add a % to repay on top of the debt
-        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
-        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
-
-        const params = buildRepayAdapterParams(
-          weth.address,
-          liquidityToSwap,
-          2,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await pool
-          .connect(user)
-          .flashLoan(
-            uniswapRepayAdapter.address,
-            [dai.address],
-            [amountToRepay.toString()],
-            [0],
-            userAddress,
-            params,
-            0
-          );
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiVariableDebtAmount).to.be.eq(Zero);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly repay debt using the same asset as collateral', async () => {
-        const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        // Add deposit for user
-        await dai.mint(parseEther('20'));
-        await dai.approve(pool.address, parseEther('20'));
-        await pool.deposit(dai.address, parseEther('20'), userAddress, 0);
-
-        const amountCollateralToSwap = parseEther('10');
-        const debtAmount = parseEther('10');
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString())
-          .multipliedBy(1.0009)
-          .toFixed(0);
-
-        await aDai.connect(user).approve(uniswapRepayAdapter.address, flashLoanDebt);
-        const userADaiBalanceBefore = await aDai.balanceOf(userAddress);
-        const userDaiBalanceBefore = await dai.balanceOf(userAddress);
-
-        const params = buildRepayAdapterParams(
-          dai.address,
-          amountCollateralToSwap,
-          1,
-          0,
-          0,
-          0,
-          '0x0000000000000000000000000000000000000000000000000000000000000000',
-          '0x0000000000000000000000000000000000000000000000000000000000000000'
-        );
-
-        await pool
-          .connect(user)
-          .flashLoan(
-            uniswapRepayAdapter.address,
-            [dai.address],
-            [amountCollateralToSwap.toString()],
-            [0],
-            userAddress,
-            params,
-            0
-          );
-
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userADaiBalance = await aDai.balanceOf(userAddress);
-        const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiBalance = await dai.balanceOf(userAddress);
-
-        expect(adapterADaiBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(debtAmount);
-        expect(userADaiBalance).to.be.lt(userADaiBalanceBefore);
-        expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(flashLoanDebt));
-        expect(userDaiBalance).to.be.eq(userDaiBalanceBefore);
-      });
-    });
-
-    describe('swapAndRepay', () => {
-      it('should correctly swap tokens and repay debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
-
-        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(weth.address, dai.address, liquidityToSwap, expectedDaiAmount, 1, {
-            amount: 0,
-            deadline: 0,
-            v: 0,
-            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-          });
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly swap tokens and repay debt with permit', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
-
-        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
-
-        const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
-        const deadline = MAX_UINT_AMOUNT;
-        const nonce = (await aWETH._nonces(userAddress)).toNumber();
-        const msgParams = buildPermitParams(
-          chainId,
-          aWETH.address,
-          '1',
-          await aWETH.name(),
-          userAddress,
-          uniswapRepayAdapter.address,
-          nonce,
-          deadline,
-          liquidityToSwap.toString()
-        );
-
-        const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
-        if (!ownerPrivateKey) {
-          throw new Error('INVALID_OWNER_PK');
-        }
-
-        const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(weth.address, dai.address, liquidityToSwap, expectedDaiAmount, 1, {
-            amount: liquidityToSwap,
-            deadline,
-            v,
-            r,
-            s,
-          });
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should revert if there is not debt to repay', async () => {
-        const { users, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
-        const user = users[0].signer;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-
-        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
-
-        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
-
-        await expect(
-          uniswapRepayAdapter
-            .connect(user)
-            .swapAndRepay(weth.address, dai.address, liquidityToSwap, expectedDaiAmount, 1, {
-              amount: 0,
-              deadline: 0,
-              v: 0,
-              r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-              s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            })
-        ).to.be.reverted;
-      });
-
-      it('should revert when max amount allowed to swap is bigger than max slippage', async () => {
-        const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap);
-
-        await mockUniswapRouter.setDefaultMockValue(bigMaxAmountToSwap);
-
-        await expect(
-          uniswapRepayAdapter
-            .connect(user)
-            .swapAndRepay(weth.address, dai.address, bigMaxAmountToSwap, expectedDaiAmount, 1, {
-              amount: 0,
-              deadline: 0,
-              v: 0,
-              r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-              s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            })
-        ).to.be.revertedWith('maxAmountToSwap exceed max slippage');
-      });
-
-      it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        const liquidityToSwap = amountWETHtoSwap;
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-        const userWethBalanceBefore = await weth.balanceOf(userAddress);
-
-        const actualWEthSwapped = new BigNumber(liquidityToSwap.toString())
-          .multipliedBy(0.995)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
-
-        await mockUniswapRouter.setDefaultMockValue(actualWEthSwapped);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(weth.address, dai.address, liquidityToSwap, expectedDaiAmount, 1, {
-            amount: 0,
-            deadline: 0,
-            v: 0,
-            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-          });
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-        const userWethBalance = await weth.balanceOf(userAddress);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped));
-        expect(userWethBalance).to.be.eq(userWethBalanceBefore);
-      });
-
-      it('should correctly swap tokens and repay the whole stable debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
-        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(weth.address, dai.address, liquidityToSwap, amountToRepay, 1, {
-            amount: 0,
-            deadline: 0,
-            v: 0,
-            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-          });
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiStableDebtAmount).to.be.eq(Zero);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly swap tokens and repay the whole variable debt', async () => {
-        const {
-          users,
-          pool,
-          weth,
-          aWETH,
-          oracle,
-          dai,
-          uniswapRepayAdapter,
-          helpersContract,
-        } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
-
-        const daiPrice = await oracle.getAssetPrice(dai.address);
-        const expectedDaiAmount = await convertToCurrencyDecimals(
-          dai.address,
-          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
-        );
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
-
-        const daiStableVariableTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).variableDebtTokenAddress;
-
-        const daiVariableDebtContract = await getContract<StableDebtToken>(
-          eContractid.VariableDebtToken,
-          daiStableVariableTokenAddress
-        );
-
-        const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf(
-          userAddress
-        );
-
-        // Add a % to repay on top of the debt
-        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
-        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
-
-        // Add a % to repay on top of the debt
-        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
-          .multipliedBy(1.1)
-          .toFixed(0);
-
-        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
-        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(weth.address, dai.address, liquidityToSwap, amountToRepay, 2, {
-            amount: 0,
-            deadline: 0,
-            v: 0,
-            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-          });
-
-        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress);
-        const userAEthBalance = await aWETH.balanceOf(userAddress);
-        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
-
-        expect(adapterAEthBalance).to.be.eq(Zero);
-        expect(adapterWethBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount);
-        expect(userDaiVariableDebtAmount).to.be.eq(Zero);
-        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
-        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
-      });
-
-      it('should correctly repay debt using the same asset as collateral', async () => {
-        const { users, pool, dai, uniswapRepayAdapter, helpersContract, aDai } = testEnv;
-        const user = users[0].signer;
-        const userAddress = users[0].address;
-
-        // Add deposit for user
-        await dai.mint(parseEther('20'));
-        await dai.approve(pool.address, parseEther('20'));
-        await pool.deposit(dai.address, parseEther('20'), userAddress, 0);
-
-        const amountCollateralToSwap = parseEther('10');
-
-        const debtAmount = parseEther('10');
-
-        // Open user Debt
-        await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress);
-
-        const daiStableDebtTokenAddress = (
-          await helpersContract.getReserveTokensAddresses(dai.address)
-        ).stableDebtTokenAddress;
-
-        const daiStableDebtContract = await getContract<StableDebtToken>(
-          eContractid.StableDebtToken,
-          daiStableDebtTokenAddress
-        );
-
-        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
-
-        await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap);
-        const userADaiBalanceBefore = await aDai.balanceOf(userAddress);
-        const userDaiBalanceBefore = await dai.balanceOf(userAddress);
-
-        await uniswapRepayAdapter
-          .connect(user)
-          .swapAndRepay(
-            dai.address,
-            dai.address,
-            amountCollateralToSwap,
-            amountCollateralToSwap,
-            1,
-            {
-              amount: 0,
-              deadline: 0,
-              v: 0,
-              r: '0x0000000000000000000000000000000000000000000000000000000000000000',
-              s: '0x0000000000000000000000000000000000000000000000000000000000000000',
-            }
-          );
-
-        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
-        const userADaiBalance = await aDai.balanceOf(userAddress);
-        const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address);
-        const userDaiBalance = await dai.balanceOf(userAddress);
-
-        expect(adapterADaiBalance).to.be.eq(Zero);
-        expect(adapterDaiBalance).to.be.eq(Zero);
-        expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount);
-        expect(userDaiStableDebtAmount).to.be.lt(debtAmount);
-        expect(userADaiBalance).to.be.lt(userADaiBalanceBefore);
-        expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(amountCollateralToSwap));
-        expect(userDaiBalance).to.be.eq(userDaiBalanceBefore);
-      });
-    });
-  });
 });
diff --git a/test/uniswapAdapters.repay.spec.ts b/test/uniswapAdapters.repay.spec.ts
new file mode 100644
index 00000000..10b12a04
--- /dev/null
+++ b/test/uniswapAdapters.repay.spec.ts
@@ -0,0 +1,1431 @@
+import { makeSuite, TestEnv } from './helpers/make-suite';
+import {
+  convertToCurrencyDecimals,
+  getContract,
+  buildPermitParams,
+  getSignatureFromTypedData,
+  buildLiquiditySwapParams,
+  buildRepayAdapterParams,
+} from '../helpers/contracts-helpers';
+import { getMockUniswapRouter } from '../helpers/contracts-getters';
+import {
+  deployUniswapLiquiditySwapAdapter,
+  deployUniswapRepayAdapter,
+} from '../helpers/contracts-deployments';
+import { MockUniswapV2Router02 } from '../types/MockUniswapV2Router02';
+import { Zero } from '@ethersproject/constants';
+import BigNumber from 'bignumber.js';
+import { DRE, evmRevert, evmSnapshot } from '../helpers/misc-utils';
+import { ethers } from 'ethers';
+import { eContractid } from '../helpers/types';
+import { StableDebtToken } from '../types/StableDebtToken';
+import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants';
+import { MAX_UINT_AMOUNT } from '../helpers/constants';
+const { parseEther } = ethers.utils;
+
+const { expect } = require('chai');
+
+makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
+  let mockUniswapRouter: MockUniswapV2Router02;
+  let evmSnapshotId: string;
+
+  before(async () => {
+    mockUniswapRouter = await getMockUniswapRouter();
+  });
+
+  beforeEach(async () => {
+    evmSnapshotId = await evmSnapshot();
+  });
+
+  afterEach(async () => {
+    await evmRevert(evmSnapshotId);
+  });
+
+  describe('UniswapRepayAdapter', () => {
+    beforeEach(async () => {
+      const { users, weth, dai, usdc, aave, pool, deployer } = testEnv;
+      const userAddress = users[0].address;
+
+      // Provide liquidity
+      await dai.mint(parseEther('20000'));
+      await dai.approve(pool.address, parseEther('20000'));
+      await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
+
+      const usdcLiquidity = await convertToCurrencyDecimals(usdc.address, '2000000');
+      await usdc.mint(usdcLiquidity);
+      await usdc.approve(pool.address, usdcLiquidity);
+      await pool.deposit(usdc.address, usdcLiquidity, deployer.address, 0);
+
+      await weth.mint(parseEther('100'));
+      await weth.approve(pool.address, parseEther('100'));
+      await pool.deposit(weth.address, parseEther('100'), deployer.address, 0);
+
+      await aave.mint(parseEther('1000000'));
+      await aave.approve(pool.address, parseEther('1000000'));
+      await pool.deposit(aave.address, parseEther('1000000'), deployer.address, 0);
+
+      // Make a deposit for user
+      await weth.mint(parseEther('1000'));
+      await weth.approve(pool.address, parseEther('1000'));
+      await pool.deposit(weth.address, parseEther('1000'), userAddress, 0);
+
+      await aave.mint(parseEther('1000000'));
+      await aave.approve(pool.address, parseEther('1000000'));
+      await pool.deposit(aave.address, parseEther('1000000'), userAddress, 0);
+
+      await usdc.mint(usdcLiquidity);
+      await usdc.approve(pool.address, usdcLiquidity);
+      await pool.deposit(usdc.address, usdcLiquidity, userAddress, 0);
+    });
+
+    describe('constructor', () => {
+      it('should deploy with correct parameters', async () => {
+        const { addressesProvider, weth } = testEnv;
+        await deployUniswapRepayAdapter([
+          addressesProvider.address,
+          mockUniswapRouter.address,
+          weth.address,
+        ]);
+      });
+
+      it('should revert if not valid addresses provider', async () => {
+        const { weth } = testEnv;
+        expect(
+          deployUniswapRepayAdapter([
+            mockUniswapRouter.address,
+            mockUniswapRouter.address,
+            weth.address,
+          ])
+        ).to.be.reverted;
+      });
+    });
+
+    describe('executeOperation', () => {
+      it('should correctly swap tokens and repay debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
+
+        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.0009)
+          .toFixed(0);
+
+        await mockUniswapRouter.setAmountIn(
+          flashLoanDebt,
+          weth.address,
+          dai.address,
+          liquidityToSwap
+        );
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly swap tokens and repay debt with permit', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
+        const deadline = MAX_UINT_AMOUNT;
+        const nonce = (await aWETH._nonces(userAddress)).toNumber();
+        const msgParams = buildPermitParams(
+          chainId,
+          aWETH.address,
+          '1',
+          await aWETH.name(),
+          userAddress,
+          uniswapRepayAdapter.address,
+          nonce,
+          deadline,
+          liquidityToSwap.toString()
+        );
+
+        const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
+        if (!ownerPrivateKey) {
+          throw new Error('INVALID_OWNER_PK');
+        }
+
+        const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
+
+        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.0009)
+          .toFixed(0);
+
+        await mockUniswapRouter.setAmountIn(
+          flashLoanDebt,
+          weth.address,
+          dai.address,
+          liquidityToSwap
+        );
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          liquidityToSwap,
+          deadline,
+          v,
+          r,
+          s
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, liquidityToSwap.toString(), flashLoanDebt);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should revert if caller not lending pool', async () => {
+        const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          uniswapRepayAdapter
+            .connect(user)
+            .executeOperation(
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params
+            )
+        ).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL');
+      });
+
+      it('should revert if there is not debt to repay with the specified rate mode', async () => {
+        const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        await weth.connect(user).mint(amountWETHtoSwap);
+        await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap);
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        ).to.be.reverted;
+      });
+
+      it('should revert if there is not debt to repay', async () => {
+        const { users, pool, weth, oracle, dai, uniswapRepayAdapter, aWETH } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        await weth.connect(user).mint(amountWETHtoSwap);
+        await weth.connect(user).transfer(uniswapRepayAdapter.address, amountWETHtoSwap);
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, liquidityToSwap);
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        ).to.be.reverted;
+      });
+
+      it('should revert when max amount allowed to swap is bigger than max slippage', async () => {
+        const { users, pool, weth, oracle, dai, aWETH, uniswapRepayAdapter } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap);
+
+        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.0009)
+          .toFixed(0);
+
+        await mockUniswapRouter.setAmountIn(
+          flashLoanDebt,
+          weth.address,
+          dai.address,
+          bigMaxAmountToSwap
+        );
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          bigMaxAmountToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        ).to.be.revertedWith('maxAmountToSwap exceed max slippage');
+      });
+
+      it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+        const userWethBalanceBefore = await weth.balanceOf(userAddress);
+
+        const actualWEthSwapped = new BigNumber(liquidityToSwap.toString())
+          .multipliedBy(0.995)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
+
+        const flashLoanDebt = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.0009)
+          .toFixed(0);
+
+        await mockUniswapRouter.setAmountIn(
+          flashLoanDebt,
+          weth.address,
+          dai.address,
+          actualWEthSwapped
+        );
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              [dai.address],
+              [expectedDaiAmount.toString()],
+              [0],
+              userAddress,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), flashLoanDebt);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+        const userWethBalance = await weth.balanceOf(userAddress);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped));
+        expect(userWethBalance).to.be.eq(userWethBalanceBefore);
+      });
+
+      it('should correctly swap tokens and repay the whole stable debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
+        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await pool
+          .connect(user)
+          .flashLoan(
+            uniswapRepayAdapter.address,
+            [dai.address],
+            [amountToRepay.toString()],
+            [0],
+            userAddress,
+            params,
+            0
+          );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.eq(Zero);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly swap tokens and repay the whole variable debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
+
+        const daiStableVariableTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).variableDebtTokenAddress;
+
+        const daiVariableDebtContract = await getContract<StableDebtToken>(
+          eContractid.VariableDebtToken,
+          daiStableVariableTokenAddress
+        );
+
+        const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf(
+          userAddress
+        );
+
+        // Add a % to repay on top of the debt
+        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
+        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
+
+        const params = buildRepayAdapterParams(
+          weth.address,
+          liquidityToSwap,
+          2,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await pool
+          .connect(user)
+          .flashLoan(
+            uniswapRepayAdapter.address,
+            [dai.address],
+            [amountToRepay.toString()],
+            [0],
+            userAddress,
+            params,
+            0
+          );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiVariableDebtAmount).to.be.eq(Zero);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly repay debt using the same asset as collateral', async () => {
+        const { users, pool, aDai, dai, uniswapRepayAdapter, helpersContract } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        // Add deposit for user
+        await dai.mint(parseEther('20'));
+        await dai.approve(pool.address, parseEther('20'));
+        await pool.deposit(dai.address, parseEther('20'), userAddress, 0);
+
+        const amountCollateralToSwap = parseEther('10');
+        const debtAmount = parseEther('10');
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const flashLoanDebt = new BigNumber(amountCollateralToSwap.toString())
+          .multipliedBy(1.0009)
+          .toFixed(0);
+
+        await aDai.connect(user).approve(uniswapRepayAdapter.address, flashLoanDebt);
+        const userADaiBalanceBefore = await aDai.balanceOf(userAddress);
+        const userDaiBalanceBefore = await dai.balanceOf(userAddress);
+
+        const params = buildRepayAdapterParams(
+          dai.address,
+          amountCollateralToSwap,
+          1,
+          0,
+          0,
+          0,
+          '0x0000000000000000000000000000000000000000000000000000000000000000',
+          '0x0000000000000000000000000000000000000000000000000000000000000000'
+        );
+
+        await pool
+          .connect(user)
+          .flashLoan(
+            uniswapRepayAdapter.address,
+            [dai.address],
+            [amountCollateralToSwap.toString()],
+            [0],
+            userAddress,
+            params,
+            0
+          );
+
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userADaiBalance = await aDai.balanceOf(userAddress);
+        const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiBalance = await dai.balanceOf(userAddress);
+
+        expect(adapterADaiBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(debtAmount);
+        expect(userADaiBalance).to.be.lt(userADaiBalanceBefore);
+        expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(flashLoanDebt));
+        expect(userDaiBalance).to.be.eq(userDaiBalanceBefore);
+      });
+    });
+
+    describe('swapAndRepay', () => {
+      it('should correctly swap tokens and repay debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
+
+        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          weth.address,
+          dai.address,
+          liquidityToSwap,
+          expectedDaiAmount,
+          1,
+          {
+            amount: 0,
+            deadline: 0,
+            v: 0,
+            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          },
+          false
+        );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly swap tokens and repay debt with permit', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
+
+        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
+
+        const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
+        const deadline = MAX_UINT_AMOUNT;
+        const nonce = (await aWETH._nonces(userAddress)).toNumber();
+        const msgParams = buildPermitParams(
+          chainId,
+          aWETH.address,
+          '1',
+          await aWETH.name(),
+          userAddress,
+          uniswapRepayAdapter.address,
+          nonce,
+          deadline,
+          liquidityToSwap.toString()
+        );
+
+        const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
+        if (!ownerPrivateKey) {
+          throw new Error('INVALID_OWNER_PK');
+        }
+
+        const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          weth.address,
+          dai.address,
+          liquidityToSwap,
+          expectedDaiAmount,
+          1,
+          {
+            amount: liquidityToSwap,
+            deadline,
+            v,
+            r,
+            s,
+          },
+          false
+        );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should revert if there is not debt to repay', async () => {
+        const { users, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
+        const user = users[0].signer;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        await mockUniswapRouter.setAmountToSwap(weth.address, liquidityToSwap);
+
+        await mockUniswapRouter.setDefaultMockValue(liquidityToSwap);
+
+        await expect(
+          uniswapRepayAdapter.connect(user).swapAndRepay(
+            weth.address,
+            dai.address,
+            liquidityToSwap,
+            expectedDaiAmount,
+            1,
+            {
+              amount: 0,
+              deadline: 0,
+              v: 0,
+              r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+              s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            },
+            false
+          )
+        ).to.be.reverted;
+      });
+
+      it('should revert when max amount allowed to swap is bigger than max slippage', async () => {
+        const { users, pool, weth, aWETH, oracle, dai, uniswapRepayAdapter } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, bigMaxAmountToSwap);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, bigMaxAmountToSwap);
+
+        await mockUniswapRouter.setDefaultMockValue(bigMaxAmountToSwap);
+
+        await expect(
+          uniswapRepayAdapter.connect(user).swapAndRepay(
+            weth.address,
+            dai.address,
+            bigMaxAmountToSwap,
+            expectedDaiAmount,
+            1,
+            {
+              amount: 0,
+              deadline: 0,
+              v: 0,
+              r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+              s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            },
+            false
+          )
+        ).to.be.revertedWith('maxAmountToSwap exceed max slippage');
+      });
+
+      it('should swap, repay debt and pull the needed ATokens leaving no leftovers', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        const liquidityToSwap = amountWETHtoSwap;
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+        const userWethBalanceBefore = await weth.balanceOf(userAddress);
+
+        const actualWEthSwapped = new BigNumber(liquidityToSwap.toString())
+          .multipliedBy(0.995)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, actualWEthSwapped);
+
+        await mockUniswapRouter.setDefaultMockValue(actualWEthSwapped);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          weth.address,
+          dai.address,
+          liquidityToSwap,
+          expectedDaiAmount,
+          1,
+          {
+            amount: 0,
+            deadline: 0,
+            v: 0,
+            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          },
+          false
+        );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+        const userWethBalance = await weth.balanceOf(userAddress);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(actualWEthSwapped));
+        expect(userWethBalance).to.be.eq(userWethBalanceBefore);
+      });
+
+      it('should correctly swap tokens and repay the whole stable debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
+        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          weth.address,
+          dai.address,
+          liquidityToSwap,
+          amountToRepay,
+          1,
+          {
+            amount: 0,
+            deadline: 0,
+            v: 0,
+            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          },
+          false
+        );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiStableDebtAmount).to.be.eq(Zero);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly swap tokens and repay the whole variable debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aWETH,
+          oracle,
+          dai,
+          uniswapRepayAdapter,
+          helpersContract,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, expectedDaiAmount, 2, 0, userAddress);
+
+        const daiStableVariableTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).variableDebtTokenAddress;
+
+        const daiVariableDebtContract = await getContract<StableDebtToken>(
+          eContractid.VariableDebtToken,
+          daiStableVariableTokenAddress
+        );
+
+        const userDaiVariableDebtAmountBefore = await daiVariableDebtContract.balanceOf(
+          userAddress
+        );
+
+        // Add a % to repay on top of the debt
+        const liquidityToSwap = new BigNumber(amountWETHtoSwap.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await aWETH.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
+
+        // Add a % to repay on top of the debt
+        const amountToRepay = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(1.1)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(weth.address, amountWETHtoSwap);
+        await mockUniswapRouter.setDefaultMockValue(amountWETHtoSwap);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          weth.address,
+          dai.address,
+          liquidityToSwap,
+          amountToRepay,
+          2,
+          {
+            amount: 0,
+            deadline: 0,
+            v: 0,
+            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          },
+          false
+        );
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiVariableDebtAmount = await daiVariableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aWETH.balanceOf(userAddress);
+        const adapterAEthBalance = await aWETH.balanceOf(uniswapRepayAdapter.address);
+
+        expect(adapterAEthBalance).to.be.eq(Zero);
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiVariableDebtAmountBefore).to.be.gte(expectedDaiAmount);
+        expect(userDaiVariableDebtAmount).to.be.eq(Zero);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should correctly repay debt using the same asset as collateral', async () => {
+        const { users, pool, dai, uniswapRepayAdapter, helpersContract, aDai } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        // Add deposit for user
+        await dai.mint(parseEther('20'));
+        await dai.approve(pool.address, parseEther('20'));
+        await pool.deposit(dai.address, parseEther('20'), userAddress, 0);
+
+        const amountCollateralToSwap = parseEther('10');
+
+        const debtAmount = parseEther('10');
+
+        // Open user Debt
+        await pool.connect(user).borrow(dai.address, debtAmount, 1, 0, userAddress);
+
+        const daiStableDebtTokenAddress = (
+          await helpersContract.getReserveTokensAddresses(dai.address)
+        ).stableDebtTokenAddress;
+
+        const daiStableDebtContract = await getContract<StableDebtToken>(
+          eContractid.StableDebtToken,
+          daiStableDebtTokenAddress
+        );
+
+        const userDaiStableDebtAmountBefore = await daiStableDebtContract.balanceOf(userAddress);
+
+        await aDai.connect(user).approve(uniswapRepayAdapter.address, amountCollateralToSwap);
+        const userADaiBalanceBefore = await aDai.balanceOf(userAddress);
+        const userDaiBalanceBefore = await dai.balanceOf(userAddress);
+
+        await uniswapRepayAdapter.connect(user).swapAndRepay(
+          dai.address,
+          dai.address,
+          amountCollateralToSwap,
+          amountCollateralToSwap,
+          1,
+          {
+            amount: 0,
+            deadline: 0,
+            v: 0,
+            r: '0x0000000000000000000000000000000000000000000000000000000000000000',
+            s: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          },
+          false
+        );
+
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userADaiBalance = await aDai.balanceOf(userAddress);
+        const adapterADaiBalance = await aDai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiBalance = await dai.balanceOf(userAddress);
+
+        expect(adapterADaiBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(userDaiStableDebtAmountBefore).to.be.gte(debtAmount);
+        expect(userDaiStableDebtAmount).to.be.lt(debtAmount);
+        expect(userADaiBalance).to.be.lt(userADaiBalanceBefore);
+        expect(userADaiBalance).to.be.gte(userADaiBalanceBefore.sub(amountCollateralToSwap));
+        expect(userDaiBalance).to.be.eq(userDaiBalanceBefore);
+      });
+    });
+  });
+});