diff --git a/contracts/arbitrum/connectors/aave/v3-import-permit/events.sol b/contracts/arbitrum/connectors/aave/v3-import-permit/events.sol
new file mode 100644
index 00000000..10a93d70
--- /dev/null
+++ b/contracts/arbitrum/connectors/aave/v3-import-permit/events.sol
@@ -0,0 +1,15 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+contract Events {
+	event LogAaveV3ImportWithPermit(
+		address indexed user,
+		address[] atokens,
+		string[] supplyIds,
+		string[] borrowIds,
+		uint256[] flashLoanFees,
+		uint256[] supplyAmts,
+		uint256[] borrowAmts
+	);
+}
diff --git a/contracts/arbitrum/connectors/aave/v3-import-permit/helpers.sol b/contracts/arbitrum/connectors/aave/v3-import-permit/helpers.sol
new file mode 100644
index 00000000..61b1687d
--- /dev/null
+++ b/contracts/arbitrum/connectors/aave/v3-import-permit/helpers.sol
@@ -0,0 +1,316 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+
+import { DSMath } from "../../../common/math.sol";
+import { Basic } from "../../../common/basic.sol";
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
+import "./events.sol";
+import "./interface.sol";
+
+abstract contract Helper is DSMath, Basic {
+	/**
+	 * @dev Aave referal code
+	 */
+	uint16 internal constant referalCode = 3228;
+
+	/**
+	 * @dev Aave Lending Pool Provider
+	 */
+	AavePoolProviderInterface internal constant aaveProvider =
+		AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb);
+
+	/**
+	 * @dev Aave Protocol Data Provider
+	 */
+	AaveDataProviderInterface internal constant aaveData =
+		AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654);
+
+	function getIsColl(address token, address user)
+		internal
+		view
+		returns (bool isCol)
+	{
+		(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
+	}
+
+	struct ImportData {
+		address[] _supplyTokens;
+		address[] _borrowTokens;
+		ATokenInterface[] aTokens;
+		uint256[] supplyAmts;
+		uint256[] variableBorrowAmts;
+		uint256[] variableBorrowAmtsWithFee;
+		uint256[] stableBorrowAmts;
+		uint256[] stableBorrowAmtsWithFee;
+		uint256[] totalBorrowAmts;
+		uint256[] totalBorrowAmtsWithFee;
+		bool convertStable;
+	}
+
+	struct ImportInputData {
+		address[] supplyTokens;
+		address[] borrowTokens;
+		bool convertStable;
+		uint256[] flashLoanFees;
+	}
+
+	struct SignedPermits {
+		uint8[] v;
+		bytes32[] r;
+		bytes32[] s;
+		uint256[] expiry;
+	}
+}
+
+contract AaveHelpers is Helper {
+	function getBorrowAmount(address _token, address userAccount)
+		internal
+		view
+		returns (uint256 stableBorrow, uint256 variableBorrow)
+	{
+		(
+			,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		) = aaveData.getReserveTokensAddresses(_token);
+
+		stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+		variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+	}
+
+	function getBorrowAmounts(
+		address userAccount,
+		AaveInterface aave,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal returns (ImportData memory) {
+		if (inputData.borrowTokens.length > 0) {
+			data._borrowTokens = new address[](inputData.borrowTokens.length);
+			data.variableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.variableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
+			data.totalBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
+					if (j != i) {
+						require(
+							inputData.borrowTokens[i] !=
+								inputData.borrowTokens[j],
+							"token-repeated"
+						);
+					}
+				}
+			}
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				address _token = inputData.borrowTokens[i] == ethAddr
+					? wethAddr
+					: inputData.borrowTokens[i];
+				data._borrowTokens[i] = _token;
+
+				(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				) = getBorrowAmount(_token, userAccount);
+
+				if (data.variableBorrowAmts[i] != 0) {
+					data.variableBorrowAmtsWithFee[i] = add(
+						data.variableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+					data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
+				} else {
+					data.stableBorrowAmtsWithFee[i] = add(
+						data.stableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+				}
+
+				data.totalBorrowAmts[i] = add(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				);
+				data.totalBorrowAmtsWithFee[i] = add(
+					data.stableBorrowAmtsWithFee[i],
+					data.variableBorrowAmtsWithFee[i]
+				);
+
+				if (data.totalBorrowAmts[i] > 0) {
+					uint256 _amt = data.totalBorrowAmts[i];
+					TokenInterface(_token).approve(address(aave), _amt);
+				}
+			}
+		}
+		return data;
+	}
+
+	function getSupplyAmounts(
+		address userAccount,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal view returns (ImportData memory) {
+		data.supplyAmts = new uint256[](inputData.supplyTokens.length);
+		data._supplyTokens = new address[](inputData.supplyTokens.length);
+		data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
+
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
+				if (j != i) {
+					require(
+						inputData.supplyTokens[i] != inputData.supplyTokens[j],
+						"token-repeated"
+					);
+				}
+			}
+		}
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			address _token = inputData.supplyTokens[i] == ethAddr
+				? wethAddr
+				: inputData.supplyTokens[i];
+			(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
+			data._supplyTokens[i] = _token;
+			data.aTokens[i] = ATokenInterface(_aToken);
+			data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
+		}
+
+		return data;
+	}
+
+	function _paybackBehalfOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode,
+		address user
+	) private {
+		aave.repay(token, amt, rateMode, user);
+	}
+
+	function _PaybackStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
+			}
+		}
+	}
+
+	function _PaybackVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
+			}
+		}
+	}
+
+	function _PermitATokens(
+		address userAccount,
+		ATokenInterface[] memory aTokenContracts,
+		address[] memory tokens,
+		uint8[] memory v,
+		bytes32[] memory r,
+		bytes32[] memory s,
+		uint256[] memory expiry
+	) internal {
+		for (uint256 i = 0; i < tokens.length; i++) {
+			aTokenContracts[i].permit(
+				userAccount,
+				address(this),
+				uint256(-1),
+				expiry[i],
+				v[i],
+				r[i],
+				s[i]
+			);
+		}
+	}
+
+	function _TransferAtokens(
+		uint256 _length,
+		AaveInterface aave,
+		ATokenInterface[] memory atokenContracts,
+		uint256[] memory amts,
+		address[] memory tokens,
+		address userAccount
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				uint256 _amt = amts[i];
+				require(
+					atokenContracts[i].transferFrom(
+						userAccount,
+						address(this),
+						_amt
+					),
+					"allowance?"
+				);
+
+				if (!getIsColl(tokens[i], address(this))) {
+					aave.setUserUseReserveAsCollateral(tokens[i], true);
+				}
+			}
+		}
+	}
+
+	function _BorrowVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 2);
+			}
+		}
+	}
+
+	function _BorrowStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 1);
+			}
+		}
+	}
+
+	function _borrowOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode
+	) private {
+		aave.borrow(token, amt, rateMode, referalCode, address(this));
+	}
+}
diff --git a/contracts/arbitrum/connectors/aave/v3-import-permit/interface.sol b/contracts/arbitrum/connectors/aave/v3-import-permit/interface.sol
new file mode 100644
index 00000000..dfd6945f
--- /dev/null
+++ b/contracts/arbitrum/connectors/aave/v3-import-permit/interface.sol
@@ -0,0 +1,105 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+
+interface AaveInterface {
+	function supply(
+		address asset,
+		uint256 amount,
+		address onBehalfOf,
+		uint16 referralCode
+	) external;
+
+	function withdraw(
+		address _asset,
+		uint256 _amount,
+		address _to
+	) external;
+
+	function borrow(
+		address _asset,
+		uint256 _amount,
+		uint256 _interestRateMode,
+		uint16 _referralCode,
+		address _onBehalfOf
+	) external;
+
+	function repay(
+		address _asset,
+		uint256 _amount,
+		uint256 _rateMode,
+		address _onBehalfOf
+	) external;
+
+	function setUserUseReserveAsCollateral(
+		address _asset,
+		bool _useAsCollateral
+	) external;
+
+	function swapBorrowRateMode(address _asset, uint256 _rateMode) external;
+}
+
+interface ATokenInterface {
+	function scaledBalanceOf(address _user) external view returns (uint256);
+
+	function isTransferAllowed(address _user, uint256 _amount)
+		external
+		view
+		returns (bool);
+
+	function balanceOf(address _user) external view returns (uint256);
+
+	function transferFrom(
+		address,
+		address,
+		uint256
+	) external returns (bool);
+
+	function permit(
+		address owner,
+		address spender,
+		uint256 value,
+		uint256 deadline,
+		uint8 v,
+		bytes32 r,
+		bytes32 s
+	) external;
+
+	function allowance(address, address) external returns (uint256);
+}
+
+interface AavePoolProviderInterface {
+	function getPool() external view returns (address);
+}
+
+interface AaveDataProviderInterface {
+	function getReserveTokensAddresses(address _asset)
+		external
+		view
+		returns (
+			address aTokenAddress,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		);
+
+	function getUserReserveData(address _asset, address _user)
+		external
+		view
+		returns (
+			uint256 currentATokenBalance,
+			uint256 currentStableDebt,
+			uint256 currentVariableDebt,
+			uint256 principalStableDebt,
+			uint256 scaledVariableDebt,
+			uint256 stableBorrowRate,
+			uint256 liquidityRate,
+			uint40 stableRateLastUpdated,
+			bool usageAsCollateralEnabled
+		);
+}
+
+interface AaveAddressProviderRegistryInterface {
+	function getAddressesProvidersList()
+		external
+		view
+		returns (address[] memory);
+}
diff --git a/contracts/arbitrum/connectors/aave/v3-import-permit/main.sol b/contracts/arbitrum/connectors/aave/v3-import-permit/main.sol
new file mode 100644
index 00000000..2a3aafe8
--- /dev/null
+++ b/contracts/arbitrum/connectors/aave/v3-import-permit/main.sol
@@ -0,0 +1,132 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+/**
+ * @title Aave v3 import connector .
+ * @dev  Import EOA's aave V3 position to DSA's aave v3 position
+ */
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, ATokenInterface } from "./interface.sol";
+import "./helpers.sol";
+import "./events.sol";
+
+contract AaveV3ImportPermitResolver is AaveHelpers {
+	function _importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	) internal returns (string memory _eventName, bytes memory _eventParam) {
+		require(
+			AccountInterface(address(this)).isAuth(userAccount),
+			"user-account-not-auth"
+		);
+
+		require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
+
+		ImportData memory data;
+
+		AaveInterface aave = AaveInterface(aaveProvider.getPool());
+
+		data = getBorrowAmounts(userAccount, aave, inputData, data);
+		data = getSupplyAmounts(userAccount, inputData, data);
+
+		//  payback borrowed amount;
+		_PaybackStable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.stableBorrowAmts,
+			userAccount
+		);
+		_PaybackVariable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.variableBorrowAmts,
+			userAccount
+		);
+
+		//permit this address to transfer aTokens
+		_PermitATokens(
+			userAccount,
+			data.aTokens,
+			data._supplyTokens,
+			permitData.v,
+			permitData.r,
+			permitData.s,
+			permitData.expiry
+		);
+
+		//  transfer atokens to this address;
+		_TransferAtokens(
+			data._supplyTokens.length,
+			aave,
+			data.aTokens,
+			data.supplyAmts,
+			data._supplyTokens,
+			userAccount
+		);
+
+		// borrow assets after migrating position
+		if (data.convertStable) {
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.totalBorrowAmtsWithFee
+			);
+		} else {
+			_BorrowStable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.stableBorrowAmtsWithFee
+			);
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.variableBorrowAmtsWithFee
+			);
+		}
+
+		_eventName = "LogAaveV3ImportWithPermit(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])";
+		_eventParam = abi.encode(
+			userAccount,
+			inputData.convertStable,
+			inputData.supplyTokens,
+			inputData.borrowTokens,
+			inputData.flashLoanFees,
+			data.supplyAmts,
+			data.stableBorrowAmts,
+			data.variableBorrowAmts
+		);
+	}
+
+	/**
+	 * @dev Import aave V3 position .
+	 * @notice Import EOA's aave V3 position to DSA's aave v3 position
+	 * @param userAccount The address of the EOA from which aave position will be imported
+	 * @param inputData The struct containing all the neccessary input data
+	 * @param permitData The struct containing signed permit data like v,r,s,expiry
+	 */
+	function importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		(_eventName, _eventParam) = _importAave(
+			userAccount,
+			inputData,
+			permitData
+		);
+	}
+}
+
+contract ConnectV2AaveV3ImportPermitArbitrum is AaveV3ImportPermitResolver {
+	string public constant name = "Aave-v3-import-permit-v1";
+}
diff --git a/contracts/avalanche/connectors/aave/v3-import-permit/events.sol b/contracts/avalanche/connectors/aave/v3-import-permit/events.sol
new file mode 100644
index 00000000..10a93d70
--- /dev/null
+++ b/contracts/avalanche/connectors/aave/v3-import-permit/events.sol
@@ -0,0 +1,15 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+contract Events {
+	event LogAaveV3ImportWithPermit(
+		address indexed user,
+		address[] atokens,
+		string[] supplyIds,
+		string[] borrowIds,
+		uint256[] flashLoanFees,
+		uint256[] supplyAmts,
+		uint256[] borrowAmts
+	);
+}
diff --git a/contracts/avalanche/connectors/aave/v3-import-permit/helpers.sol b/contracts/avalanche/connectors/aave/v3-import-permit/helpers.sol
new file mode 100644
index 00000000..2d77c4fb
--- /dev/null
+++ b/contracts/avalanche/connectors/aave/v3-import-permit/helpers.sol
@@ -0,0 +1,318 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+import { DSMath } from "../../../common/math.sol";
+import { Basic } from "../../../common/basic.sol";
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
+import "./events.sol";
+import "./interface.sol";
+
+abstract contract Helper is DSMath, Basic {
+	/**
+	 * @dev Aave referal code
+	 */
+	uint16 internal constant referalCode = 3228;
+
+	/**
+	 * @dev Aave Pool Provider
+	 */
+	AavePoolProviderInterface internal constant aaveProvider =
+		AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb);
+
+	/**
+	 * @dev Aave Protocol Data Provider
+	 */
+	AaveDataProviderInterface internal constant aaveData =
+		AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654);
+
+	function getIsColl(address token, address user)
+		internal
+		view
+		returns (bool isCol)
+	{
+		(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
+	}
+
+	struct ImportData {
+		address[] _supplyTokens;
+		address[] _borrowTokens;
+		ATokenInterface[] aTokens;
+		uint256[] supplyAmts;
+		uint256[] variableBorrowAmts;
+		uint256[] variableBorrowAmtsWithFee;
+		uint256[] stableBorrowAmts;
+		uint256[] stableBorrowAmtsWithFee;
+		uint256[] totalBorrowAmts;
+		uint256[] totalBorrowAmtsWithFee;
+		bool convertStable;
+	}
+
+	struct ImportInputData {
+		address[] supplyTokens;
+		address[] borrowTokens;
+		bool convertStable;
+		uint256[] flashLoanFees;
+	}
+
+	struct SignedPermits {
+		uint8[] v;
+		bytes32[] r;
+		bytes32[] s;
+		uint256[] expiry;
+	}
+}
+
+contract AaveHelpers is Helper {
+	function getBorrowAmount(address _token, address userAccount)
+		internal
+		view
+		returns (uint256 stableBorrow, uint256 variableBorrow)
+	{
+		(
+			,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		) = aaveData.getReserveTokensAddresses(_token);
+
+		stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+		variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+	}
+
+	function getBorrowAmounts(
+		address userAccount,
+		AaveInterface aave,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal returns (ImportData memory) {
+		if (inputData.borrowTokens.length > 0) {
+			data._borrowTokens = new address[](inputData.borrowTokens.length);
+			data.variableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.variableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
+			data.totalBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
+					if (j != i) {
+						require(
+							inputData.borrowTokens[i] !=
+								inputData.borrowTokens[j],
+							"token-repeated"
+						);
+					}
+				}
+			}
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				address _token = inputData.borrowTokens[i] == avaxAddr
+					? wavaxAddr
+					: inputData.borrowTokens[i];
+				data._borrowTokens[i] = _token;
+
+				(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				) = getBorrowAmount(_token, userAccount);
+
+				if (data.variableBorrowAmts[i] != 0) {
+					data.variableBorrowAmtsWithFee[i] = add(
+						data.variableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+					data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
+				} else {
+					data.stableBorrowAmtsWithFee[i] = add(
+						data.stableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+					data.variableBorrowAmtsWithFee[i] = data.variableBorrowAmts[
+						i
+					];
+				}
+
+				data.totalBorrowAmts[i] = add(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				);
+				data.totalBorrowAmtsWithFee[i] = add(
+					data.stableBorrowAmtsWithFee[i],
+					data.variableBorrowAmtsWithFee[i]
+				);
+
+				if (data.totalBorrowAmts[i] > 0) {
+					uint256 _amt = data.totalBorrowAmts[i];
+					TokenInterface(_token).approve(address(aave), _amt);
+				}
+			}
+		}
+		return data;
+	}
+
+	function getSupplyAmounts(
+		address userAccount,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal view returns (ImportData memory) {
+		data.supplyAmts = new uint256[](inputData.supplyTokens.length);
+		data._supplyTokens = new address[](inputData.supplyTokens.length);
+		data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
+
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
+				if (j != i) {
+					require(
+						inputData.supplyTokens[i] != inputData.supplyTokens[j],
+						"token-repeated"
+					);
+				}
+			}
+		}
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			address _token = inputData.supplyTokens[i] == avaxAddr
+				? wavaxAddr
+				: inputData.supplyTokens[i];
+			(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
+			data._supplyTokens[i] = _token;
+			data.aTokens[i] = ATokenInterface(_aToken);
+			data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
+		}
+
+		return data;
+	}
+
+	function _paybackBehalfOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode,
+		address user
+	) private {
+		aave.repay(token, amt, rateMode, user);
+	}
+
+	function _PaybackStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
+			}
+		}
+	}
+
+	function _PaybackVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
+			}
+		}
+	}
+
+	function _PermitATokens(
+		address userAccount,
+		ATokenInterface[] memory aTokenContracts,
+		address[] memory tokens,
+		uint8[] memory v,
+		bytes32[] memory r,
+		bytes32[] memory s,
+		uint256[] memory expiry
+	) internal {
+		for (uint256 i = 0; i < tokens.length; i++) {
+			aTokenContracts[i].permit(
+				userAccount,
+				address(this),
+				uint256(-1),
+				expiry[i],
+				v[i],
+				r[i],
+				s[i]
+			);
+		}
+	}
+
+	function _TransferAtokens(
+		uint256 _length,
+		AaveInterface aave,
+		ATokenInterface[] memory atokenContracts,
+		uint256[] memory amts,
+		address[] memory tokens,
+		address userAccount
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				uint256 _amt = amts[i];
+				require(
+					atokenContracts[i].transferFrom(
+						userAccount,
+						address(this),
+						_amt
+					),
+					"allowance?"
+				);
+
+				if (!getIsColl(tokens[i], address(this))) {
+					aave.setUserUseReserveAsCollateral(tokens[i], true);
+				}
+			}
+		}
+	}
+
+	function _BorrowVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 2);
+			}
+		}
+	}
+
+	function _BorrowStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 1);
+			}
+		}
+	}
+
+	function _borrowOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode
+	) private {
+		aave.borrow(token, amt, rateMode, referalCode, address(this));
+	}
+}
diff --git a/contracts/avalanche/connectors/aave/v3-import-permit/interface.sol b/contracts/avalanche/connectors/aave/v3-import-permit/interface.sol
new file mode 100644
index 00000000..55f15512
--- /dev/null
+++ b/contracts/avalanche/connectors/aave/v3-import-permit/interface.sol
@@ -0,0 +1,105 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+
+interface AaveInterface {
+	function supply(
+		address _asset,
+		uint256 _amount,
+		address _onBehalfOf,
+		uint16 _referralCode
+	) external;
+
+	function withdraw(
+		address _asset,
+		uint256 _amount,
+		address _to
+	) external;
+
+	function borrow(
+		address _asset,
+		uint256 _amount,
+		uint256 _interestRateMode,
+		uint16 _referralCode,
+		address _onBehalfOf
+	) external;
+
+	function repay(
+		address _asset,
+		uint256 _amount,
+		uint256 _rateMode,
+		address _onBehalfOf
+	) external;
+
+	function setUserUseReserveAsCollateral(
+		address _asset,
+		bool _useAsCollateral
+	) external;
+
+	function swapBorrowRateMode(address _asset, uint256 _rateMode) external;
+}
+
+interface ATokenInterface {
+	function scaledBalanceOf(address _user) external view returns (uint256);
+
+	function isTransferAllowed(address _user, uint256 _amount)
+		external
+		view
+		returns (bool);
+
+	function balanceOf(address _user) external view returns (uint256);
+
+	function permit(
+		address owner,
+		address spender,
+		uint256 value,
+		uint256 deadline,
+		uint8 v,
+		bytes32 r,
+		bytes32 s
+	) external;
+	
+	function transferFrom(
+		address,
+		address,
+		uint256
+	) external returns (bool);
+
+	function allowance(address, address) external returns (uint256);
+}
+
+interface AavePoolProviderInterface {
+	function getPool() external view returns (address);
+}
+
+interface AaveDataProviderInterface {
+	function getReserveTokensAddresses(address _asset)
+		external
+		view
+		returns (
+			address aTokenAddress,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		);
+
+	function getUserReserveData(address _asset, address _user)
+		external
+		view
+		returns (
+			uint256 currentATokenBalance,
+			uint256 currentStableDebt,
+			uint256 currentVariableDebt,
+			uint256 principalStableDebt,
+			uint256 scaledVariableDebt,
+			uint256 stableBorrowRate,
+			uint256 liquidityRate,
+			uint40 stableRateLastUpdated,
+			bool usageAsCollateralEnabled
+		);
+}
+
+interface AaveAddressProviderRegistryInterface {
+	function getAddressesProvidersList()
+		external
+		view
+		returns (address[] memory);
+}
diff --git a/contracts/avalanche/connectors/aave/v3-import-permit/main.sol b/contracts/avalanche/connectors/aave/v3-import-permit/main.sol
new file mode 100644
index 00000000..96f000ac
--- /dev/null
+++ b/contracts/avalanche/connectors/aave/v3-import-permit/main.sol
@@ -0,0 +1,132 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+/**
+ * @title Aave v3 import connector .
+ * @dev  Import EOA's aave V3 position to DSA's aave v3 position
+ */
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, ATokenInterface } from "./interface.sol";
+import "./helpers.sol";
+import "./events.sol";
+
+contract AaveV3ImportPermitResolver is AaveHelpers {
+	function _importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	) internal returns (string memory _eventName, bytes memory _eventParam) {
+		require(
+			AccountInterface(address(this)).isAuth(userAccount),
+			"user-account-not-auth"
+		);
+
+		require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
+
+		ImportData memory data;
+
+		AaveInterface aave = AaveInterface(aaveProvider.getPool());
+
+		data = getBorrowAmounts(userAccount, aave, inputData, data);
+		data = getSupplyAmounts(userAccount, inputData, data);
+
+		//  payback borrowed amount;
+		_PaybackStable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.stableBorrowAmts,
+			userAccount
+		);
+		_PaybackVariable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.variableBorrowAmts,
+			userAccount
+		);
+
+		//permit this address to transfer aTokens
+		_PermitATokens(
+			userAccount,
+			data.aTokens,
+			data._supplyTokens,
+			permitData.v,
+			permitData.r,
+			permitData.s,
+			permitData.expiry
+		);
+
+		//  transfer atokens to this address;
+		_TransferAtokens(
+			data._supplyTokens.length,
+			aave,
+			data.aTokens,
+			data.supplyAmts,
+			data._supplyTokens,
+			userAccount
+		);
+
+		// borrow assets after migrating position
+		if (data.convertStable) {
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.totalBorrowAmtsWithFee
+			);
+		} else {
+			_BorrowStable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.stableBorrowAmtsWithFee
+			);
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.variableBorrowAmtsWithFee
+			);
+		}
+
+		_eventName = "LogAaveV3ImportWithPermit(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])";
+		_eventParam = abi.encode(
+			userAccount,
+			inputData.convertStable,
+			inputData.supplyTokens,
+			inputData.borrowTokens,
+			inputData.flashLoanFees,
+			data.supplyAmts,
+			data.stableBorrowAmts,
+			data.variableBorrowAmts
+		);
+	}
+
+	/**
+	 * @dev Import aave V3 position .
+	 * @notice Import EOA's aave V3 position to DSA's aave v3 position
+	 * @param userAccount The address of the EOA from which aave position will be imported
+	 * @param inputData The struct containing all the neccessary input data
+	 * @param permitData The struct containing signed permit data like v,r,s,expiry
+	 */
+	function importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		(_eventName, _eventParam) = _importAave(
+			userAccount,
+			inputData,
+			permitData
+		);
+	}
+}
+
+contract ConnectV2AaveV3ImportPermitAvalanche is AaveV3ImportPermitResolver {
+	string public constant name = "Aave-v3-import-permit-v1";
+}
diff --git a/contracts/polygon/connectors/aave/v3-import-permit/events.sol b/contracts/polygon/connectors/aave/v3-import-permit/events.sol
new file mode 100644
index 00000000..10a93d70
--- /dev/null
+++ b/contracts/polygon/connectors/aave/v3-import-permit/events.sol
@@ -0,0 +1,15 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+contract Events {
+	event LogAaveV3ImportWithPermit(
+		address indexed user,
+		address[] atokens,
+		string[] supplyIds,
+		string[] borrowIds,
+		uint256[] flashLoanFees,
+		uint256[] supplyAmts,
+		uint256[] borrowAmts
+	);
+}
diff --git a/contracts/polygon/connectors/aave/v3-import-permit/helpers.sol b/contracts/polygon/connectors/aave/v3-import-permit/helpers.sol
new file mode 100644
index 00000000..dc514687
--- /dev/null
+++ b/contracts/polygon/connectors/aave/v3-import-permit/helpers.sol
@@ -0,0 +1,316 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+
+import { DSMath } from "../../../common/math.sol";
+import { Basic } from "../../../common/basic.sol";
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
+import "./events.sol";
+import "./interface.sol";
+
+abstract contract Helper is DSMath, Basic {
+	/**
+	 * @dev Aave referal code
+	 */
+	uint16 internal constant referalCode = 3228;
+
+	/**
+	 * @dev Aave Lending Pool Provider
+	 */
+	AavePoolProviderInterface internal constant aaveProvider =
+		AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb);
+
+	/**
+	 * @dev Aave Protocol Data Provider
+	 */
+	AaveDataProviderInterface internal constant aaveData =
+		AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654);
+
+	function getIsColl(address token, address user)
+		internal
+		view
+		returns (bool isCol)
+	{
+		(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
+	}
+
+	struct ImportData {
+		address[] _supplyTokens;
+		address[] _borrowTokens;
+		ATokenInterface[] aTokens;
+		uint256[] supplyAmts;
+		uint256[] variableBorrowAmts;
+		uint256[] variableBorrowAmtsWithFee;
+		uint256[] stableBorrowAmts;
+		uint256[] stableBorrowAmtsWithFee;
+		uint256[] totalBorrowAmts;
+		uint256[] totalBorrowAmtsWithFee;
+		bool convertStable;
+	}
+
+	struct ImportInputData {
+		address[] supplyTokens;
+		address[] borrowTokens;
+		bool convertStable;
+		uint256[] flashLoanFees;
+	}
+
+	struct SignedPermits {
+		uint8[] v;
+		bytes32[] r;
+		bytes32[] s;
+		uint256[] expiry;
+	}
+}
+
+contract AaveHelpers is Helper {
+	function getBorrowAmount(address _token, address userAccount)
+		internal
+		view
+		returns (uint256 stableBorrow, uint256 variableBorrow)
+	{
+		(
+			,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		) = aaveData.getReserveTokensAddresses(_token);
+
+		stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+		variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
+			userAccount
+		);
+	}
+
+	function getBorrowAmounts(
+		address userAccount,
+		AaveInterface aave,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal returns (ImportData memory) {
+		if (inputData.borrowTokens.length > 0) {
+			data._borrowTokens = new address[](inputData.borrowTokens.length);
+			data.variableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.variableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmts = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.stableBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
+			data.totalBorrowAmtsWithFee = new uint256[](
+				inputData.borrowTokens.length
+			);
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
+					if (j != i) {
+						require(
+							inputData.borrowTokens[i] !=
+								inputData.borrowTokens[j],
+							"token-repeated"
+						);
+					}
+				}
+			}
+			for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
+				address _token = inputData.borrowTokens[i] == maticAddr
+					? wmaticAddr
+					: inputData.borrowTokens[i];
+				data._borrowTokens[i] = _token;
+
+				(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				) = getBorrowAmount(_token, userAccount);
+
+				if (data.variableBorrowAmts[i] != 0) {
+					data.variableBorrowAmtsWithFee[i] = add(
+						data.variableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+					data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
+				} else {
+					data.stableBorrowAmtsWithFee[i] = add(
+						data.stableBorrowAmts[i],
+						inputData.flashLoanFees[i]
+					);
+				}
+
+				data.totalBorrowAmts[i] = add(
+					data.stableBorrowAmts[i],
+					data.variableBorrowAmts[i]
+				);
+				data.totalBorrowAmtsWithFee[i] = add(
+					data.stableBorrowAmtsWithFee[i],
+					data.variableBorrowAmtsWithFee[i]
+				);
+
+				if (data.totalBorrowAmts[i] > 0) {
+					uint256 _amt = data.totalBorrowAmts[i];
+					TokenInterface(_token).approve(address(aave), _amt);
+				}
+			}
+		}
+		return data;
+	}
+
+	function getSupplyAmounts(
+		address userAccount,
+		ImportInputData memory inputData,
+		ImportData memory data
+	) internal view returns (ImportData memory) {
+		data.supplyAmts = new uint256[](inputData.supplyTokens.length);
+		data._supplyTokens = new address[](inputData.supplyTokens.length);
+		data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
+
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
+				if (j != i) {
+					require(
+						inputData.supplyTokens[i] != inputData.supplyTokens[j],
+						"token-repeated"
+					);
+				}
+			}
+		}
+		for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
+			address _token = inputData.supplyTokens[i] == maticAddr
+				? wmaticAddr
+				: inputData.supplyTokens[i];
+			(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
+			data._supplyTokens[i] = _token;
+			data.aTokens[i] = ATokenInterface(_aToken);
+			data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
+		}
+
+		return data;
+	}
+
+	function _paybackBehalfOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode,
+		address user
+	) private {
+		aave.repay(token, amt, rateMode, user);
+	}
+
+	function _PaybackStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
+			}
+		}
+	}
+
+	function _PaybackVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts,
+		address user
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
+			}
+		}
+	}
+
+	function _PermitATokens(
+		address userAccount,
+		ATokenInterface[] memory aTokenContracts,
+		address[] memory tokens,
+		uint8[] memory v,
+		bytes32[] memory r,
+		bytes32[] memory s,
+		uint256[] memory expiry
+	) internal {
+		for (uint256 i = 0; i < tokens.length; i++) {
+			aTokenContracts[i].permit(
+				userAccount,
+				address(this),
+				uint256(-1),
+				expiry[i],
+				v[i],
+				r[i],
+				s[i]
+			);
+		}
+	}
+
+	function _TransferAtokens(
+		uint256 _length,
+		AaveInterface aave,
+		ATokenInterface[] memory atokenContracts,
+		uint256[] memory amts,
+		address[] memory tokens,
+		address userAccount
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				uint256 _amt = amts[i];
+				require(
+					atokenContracts[i].transferFrom(
+						userAccount,
+						address(this),
+						_amt
+					),
+					"allowance?"
+				);
+
+				if (!getIsColl(tokens[i], address(this))) {
+					aave.setUserUseReserveAsCollateral(tokens[i], true);
+				}
+			}
+		}
+	}
+
+	function _BorrowVariable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 2);
+			}
+		}
+	}
+
+	function _BorrowStable(
+		uint256 _length,
+		AaveInterface aave,
+		address[] memory tokens,
+		uint256[] memory amts
+	) internal {
+		for (uint256 i = 0; i < _length; i++) {
+			if (amts[i] > 0) {
+				_borrowOne(aave, tokens[i], amts[i], 1);
+			}
+		}
+	}
+
+	function _borrowOne(
+		AaveInterface aave,
+		address token,
+		uint256 amt,
+		uint256 rateMode
+	) private {
+		aave.borrow(token, amt, rateMode, referalCode, address(this));
+	}
+}
diff --git a/contracts/polygon/connectors/aave/v3-import-permit/interface.sol b/contracts/polygon/connectors/aave/v3-import-permit/interface.sol
new file mode 100644
index 00000000..32140247
--- /dev/null
+++ b/contracts/polygon/connectors/aave/v3-import-permit/interface.sol
@@ -0,0 +1,105 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+
+interface AaveInterface {
+	function supply(
+		address asset,
+		uint256 amount,
+		address onBehalfOf,
+		uint16 referralCode
+	) external;
+
+	function withdraw(
+		address _asset,
+		uint256 _amount,
+		address _to
+	) external;
+
+	function borrow(
+		address _asset,
+		uint256 _amount,
+		uint256 _interestRateMode,
+		uint16 _referralCode,
+		address _onBehalfOf
+	) external;
+
+	function repay(
+		address _asset,
+		uint256 _amount,
+		uint256 _rateMode,
+		address _onBehalfOf
+	) external;
+
+	function setUserUseReserveAsCollateral(
+		address _asset,
+		bool _useAsCollateral
+	) external;
+
+	function swapBorrowRateMode(address _asset, uint256 _rateMode) external;
+}
+
+interface ATokenInterface {
+	function scaledBalanceOf(address _user) external view returns (uint256);
+
+	function isTransferAllowed(address _user, uint256 _amount)
+		external
+		view
+		returns (bool);
+
+	function balanceOf(address _user) external view returns (uint256);
+
+	function permit(
+		address owner,
+		address spender,
+		uint256 value,
+		uint256 deadline,
+		uint8 v,
+		bytes32 r,
+		bytes32 s
+	) external;
+
+	function transferFrom(
+		address,
+		address,
+		uint256
+	) external returns (bool);
+
+	function allowance(address, address) external returns (uint256);
+}
+
+interface AavePoolProviderInterface {
+	function getPool() external view returns (address);
+}
+
+interface AaveDataProviderInterface {
+	function getReserveTokensAddresses(address _asset)
+		external
+		view
+		returns (
+			address aTokenAddress,
+			address stableDebtTokenAddress,
+			address variableDebtTokenAddress
+		);
+
+	function getUserReserveData(address _asset, address _user)
+		external
+		view
+		returns (
+			uint256 currentATokenBalance,
+			uint256 currentStableDebt,
+			uint256 currentVariableDebt,
+			uint256 principalStableDebt,
+			uint256 scaledVariableDebt,
+			uint256 stableBorrowRate,
+			uint256 liquidityRate,
+			uint40 stableRateLastUpdated,
+			bool usageAsCollateralEnabled
+		);
+}
+
+interface AaveAddressProviderRegistryInterface {
+	function getAddressesProvidersList()
+		external
+		view
+		returns (address[] memory);
+}
diff --git a/contracts/polygon/connectors/aave/v3-import-permit/main.sol b/contracts/polygon/connectors/aave/v3-import-permit/main.sol
new file mode 100644
index 00000000..8a6c61a5
--- /dev/null
+++ b/contracts/polygon/connectors/aave/v3-import-permit/main.sol
@@ -0,0 +1,133 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+/**
+ * @title Aave v3 import connector .
+ * @dev  Import EOA's aave V3 position to DSA's aave v3 position
+ */
+
+import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
+import { AaveInterface, ATokenInterface } from "./interface.sol";
+import "./helpers.sol";
+import "./events.sol";
+
+contract AaveV3ImportPermitResolver is AaveHelpers {
+	function _importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	) internal returns (string memory _eventName, bytes memory _eventParam) {
+		require(
+			AccountInterface(address(this)).isAuth(userAccount),
+			"user-account-not-auth"
+		);
+
+		require(inputData.supplyTokens.length > 0, "0-length-not-allowed");
+
+		ImportData memory data;
+
+		AaveInterface aave = AaveInterface(aaveProvider.getPool());
+
+		data = getBorrowAmounts(userAccount, aave, inputData, data);
+		data = getSupplyAmounts(userAccount, inputData, data);
+
+		//  payback borrowed amount;
+		_PaybackStable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.stableBorrowAmts,
+			userAccount
+		);
+		_PaybackVariable(
+			data._borrowTokens.length,
+			aave,
+			data._borrowTokens,
+			data.variableBorrowAmts,
+			userAccount
+		);
+
+		//permit this address to transfer aTokens
+		_PermitATokens(
+			userAccount,
+			data.aTokens,
+			data._supplyTokens,
+			permitData.v,
+			permitData.r,
+			permitData.s,
+			permitData.expiry
+		);
+
+		//  transfer atokens to this address;
+		_TransferAtokens(
+			data._supplyTokens.length,
+			aave,
+			data.aTokens,
+			data.supplyAmts,
+			data._supplyTokens,
+			userAccount
+		);
+
+		// borrow assets after migrating position
+		if (data.convertStable) {
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.totalBorrowAmtsWithFee
+			);
+		} else {
+			_BorrowStable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.stableBorrowAmtsWithFee
+			);
+			_BorrowVariable(
+				data._borrowTokens.length,
+				aave,
+				data._borrowTokens,
+				data.variableBorrowAmtsWithFee
+			);
+		}
+
+		_eventName = "LogAaveV3ImportWithPermit(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])";
+		_eventParam = abi.encode(
+			userAccount,
+			inputData.convertStable,
+			inputData.supplyTokens,
+			inputData.borrowTokens,
+			inputData.flashLoanFees,
+			data.supplyAmts,
+			data.stableBorrowAmts,
+			data.variableBorrowAmts
+		);
+	}
+
+	/**
+	 * @dev Import aave V3 position .
+	 * @notice Import EOA's aave V3 position to DSA's aave v3 position
+	 * @param userAccount The address of the EOA from which aave position will be imported
+	 * @param inputData The struct containing all the neccessary input data
+	 * @param permitData The struct containing signed permit data like v,r,s,expiry
+	 */
+	function importAave(
+		address userAccount,
+		ImportInputData memory inputData,
+		SignedPermits memory permitData
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		(_eventName, _eventParam) = _importAave(
+			userAccount,
+			inputData,
+			permitData
+		);
+	}
+}
+
+contract ConnectV2AaveV3ImportPermitPolygon is AaveV3ImportPermitResolver {
+	string public constant name = "Aave-v3-import-permit-v1";
+}
diff --git a/scripts/tests/addLiquidity.ts b/scripts/tests/addLiquidity.ts
index a1250bcc..fd969222 100644
--- a/scripts/tests/addLiquidity.ts
+++ b/scripts/tests/addLiquidity.ts
@@ -4,6 +4,7 @@ import { impersonateAccounts } from "./impersonate";
 import { tokenMapping as mainnetMapping } from "./mainnet/tokens";
 import { tokenMapping as polygonMapping } from "./polygon/tokens";
 import { tokenMapping as avalancheMapping } from "./avalanche/tokens";
+import { tokenMapping as optimismMapping } from "./optimism/tokens";
 
 const mineTx = async (tx: any) => {
   await (await tx).wait();
@@ -12,7 +13,8 @@ const mineTx = async (tx: any) => {
 const tokenMapping: Record<string, Record<string, any>> = {
   mainnet: mainnetMapping,
   polygon: polygonMapping,
-  avalanche: avalancheMapping
+  avalanche: avalancheMapping,
+  optimism: optimismMapping
 };
 
 export async function addLiquidity(tokenName: string, address: any, amt: any) {
diff --git a/scripts/tests/buildDSAv2.ts b/scripts/tests/buildDSAv2.ts
index 163db741..e54dd68d 100644
--- a/scripts/tests/buildDSAv2.ts
+++ b/scripts/tests/buildDSAv2.ts
@@ -3,6 +3,7 @@ import { ethers } from "hardhat";
 import { addresses as addressesPolygon } from "./polygon/addresses";
 import { addresses as addressesArbitrum } from "./arbitrum/addresses";
 import { addresses as addressesAvalanche } from "./avalanche/addresses";
+import { addresses as addressesOptimism } from "./optimism/addresses";
 import { addresses } from "./mainnet/addresses";
 import { abis } from "../constant/abis";
 import { abi } from "../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json";
@@ -11,6 +12,7 @@ function getAddress(network: string | undefined) {
   if (network === "polygon") return addressesPolygon.core.instaIndex;
   else if (network === "arbitrum") return addressesArbitrum.core.instaIndex;
   else if (network === "avalanche") return addressesAvalanche.core.instaIndex;
+  else if (network === "optimism") return addressesOptimism.core.instaIndex;
   else return addresses.core.instaIndex;
 }
 
diff --git a/scripts/tests/deployAndEnableConnector.ts b/scripts/tests/deployAndEnableConnector.ts
index e08142e4..fe3d71dd 100644
--- a/scripts/tests/deployAndEnableConnector.ts
+++ b/scripts/tests/deployAndEnableConnector.ts
@@ -3,6 +3,7 @@ import { addresses } from "./mainnet/addresses";
 import { abis } from "../constant/abis";
 import { addresses as addressesArbitrum } from "./arbitrum/addresses";
 import { addresses as addressesAvalanche } from "./avalanche/addresses";
+import { addresses as addressesOptimism } from "./optimism/addresses";
 
 import hre from "hardhat";
 import type { Signer, Contract } from "ethers";
@@ -22,6 +23,7 @@ function getAddress(network: string | undefined) {
   if (network === "polygon") return addressesPolygon;
   else if (network === "arbitrum") return addressesArbitrum;
   else if (network === "avalanche") return addressesAvalanche;
+  else if (network === "optimism") return addressesOptimism;
   else return addresses;
 }
 
diff --git a/scripts/tests/getMasterSigner.ts b/scripts/tests/getMasterSigner.ts
index c09fec74..040e4e4f 100644
--- a/scripts/tests/getMasterSigner.ts
+++ b/scripts/tests/getMasterSigner.ts
@@ -3,12 +3,14 @@ import { addresses } from "./mainnet/addresses";
 import { addresses as addressesPolygon } from "./polygon/addresses";
 import { addresses as addressesArbitrum } from "./arbitrum/addresses";
 import { addresses as addressesAvalanche } from "./avalanche/addresses";
+import { addresses as addressesOptimism } from "./optimism/addresses";
 import { abis } from "../constant/abis";
 
 function getAddress(network: string | undefined) {
   if (network === "polygon") return addressesPolygon.core.instaIndex;
   else if (network === "arbitrum") return addressesArbitrum.core.instaIndex;
   else if (network === "avalanche") return addressesAvalanche.core.instaIndex;
+  else if (network === "optimism") return addressesOptimism.core.instaIndex;
   else return addresses.core.instaIndex;
 }
 
diff --git a/scripts/tests/global-test.ts b/scripts/tests/global-test.ts
index 444abe8e..4c137c33 100644
--- a/scripts/tests/global-test.ts
+++ b/scripts/tests/global-test.ts
@@ -6,7 +6,7 @@ import { execScript } from "./command";
 let start: number, end: number;
 
 async function testRunner() {
-  const chain = ["avalanche", "mainnet", "polygon", "arbitrum"];
+  const chain = ["avalanche", "mainnet", "polygon", "arbitrum", "optimism"];
   start = Date.now();
 
   for (let ch of chain) {
diff --git a/scripts/tests/optimism/addresses.ts b/scripts/tests/optimism/addresses.ts
new file mode 100644
index 00000000..ecd46a57
--- /dev/null
+++ b/scripts/tests/optimism/addresses.ts
@@ -0,0 +1,10 @@
+export const addresses: Record<string, any> = {
+  connectors: {
+    basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
+    auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
+  },
+  core: {
+    connectorsV2: "0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14",
+    instaIndex: "0x6CE3e607C808b4f4C26B7F6aDAeB619e49CAbb25",
+  },
+};
\ No newline at end of file
diff --git a/scripts/tests/optimism/tokens.ts b/scripts/tests/optimism/tokens.ts
new file mode 100644
index 00000000..d12cd92c
--- /dev/null
+++ b/scripts/tests/optimism/tokens.ts
@@ -0,0 +1,87 @@
+import { Provider } from "@ethersproject/abstract-provider";
+import { Signer } from "@ethersproject/abstract-signer";
+import { ethers } from "hardhat";
+
+const mineTx = async (tx: any) => {
+  await (await tx).wait();
+};
+
+export const tokens = {
+  eth: {
+    type: "token",
+    symbol: "ETH",
+    name: "Eth",
+    address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
+    decimals: 18,
+  },
+  dai: {
+    type: "token",
+    symbol: "DAI",
+    name: "DAI Stable",
+    address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
+    decimals: 18,
+  },
+  usdc: {
+    type: "token",
+    symbol: "USDC",
+    name: "USD Coin",
+    address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
+    decimals: 6,
+  },
+};
+
+export const tokenMapping: Record<string, any> = {
+  usdc: {
+    impersonateSigner: "0x31efc4aeaa7c39e54a33fdc3c46ee2bd70ae0a09",
+    address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
+    abi: [
+      "function mint(address _to, uint256 _amount) external returns (bool);",
+    ],
+    process: async function (owner: Signer | Provider, to: any, amt: any) {
+      const contract = new ethers.Contract(this.address, this.abi, owner);
+
+      await mineTx(contract.mint(to, amt));
+    },
+  },
+  dai: {
+    impersonateSigner: "0x31efc4aeaa7c39e54a33fdc3c46ee2bd70ae0a09",
+    address: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
+    abi: ["function transfer(address to, uint value)"],
+    process: async function (owner: Signer | Provider, to: any, amt: any) {
+      const contract = new ethers.Contract(this.address, this.abi, owner);
+      await mineTx(contract.transfer(to, amt));
+    },
+  },
+  usdt: {
+    impersonateSigner: "0x31efc4aeaa7c39e54a33fdc3c46ee2bd70ae0a09",
+    address: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
+    abi: [
+      "function issue(uint amount)",
+      "function transfer(address to, uint value)",
+    ],
+    process: async function (owner: Signer | Provider, address: any, amt: any) {
+      const contract = new ethers.Contract(this.address, this.abi, owner);
+
+      await mineTx(contract.issue(amt));
+      await mineTx(contract.transfer(address, amt));
+    },
+  },
+  wbtc: {
+    impersonateSigner: "0x3aa76aa74bdfa09d68d9ebeb462c5f40d727283f",
+    address: "0x68f180fcCe6836688e9084f035309E29Bf0A2095",
+    abi: ["function mint(address _to, uint256 _amount) public returns (bool)"],
+    process: async function (owner: Signer | Provider, address: any, amt: any) {
+      const contract = new ethers.Contract(this.address, this.abi, owner);
+      await mineTx(contract.mint(address, amt));
+    },
+  },
+  // inst: {
+  //   impersonateSigner: "0xf1f22f25f748f79263d44735198e023b72806ab1",
+  //   address: "0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb",
+  //   abi: ["function transfer(address to, uint value)"],
+  //   process: async function (owner: Signer | Provider, address: any, amt: any) {
+  //     const contract = new ethers.Contract(this.address, this.abi, owner);
+  //     await mineTx(contract.transfer(address, amt));
+  //   },
+  // },
+};
diff --git a/scripts/tests/run-tests.ts b/scripts/tests/run-tests.ts
index 9a3c3927..5b2f22bd 100644
--- a/scripts/tests/run-tests.ts
+++ b/scripts/tests/run-tests.ts
@@ -12,7 +12,7 @@ async function testRunner() {
       name: "chain",
       message: "What chain do you want to run tests on?",
       type: "list",
-      choices: ["mainnet", "polygon", "avalanche", "arbitrum"],
+      choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism"],
     },
   ]);
   const testsPath = join(__dirname, "../../test", chain);
diff --git a/test/arbitrum/aave/aaveV3-import-test.ts b/test/arbitrum/aave/aaveV3-import-test.ts
new file mode 100644
index 00000000..88ce4533
--- /dev/null
+++ b/test/arbitrum/aave/aaveV3-import-test.ts
@@ -0,0 +1,303 @@
+import { expect, should } from "chai";
+import hre, { ethers, waffle } from "hardhat";
+import type { Signer, Contract } from "ethers";
+import { ecsign, ecrecover, pubToAddress } from "ethereumjs-util";
+import { keccak256 } from "@ethersproject/keccak256";
+import { defaultAbiCoder } from "@ethersproject/abi";
+import { BigNumber } from "bignumber.js";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import { addresses } from "../../../scripts/tests/arbitrum/addresses";
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { abis } from "../../../scripts/constant/abis";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { parseEther, parseUnits } from "ethers/lib/utils";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData";
+import { ConnectV2AaveV3ImportPermitArbitrum__factory, IERC20__factory } from "../../../typechain";
+
+const ABI = [
+  "function DOMAIN_SEPARATOR() public view returns (bytes32)",
+  "function balanceOf(address account) public view returns (uint256)",
+  "function nonces(address owner) public view returns (uint256)"
+];
+
+const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE"; 
+const aaveAddress = "0x794a61358D6845594F94dc1DB02A252b5b4814aD";
+let account = "0xc5ed2333f8a2c351fca35e5ebadb2a82f5d254c3";
+const DAI = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";
+const USDC = "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8";
+const mnemonic = "test test test test test test test test test test test junk";
+const connectorName = "AAVE-V3-IMPORT-PERMIT-X";
+let signer: any, wallet0: any;
+
+const aaveAbi = [
+  {
+    inputs: [
+      { internalType: "address", name: "asset", type: "address" },
+      { internalType: "uint256", name: "amount", type: "uint256" },
+      { internalType: "uint256", name: "interestRateMode", type: "uint256" },
+      { internalType: "uint16", name: "referralCode", type: "uint16" },
+      { internalType: "address", name: "onBehalfOf", type: "address" }
+    ],
+    name: "borrow",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    inputs: [
+      { internalType: "address", name: "asset", type: "address" },
+      { internalType: "uint256", name: "amount", type: "uint256" },
+      { internalType: "address", name: "onBehalfOf", type: "address" },
+      { internalType: "uint16", name: "referralCode", type: "uint16" }
+    ],
+    name: "supply",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const erc20Abi = [
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_spender",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "approve",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    constant: true,
+    inputs: [],
+    name: "totalSupply",
+    outputs: [
+      {
+        name: "",
+        type: "uint256"
+      }
+    ],
+    payable: false,
+    stateMutability: "view",
+    type: "function"
+  },
+  {
+    constant: true,
+    inputs: [
+      {
+        name: "_owner",
+        type: "address"
+      }
+    ],
+    name: "balanceOf",
+    outputs: [
+      {
+        name: "balance",
+        type: "uint256"
+      }
+    ],
+    payable: false,
+    stateMutability: "view",
+    type: "function"
+  },
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_to",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "transfer",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const token = new ethers.Contract(DAI, erc20Abi);
+const aDai = new ethers.Contract(aDaiAddress, ABI);
+const usdcToken = new ethers.Contract(USDC, erc20Abi);
+const aave = new ethers.Contract(aaveAddress, aaveAbi);
+
+describe("Import Aave v3 Position for Arbitrum", function () {
+  let dsaWallet0: any;
+  let masterSigner: Signer;
+  let instaConnectorsV2: Contract;
+  let connector: any;
+
+  const wallet = ethers.Wallet.fromMnemonic(mnemonic);
+
+  before(async () => {
+    await hre.network.provider.request({
+      method: "hardhat_reset",
+      params: [
+        {
+          forking: {
+            //@ts-ignore
+            jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+            blockNumber: 9333600
+          }
+        }
+      ]
+    });
+    masterSigner = await getMasterSigner();
+    [wallet0] = await ethers.getSigners();
+    await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
+
+    await hre.network.provider.request({
+      method: "hardhat_impersonateAccount",
+      params: [account]
+    });
+
+    signer = await ethers.getSigner(account);
+
+    await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("10"));
+
+    instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+    connector = await deployAndEnableConnector({
+      connectorName,
+      contractArtifact: ConnectV2AaveV3ImportPermitArbitrum__factory,
+      signer: masterSigner,
+      connectors: instaConnectorsV2
+    });
+  });
+
+  describe("check user AAVE position", async () => {
+    it("Should create Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
+      // approve DAI to aavePool
+      await token.connect(wallet0).approve(aaveAddress, parseEther("10"));
+
+      //deposit DAI in aave
+      await aave.connect(wallet0).supply(DAI, parseEther("10"), wallet.address, 3228);
+      console.log("Supplied DAI on aave");
+
+      //borrow USDC from aave
+      await aave.connect(wallet0).borrow(USDC, parseUnits("3", 6), 2, 3228, wallet.address);
+      console.log("Borrowed USDC from aave");
+    });
+
+    it("Should check position of user", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(10).multipliedBy(1e18).toString()
+      );
+
+      expect(await usdcToken.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(3).multipliedBy(1e6).toString()
+      );
+    });
+  });
+
+  describe("Deployment", async () => {
+    it("Should set correct name", async () => {
+      expect(await connector.name()).to.eq("Aave-v3-import-permit-v1");
+    });
+  });
+
+  describe("DSA wallet setup", async () => {
+    it("Should build DSA v2", async () => {
+      dsaWallet0 = await buildDSAv2(wallet.address);
+      expect(!!dsaWallet0.address).to.be.true;
+    });
+
+    it("Deposit ETH into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("5")
+      });
+
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
+    });
+  });
+
+  describe("Aave position migration", async () => {
+    it("Should migrate Aave position", async () => {
+      const DOMAIN_SEPARATOR = await aDai.connect(wallet0).DOMAIN_SEPARATOR();
+      const PERMIT_TYPEHASH = "0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9";
+
+      let nonce = (await aDai.connect(wallet0).nonces(wallet.address)).toNumber();
+      //Approving max amount
+      const amount = ethers.constants.MaxUint256;
+      const expiry = Date.now() + 20 * 60;
+
+      const digest = keccak256(
+        ethers.utils.solidityPack(
+          ["bytes1", "bytes1", "bytes32", "bytes32"],
+          [
+            "0x19",
+            "0x01",
+            DOMAIN_SEPARATOR,
+            keccak256(
+              defaultAbiCoder.encode(
+                ["bytes32", "address", "address", "uint256", "uint256", "uint256"],
+                [PERMIT_TYPEHASH, wallet.address, dsaWallet0.address, amount, nonce, expiry]
+              )
+            )
+          ]
+        )
+      );
+      const { v, r, s } = ecsign(Buffer.from(digest.slice(2), "hex"), Buffer.from(wallet.privateKey.slice(2), "hex"));
+      const amount0 = new BigNumber(await usdcToken.connect(wallet0).balanceOf(wallet.address));
+      const amountB = new BigNumber(amount0.toString()).multipliedBy(5).dividedBy(1e4);
+      const amountWithFee = amount0.plus(amountB);
+
+      const flashSpells = [
+        {
+          connector: "AAVE-V3-IMPORT-PERMIT-X",
+          method: "importAave",
+          args: [
+            wallet.address,
+            [[DAI], [USDC], false, [amountB.toFixed(0)]],
+            [[v], [ethers.utils.hexlify(r)], [ethers.utils.hexlify(s)], [expiry]]
+          ]
+        },
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashPayback",
+          args: [USDC, amountWithFee.toFixed(0), 0, 0]
+        }
+      ];
+
+      const spells = [
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashBorrowAndCast",
+          args: [USDC, amount0.toString(), 5, encodeFlashcastData(flashSpells), "0x"]
+        }
+      ];
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet.address);
+      const receipt = await tx.wait();
+    });
+
+    it("Should check DSA AAVE position", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
+        new BigNumber(10).multipliedBy(1e18).toString()
+      );
+    });
+  });
+});
diff --git a/test/avalanche/aave/aaveV3-import-test.ts b/test/avalanche/aave/aaveV3-import-test.ts
new file mode 100644
index 00000000..563ccec0
--- /dev/null
+++ b/test/avalanche/aave/aaveV3-import-test.ts
@@ -0,0 +1,353 @@
+import { expect, should } from "chai";
+import hre, { ethers, waffle } from "hardhat";
+import type { Signer, Contract } from "ethers";
+import { ecsign, ecrecover, pubToAddress } from "ethereumjs-util";
+import { keccak256 } from "@ethersproject/keccak256";
+import { defaultAbiCoder } from "@ethersproject/abi";
+import { BigNumber } from "bignumber.js";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import { addresses } from "../../../scripts/tests/avalanche/addresses";
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { abis } from "../../../scripts/constant/abis";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { parseEther, parseUnits } from "ethers/lib/utils";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData";
+import { ConnectV2AaveV3ImportPermitAvalanche__factory, IERC20__factory } from "../../../typechain";
+
+const ABI = [
+  "function DOMAIN_SEPARATOR() public view returns (bytes32)",
+  "function balanceOf(address account) public view returns (uint256)",
+  "function nonces(address owner) public view returns (uint256)"
+];
+
+const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE"; 
+const aaveAddress = "0x794a61358d6845594f94dc1db02a252b5b4814ad";
+// const account = "0xf04adbf75cdfc5ed26eea4bbbb991db002036bdd";
+let account = "0x95eEA1Bdd19A8C40E9575048Dd0d6577D11a84e5";
+const DAI = "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70";
+const ETH = "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB";
+const mnemonic = "test test test test test test test test test test test junk";
+const connectorName = "AAVE-V3-IMPORT-PERMIT-X";
+let signer: any, wallet0: any;
+
+const aaveAbi =[
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "uint256",
+        name: "interestRateMode",
+        type: "uint256"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      }
+    ],
+    name: "borrow",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      }
+    ],
+    name: "deposit",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      }
+    ],
+    name: "supply",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const erc20Abi = [
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_spender",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "approve",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    constant: true,
+    inputs: [
+      {
+        name: "_owner",
+        type: "address"
+      }
+    ],
+    name: "balanceOf",
+    outputs: [
+      {
+        name: "balance",
+        type: "uint256"
+      }
+    ],
+    payable: false,
+    stateMutability: "view",
+    type: "function"
+  },
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_to",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "transfer",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const token = new ethers.Contract(DAI, erc20Abi);
+const aDai = new ethers.Contract(aDaiAddress, ABI);
+const ethToken = new ethers.Contract(ETH, erc20Abi);
+const aave = new ethers.Contract(aaveAddress, aaveAbi);
+
+describe("Import Aave v3 Position for Avalanche", function () {
+  let dsaWallet0: any;
+  let masterSigner: Signer;
+  let instaConnectorsV2: Contract;
+  let connector: any;
+
+  const wallet = ethers.Wallet.fromMnemonic(mnemonic);
+
+  before(async () => {
+    await hre.network.provider.request({
+      method: "hardhat_reset",
+      params: [
+        {
+          forking: {
+            //@ts-ignore
+            jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+            blockNumber: 13024200
+          }
+        }
+      ]
+    });
+    masterSigner = await getMasterSigner();
+    [wallet0] = await ethers.getSigners();
+    await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
+
+    await hre.network.provider.request({
+      method: "hardhat_impersonateAccount",
+      params: [account]
+    });
+
+    signer = await ethers.getSigner(account);
+
+    await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("8"));
+    instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+    connector = await deployAndEnableConnector({
+      connectorName,
+      contractArtifact: ConnectV2AaveV3ImportPermitAvalanche__factory,
+      signer: masterSigner,
+      connectors: instaConnectorsV2
+    });
+  });
+
+  describe("check user AAVE position", async () => {
+    it("Should create Aave v3 position of DAI(collateral) and ETH(debt)", async () => {
+      // approve DAI to aavePool
+      await token.connect(wallet0).approve(aaveAddress, parseEther("8"));
+
+      //deposit DAI in aave
+      await aave.connect(wallet0).supply(DAI, parseEther("8"), wallet.address, 3228);
+      console.log("Supplied DAI on aave");
+
+      //borrow ETH from aave
+      await aave.connect(wallet0).borrow(ETH, parseUnits("3", 6), 2, 3228, wallet.address);
+      console.log("Borrowed ETH from aave");
+    });
+
+    it("Should check position of user", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(8).multipliedBy(1e18).toString()
+      );
+
+      expect(await ethToken.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(3).multipliedBy(1e6).toString()
+      );
+    });
+  });
+
+  describe("Deployment", async () => {
+    it("Should set correct name", async () => {
+      expect(await connector.name()).to.eq("Aave-v3-import-permit-v1");
+    });
+  });
+
+  describe("DSA wallet setup", async () => {
+    it("Should build DSA v2", async () => {
+      dsaWallet0 = await buildDSAv2(wallet.address);
+      expect(!!dsaWallet0.address).to.be.true;
+    });
+
+    it("Deposit ETH into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("3")
+      });
+
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("3"));
+    });
+  });
+
+  describe("Aave position migration", async () => {
+    it("Should migrate Aave position", async () => {
+      const DOMAIN_SEPARATOR = await aDai.connect(wallet0).DOMAIN_SEPARATOR();
+      const PERMIT_TYPEHASH = "0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9";
+
+      let nonce = (await aDai.connect(wallet0).nonces(wallet.address)).toNumber();
+      //Approving max amount
+      const amount = ethers.constants.MaxUint256;
+      const expiry = Date.now() + 20 * 60;
+
+      const digest = keccak256(
+        ethers.utils.solidityPack(
+          ["bytes1", "bytes1", "bytes32", "bytes32"],
+          [
+            "0x19",
+            "0x01",
+            DOMAIN_SEPARATOR,
+            keccak256(
+              defaultAbiCoder.encode(
+                ["bytes32", "address", "address", "uint256", "uint256", "uint256"],
+                [PERMIT_TYPEHASH, wallet.address, dsaWallet0.address, amount, nonce, expiry]
+              )
+            )
+          ]
+        )
+      );
+      const { v, r, s } = ecsign(Buffer.from(digest.slice(2), "hex"), Buffer.from(wallet.privateKey.slice(2), "hex"));
+      const amount0 = new BigNumber(await ethToken.connect(wallet0).balanceOf(wallet.address));
+      const amountB = new BigNumber(amount0.toString()).multipliedBy(9).dividedBy(1e4);
+      const amountWithFee = amount0.plus(amountB);
+
+      const flashSpells = [
+        {
+          connector: "AAVE-V3-IMPORT-PERMIT-X",
+          method: "importAave",
+          args: [
+            wallet.address,
+            [[DAI], [ETH], false, [amountB.toFixed(0)]],
+            [[v], [ethers.utils.hexlify(r)], [ethers.utils.hexlify(s)], [expiry]]
+          ]
+        },
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashPayback",
+          args: [ETH, amountWithFee.toFixed(0), 0, 0]
+        }
+      ];
+
+      const spells = [
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashBorrowAndCast",
+          args: [ETH, amount0.toString(), 1, encodeFlashcastData(flashSpells), "0x"]
+        }
+      ];
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet.address);
+      const receipt = await tx.wait();
+    });
+
+    it("Should check DSA AAVE position", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
+        new BigNumber(3).multipliedBy(1e18).toString()
+      );
+    });
+  });
+});
\ No newline at end of file
diff --git a/test/polygon/aave/aaveV3-import-test.ts b/test/polygon/aave/aaveV3-import-test.ts
new file mode 100644
index 00000000..86fd50dd
--- /dev/null
+++ b/test/polygon/aave/aaveV3-import-test.ts
@@ -0,0 +1,368 @@
+import { expect, should } from "chai";
+import hre, { ethers, waffle } from "hardhat";
+import type { Signer, Contract } from "ethers";
+import { ecsign, ecrecover, pubToAddress } from "ethereumjs-util";
+import { keccak256 } from "@ethersproject/keccak256";
+import { toUtf8Bytes } from "@ethersproject/strings";
+import { defaultAbiCoder } from "@ethersproject/abi";
+import { BigNumber } from "bignumber.js";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import { addresses } from "../../../scripts/tests/polygon/addresses";
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { abis } from "../../../scripts/constant/abis";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { parseEther, parseUnits } from "ethers/lib/utils";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData";
+import { ConnectV2AaveV3ImportPermitPolygon__factory, IERC20__factory } from "../../../typechain";
+
+const ABI = [
+  "function DOMAIN_SEPARATOR() public view returns (bytes32)",
+  "function balanceOf(address account) public view returns (uint256)",
+  "function nonces(address owner) public view returns (uint256)"
+];
+
+const aDaiAddress = "0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE";
+const aaveAddress = "0x794a61358D6845594F94dc1DB02A252b5b4814aD";
+const account = "0xf04adbf75cdfc5ed26eea4bbbb991db002036bdd";
+const DAI = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063";
+const USDC = "0x2791bca1f2de4661ed88a30c99a7a9449aa84174";
+const mnemonic = "test test test test test test test test test test test junk";
+const connectorName = "AAVE-V3-IMPORT-PERMIT-X";
+let signer: any, wallet0: any;
+
+const aaveAbi = [
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "uint256",
+        name: "interestRateMode",
+        type: "uint256"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      }
+    ],
+    name: "borrow",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      }
+    ],
+    name: "deposit",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    inputs: [
+      {
+        internalType: "address",
+        name: "asset",
+        type: "address"
+      },
+      {
+        internalType: "uint256",
+        name: "amount",
+        type: "uint256"
+      },
+      {
+        internalType: "address",
+        name: "onBehalfOf",
+        type: "address"
+      },
+      {
+        internalType: "uint16",
+        name: "referralCode",
+        type: "uint16"
+      }
+    ],
+    name: "supply",
+    outputs: [],
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const erc20Abi = [
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_spender",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "approve",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  },
+  {
+    constant: true,
+    inputs: [],
+    name: "totalSupply",
+    outputs: [
+      {
+        name: "",
+        type: "uint256"
+      }
+    ],
+    payable: false,
+    stateMutability: "view",
+    type: "function"
+  },
+  {
+    constant: true,
+    inputs: [
+      {
+        name: "_owner",
+        type: "address"
+      }
+    ],
+    name: "balanceOf",
+    outputs: [
+      {
+        name: "balance",
+        type: "uint256"
+      }
+    ],
+    payable: false,
+    stateMutability: "view",
+    type: "function"
+  },
+  {
+    constant: false,
+    inputs: [
+      {
+        name: "_to",
+        type: "address"
+      },
+      {
+        name: "_value",
+        type: "uint256"
+      }
+    ],
+    name: "transfer",
+    outputs: [
+      {
+        name: "",
+        type: "bool"
+      }
+    ],
+    payable: false,
+    stateMutability: "nonpayable",
+    type: "function"
+  }
+];
+
+const token = new ethers.Contract(DAI, erc20Abi);
+const aDai = new ethers.Contract(aDaiAddress, ABI);
+const usdcToken = new ethers.Contract(USDC, erc20Abi);
+const aave = new ethers.Contract(aaveAddress, aaveAbi);
+
+describe("Import Aave v3 Position", function () {
+  let dsaWallet0: any;
+  let masterSigner: Signer;
+  let instaConnectorsV2: Contract;
+  let connector: any;
+
+  const wallet = ethers.Wallet.fromMnemonic(mnemonic);
+
+  before(async () => {
+    await hre.network.provider.request({
+      method: "hardhat_reset",
+      params: [
+        {
+          forking: {
+            //@ts-ignore
+            jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+            blockNumber: 26652016
+          }
+        }
+      ]
+    });
+    masterSigner = await getMasterSigner();
+    [wallet0] = await ethers.getSigners();
+    await hre.network.provider.send("hardhat_setBalance", [account, ethers.utils.parseEther("10").toHexString()]);
+
+    await hre.network.provider.request({
+      method: "hardhat_impersonateAccount",
+      params: [account]
+    });
+
+    signer = await ethers.getSigner(account);
+
+    await token.connect(signer).transfer(wallet0.address, ethers.utils.parseEther("8"));
+
+    instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+    connector = await deployAndEnableConnector({
+      connectorName,
+      contractArtifact: ConnectV2AaveV3ImportPermitPolygon__factory,
+      signer: masterSigner,
+      connectors: instaConnectorsV2
+    });
+  });
+
+  describe("check user AAVE position", async () => {
+    it("Should create Aave v3 position of DAI(collateral) and USDC(debt)", async () => {
+      // approve DAI to aavePool
+      await token.connect(wallet0).approve(aaveAddress, parseEther("8"));
+
+      //deposit DAI in aave
+      await aave.connect(wallet0).supply(DAI, parseEther("8"), wallet.address, 3228);
+      console.log("Supplied DAI on aave");
+
+      //borrow USDC from aave
+      await aave.connect(wallet0).borrow(USDC, parseUnits("5", 6), 2, 3228, wallet.address);
+      console.log("Borrowed USDC from aave");
+    });
+
+    it("Should check position of user", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(8).multipliedBy(1e18).toString()
+      );
+
+      expect(await usdcToken.connect(wallet0).balanceOf(wallet.address)).to.be.gte(
+        new BigNumber(5).multipliedBy(1e6).toString()
+      );
+    });
+  });
+
+  describe("Deployment", async () => {
+    it("Should set correct name", async () => {
+      expect(await connector.name()).to.eq("Aave-v3-import-permit-v1");
+    });
+  });
+
+  describe("DSA wallet setup", async () => {
+    it("Should build DSA v2", async () => {
+      dsaWallet0 = await buildDSAv2(wallet.address);
+      expect(!!dsaWallet0.address).to.be.true;
+    });
+
+    it("Deposit ETH into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("5")
+      });
+
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("5"));
+    });
+  });
+
+  describe("Aave position migration", async () => {
+    it("Should migrate Aave position", async () => {
+      const DOMAIN_SEPARATOR = await aDai.connect(wallet0).DOMAIN_SEPARATOR();
+      const PERMIT_TYPEHASH = "0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9";
+
+      let nonce = (await aDai.connect(wallet0).nonces(wallet.address)).toNumber();
+      //Approving max amount
+      const amount = ethers.constants.MaxUint256;
+      const expiry = Date.now() + 20 * 60;
+
+      const digest = keccak256(
+        ethers.utils.solidityPack(
+          ["bytes1", "bytes1", "bytes32", "bytes32"],
+          [
+            "0x19",
+            "0x01",
+            DOMAIN_SEPARATOR,
+            keccak256(
+              defaultAbiCoder.encode(
+                ["bytes32", "address", "address", "uint256", "uint256", "uint256"],
+                [PERMIT_TYPEHASH, wallet.address, dsaWallet0.address, amount, nonce, expiry]
+              )
+            )
+          ]
+        )
+      );
+      const { v, r, s } = ecsign(Buffer.from(digest.slice(2), "hex"), Buffer.from(wallet.privateKey.slice(2), "hex"));
+      const amount0 = new BigNumber(await usdcToken.connect(wallet0).balanceOf(wallet.address));
+      const amountB = new BigNumber(amount0.toString()).multipliedBy(5).dividedBy(1e4);
+      const amountWithFee = amount0.plus(amountB);
+
+      const flashSpells = [
+        {
+          connector: "AAVE-V3-IMPORT-PERMIT-X",
+          method: "importAave",
+          args: [
+            wallet.address,
+            [[DAI], [USDC], false, [amountB.toFixed(0)]],
+            [[ethers.utils.hexlify(v)], [ethers.utils.hexlify(r)], [ethers.utils.hexlify(s)], [expiry]]
+          ]
+        },
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashPayback",
+          args: [USDC, amountWithFee.toFixed(0), 0, 0]
+        }
+      ];
+
+      const spells = [
+        {
+          connector: "INSTAPOOL-C",
+          method: "flashBorrowAndCast",
+          args: [USDC, amount0.toString(), 5, encodeFlashcastData(flashSpells), "0x"]
+        }
+      ];
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet.address);
+      const receipt = await tx.wait();
+    });
+
+    it("Should check DSA AAVE position", async () => {
+      expect(await aDai.connect(wallet0).balanceOf(dsaWallet0.address)).to.be.gte(
+        new BigNumber(8).multipliedBy(1e18).toString()
+      );
+    });
+  });
+});