diff --git a/contracts/interfaces/IUniswapV2Router02.sol b/contracts/interfaces/IUniswapV2Router02.sol
new file mode 100644
index 00000000..cb04c269
--- /dev/null
+++ b/contracts/interfaces/IUniswapV2Router02.sol
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: agpl-3.0
+pragma solidity ^0.6.8;
+
+interface IUniswapV2Router02 {
+  function swapExactTokensForTokens(
+    uint256 amountIn,
+    uint256 amountOutMin,
+    address[] calldata path,
+    address to,
+    uint256 deadline
+  ) external returns (uint256[] memory amounts);
+
+  function swapTokensForExactTokens(
+    uint amountOut,
+    uint amountInMax,
+    address[] calldata path,
+    address to,
+    uint deadline
+  ) external returns (uint256[] memory amounts);
+}
diff --git a/contracts/mocks/swap/MockUniswapV2Router02.sol b/contracts/mocks/swap/MockUniswapV2Router02.sol
new file mode 100644
index 00000000..64cb935f
--- /dev/null
+++ b/contracts/mocks/swap/MockUniswapV2Router02.sol
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: agpl-3.0
+pragma solidity ^0.6.8;
+
+import {IUniswapV2Router02} from "../../interfaces/IUniswapV2Router02.sol";
+import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
+import {MintableERC20} from '../tokens/MintableERC20.sol';
+
+contract MockUniswapV2Router02 is IUniswapV2Router02 {
+  uint256 internal _amountToReturn;
+  uint256 internal _amountToSwap;
+
+  function setAmountToReturn(uint256 amount) public {
+    _amountToReturn = amount;
+  }
+
+  function setAmountToSwap(uint256 amount) public {
+    _amountToSwap = amount;
+  }
+
+  function swapExactTokensForTokens(
+    uint256 amountIn,
+    uint256 /* amountOutMin */,
+    address[] calldata path,
+    address to,
+    uint256 /* deadline */
+  ) external override returns (uint256[] memory amounts) {
+    IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
+
+    MintableERC20(path[1]).mint(_amountToReturn);
+    IERC20(path[1]).transfer(to, _amountToReturn);
+
+    amounts = new uint[](path.length);
+    amounts[0] = amountIn;
+    amounts[1] = _amountToReturn;
+  }
+
+  function swapTokensForExactTokens(
+    uint amountOut,
+    uint amountInMax,
+    address[] calldata path,
+    address to,
+    uint /* deadline */
+  ) external override returns (uint256[] memory amounts) {
+    IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap);
+
+    MintableERC20(path[1]).mint(_amountToReturn);
+    IERC20(path[1]).transfer(to, _amountToReturn);
+
+    amounts = new uint[](path.length);
+    amounts[0] = _amountToSwap;
+    amounts[1] = _amountToReturn;
+  }
+}
diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts
index 77730b04..eaee15ab 100644
--- a/helpers/contracts-helpers.ts
+++ b/helpers/contracts-helpers.ts
@@ -37,6 +37,9 @@ import BigNumber from 'bignumber.js';
 import {Ierc20Detailed} from '../types/Ierc20Detailed';
 import {StableDebtToken} from '../types/StableDebtToken';
 import {VariableDebtToken} from '../types/VariableDebtToken';
+import {MockUniswapV2Router02} from '../types/MockUniswapV2Router02';
+import {UniswapLiquiditySwapAdapter} from '../types/UniswapLiquiditySwapAdapter';
+import {UniswapRepayAdapter} from '../types/UniswapRepayAdapter';
 import {MockContract} from 'ethereum-waffle';
 import {getReservesConfigByPool} from './configuration';
 import {verifyContract} from './etherscan-verification';
@@ -47,7 +50,6 @@ const {
 
 export type MockTokenMap = {[symbol: string]: MintableERC20};
 import {ZERO_ADDRESS} from './constants';
-import {MockSwapAdapter} from '../types/MockSwapAdapter';
 import {signTypedData_v4, TypedData} from 'eth-sig-util';
 import {fromRpcSig, ECDSASignature} from 'ethereumjs-util';
 import {SignerWithAddress} from '../test/helpers/make-suite';
@@ -256,6 +258,27 @@ export const deployChainlinkProxyPriceProvider = async (
   return instance;
 };
 
+export const deployMockUniswapRouter = async () =>
+  await deployContract<MockUniswapV2Router02>(eContractid.MockUniswapV2Router02, []);
+
+export const deployUniswapLiquiditySwapAdapter = async (
+  addressesProvider: tEthereumAddress,
+  uniswapRouter: tEthereumAddress
+) =>
+  await deployContract<UniswapLiquiditySwapAdapter>(eContractid.UniswapLiquiditySwapAdapter, [
+    addressesProvider,
+    uniswapRouter,
+  ]);
+
+export const deployUniswapRepayAdapter = async (
+  addressesProvider: tEthereumAddress,
+  uniswapRouter: tEthereumAddress
+) =>
+  await deployContract<UniswapRepayAdapter>(eContractid.UniswapRepayAdapter, [
+    addressesProvider,
+    uniswapRouter,
+  ]);
+
 export const getChainlingProxyPriceProvider = async (address?: tEthereumAddress) =>
   await getContract<MockAggregator>(
     eContractid.ChainlinkProxyPriceProvider,
@@ -321,8 +344,6 @@ export const deployWalletBalancerProvider = async (
   }
   return instance;
 };
-export const deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) =>
-  await deployContract<MockSwapAdapter>(eContractid.MockSwapAdapter, [addressesProvider]);
 
 export const deployAaveProtocolTestHelpers = async (
   addressesProvider: tEthereumAddress,
@@ -548,11 +569,29 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => {
   );
 };
 
-export const getMockSwapAdapter = async (address?: tEthereumAddress) => {
-  return await getContract<MockSwapAdapter>(
-    eContractid.MockSwapAdapter,
+export const getMockUniswapRouter = async (address?: tEthereumAddress) => {
+  return await getContract<MockUniswapV2Router02>(
+    eContractid.MockUniswapV2Router02,
     address ||
-      (await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address
+      (await getDb().get(`${eContractid.MockUniswapV2Router02}.${BRE.network.name}`).value())
+        .address
+  );
+};
+
+export const getUniswapLiquiditySwapAdapter = async (address?: tEthereumAddress) => {
+  return await getContract<UniswapLiquiditySwapAdapter>(
+    eContractid.UniswapLiquiditySwapAdapter,
+    address ||
+      (await getDb().get(`${eContractid.UniswapLiquiditySwapAdapter}.${BRE.network.name}`).value())
+        .address
+  );
+};
+
+export const getUniswapRepayAdapter = async (address?: tEthereumAddress) => {
+  return await getContract<UniswapLiquiditySwapAdapter>(
+    eContractid.UniswapRepayAdapter,
+    address ||
+      (await getDb().get(`${eContractid.UniswapRepayAdapter}.${BRE.network.name}`).value()).address
   );
 };
 
diff --git a/helpers/types.ts b/helpers/types.ts
index 26644896..877441ea 100644
--- a/helpers/types.ts
+++ b/helpers/types.ts
@@ -44,7 +44,6 @@ export enum eContractid {
   LendingPoolCollateralManager = 'LendingPoolCollateralManager',
   InitializableAdminUpgradeabilityProxy = 'InitializableAdminUpgradeabilityProxy',
   MockFlashLoanReceiver = 'MockFlashLoanReceiver',
-  MockSwapAdapter = 'MockSwapAdapter',
   WalletBalanceProvider = 'WalletBalanceProvider',
   AToken = 'AToken',
   MockAToken = 'MockAToken',
@@ -56,6 +55,9 @@ export enum eContractid {
   VariableDebtToken = 'VariableDebtToken',
   FeeProvider = 'FeeProvider',
   TokenDistributor = 'TokenDistributor',
+  MockUniswapV2Router02 = 'MockUniswapV2Router02',
+  UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
+  UniswapRepayAdapter = 'UniswapRepayAdapter',
 }
 
 export enum ProtocolErrors {
diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts
index 676ae52a..40ed2ced 100644
--- a/test/__setup.spec.ts
+++ b/test/__setup.spec.ts
@@ -19,8 +19,10 @@ import {
   registerContractInJsonDb,
   getPairsTokenAggregator,
   initReserves,
-  deployMockSwapAdapter,
   deployLendingRateOracle,
+  deployMockUniswapRouter,
+  deployUniswapLiquiditySwapAdapter,
+  deployUniswapRepayAdapter,
 } from '../helpers/contracts-helpers';
 import {Signer} from 'ethers';
 import {TokenContractId, eContractid, tEthereumAddress, AavePools} from '../helpers/types';
@@ -239,8 +241,23 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
   const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address);
   await insertContractAddressInDb(eContractid.MockFlashLoanReceiver, mockFlashLoanReceiver.address);
 
-  const mockSwapAdapter = await deployMockSwapAdapter(addressesProvider.address);
-  await insertContractAddressInDb(eContractid.MockSwapAdapter, mockSwapAdapter.address);
+  const mockUniswapRouter = await deployMockUniswapRouter();
+  await insertContractAddressInDb(eContractid.MockUniswapV2Router02, mockUniswapRouter.address);
+
+  const UniswapLiquiditySwapAdapter = await deployUniswapLiquiditySwapAdapter(
+    addressesProvider.address,
+    mockUniswapRouter.address
+  );
+  await insertContractAddressInDb(
+    eContractid.UniswapLiquiditySwapAdapter,
+    UniswapLiquiditySwapAdapter.address
+  );
+
+  const UniswapRepayAdapter = await deployUniswapRepayAdapter(
+    addressesProvider.address,
+    mockUniswapRouter.address
+  );
+  await insertContractAddressInDb(eContractid.UniswapRepayAdapter, UniswapRepayAdapter.address);
 
   await deployWalletBalancerProvider(addressesProvider.address);
 
diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts
index 5eb8788f..de9cfb13 100644
--- a/test/helpers/make-suite.ts
+++ b/test/helpers/make-suite.ts
@@ -9,8 +9,9 @@ import {
   getMintableErc20,
   getLendingPoolConfiguratorProxy,
   getPriceOracle,
-  getMockSwapAdapter,
   getLendingPoolAddressesProviderRegistry,
+  getUniswapLiquiditySwapAdapter,
+  getUniswapRepayAdapter,
 } from '../../helpers/contracts-helpers';
 import {tEthereumAddress} from '../../helpers/types';
 import {LendingPool} from '../../types/LendingPool';
@@ -25,8 +26,9 @@ import bignumberChai from 'chai-bignumber';
 import {almostEqual} from './almost-equal';
 import {PriceOracle} from '../../types/PriceOracle';
 import {LendingPoolAddressesProvider} from '../../types/LendingPoolAddressesProvider';
-import {MockSwapAdapter} from '../../types/MockSwapAdapter';
 import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddressesProviderRegistry';
+import {UniswapLiquiditySwapAdapter} from '../../types/UniswapLiquiditySwapAdapter';
+import {UniswapRepayAdapter} from '../../types/UniswapRepayAdapter';
 chai.use(bignumberChai());
 chai.use(almostEqual());
 
@@ -48,7 +50,8 @@ export interface TestEnv {
   usdc: MintableERC20;
   lend: MintableERC20;
   addressesProvider: LendingPoolAddressesProvider;
-  mockSwapAdapter: MockSwapAdapter;
+  uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter;
+  uniswapRepayAdapter: UniswapRepayAdapter;
   registry: LendingPoolAddressesProviderRegistry;
 }
 
@@ -73,7 +76,8 @@ const testEnv: TestEnv = {
   usdc: {} as MintableERC20,
   lend: {} as MintableERC20,
   addressesProvider: {} as LendingPoolAddressesProvider,
-  mockSwapAdapter: {} as MockSwapAdapter,
+  uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter,
+  uniswapRepayAdapter: {} as UniswapRepayAdapter,
   registry: {} as LendingPoolAddressesProviderRegistry,
 } as TestEnv;
 
@@ -135,7 +139,8 @@ export async function initializeMakeSuite() {
   testEnv.lend = await getMintableErc20(lendAddress);
   testEnv.weth = await getMintableErc20(wethAddress);
 
-  testEnv.mockSwapAdapter = await getMockSwapAdapter();
+  testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter();
+  testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter();
 }
 
 export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) {
diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts
index 8e7cc2a7..fdfe5341 100644
--- a/test/pausable-functions.spec.ts
+++ b/test/pausable-functions.spec.ts
@@ -275,7 +275,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
   });
 
   it('SwapBorrowRateMode', async () => {
-    const {pool, weth, dai, usdc, users, configurator, mockSwapAdapter} = testEnv;
+    const {pool, weth, dai, usdc, users, configurator} = testEnv;
     const user = users[1];
     const amountWETHToDeposit = parseEther('10');
     const amountDAIToDeposit = parseEther('120');
diff --git a/test/uniswapAdapters.spec.ts b/test/uniswapAdapters.spec.ts
new file mode 100644
index 00000000..6bf2cbc4
--- /dev/null
+++ b/test/uniswapAdapters.spec.ts
@@ -0,0 +1,805 @@
+import {makeSuite, TestEnv} from './helpers/make-suite';
+import {
+  convertToCurrencyDecimals,
+  deployUniswapLiquiditySwapAdapter,
+  deployUniswapRepayAdapter,
+  getContract,
+  getMockUniswapRouter,
+} from '../helpers/contracts-helpers';
+import {MockUniswapV2Router02} from '../types/MockUniswapV2Router02';
+import {Zero} from '@ethersproject/constants';
+import BigNumber from 'bignumber.js';
+import {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';
+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('UniswapLiquiditySwapAdapter', () => {
+    describe('constructor', () => {
+      it('should deploy with correct parameters', async () => {
+        const {addressesProvider} = testEnv;
+        await deployUniswapLiquiditySwapAdapter(
+          addressesProvider.address,
+          mockUniswapRouter.address
+        );
+      });
+
+      it('should revert if not valid addresses provider', async () => {
+        expect(
+          deployUniswapLiquiditySwapAdapter(mockUniswapRouter.address, mockUniswapRouter.address)
+        ).to.be.reverted;
+      });
+    });
+
+    describe('executeOperation', () => {
+      beforeEach(async () => {
+        const {users, weth, dai, 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);
+
+        // Make a deposit for user
+        await weth.mint(parseEther('100'));
+        await weth.approve(pool.address, parseEther('100'));
+        await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
+      });
+
+      it('should correctly swap tokens and deposit the out tokens in the pool', async () => {
+        const {users, weth, oracle, dai, aDai, aEth, pool, uniswapLiquiditySwapAdapter} = 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)
+        );
+
+        await mockUniswapRouter.setAmountToReturn(expectedDaiAmount);
+
+        // User will swap liquidity 10 aEth to aDai
+        const liquidityToSwap = parseEther('10');
+        await aEth.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        // 0,5% slippage
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256'],
+          [dai.address, userAddress, 50]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapLiquiditySwapAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapLiquiditySwapAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address);
+        const adapterDaiAllowance = await dai.allowance(
+          uniswapLiquiditySwapAdapter.address,
+          userAddress
+        );
+        const userADaiBalance = await aDai.balanceOf(userAddress);
+        const userAEthBalance = await aEth.balanceOf(userAddress);
+
+        expect(adapterWethBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(adapterDaiAllowance).to.be.eq(Zero);
+        expect(userADaiBalance).to.be.eq(expectedDaiAmount);
+        expect(userAEthBalance).to.be.lt(userAEthBalanceBefore);
+        expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(liquidityToSwap));
+      });
+
+      it('should work correctly with tokens of different decimals', async () => {
+        const {
+          users,
+          usdc,
+          oracle,
+          dai,
+          aDai,
+          uniswapLiquiditySwapAdapter,
+          pool,
+          deployer,
+        } = testEnv;
+        const user = users[0].signer;
+        const userAddress = users[0].address;
+
+        const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10');
+        const liquidity = await convertToCurrencyDecimals(usdc.address, '20000');
+
+        // Provide liquidity
+        await usdc.mint(liquidity);
+        await usdc.approve(pool.address, liquidity);
+        await pool.deposit(usdc.address, liquidity, deployer.address, 0);
+
+        // Make a deposit for user
+        await usdc.connect(user).mint(amountUSDCtoSwap);
+        await usdc.connect(user).approve(pool.address, amountUSDCtoSwap);
+        await pool.connect(user).deposit(usdc.address, amountUSDCtoSwap, userAddress, 0);
+
+        const usdcPrice = await oracle.getAssetPrice(usdc.address);
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+
+        // usdc 6
+        const collateralDecimals = (await usdc.decimals()).toString();
+        const principalDecimals = (await dai.decimals()).toString();
+
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountUSDCtoSwap.toString())
+            .times(
+              new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals))
+            )
+            .div(
+              new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
+            )
+            .toFixed(0)
+        );
+
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const aUsdcData = await pool.getReserveData(usdc.address);
+        const aUsdc = await getContract<AToken>(eContractid.AToken, aUsdcData.aTokenAddress);
+        const aUsdcBalance = await aUsdc.balanceOf(userAddress);
+        await aUsdc.connect(user).approve(uniswapLiquiditySwapAdapter.address, aUsdcBalance);
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(amountUSDCtoSwap.toString()).div(1.0009).toFixed(0);
+
+        // 0,5% slippage
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256'],
+          [dai.address, userAddress, 50]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapLiquiditySwapAdapter.address,
+              usdc.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapLiquiditySwapAdapter, 'Swapped')
+          .withArgs(usdc.address, dai.address, flashloanAmount.toString(), expectedDaiAmount);
+
+        const adapterUsdcBalance = await usdc.balanceOf(uniswapLiquiditySwapAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapLiquiditySwapAdapter.address);
+        const adapterDaiAllowance = await dai.allowance(
+          uniswapLiquiditySwapAdapter.address,
+          userAddress
+        );
+        const aDaiBalance = await aDai.balanceOf(userAddress);
+
+        expect(adapterUsdcBalance).to.be.eq(Zero);
+        expect(adapterDaiBalance).to.be.eq(Zero);
+        expect(adapterDaiAllowance).to.be.eq(Zero);
+        expect(aDaiBalance).to.be.eq(expectedDaiAmount);
+      });
+
+      it('should revert if slippage param is not inside limits', async () => {
+        const {users, pool, weth, oracle, dai, aEth, uniswapLiquiditySwapAdapter} = 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(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap);
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        // User will swap liquidity 10 aEth to aDai
+        const liquidityToSwap = parseEther('10');
+        await aEth.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap);
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        // 30% slippage
+        const params1 = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256'],
+          [dai.address, userAddress, 3000]
+        );
+
+        // 0,05% slippage
+        const params2 = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256'],
+          [dai.address, userAddress, 5]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapLiquiditySwapAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params1,
+              0
+            )
+        ).to.be.revertedWith('SLIPPAGE_OUT_OF_RANGE');
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapLiquiditySwapAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params2,
+              0
+            )
+        ).to.be.revertedWith('SLIPPAGE_OUT_OF_RANGE');
+      });
+
+      it('should revert when swap exceed slippage', async () => {
+        const {users, weth, oracle, dai, aEth, pool, uniswapLiquiditySwapAdapter} = 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(uniswapLiquiditySwapAdapter.address, amountWETHtoSwap);
+
+        const daiPrice = await oracle.getAssetPrice(dai.address);
+        const expectedDaiAmount = await convertToCurrencyDecimals(
+          dai.address,
+          new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
+        );
+
+        // 1,5% slippage
+        const returnedDaiAmountWithBigSlippage = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(0.985)
+          .toFixed(0);
+        await mockUniswapRouter.connect(user).setAmountToReturn(returnedDaiAmountWithBigSlippage);
+
+        // User will swap liquidity 10 aEth to aDai
+        const liquidityToSwap = parseEther('10');
+        await aEth.connect(user).approve(uniswapLiquiditySwapAdapter.address, liquidityToSwap);
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        // 0,5% slippage
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256'],
+          [dai.address, userAddress, 50]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapLiquiditySwapAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        ).to.be.revertedWith('INSUFFICIENT_OUTPUT_AMOUNT');
+      });
+    });
+  });
+
+  describe('UniswapRepayAdapter', () => {
+    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', () => {
+      beforeEach(async () => {
+        const {users, weth, dai, 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);
+
+        // Make a deposit for user
+        await weth.mint(parseEther('100'));
+        await weth.approve(pool.address, parseEther('100'));
+        await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
+      });
+
+      it('should correctly swap tokens and repay debt', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aEth,
+          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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, flashloanAmount.toString(), expectedDaiAmount);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aEth.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 with the specified rate mode', async () => {
+        const {users, pool, weth, oracle, dai, uniswapRepayAdapter, aEth} = 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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        ).to.be.reverted;
+      });
+
+      it('should revert if there is not debt to repay', async () => {
+        const {users, pool, weth, oracle, dai, uniswapRepayAdapter, aEth} = 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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        ).to.be.reverted;
+      });
+
+      it('should revert when the received amount is less than expected', async () => {
+        const {users, pool, weth, oracle, dai, aEth, uniswapRepayAdapter, deployer} = 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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        const insufficientOutput = new BigNumber(expectedDaiAmount.toString())
+          .multipliedBy(0.985)
+          .toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount);
+        await mockUniswapRouter.connect(user).setAmountToReturn(insufficientOutput);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        ).to.be.revertedWith('INSUFFICIENT_OUTPUT_AMOUNT');
+      });
+
+      it('should revert when max amount allowed to swap is bigger than max slippage', async () => {
+        const {users, pool, weth, oracle, dai, aEth, 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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const bigMaxAmountToSwap = amountWETHtoSwap.mul(2);
+        const flashloanAmount = new BigNumber(bigMaxAmountToSwap.toString()).div(1.0009).toFixed(0);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(flashloanAmount);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        ).to.be.revertedWith('maxAmountToSwap exceed max slippage');
+      });
+
+      it('should swap tokens, repay debt and deposit in pool the left over', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aEth,
+          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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        const actualWEthSwapped = new BigNumber(flashloanAmount.toString())
+          .multipliedBy(0.995)
+          .toFixed(0);
+
+        const leftOverWeth = new BigNumber(flashloanAmount).minus(actualWEthSwapped);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(actualWEthSwapped);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 0, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), expectedDaiAmount);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aEth.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.gt(userAEthBalanceBefore.sub(liquidityToSwap));
+        expect(userAEthBalance).to.be.gte(
+          userAEthBalanceBefore.sub(liquidityToSwap).add(leftOverWeth.toString())
+        );
+      });
+
+      it('should swap tokens, repay debt and transfer to user the left over', async () => {
+        const {
+          users,
+          pool,
+          weth,
+          aEth,
+          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 aEth.connect(user).approve(uniswapRepayAdapter.address, liquidityToSwap);
+        const userAEthBalanceBefore = await aEth.balanceOf(userAddress);
+
+        // Subtract the FL fee from the amount to be swapped 0,09%
+        const flashloanAmount = new BigNumber(liquidityToSwap.toString()).div(1.0009).toFixed(0);
+
+        const actualWEthSwapped = new BigNumber(flashloanAmount.toString())
+          .multipliedBy(0.995)
+          .toFixed(0);
+
+        const leftOverWeth = new BigNumber(flashloanAmount).minus(actualWEthSwapped);
+
+        await mockUniswapRouter.connect(user).setAmountToSwap(actualWEthSwapped);
+        await mockUniswapRouter.connect(user).setAmountToReturn(expectedDaiAmount);
+
+        const wethBalanceBefore = await weth.balanceOf(userAddress);
+
+        const params = ethers.utils.defaultAbiCoder.encode(
+          ['address', 'address', 'uint256', 'uint256', 'uint256'],
+          [dai.address, userAddress, 1, expectedDaiAmount, 1]
+        );
+
+        await expect(
+          pool
+            .connect(user)
+            .flashLoan(
+              uniswapRepayAdapter.address,
+              weth.address,
+              flashloanAmount.toString(),
+              0,
+              params,
+              0
+            )
+        )
+          .to.emit(uniswapRepayAdapter, 'Swapped')
+          .withArgs(weth.address, dai.address, actualWEthSwapped.toString(), expectedDaiAmount);
+
+        const adapterWethBalance = await weth.balanceOf(uniswapRepayAdapter.address);
+        const adapterDaiBalance = await dai.balanceOf(uniswapRepayAdapter.address);
+        const userDaiStableDebtAmount = await daiStableDebtContract.balanceOf(userAddress);
+        const userAEthBalance = await aEth.balanceOf(userAddress);
+        const wethBalance = await weth.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.gt(userAEthBalanceBefore.sub(liquidityToSwap));
+        expect(wethBalance).to.be.eq(wethBalanceBefore.add(leftOverWeth.toString()));
+      });
+    });
+  });
+});