diff --git a/contracts/mainnet/common/basic.sol b/contracts/mainnet/common/basic.sol
index febeb784..c0650dfb 100644
--- a/contracts/mainnet/common/basic.sol
+++ b/contracts/mainnet/common/basic.sol
@@ -41,6 +41,10 @@ abstract contract Basic is DSMath, Stores {
         _sell = sell == ethAddr ? TokenInterface(wethAddr) : TokenInterface(sell);
     }
 
+    function changeEthAddrToWethAddr(address token) internal pure returns(address tokenAddr){
+        tokenAddr = token == ethAddr ? wethAddr : token;
+    }
+
     function convertEthToWeth(bool isEth, TokenInterface token, uint amount) internal {
         if(isEth) token.deposit{value: amount}();
     }
diff --git a/contracts/mainnet/common/interfaces.sol b/contracts/mainnet/common/interfaces.sol
index 24a4eb47..53e848d3 100644
--- a/contracts/mainnet/common/interfaces.sol
+++ b/contracts/mainnet/common/interfaces.sol
@@ -8,6 +8,7 @@ interface TokenInterface {
     function withdraw(uint) external;
     function balanceOf(address) external view returns (uint);
     function decimals() external view returns (uint);
+    function totalSupply() external view returns (uint);
 }
 
 interface MemoryInterface {
diff --git a/contracts/mainnet/connectors/1inch/1inch-v3/main.sol b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol
index 84c6aeb4..bbe3bb8e 100644
--- a/contracts/mainnet/connectors/1inch/1inch-v3/main.sol
+++ b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol
@@ -96,7 +96,7 @@ abstract contract OneInch is OneInchResolverHelpers {
      * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
      * @param sellAmt The amount of the token to sell.
      * @param unitAmt The amount of buyAmt/sellAmt with slippage.
-     * @param callData Data from 1inch API.
+     * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange: <a href="https://api.1inch.exchange/swagger/ethereum/#/Swap/SwapFactoryCommonController_getSwap" target="_blank">here </a>
      * @param setId ID stores the amount of token brought.
     */
     function sell(
diff --git a/contracts/mainnet/connectors/sushi-incentive/events.sol b/contracts/mainnet/connectors/sushi-incentive/events.sol
new file mode 100644
index 00000000..aa1c890d
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/events.sol
@@ -0,0 +1,31 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+    event LogDeposit(
+        uint256 indexed pid,
+        uint256 indexed version,
+        uint256 amount
+    );
+    event LogWithdraw(
+        uint256 indexed pid,
+        uint256 indexed version,
+        uint256 amount
+    );
+    event LogEmergencyWithdraw(
+        uint256 indexed pid,
+        uint256 indexed version,
+        uint256 lpAmount,
+        uint256 rewardsAmount
+    );
+    event LogHarvest(
+        uint256 indexed pid,
+        uint256 indexed version,
+        uint256 amount
+    );
+    event LogWithdrawAndHarvest(
+        uint256 indexed pid,
+        uint256 indexed version,
+        uint256 widrawAmount,
+        uint256 harvestAmount
+    );
+}
diff --git a/contracts/mainnet/connectors/sushi-incentive/helpers.sol b/contracts/mainnet/connectors/sushi-incentive/helpers.sol
new file mode 100644
index 00000000..97522f22
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/helpers.sol
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+import {DSMath} from "../../common/math.sol";
+import {Basic} from "../../common/basic.sol";
+import "./interface.sol";
+
+contract Helpers is DSMath, Basic {
+    IMasterChefV2 immutable masterChefV2 =
+        IMasterChefV2(0xEF0881eC094552b2e128Cf945EF17a6752B4Ec5d);
+    IMasterChef immutable masterChef =
+        IMasterChef(0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd);
+    ISushiSwapFactory immutable factory =
+        ISushiSwapFactory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac);
+
+    function _deposit(uint256 _pid, uint256 _amount, uint256 _version) internal {
+        if(_version == 2)
+            masterChefV2.deposit(_pid, _amount, address(this));
+        else
+            masterChef.deposit(_pid, _amount);
+    }
+
+    function _withdraw(uint256 _pid, uint256 _amount, uint256 _version) internal {
+        if(_version == 2)
+            masterChefV2.withdraw(_pid, _amount, address(this));
+        else
+            masterChef.withdraw(_pid, _amount);
+    }
+
+    function _harvest(uint256 _pid) internal {
+        masterChefV2.harvest(_pid, address(this));
+    }
+
+    function _withdrawAndHarvest(uint256 _pid, uint256 _amount, uint256 _version) internal {
+        if(_version == 2)
+            masterChefV2.withdrawAndHarvest(_pid, _amount, address(this));
+        else _withdraw(_pid, _amount, _version);
+    }
+
+    function _emergencyWithdraw(uint256 _pid, uint256 _version) internal {
+        if(_version == 2)
+            masterChefV2.emergencyWithdraw(_pid, address(this));
+        else 
+            masterChef.emergencyWithdraw(_pid, address(this));
+    }
+
+    function _getPoolId(address tokenA, address tokenB)
+        internal
+        view
+        returns (uint256 poolId, uint256 version, address lpToken)
+    {
+        address pair = factory.getPair(tokenA, tokenB);
+        uint256 length = masterChefV2.poolLength();
+        version = 2;
+        poolId = uint256(-1);
+
+        for (uint256 i = 0; i < length; i++) {
+            lpToken = masterChefV2.lpToken(i);
+            if (pair == lpToken) {
+                poolId = i;
+                break;
+            }
+        }
+
+        uint256 lengthV1 = masterChef.poolLength();
+        for (uint256 i = 0; i < lengthV1; i++) {
+            (lpToken, , , ) = masterChef.poolInfo(i);
+            if (pair == lpToken) {
+                poolId = i;
+                version = 1;
+                break;
+            }
+        }
+    }
+
+    function _getUserInfo(uint256 _pid, uint256 _version)
+        internal
+        view
+        returns (uint256 lpAmount, uint256 rewardsAmount)
+    {
+        if(_version == 2)
+            (lpAmount, rewardsAmount) = masterChefV2.userInfo(_pid, address(this));
+        else 
+            (lpAmount, rewardsAmount) = masterChef.userInfo(_pid, address(this));
+    }
+}
diff --git a/contracts/mainnet/connectors/sushi-incentive/interface.sol b/contracts/mainnet/connectors/sushi-incentive/interface.sol
new file mode 100644
index 00000000..ba3b1c6c
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/interface.sol
@@ -0,0 +1,117 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+struct UserInfo {
+    uint256 amount;
+    uint256 rewardDebt;
+}
+
+struct PoolInfo {
+    IERC20 lpToken; // Address of LP token contract.
+    uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block.
+    uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs.
+    uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below.
+}
+
+interface IERC20 {
+    function totalSupply() external view returns (uint256);
+
+    function balanceOf(address account) external view returns (uint256);
+
+    function allowance(address owner, address spender) external view returns (uint256);
+
+    function approve(address spender, uint256 amount) external returns (bool);
+
+    event Transfer(address indexed from, address indexed to, uint256 value);
+    event Approval(address indexed owner, address indexed spender, uint256 value);
+
+    /// @notice EIP 2612
+    function permit(
+        address owner,
+        address spender,
+        uint256 value,
+        uint256 deadline,
+        uint8 v,
+        bytes32 r,
+        bytes32 s
+    ) external;
+}
+
+interface IMasterChef {
+    function poolLength() external view returns (uint256);
+
+    function updatePool(uint256 pid) external returns (PoolInfo memory);
+
+    function poolInfo(uint256 pid) external view returns (address, uint256, uint256, uint256);
+
+    function userInfo(uint256 _pid, address _user)
+        external
+        view
+        returns (uint256, uint256);
+
+    function deposit(
+        uint256 pid,
+        uint256 amount
+    ) external;
+
+    function withdraw(
+        uint256 pid,
+        uint256 amount
+    ) external;
+
+    function emergencyWithdraw(uint256 pid, address to) external;
+}
+
+interface IMasterChefV2 {
+    function poolLength() external view returns (uint256);
+
+    function updatePool(uint256 pid) external returns (PoolInfo memory);
+
+    function lpToken(uint256 pid) external view returns (address);
+
+    function userInfo(uint256 _pid, address _user)
+        external
+        view
+        returns (uint256, uint256);
+
+    function deposit(
+        uint256 pid,
+        uint256 amount,
+        address to
+    ) external;
+
+    function withdraw(
+        uint256 pid,
+        uint256 amount,
+        address to
+    ) external;
+
+    function emergencyWithdraw(uint256 pid, address to) external;
+
+    function harvest(uint256 pid, address to) external;
+
+    function withdrawAndHarvest(
+        uint256 pid,
+        uint256 amount,
+        address to
+    ) external;
+}
+
+interface ISushiSwapFactory {
+    function getPair(address tokenA, address tokenB)
+        external
+        view
+        returns (address pair);
+
+    function allPairs(uint256) external view returns (address pair);
+
+    function allPairsLength() external view returns (uint256);
+
+    function feeTo() external view returns (address);
+
+    function feeToSetter() external view returns (address);
+
+    function createPair(address tokenA, address tokenB)
+        external
+        returns (address pair);
+}
diff --git a/contracts/mainnet/connectors/sushi-incentive/main.sol b/contracts/mainnet/connectors/sushi-incentive/main.sol
new file mode 100644
index 00000000..cc448434
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/main.sol
@@ -0,0 +1,174 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @title SushiSwap Double Incentive.
+ * @dev Decentralized Exchange.
+ */
+
+import {TokenInterface} from "../../common/interfaces.sol";
+import {Helpers} from "./helpers.sol";
+import {Events} from "./events.sol";
+
+abstract contract SushipswapIncentiveResolver is Helpers, Events {
+    /**
+     * @dev deposit LP token to masterChef
+     * @notice deposit LP token to masterChef
+     * @param token1 token1 of LP token
+     * @param token2 token2 of LP token
+     * @param amount amount of LP token
+     * @param getId ID to retrieve amount
+     * @param setId ID stores Pool ID
+     */
+    function deposit(
+        address token1,
+        address token2,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        token1 = changeEthAddrToWethAddr(token1);
+        token2 = changeEthAddrToWethAddr(token2);
+        amount = getUint(getId, amount);
+        (uint256 _pid, uint256 _version, address lpTokenAddr) = _getPoolId(
+            token1,
+            token2
+        );
+        setUint(setId, _pid);
+        require(_pid != uint256(-1), "pool-does-not-exist");
+        TokenInterface lpToken = TokenInterface(lpTokenAddr);
+        lpToken.approve(address(masterChef), amount);
+        _deposit(_pid, amount, _version);
+        _eventName = "LogDeposit(uint256,uint256,uint256)";
+        _eventParam = abi.encode(_pid, _version, amount);
+    }
+
+    /**
+     * @dev withdraw LP token from masterChef
+     * @notice withdraw LP token from masterChef
+     * @param token1 token1 of LP token
+     * @param token2 token2 of LP token
+     * @param amount amount of LP token
+     * @param getId ID to retrieve amount
+     * @param setId ID stores Pool ID
+     */
+    function withdraw(
+        address token1,
+        address token2,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        token1 = changeEthAddrToWethAddr(token1);
+        token2 = changeEthAddrToWethAddr(token2);
+        amount = getUint(getId, amount);
+        (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2);
+        setUint(setId, _pid);
+        require(_pid != uint256(-1), "pool-does-not-exist");
+        _withdraw(_pid, amount, _version);
+        _eventName = "LogWithdraw(uint256,uint256,uint256)";
+        _eventParam = abi.encode(_pid, _version, amount);
+    }
+
+    /**
+     * @dev harvest from masterChef
+     * @notice harvest from masterChef
+     * @param token1 token1 deposited of LP token
+     * @param token2 token2 deposited LP token
+     * @param setId ID stores Pool ID
+     */
+    function harvest(
+        address token1,
+        address token2,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        token1 = changeEthAddrToWethAddr(token1);
+        token2 = changeEthAddrToWethAddr(token2);
+        (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2);
+        setUint(setId, _pid);
+        require(_pid != uint256(-1), "pool-does-not-exist");
+        (, uint256 rewardsAmount) = _getUserInfo(_pid, _version);
+        if (_version == 2) _harvest(_pid);
+        else _withdraw(_pid, 0, _version);
+        _eventName = "LogHarvest(uint256,uint256,uint256)";
+        _eventParam = abi.encode(_pid, _version, rewardsAmount);
+    }
+
+    /**
+     * @dev withdraw LP token and harvest from masterChef
+     * @notice withdraw LP token and harvest from masterChef
+     * @param token1 token1 of LP token
+     * @param token2 token2 of LP token
+     * @param amount amount of LP token
+     * @param getId ID to retrieve amount
+     * @param setId ID stores Pool ID
+     */
+    function withdrawAndHarvest(
+        address token1,
+        address token2,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        token1 = changeEthAddrToWethAddr(token1);
+        token2 = changeEthAddrToWethAddr(token2);
+        amount = getUint(getId, amount);
+        (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2);
+        setUint(setId, _pid);
+        require(_pid != uint256(-1), "pool-does-not-exist");
+        (, uint256 rewardsAmount) = _getUserInfo(_pid, _version);
+        _withdrawAndHarvest(_pid, amount, _version);
+        _eventName = "LogWithdrawAndHarvest(uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(_pid, _version, amount, rewardsAmount);
+    }
+
+    /**
+     * @dev emergency withdraw from masterChef
+     * @notice emergency withdraw from masterChef
+     * @param token1 token1 deposited of LP token
+     * @param token2 token2 deposited LP token
+     * @param setId ID stores Pool ID
+     */
+    function emergencyWithdraw(
+        address token1,
+        address token2,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        token1 = changeEthAddrToWethAddr(token1);
+        token2 = changeEthAddrToWethAddr(token2);
+        (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2);
+        setUint(setId, _pid);
+        require(_pid != uint256(-1), "pool-does-not-exist");
+        (uint256 lpAmount, uint256 rewardsAmount) = _getUserInfo(
+            _pid,
+            _version
+        );
+        _emergencyWithdraw(_pid, _version);
+        _eventName = "LogEmergencyWithdraw(uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(_pid, _version, lpAmount, rewardsAmount);
+    }
+}
+
+contract ConnectV2SushiswapIncentive is SushipswapIncentiveResolver {
+    string public constant name = "SushipswapIncentive-v1.1";
+}
diff --git a/contracts/mainnet/connectors/sushiswap/events.sol b/contracts/mainnet/connectors/sushiswap/events.sol
new file mode 100644
index 00000000..2717b0a3
--- /dev/null
+++ b/contracts/mainnet/connectors/sushiswap/events.sol
@@ -0,0 +1,41 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+    event LogDepositLiquidity(
+        address indexed tokenA,
+        address indexed tokenB,
+        uint256 amtA,
+        uint256 amtB,
+        uint256 uniAmount,
+        uint256 getId,
+        uint256 setId
+    );
+
+    event LogWithdrawLiquidity(
+        address indexed tokenA,
+        address indexed tokenB,
+        uint256 amountA,
+        uint256 amountB,
+        uint256 uniAmount,
+        uint256 getId,
+        uint256[] setId
+    );
+    
+    event LogBuy(
+        address indexed buyToken,
+        address indexed sellToken,
+        uint256 buyAmt,
+        uint256 sellAmt,
+        uint256 getId,
+        uint256 setId
+    );
+
+    event LogSell(
+        address indexed buyToken,
+        address indexed sellToken,
+        uint256 buyAmt,
+        uint256 sellAmt,
+        uint256 getId,
+        uint256 setId
+    );
+}
\ No newline at end of file
diff --git a/contracts/mainnet/connectors/sushiswap/helpers.sol b/contracts/mainnet/connectors/sushiswap/helpers.sol
new file mode 100644
index 00000000..ea29a03f
--- /dev/null
+++ b/contracts/mainnet/connectors/sushiswap/helpers.sol
@@ -0,0 +1,184 @@
+pragma solidity ^0.7.0;
+
+import {TokenInterface} from "../../common/interfaces.sol";
+import {DSMath} from "../../common/math.sol";
+import {Basic} from "../../common/basic.sol";
+import {ISushiSwapRouter, ISushiSwapFactory} from "./interface.sol";
+
+abstract contract Helpers is DSMath, Basic {
+    /**
+     * @dev ISushiSwapRouter
+     */
+    ISushiSwapRouter internal constant router =
+        ISushiSwapRouter(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F);
+
+    function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt)
+        internal
+        view
+        returns (uint256 buyAmt)
+    {
+        uint256[] memory amts = router.getAmountsOut(sellAmt, paths);
+        buyAmt = amts[1];
+    }
+
+    function getExpectedSellAmt(address[] memory paths, uint256 buyAmt)
+        internal
+        view
+        returns (uint256 sellAmt)
+    {
+        uint256[] memory amts = router.getAmountsIn(buyAmt, paths);
+        sellAmt = amts[0];
+    }
+
+    function checkPair(address[] memory paths) internal view {
+        address pair = ISushiSwapFactory(router.factory()).getPair(
+            paths[0],
+            paths[1]
+        );
+        require(pair != address(0), "No-exchange-address");
+    }
+
+    function getPaths(address buyAddr, address sellAddr)
+        internal
+        pure
+        returns (address[] memory paths)
+    {
+        paths = new address[](2);
+        paths[0] = address(sellAddr);
+        paths[1] = address(buyAddr);
+    }
+
+    function getMinAmount(
+        TokenInterface token,
+        uint256 amt,
+        uint256 slippage
+    ) internal view returns (uint256 minAmt) {
+        uint256 _amt18 = convertTo18(token.decimals(), amt);
+        minAmt = wmul(_amt18, sub(WAD, slippage));
+        minAmt = convert18ToDec(token.decimals(), minAmt);
+    }
+
+    function _addLiquidity(
+        address tokenA,
+        address tokenB,
+        uint256 _amt,
+        uint256 unitAmt,
+        uint256 slippage
+    )
+        internal
+        returns (
+            uint256 _amtA,
+            uint256 _amtB,
+            uint256 _liquidity
+        )
+    {
+        (TokenInterface _tokenA, TokenInterface _tokenB) = changeEthAddress(
+            tokenA,
+            tokenB
+        );
+
+        _amtA = _amt == uint256(-1)
+            ? getTokenBal(TokenInterface(tokenA))
+            : _amt;
+        _amtB = convert18ToDec(
+            _tokenB.decimals(),
+            wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA))
+        );
+
+        bool isEth = address(_tokenA) == wethAddr;
+        convertEthToWeth(isEth, _tokenA, _amtA);
+
+        isEth = address(_tokenB) == wethAddr;
+        convertEthToWeth(isEth, _tokenB, _amtB);
+
+        approve(_tokenA, address(router), _amtA);
+        approve(_tokenB, address(router), _amtB);
+
+        uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage);
+        uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage);
+        (_amtA, _amtB, _liquidity) = router.addLiquidity(
+            address(_tokenA),
+            address(_tokenB),
+            _amtA,
+            _amtB,
+            minAmtA,
+            minAmtB,
+            address(this),
+            block.timestamp + 1
+        );
+    }
+
+    function _removeLiquidity(
+        address tokenA,
+        address tokenB,
+        uint256 _amt,
+        uint256 unitAmtA,
+        uint256 unitAmtB
+    )
+        internal
+        returns (
+            uint256 _amtA,
+            uint256 _amtB,
+            uint256 _uniAmt
+        )
+    {
+        TokenInterface _tokenA;
+        TokenInterface _tokenB;
+        (_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData(
+            tokenA,
+            tokenB,
+            _amt
+        );
+        {
+            uint256 minAmtA = convert18ToDec(
+                _tokenA.decimals(),
+                wmul(unitAmtA, _uniAmt)
+            );
+            uint256 minAmtB = convert18ToDec(
+                _tokenB.decimals(),
+                wmul(unitAmtB, _uniAmt)
+            );
+            (_amtA, _amtB) = router.removeLiquidity(
+                address(_tokenA),
+                address(_tokenB),
+                _uniAmt,
+                minAmtA,
+                minAmtB,
+                address(this),
+                block.timestamp + 1
+            );
+        }
+
+        bool isEth = address(_tokenA) == wethAddr;
+        convertWethToEth(isEth, _tokenA, _amtA);
+
+        isEth = address(_tokenB) == wethAddr;
+        convertWethToEth(isEth, _tokenB, _amtB);
+    }
+
+    function _getRemoveLiquidityData(
+        address tokenA,
+        address tokenB,
+        uint256 _amt
+    )
+        internal
+        returns (
+            TokenInterface _tokenA,
+            TokenInterface _tokenB,
+            uint256 _uniAmt
+        )
+    {
+        (_tokenA, _tokenB) = changeEthAddress(tokenA, tokenB);
+        address exchangeAddr = ISushiSwapFactory(router.factory()).getPair(
+            address(_tokenA),
+            address(_tokenB)
+        );
+        require(exchangeAddr != address(0), "pair-not-found.");
+
+        TokenInterface uniToken = TokenInterface(exchangeAddr);
+        _uniAmt = _amt == uint256(-1)
+            ? uniToken.balanceOf(address(this))
+            : _amt;
+        approve(uniToken, address(router), _uniAmt);
+    }
+}
diff --git a/contracts/mainnet/connectors/sushiswap/interface.sol b/contracts/mainnet/connectors/sushiswap/interface.sol
new file mode 100644
index 00000000..bd3be483
--- /dev/null
+++ b/contracts/mainnet/connectors/sushiswap/interface.sol
@@ -0,0 +1,57 @@
+pragma solidity ^0.7.0;
+
+interface ISushiSwapRouter {
+    function factory() external pure returns (address);
+    function WETH() external pure returns (address);
+
+    function addLiquidity(
+        address tokenA,
+        address tokenB,
+        uint amountADesired,
+        uint amountBDesired,
+        uint amountAMin,
+        uint amountBMin,
+        address to,
+        uint deadline
+    ) external returns (uint amountA, uint amountB, uint liquidity);
+    function removeLiquidity(
+        address tokenA,
+        address tokenB,
+        uint liquidity,
+        uint amountAMin,
+        uint amountBMin,
+        address to,
+        uint deadline
+    ) external returns (uint amountA, uint amountB);
+    function swapExactTokensForTokens(
+        uint amountIn,
+        uint amountOutMin,
+        address[] calldata path,
+        address to,
+        uint deadline
+    ) external returns (uint[] memory amounts);
+    function swapTokensForExactTokens(
+        uint amountOut,
+        uint amountInMax,
+        address[] calldata path,
+        address to,
+        uint deadline
+    ) external returns (uint[] memory amounts);
+
+    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
+    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
+    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
+    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
+    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
+}
+
+interface ISushiSwapFactory {
+    function getPair(address tokenA, address tokenB) external view returns (address pair);
+    function allPairs(uint) external view returns (address pair);
+    function allPairsLength() external view returns (uint);
+
+    function feeTo() external view returns (address);
+    function feeToSetter() external view returns (address);
+
+    function createPair(address tokenA, address tokenB) external returns (address pair);
+}
diff --git a/contracts/mainnet/connectors/sushiswap/main.sol b/contracts/mainnet/connectors/sushiswap/main.sol
new file mode 100644
index 00000000..bd0078bc
--- /dev/null
+++ b/contracts/mainnet/connectors/sushiswap/main.sol
@@ -0,0 +1,196 @@
+pragma solidity ^0.7.0;
+
+/**
+ * @title SushiSwap.
+ * @dev Decentralized Exchange.
+ */
+
+import { TokenInterface } from "../../common/interfaces.sol";
+import { Helpers } from "./helpers.sol";
+import { Events } from "./events.sol";
+
+abstract contract SushipswapResolver is Helpers, Events {
+    /**
+     * @dev Deposit Liquidity.
+     * @notice Deposit Liquidity to a SushiSwap pool.
+     * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param amtA The amount of A tokens to deposit.
+     * @param unitAmt The unit amount of of amtB/amtA with slippage.
+     * @param slippage Slippage amount.
+     * @param getId ID to retrieve amtA.
+     * @param setId ID stores the amount of pools tokens received.
+    */
+    function deposit(
+        address tokenA,
+        address tokenB,
+        uint256 amtA,
+        uint256 unitAmt,
+        uint256 slippage,
+        uint256 getId,
+        uint256 setId
+    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+        uint _amt = getUint(getId, amtA);
+
+        (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity(
+                                            tokenA,
+                                            tokenB,
+                                            _amt,
+                                            unitAmt,
+                                            slippage
+                                        );
+        setUint(setId, _uniAmt);
+        
+        _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId);
+    }
+
+    /**
+     * @dev Withdraw Liquidity.
+     * @notice Withdraw Liquidity from a SushiSwap pool.
+     * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param uniAmt The amount of pool tokens to withdraw.
+     * @param unitAmtA The unit amount of amtA/uniAmt with slippage.
+     * @param unitAmtB The unit amount of amtB/uniAmt with slippage.
+     * @param getId ID to retrieve uniAmt.
+     * @param setIds Array of IDs to store the amount tokens received.
+    */
+    function withdraw(
+        address tokenA,
+        address tokenB,
+        uint256 uniAmt,
+        uint256 unitAmtA,
+        uint256 unitAmtB,
+        uint256 getId,
+        uint256[] calldata setIds
+    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+        uint _amt = getUint(getId, uniAmt);
+
+        (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity(
+            tokenA,
+            tokenB,
+            _amt,
+            unitAmtA,
+            unitAmtB
+        );
+
+        setUint(setIds[0], _amtA);
+        setUint(setIds[1], _amtB);
+        
+        _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])";
+        _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds);
+    }
+
+    /**
+     * @dev Buy ETH/ERC20_Token.
+     * @notice Buy a token using a SushiSwap
+     * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param buyAmt The amount of tokens to buy.
+     * @param unitAmt The unit amount of sellAmt/buyAmt with slippage.
+     * @param getId ID to retrieve buyAmt.
+     * @param setId ID to store the amount of tokens sold.
+    */
+    function buy(
+        address buyAddr,
+        address sellAddr,
+        uint256 buyAmt,
+        uint256 unitAmt,
+        uint256 getId,
+        uint256 setId
+    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+        uint _buyAmt = getUint(getId, buyAmt);
+        (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeEthAddress(buyAddr, sellAddr);
+        address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr));
+
+        uint _slippageAmt = convert18ToDec(_sellAddr.decimals(),
+            wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt))
+        );
+
+        checkPair(paths);
+        uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt);
+        require(_slippageAmt >= _expectedAmt, "Too much slippage");
+
+        bool isEth = address(_sellAddr) == wethAddr;
+        convertEthToWeth(isEth, _sellAddr, _expectedAmt);
+        approve(_sellAddr, address(router), _expectedAmt);
+
+        uint _sellAmt = router.swapTokensForExactTokens(
+            _buyAmt,
+            _expectedAmt,
+            paths,
+            address(this),
+            block.timestamp + 1
+        )[0];
+
+        isEth = address(_buyAddr) == wethAddr;
+        convertWethToEth(isEth, _buyAddr, _buyAmt);
+
+        setUint(setId, _sellAmt);
+
+        _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
+    }
+
+    /**
+     * @dev Sell ETH/ERC20_Token.
+     * @notice Sell a token using a SushiSwap
+     * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+     * @param sellAmt The amount of the token to sell.
+     * @param unitAmt The unit amount of buyAmt/sellAmt with slippage.
+     * @param getId ID to retrieve sellAmt.
+     * @param setId ID stores the amount of token brought.
+    */
+    function sell(
+        address buyAddr,
+        address sellAddr,
+        uint256 sellAmt,
+        uint256 unitAmt,
+        uint256 getId,
+        uint256 setId
+    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+        uint _sellAmt = getUint(getId, sellAmt);
+        (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeEthAddress(buyAddr, sellAddr);
+        address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr));
+
+        if (_sellAmt == uint(-1)) {
+            _sellAmt = sellAddr == ethAddr ?
+                address(this).balance :
+                _sellAddr.balanceOf(address(this));
+        }
+
+        uint _slippageAmt = convert18ToDec(_buyAddr.decimals(),
+            wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt))
+        );
+
+        checkPair(paths);
+        uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt);
+        require(_slippageAmt <= _expectedAmt, "Too much slippage");
+
+        bool isEth = address(_sellAddr) == wethAddr;
+        convertEthToWeth(isEth, _sellAddr, _sellAmt);
+        approve(_sellAddr, address(router), _sellAmt);
+
+        uint _buyAmt = router.swapExactTokensForTokens(
+            _sellAmt,
+            _expectedAmt,
+            paths,
+            address(this),
+            block.timestamp + 1
+        )[1];
+
+        isEth = address(_buyAddr) == wethAddr;
+        convertWethToEth(isEth, _buyAddr, _buyAmt);
+
+        setUint(setId, _buyAmt);
+
+        _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
+    }
+}
+
+contract ConnectV2Sushiswap is SushipswapResolver {
+    string public constant name = "Sushipswap-v1.1";
+}
diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol
new file mode 100644
index 00000000..9e01ef9d
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/events.sol
@@ -0,0 +1,41 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+	event LogDepositLiquidity(
+		address indexed tokenA,
+		address indexed tokenB,
+		uint256 amtA,
+		uint256 amtB,
+		uint256 uniAmount,
+		uint256 getId,
+		uint256 setId
+	);
+
+	event LogWithdrawLiquidity(
+		address indexed tokenA,
+		address indexed tokenB,
+		uint256 amountA,
+		uint256 amountB,
+		uint256 uniAmount,
+		uint256 getId,
+		uint256[] setId
+	);
+
+	event LogBuy(
+		address indexed buyToken,
+		address indexed sellToken,
+		uint256 buyAmt,
+		uint256 sellAmt,
+		uint256 getId,
+		uint256 setId
+	);
+
+	event LogSell(
+		address indexed buyToken,
+		address indexed sellToken,
+		uint256 buyAmt,
+		uint256 sellAmt,
+		uint256 getId,
+		uint256 setId
+	);
+}
diff --git a/contracts/polygon/connectors/quickswap/helpers.sol b/contracts/polygon/connectors/quickswap/helpers.sol
new file mode 100644
index 00000000..594b56e1
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/helpers.sol
@@ -0,0 +1,184 @@
+pragma solidity ^0.7.0;
+
+import { TokenInterface } from "../../common/interfaces.sol";
+import { DSMath } from "../../common/math.sol";
+import { Basic } from "../../common/basic.sol";
+import { IQuickSwapRouter, IQuickSwapFactory } from "./interface.sol";
+
+abstract contract Helpers is DSMath, Basic {
+	/**
+	 * @dev IQuickSwapRouter
+	 */
+	IQuickSwapRouter internal constant router =
+		IQuickSwapRouter(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff);
+
+	function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt)
+		internal
+		view
+		returns (uint256 buyAmt)
+	{
+		uint256[] memory amts = router.getAmountsOut(sellAmt, paths);
+		buyAmt = amts[1];
+	}
+
+	function getExpectedSellAmt(address[] memory paths, uint256 buyAmt)
+		internal
+		view
+		returns (uint256 sellAmt)
+	{
+		uint256[] memory amts = router.getAmountsIn(buyAmt, paths);
+		sellAmt = amts[0];
+	}
+
+	function checkPair(address[] memory paths) internal view {
+		address pair = IQuickSwapFactory(router.factory()).getPair(
+			paths[0],
+			paths[1]
+		);
+		require(pair != address(0), "No-exchange-address");
+	}
+
+	function getPaths(address buyAddr, address sellAddr)
+		internal
+		pure
+		returns (address[] memory paths)
+	{
+		paths = new address[](2);
+		paths[0] = address(sellAddr);
+		paths[1] = address(buyAddr);
+	}
+
+	function getMinAmount(
+		TokenInterface token,
+		uint256 amt,
+		uint256 slippage
+	) internal view returns (uint256 minAmt) {
+		uint256 _amt18 = convertTo18(token.decimals(), amt);
+		minAmt = wmul(_amt18, sub(WAD, slippage));
+		minAmt = convert18ToDec(token.decimals(), minAmt);
+	}
+
+	function _addLiquidity(
+		address tokenA,
+		address tokenB,
+		uint256 _amt,
+		uint256 unitAmt,
+		uint256 slippage
+	)
+		internal
+		returns (
+			uint256 _amtA,
+			uint256 _amtB,
+			uint256 _liquidity
+		)
+	{
+		(TokenInterface _tokenA, TokenInterface _tokenB) = changeMaticAddress(
+			tokenA,
+			tokenB
+		);
+
+		_amtA = _amt == uint256(-1)
+			? getTokenBal(TokenInterface(tokenA))
+			: _amt;
+		_amtB = convert18ToDec(
+			_tokenB.decimals(),
+			wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA))
+		);
+
+		bool isMatic = address(_tokenA) == wmaticAddr;
+		convertMaticToWmatic(isMatic, _tokenA, _amtA);
+
+		isMatic = address(_tokenB) == wmaticAddr;
+		convertMaticToWmatic(isMatic, _tokenB, _amtB);
+
+		approve(_tokenA, address(router), _amtA);
+		approve(_tokenB, address(router), _amtB);
+
+		uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage);
+		uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage);
+		(_amtA, _amtB, _liquidity) = router.addLiquidity(
+			address(_tokenA),
+			address(_tokenB),
+			_amtA,
+			_amtB,
+			minAmtA,
+			minAmtB,
+			address(this),
+			block.timestamp + 1
+		);
+	}
+
+	function _removeLiquidity(
+		address tokenA,
+		address tokenB,
+		uint256 _amt,
+		uint256 unitAmtA,
+		uint256 unitAmtB
+	)
+		internal
+		returns (
+			uint256 _amtA,
+			uint256 _amtB,
+			uint256 _uniAmt
+		)
+	{
+		TokenInterface _tokenA;
+		TokenInterface _tokenB;
+		(_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData(
+			tokenA,
+			tokenB,
+			_amt
+		);
+		{
+			uint256 minAmtA = convert18ToDec(
+				_tokenA.decimals(),
+				wmul(unitAmtA, _uniAmt)
+			);
+			uint256 minAmtB = convert18ToDec(
+				_tokenB.decimals(),
+				wmul(unitAmtB, _uniAmt)
+			);
+			(_amtA, _amtB) = router.removeLiquidity(
+				address(_tokenA),
+				address(_tokenB),
+				_uniAmt,
+				minAmtA,
+				minAmtB,
+				address(this),
+				block.timestamp + 1
+			);
+		}
+
+		bool isMatic = address(_tokenA) == wmaticAddr;
+		convertWmaticToMatic(isMatic, _tokenA, _amtA);
+
+		isMatic = address(_tokenB) == wmaticAddr;
+		convertWmaticToMatic(isMatic, _tokenB, _amtB);
+	}
+
+	function _getRemoveLiquidityData(
+		address tokenA,
+		address tokenB,
+		uint256 _amt
+	)
+		internal
+		returns (
+			TokenInterface _tokenA,
+			TokenInterface _tokenB,
+			uint256 _uniAmt
+		)
+	{
+		(_tokenA, _tokenB) = changeMaticAddress(tokenA, tokenB);
+		address exchangeAddr = IQuickSwapFactory(router.factory()).getPair(
+			address(_tokenA),
+			address(_tokenB)
+		);
+		require(exchangeAddr != address(0), "pair-not-found.");
+
+		TokenInterface uniToken = TokenInterface(exchangeAddr);
+		_uniAmt = _amt == uint256(-1)
+			? uniToken.balanceOf(address(this))
+			: _amt;
+		approve(uniToken, address(router), _uniAmt);
+	}
+}
diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol
new file mode 100644
index 00000000..bd210215
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/interface.sol
@@ -0,0 +1,97 @@
+pragma solidity ^0.7.0;
+
+interface IQuickSwapRouter {
+	function factory() external pure returns (address);
+
+	function WETH() external pure returns (address);
+
+	function addLiquidity(
+		address tokenA,
+		address tokenB,
+		uint256 amountADesired,
+		uint256 amountBDesired,
+		uint256 amountAMin,
+		uint256 amountBMin,
+		address to,
+		uint256 deadline
+	)
+		external
+		returns (
+			uint256 amountA,
+			uint256 amountB,
+			uint256 liquidity
+		);
+
+	function removeLiquidity(
+		address tokenA,
+		address tokenB,
+		uint256 liquidity,
+		uint256 amountAMin,
+		uint256 amountBMin,
+		address to,
+		uint256 deadline
+	) external returns (uint256 amountA, uint256 amountB);
+
+	function swapExactTokensForTokens(
+		uint256 amountIn,
+		uint256 amountOutMin,
+		address[] calldata path,
+		address to,
+		uint256 deadline
+	) external returns (uint256[] memory amounts);
+
+	function swapTokensForExactTokens(
+		uint256 amountOut,
+		uint256 amountInMax,
+		address[] calldata path,
+		address to,
+		uint256 deadline
+	) external returns (uint256[] memory amounts);
+
+	function quote(
+		uint256 amountA,
+		uint256 reserveA,
+		uint256 reserveB
+	) external pure returns (uint256 amountB);
+
+	function getAmountOut(
+		uint256 amountIn,
+		uint256 reserveIn,
+		uint256 reserveOut
+	) external pure returns (uint256 amountOut);
+
+	function getAmountIn(
+		uint256 amountOut,
+		uint256 reserveIn,
+		uint256 reserveOut
+	) external pure returns (uint256 amountIn);
+
+	function getAmountsOut(uint256 amountIn, address[] calldata path)
+		external
+		view
+		returns (uint256[] memory amounts);
+
+	function getAmountsIn(uint256 amountOut, address[] calldata path)
+		external
+		view
+		returns (uint256[] memory amounts);
+}
+
+interface IQuickSwapFactory {
+	function getPair(address tokenA, address tokenB)
+		external
+		view
+		returns (address pair);
+
+	function allPairs(uint256) external view returns (address pair);
+
+	function allPairsLength() external view returns (uint256);
+
+	function feeTo() external view returns (address);
+
+	function feeToSetter() external view returns (address);
+
+	function createPair(address tokenA, address tokenB)
+		external
+		returns (address pair);
+}
diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol
new file mode 100644
index 00000000..404b6be0
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/main.sol
@@ -0,0 +1,256 @@
+pragma solidity ^0.7.0;
+
+/**
+ * @title QuickSwap.
+ * @dev Decentralized Exchange.
+ */
+
+import { TokenInterface } from "../../common/interfaces.sol";
+import { Helpers } from "./helpers.sol";
+import { Events } from "./events.sol";
+
+abstract contract QuickpswapResolver is Helpers, Events {
+	/**
+	 * @dev Deposit Liquidity.
+	 * @notice Deposit Liquidity to a QuickSwap pool.
+	 * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param amtA The amount of A tokens to deposit.
+	 * @param unitAmt The unit amount of of amtB/amtA with slippage.
+	 * @param slippage Slippage amount.
+	 * @param getId ID to retrieve amtA.
+	 * @param setId ID stores the amount of pools tokens received.
+	 */
+	function deposit(
+		address tokenA,
+		address tokenB,
+		uint256 amtA,
+		uint256 unitAmt,
+		uint256 slippage,
+		uint256 getId,
+		uint256 setId
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		uint256 _amt = getUint(getId, amtA);
+
+		(uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _addLiquidity(
+			tokenA,
+			tokenB,
+			_amt,
+			unitAmt,
+			slippage
+		);
+		setUint(setId, _uniAmt);
+
+		_eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)";
+		_eventParam = abi.encode(
+			tokenA,
+			tokenB,
+			_amtA,
+			_amtB,
+			_uniAmt,
+			getId,
+			setId
+		);
+	}
+
+	/**
+	 * @dev Withdraw Liquidity.
+	 * @notice Withdraw Liquidity from a QuickSwap pool.
+	 * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param uniAmt The amount of pool tokens to withdraw.
+	 * @param unitAmtA The unit amount of amtA/uniAmt with slippage.
+	 * @param unitAmtB The unit amount of amtB/uniAmt with slippage.
+	 * @param getId ID to retrieve uniAmt.
+	 * @param setIds Array of IDs to store the amount tokens received.
+	 */
+	function withdraw(
+		address tokenA,
+		address tokenB,
+		uint256 uniAmt,
+		uint256 unitAmtA,
+		uint256 unitAmtB,
+		uint256 getId,
+		uint256[] calldata setIds
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		uint256 _amt = getUint(getId, uniAmt);
+
+		(uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity(
+			tokenA,
+			tokenB,
+			_amt,
+			unitAmtA,
+			unitAmtB
+		);
+
+		setUint(setIds[0], _amtA);
+		setUint(setIds[1], _amtB);
+
+		_eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])";
+		_eventParam = abi.encode(
+			tokenA,
+			tokenB,
+			_amtA,
+			_amtB,
+			_uniAmt,
+			getId,
+			setIds
+		);
+	}
+
+	/**
+	 * @dev Buy ETH/ERC20_Token.
+	 * @notice Buy a token using a QuickSwap
+	 * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param buyAmt The amount of tokens to buy.
+	 * @param unitAmt The unit amount of sellAmt/buyAmt with slippage.
+	 * @param getId ID to retrieve buyAmt.
+	 * @param setId ID to store the amount of tokens sold.
+	 */
+	function buy(
+		address buyAddr,
+		address sellAddr,
+		uint256 buyAmt,
+		uint256 unitAmt,
+		uint256 getId,
+		uint256 setId
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		uint256 _buyAmt = getUint(getId, buyAmt);
+		(
+			TokenInterface _buyAddr,
+			TokenInterface _sellAddr
+		) = changeMaticAddress(buyAddr, sellAddr);
+		address[] memory paths = getPaths(
+			address(_buyAddr),
+			address(_sellAddr)
+		);
+
+		uint256 _slippageAmt = convert18ToDec(
+			_sellAddr.decimals(),
+			wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt))
+		);
+
+		checkPair(paths);
+		uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt);
+		require(_slippageAmt >= _expectedAmt, "Too much slippage");
+
+		bool isEth = address(_sellAddr) == wmaticAddr;
+		convertMaticToWmatic(isEth, _sellAddr, _expectedAmt);
+		approve(_sellAddr, address(router), _expectedAmt);
+
+		uint256 _sellAmt = router.swapTokensForExactTokens(
+			_buyAmt,
+			_expectedAmt,
+			paths,
+			address(this),
+			block.timestamp + 1
+		)[0];
+
+		isEth = address(_buyAddr) == wmaticAddr;
+		convertWmaticToMatic(isEth, _buyAddr, _buyAmt);
+
+		setUint(setId, _sellAmt);
+
+		_eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)";
+		_eventParam = abi.encode(
+			buyAddr,
+			sellAddr,
+			_buyAmt,
+			_sellAmt,
+			getId,
+			setId
+		);
+	}
+
+	/**
+	 * @dev Sell ETH/ERC20_Token.
+	 * @notice Sell a token using a QuickSwap
+	 * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
+	 * @param sellAmt The amount of the token to sell.
+	 * @param unitAmt The unit amount of buyAmt/sellAmt with slippage.
+	 * @param getId ID to retrieve sellAmt.
+	 * @param setId ID stores the amount of token brought.
+	 */
+	function sell(
+		address buyAddr,
+		address sellAddr,
+		uint256 sellAmt,
+		uint256 unitAmt,
+		uint256 getId,
+		uint256 setId
+	)
+		external
+		payable
+		returns (string memory _eventName, bytes memory _eventParam)
+	{
+		uint256 _sellAmt = getUint(getId, sellAmt);
+		(
+			TokenInterface _buyAddr,
+			TokenInterface _sellAddr
+		) = changeMaticAddress(buyAddr, sellAddr);
+		address[] memory paths = getPaths(
+			address(_buyAddr),
+			address(_sellAddr)
+		);
+
+		if (_sellAmt == uint256(-1)) {
+			_sellAmt = sellAddr == maticAddr
+				? address(this).balance
+				: _sellAddr.balanceOf(address(this));
+		}
+
+		uint256 _slippageAmt = convert18ToDec(
+			_buyAddr.decimals(),
+			wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt))
+		);
+
+		checkPair(paths);
+		uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt);
+		require(_slippageAmt <= _expectedAmt, "Too much slippage");
+
+		bool isEth = address(_sellAddr) == wmaticAddr;
+		convertMaticToWmatic(isEth, _sellAddr, _sellAmt);
+		approve(_sellAddr, address(router), _sellAmt);
+
+		uint256 _buyAmt = router.swapExactTokensForTokens(
+			_sellAmt,
+			_expectedAmt,
+			paths,
+			address(this),
+			block.timestamp + 1
+		)[1];
+
+		isEth = address(_buyAddr) == wmaticAddr;
+		convertWmaticToMatic(isEth, _buyAddr, _buyAmt);
+
+		setUint(setId, _buyAmt);
+
+		_eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)";
+		_eventParam = abi.encode(
+			buyAddr,
+			sellAddr,
+			_buyAmt,
+			_sellAmt,
+			getId,
+			setId
+		);
+	}
+}
+
+contract ConnectV2QuickswapPolygon is QuickpswapResolver {
+	string public constant name = "Quickpswap-v1.1";
+}
diff --git a/contracts/polygon/connectors/uniswap/v3/events.sol b/contracts/polygon/connectors/uniswap/v3/events.sol
index 829fadd2..b464e28e 100644
--- a/contracts/polygon/connectors/uniswap/v3/events.sol
+++ b/contracts/polygon/connectors/uniswap/v3/events.sol
@@ -1,6 +1,14 @@
 pragma solidity ^0.7.0;
 
 contract Events {
+    event LogcreateAndInitializePool (
+        address tokenA,
+        address tokenB,
+        address pool,
+        uint24 fee,
+        int24 initialTick
+    );
+
     event LogMint(
         uint256 indexed tokenId,
         uint256 liquidity,
diff --git a/contracts/polygon/connectors/uniswap/v3/helpers.sol b/contracts/polygon/connectors/uniswap/v3/helpers.sol
index f43be452..f1ae3324 100644
--- a/contracts/polygon/connectors/uniswap/v3/helpers.sol
+++ b/contracts/polygon/connectors/uniswap/v3/helpers.sol
@@ -1,9 +1,9 @@
 pragma solidity ^0.7.6;
 pragma abicoder v2;
 
-import {TokenInterface} from "../../../common/interfaces.sol";
-import {DSMath} from "../../../common/math.sol";
-import {Basic} from "../../../common/basic.sol";
+import { TokenInterface}  from "../../../common/interfaces.sol";
+import { DSMath } from "../../../common/math.sol";
+import { Basic } from "../../../common/basic.sol";
 import "./interface.sol";
 import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
 import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
@@ -65,6 +65,27 @@ abstract contract Helpers is DSMath, Basic {
         }
     }
 
+    function _createAndInitializePoolIfNecessary (
+        address tokenA,
+        address tokenB,
+        uint24 fee,
+        int24 initialTick
+    ) internal returns (address pool) {
+        (TokenInterface token0Contract_, TokenInterface token1Contract_) = changeMaticAddress(
+            tokenA,
+            tokenB
+        );
+        
+        (address token0_, address token1_) =  sortTokenAddress(address(token0Contract_), address(token1Contract_));
+
+        return nftManager.createAndInitializePoolIfNecessary(
+            token0_,
+            token1_,
+            fee,
+            TickMath.getSqrtRatioAtTick(initialTick)
+        );
+    }
+
     /**
      * @dev Mint function which interact with Uniswap v3
      */
diff --git a/contracts/polygon/connectors/uniswap/v3/main.sol b/contracts/polygon/connectors/uniswap/v3/main.sol
index b6195a6f..4cb74195 100644
--- a/contracts/polygon/connectors/uniswap/v3/main.sol
+++ b/contracts/polygon/connectors/uniswap/v3/main.sol
@@ -11,6 +11,43 @@ import {Helpers} from "./helpers.sol";
 import {Events} from "./events.sol";
 
 abstract contract UniswapResolver is Helpers, Events {
+
+    /**
+     * @dev Create and Initialize pool
+     * @notice Create and Initialize new pool if required
+     * @param tokenA tokenA addreess
+     * @param tokenB tokenB addreess
+     * @param fee fee percentage
+     * @param initialTick Initial tick for the pool
+     */
+    function createAndInitializePool (
+        address tokenA,
+        address tokenB,
+        uint24 fee,
+        int24 initialTick
+    ) 
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    { 
+
+        address pool = _createAndInitializePoolIfNecessary(
+            tokenA,
+            tokenB,
+            fee,
+            initialTick
+        );
+
+        _eventName = "LogcreateAndInitializePool(address,address,address,uint24,int24)";
+        _eventParam = abi.encode(
+            tokenA,
+            tokenB,
+            pool,
+            fee,
+            initialTick
+        );
+    }
+
     /**
      * @dev Mint New Position
      * @notice Mint New NFT LP Position
diff --git a/hardhat.config.ts b/hardhat.config.ts
index c74d290f..8c10d28f 100644
--- a/hardhat.config.ts
+++ b/hardhat.config.ts
@@ -39,6 +39,13 @@ const mnemonic =
   process.env.MNEMONIC ??
   "test test test test test test test test test test test junk";
 
+const networkGasPriceConfig: Record<string, string> = {
+  "mainnet": "160",
+  "polygon": "50",
+  "avalanche": "50",
+  "arbitrum": "2"
+}
+
 function createConfig(network: string) {
   return {
     url: getNetworkUrl(network),
@@ -47,7 +54,6 @@ function createConfig(network: string) {
 }
 
 function getNetworkUrl(networkType: string) {
-  //console.log(process.env);
   if (networkType === "avalanche")
     return "https://api.avax.network/ext/bc/C/rpc";
   else if (networkType === "polygon")
diff --git a/scripts/deployment/deploy.ts b/scripts/deployment/deploy.ts
index d0f60816..c32788fd 100644
--- a/scripts/deployment/deploy.ts
+++ b/scripts/deployment/deploy.ts
@@ -18,6 +18,7 @@ async function main() {
     "GELATO-A": "ConnectV2Gelato",
     "MAKERDAO-A": "ConnectV2Maker",
     "UNISWAP-A": "ConnectV2UniswapV2",
+    "QUICKSWAP-A": "ConnectV2QuickswapPolygon"
     "UniswapV3-v1" : "ConnectV2UniswapV3Polygon", 
     "Uniswap-V3-Staker-v1.1" : "ConnectV2UniswapV3StakerPolygon"
   };
diff --git a/test/mainnet/sushiswap/sushiswap.test.ts b/test/mainnet/sushiswap/sushiswap.test.ts
new file mode 100644
index 00000000..8c70125b
--- /dev/null
+++ b/test/mainnet/sushiswap/sushiswap.test.ts
@@ -0,0 +1,147 @@
+import { expect } from "chai";
+import hre from "hardhat";
+const { waffle, ethers } = hre;
+const { provider } = waffle;
+
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { addLiquidity } from "../../../scripts/tests/addLiquidity";
+
+import { addresses } from "../../../scripts/tests/mainnet/addresses";
+import { abis } from "../../../scripts/constant/abis";
+import { ConnectV2Sushiswap__factory, ConnectV2Sushiswap } from "../../../typechain";
+import type { Signer, Contract } from "ethers";
+
+const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f";
+
+describe("Sushiswap", function () {
+  const connectorName = "Sushiswap-v1";
+
+  let dsaWallet0: Contract;
+  let masterSigner: Signer;
+  let instaConnectorsV2: Contract;
+  let connector: Contract;
+
+  const wallets = provider.getWallets();
+  const [wallet0, wallet1, wallet2, wallet3] = wallets;
+  before(async () => {
+    await hre.network.provider.request({
+      method: "hardhat_reset",
+      params: [
+        {
+          forking: {
+            // @ts-ignore
+            jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+            blockNumber: 13005785
+          }
+        }
+      ]
+    });
+
+    masterSigner = await getMasterSigner();
+    instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+    connector = await deployAndEnableConnector({
+      connectorName,
+      contractArtifact: ConnectV2Sushiswap__factory,
+      signer: masterSigner,
+      connectors: instaConnectorsV2
+    });
+    console.log("Connector address", connector.address);
+  });
+
+  it("Should have contracts deployed.", async function () {
+    expect(!!instaConnectorsV2.address).to.be.true;
+    expect(!!connector.address).to.be.true;
+    expect(!!(await masterSigner.getAddress())).to.be.true;
+  });
+
+  describe("DSA wallet setup", function () {
+    it("Should build DSA v2", async function () {
+      dsaWallet0 = await buildDSAv2(wallet0.address);
+      expect(!!dsaWallet0.address).to.be.true;
+    });
+
+    it("Deposit ETH & DAI into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("10")
+      });
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+
+      await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
+    });
+
+    it("Deposit ETH & USDT into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("10")
+      });
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+
+      await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000"));
+    });
+  });
+
+  describe("Main", function () {
+    it("Should deposit successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
+      const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setId = "0";
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "deposit",
+          args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, "500000000000000000", getId, setId]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    }).timeout(10000000000);
+
+    it("Should withdraw successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setIds = ["0", "0"];
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "withdraw",
+          args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    });
+
+    it("Should buy successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
+      const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setId = "0";
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "buy",
+          args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    });
+  });
+});
diff --git a/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts b/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts
new file mode 100644
index 00000000..b8a9c32a
--- /dev/null
+++ b/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts
@@ -0,0 +1,235 @@
+import { expect } from "chai";
+import hre from "hardhat";
+const { waffle, ethers } = hre;
+const { provider } = waffle
+
+import {deployAndEnableConnector} from "../../../scripts/tests/deployAndEnableConnector";
+import {buildDSAv2} from "../../../scripts/tests/buildDSAv2";
+import {encodeSpells} from "../../../scripts/tests/encodeSpells";
+import {getMasterSigner} from "../../../scripts/tests/getMasterSigner";
+import {addLiquidity} from "../../../scripts/tests/addLiquidity";
+import {addresses} from "../../../scripts/tests/mainnet/addresses";
+import {abis} from "../../../scripts/constant/abis";
+
+import { ConnectV2Sushiswap__factory, ConnectV2Sushiswap, ConnectV2SushiswapIncentive, ConnectV2SushiswapIncentive__factory } from "../../../typechain";
+import { Contract, Signer } from "ethers";
+
+const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"
+const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
+
+describe("Sushiswap", function () {
+    const connectorName = "Sushiswap-v1"
+    const incentiveConnectorName = "Sushiswp-Incentive-v1"
+
+    let dsaWallet0: Contract;
+    let masterSigner: Signer;
+    let instaConnectorsV2: Contract;
+    let connector: Contract, connectorIncentive;
+
+    const wallets = provider.getWallets()
+    const [wallet0, wallet1, wallet2, wallet3] = wallets
+    before(async () => {
+        await hre.network.provider.request({
+            method: "hardhat_reset",
+            params: [
+                {
+                    forking: {
+                        // @ts-ignore
+                        jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+                        blockNumber: 13005785,
+                    },
+                },
+            ],
+        });
+        masterSigner = await getMasterSigner()
+        instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+        connector = await deployAndEnableConnector({
+            connectorName,
+            contractArtifact: ConnectV2Sushiswap__factory,
+            signer: masterSigner,
+            connectors: instaConnectorsV2
+        })
+        console.log("Connector address", connector.address)
+
+        connectorIncentive = await deployAndEnableConnector({
+            connectorName: incentiveConnectorName,
+            contractArtifact: ConnectV2SushiswapIncentive__factory,
+            signer: masterSigner,
+            connectors: instaConnectorsV2
+        })
+        console.log("Incentive Connector address", connectorIncentive.address)
+    })
+
+    it("Should have contracts deployed.", async function () {
+        expect(!!instaConnectorsV2.address).to.be.true;
+        expect(!!connector.address).to.be.true;
+        expect(!!(await masterSigner.getAddress())).to.be.true;
+    });
+
+    describe("DSA wallet setup", function () {
+        it("Should build DSA v2", async function () {
+            dsaWallet0 = await buildDSAv2(wallet0.address)
+            expect(!!dsaWallet0.address).to.be.true;
+        });
+
+        it("Deposit ETH & DAI into DSA wallet", async function () {
+            await wallet0.sendTransaction({
+                to: dsaWallet0.address,
+                value: ethers.utils.parseEther("10")
+            });
+            expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+
+            await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
+        });
+
+        it("Deposit ETH & USDT into DSA wallet", async function () {
+            await wallet0.sendTransaction({
+                to: dsaWallet0.address,
+                value: ethers.utils.parseEther("10")
+            });
+            expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+
+            await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000"));
+        });
+    });
+
+    describe("Main", function () {
+        it("Should deposit successfully", async function () {
+            const ethAmount = ethers.utils.parseEther("2") // 1 ETH
+            const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH
+            const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+
+            const getId = "0"
+            const setId = "0"
+
+            const spells = [
+                {
+                    connector: connectorName,
+                    method: "deposit",
+                    args: [
+                        ethAddress,
+                        DAI_ADDR,
+                        ethAmount,
+                        daiUnitAmount,
+                        "500000000000000000",
+                        getId,
+                        setId
+                    ],
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            await tx.wait()
+
+            describe("Incentive", () => {
+                it("Should deposit successfully", async () => {
+                    const getId = 0
+                    const setId = 0
+                    const spells = [
+                        {
+                            connector: incentiveConnectorName,
+                            method: "deposit",
+                            args: [
+                                WETH_ADDR,
+                                DAI_ADDR,
+                                ethers.utils.parseEther("10"),
+                                getId,
+                                setId
+                            ]
+                        }
+                    ]
+
+                    const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address)
+                    await tx.wait();
+                })
+
+                it("Should harvest successfully", async () => {
+                    const setId = 0
+                    const spells = [
+                        {
+                            connector: incentiveConnectorName,
+                            method: "harvest",
+                            args: [
+                                WETH_ADDR,
+                                DAI_ADDR,
+                                setId
+                            ]
+                        }
+                    ]
+
+                    const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address)
+                    await tx.wait();
+                })
+
+                it("Should harvest and withdraw successfully", async () => {
+                    const getId = 0
+                    const setId = 0
+                    const spells = [
+                        {
+                            connector: incentiveConnectorName,
+                            method: "withdrawAndHarvest",
+                            args: [
+                                WETH_ADDR,
+                                DAI_ADDR,
+                                ethers.utils.parseEther("1"),
+                                getId,
+                                setId
+                            ]
+                        }
+                    ]
+
+                    const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address)
+                    await tx.wait();
+                })
+
+                it("Should withdraw successfully", async () => {
+                    const getId = 0
+                    const setId = 0
+                    const spells = [
+                        {
+                            connector: incentiveConnectorName,
+                            method: "withdraw",
+                            args: [
+                                WETH_ADDR,
+                                DAI_ADDR,
+                                ethers.utils.parseEther("1"),
+                                getId,
+                                setId
+                            ]
+                        }
+                    ]
+
+                    const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address)
+                    await tx.wait();
+                })
+            })
+        }).timeout(10000000000);
+
+        it("Should buy successfully", async function () {
+            const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH
+            const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH
+            const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+
+            const getId = "0"
+            const setId = "0"
+
+            const spells = [
+                {
+                    connector: connectorName,
+                    method: "buy",
+                    args: [
+                        ethAddress,
+                        DAI_ADDR,
+                        ethAmount,
+                        daiUnitAmount,
+                        getId,
+                        setId
+                    ]
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+        });
+    });
+}) 
diff --git a/test/polygon/quickswap/quickswap.test.ts b/test/polygon/quickswap/quickswap.test.ts
new file mode 100644
index 00000000..3d3a9346
--- /dev/null
+++ b/test/polygon/quickswap/quickswap.test.ts
@@ -0,0 +1,137 @@
+import { expect } from "chai";
+import hre from "hardhat";
+const { waffle, ethers } = hre;
+const { provider } = waffle;
+
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { addLiquidity } from "../../../scripts/tests/addLiquidity";
+
+import { addresses } from "../../../scripts/tests/polygon/addresses";
+import { abis } from "../../../scripts/constant/abis";
+import { ConnectV2QuickswapPolygon__factory, ConnectV2QuickswapPolygon } from "../../../typechain";
+import type { Signer, Contract } from "ethers";
+
+const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063";
+
+describe("Quickswap", function () {
+  const connectorName = "Quickswap-v1";
+
+  let dsaWallet0: Contract;
+  let masterSigner: Signer;
+  let instaConnectorsV2: Contract;
+  let connector: Contract;
+
+  const wallets = provider.getWallets();
+  const [wallet0, wallet1, wallet2, wallet3] = wallets;
+  before(async () => {
+    await hre.network.provider.request({
+      method: "hardhat_reset",
+      params: [
+        {
+          forking: {
+            // @ts-ignore
+            jsonRpcUrl: hre.config.networks.hardhat.forking.url
+            // blockNumber: 13005785
+          }
+        }
+      ]
+    });
+
+    masterSigner = await getMasterSigner();
+    instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+    connector = await deployAndEnableConnector({
+      connectorName,
+      contractArtifact: ConnectV2QuickswapPolygon__factory,
+      signer: masterSigner,
+      connectors: instaConnectorsV2
+    });
+    console.log("Connector address", connector.address);
+  });
+
+  it("Should have contracts deployed.", async function () {
+    expect(!!instaConnectorsV2.address).to.be.true;
+    expect(!!connector.address).to.be.true;
+    expect(!!(await masterSigner.getAddress())).to.be.true;
+  });
+
+  describe("DSA wallet setup", function () {
+    it("Should build DSA v2", async function () {
+      dsaWallet0 = await buildDSAv2(wallet0.address);
+      expect(!!dsaWallet0.address).to.be.true;
+    });
+
+    it("Deposit ETH & DAI into DSA wallet", async function () {
+      await wallet0.sendTransaction({
+        to: dsaWallet0.address,
+        value: ethers.utils.parseEther("10")
+      });
+      expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+
+      await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("10000"));
+    });
+  });
+
+  describe("Main", function () {
+    it("Should deposit successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
+      const daiUnitAmount = ethers.utils.parseEther("1"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setId = "0";
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "deposit",
+          args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, "500000000000000000", getId, setId]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    }).timeout(10000000000);
+
+    it("Should withdraw successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.001"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setIds = ["0", "0"];
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "withdraw",
+          args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    });
+
+    it("Should buy successfully", async function () {
+      const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
+      const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH
+      const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
+
+      const getId = "0";
+      const setId = "0";
+
+      const spells = [
+        {
+          connector: connectorName,
+          method: "buy",
+          args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId]
+        }
+      ];
+
+      const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
+      let receipt = await tx.wait();
+    });
+  });
+});
diff --git a/yarn.lock b/yarn.lock
index a5bbacb4..42a9309f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,27 @@
 # yarn lockfile v1
 
 
+"@babel/code-frame@^7.0.0":
+  "integrity" "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA=="
+  "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz"
+  "version" "7.16.0"
+  dependencies:
+    "@babel/highlight" "^7.16.0"
+
+"@babel/helper-validator-identifier@^7.15.7":
+  "integrity" "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w=="
+  "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz"
+  "version" "7.15.7"
+
+"@babel/highlight@^7.16.0":
+  "integrity" "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g=="
+  "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz"
+  "version" "7.16.0"
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.15.7"
+    "chalk" "^2.0.0"
+    "js-tokens" "^4.0.0"
+
 "@babel/runtime@^7.4.4":
   "integrity" "sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA=="
   "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.5.tgz"
@@ -1700,6 +1721,11 @@
   dependencies:
     "acorn" "^4.0.3"
 
+"acorn-jsx@^5.0.0":
+  "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="
+  "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
+  "version" "5.3.2"
+
 "acorn-walk@^8.1.1":
   "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
   "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz"
@@ -1715,7 +1741,7 @@
   "resolved" "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz"
   "version" "5.7.4"
 
-"acorn@^6.4.1":
+"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.0.7", "acorn@^6.4.1":
   "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="
   "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz"
   "version" "6.4.2"
@@ -1760,7 +1786,7 @@
   "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz"
   "version" "3.5.2"
 
-"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.9.1", "ajv@>=5.0.0":
+"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.6.1", "ajv@^6.9.1", "ajv@>=5.0.0":
   "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="
   "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
   "version" "6.12.6"
@@ -1799,6 +1825,11 @@
   "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz"
   "version" "3.2.3"
 
+"ansi-escapes@^3.2.0":
+  "integrity" "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ=="
+  "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz"
+  "version" "3.2.0"
+
 "ansi-escapes@^4.2.1", "ansi-escapes@^4.3.0":
   "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="
   "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz"
@@ -1854,6 +1885,11 @@
   dependencies:
     "color-convert" "^2.0.1"
 
+"antlr4@4.7.1":
+  "integrity" "sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ=="
+  "resolved" "https://registry.npmjs.org/antlr4/-/antlr4-4.7.1.tgz"
+  "version" "4.7.1"
+
 "antlr4ts@^0.5.0-alpha.4":
   "integrity" "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ=="
   "resolved" "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz"
@@ -1996,6 +2032,16 @@
   "resolved" "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz"
   "version" "1.0.0"
 
+"ast-parents@0.0.1":
+  "integrity" "sha1-UI/Q8F0MSHddnszaLhdEIyYejdM="
+  "resolved" "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz"
+  "version" "0.0.1"
+
+"astral-regex@^1.0.0":
+  "integrity" "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg=="
+  "resolved" "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz"
+  "version" "1.0.0"
+
 "async-each@^1.0.1":
   "integrity" "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
   "resolved" "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz"
@@ -2940,6 +2986,30 @@
     "function-bind" "^1.1.1"
     "get-intrinsic" "^1.0.2"
 
+"caller-callsite@^2.0.0":
+  "integrity" "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ="
+  "resolved" "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz"
+  "version" "2.0.0"
+  dependencies:
+    "callsites" "^2.0.0"
+
+"caller-path@^2.0.0":
+  "integrity" "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ="
+  "resolved" "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz"
+  "version" "2.0.0"
+  dependencies:
+    "caller-callsite" "^2.0.0"
+
+"callsites@^2.0.0":
+  "integrity" "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+  "resolved" "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz"
+  "version" "2.0.0"
+
+"callsites@^3.0.0":
+  "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
+  "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
+  "version" "3.1.0"
+
 "camel-case@^3.0.0", "camel-case@3.0.x":
   "integrity" "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M="
   "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz"
@@ -3030,6 +3100,24 @@
     "strip-ansi" "^3.0.0"
     "supports-color" "^2.0.0"
 
+"chalk@^2.0.0":
+  "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
+  "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
+  "version" "2.4.2"
+  dependencies:
+    "ansi-styles" "^3.2.1"
+    "escape-string-regexp" "^1.0.5"
+    "supports-color" "^5.3.0"
+
+"chalk@^2.1.0", "chalk@^2.4.2":
+  "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
+  "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
+  "version" "2.4.2"
+  dependencies:
+    "ansi-styles" "^3.2.1"
+    "escape-string-regexp" "^1.0.5"
+    "supports-color" "^5.3.0"
+
 "chalk@^2.3.2":
   "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
   "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
@@ -3048,15 +3136,6 @@
     "escape-string-regexp" "^1.0.5"
     "supports-color" "^5.3.0"
 
-"chalk@^2.4.2":
-  "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
-  "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
-  "version" "2.4.2"
-  dependencies:
-    "ansi-styles" "^3.2.1"
-    "escape-string-regexp" "^1.0.5"
-    "supports-color" "^5.3.0"
-
 "chalk@^4.1.0":
   "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
   "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
@@ -3254,6 +3333,13 @@
   dependencies:
     "source-map" "~0.6.0"
 
+"cli-cursor@^2.1.0":
+  "integrity" "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU="
+  "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz"
+  "version" "2.1.0"
+  dependencies:
+    "restore-cursor" "^2.0.0"
+
 "cli-cursor@^3.1.0":
   "integrity" "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="
   "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz"
@@ -3266,6 +3352,11 @@
   "resolved" "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz"
   "version" "2.6.1"
 
+"cli-width@^2.0.0":
+  "integrity" "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
+  "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz"
+  "version" "2.2.1"
+
 "cli-width@^3.0.0":
   "integrity" "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="
   "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz"
@@ -3396,6 +3487,11 @@
   "resolved" "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz"
   "version" "2.17.1"
 
+"commander@2.18.0":
+  "integrity" "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ=="
+  "resolved" "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz"
+  "version" "2.18.0"
+
 "commander@3.0.2":
   "integrity" "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow=="
   "resolved" "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz"
@@ -3548,6 +3644,16 @@
     "object-assign" "^4"
     "vary" "^1"
 
+"cosmiconfig@^5.0.7":
+  "integrity" "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="
+  "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz"
+  "version" "5.2.1"
+  dependencies:
+    "import-fresh" "^2.0.0"
+    "is-directory" "^0.3.1"
+    "js-yaml" "^3.13.1"
+    "parse-json" "^4.0.0"
+
 "crc-32@^1.2.0":
   "integrity" "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA=="
   "resolved" "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz"
@@ -3765,7 +3871,7 @@
   dependencies:
     "ms" "^2.1.1"
 
-"debug@^4.1.1", "debug@^4.3.1", "debug@4":
+"debug@^4.0.1", "debug@^4.1.1", "debug@^4.3.1", "debug@4":
   "integrity" "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ=="
   "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz"
   "version" "4.3.1"
@@ -3984,6 +4090,13 @@
   dependencies:
     "path-type" "^4.0.0"
 
+"doctrine@^3.0.0":
+  "integrity" "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="
+  "resolved" "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz"
+  "version" "3.0.0"
+  dependencies:
+    "esutils" "^2.0.2"
+
 "dom-converter@^0.2.0":
   "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA=="
   "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz"
@@ -4103,6 +4216,11 @@
     "minimalistic-assert" "^1.0.0"
     "minimalistic-crypto-utils" "^1.0.0"
 
+"emoji-regex@^10.0.0":
+  "integrity" "sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw=="
+  "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.0.0.tgz"
+  "version" "10.0.0"
+
 "emoji-regex@^7.0.1":
   "integrity" "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
   "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz"
@@ -4207,7 +4325,7 @@
   dependencies:
     "prr" "~1.0.1"
 
-"error-ex@^1.2.0":
+"error-ex@^1.2.0", "error-ex@^1.3.1":
   "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="
   "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
   "version" "1.3.2"
@@ -4357,6 +4475,11 @@
   "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
   "version" "1.0.5"
 
+"escape-string-regexp@^4.0.0":
+  "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+  "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
+  "version" "4.0.0"
+
 "escodegen@1.8.x":
   "integrity" "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg="
   "resolved" "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz"
@@ -4387,6 +4510,69 @@
     "esrecurse" "^4.1.0"
     "estraverse" "^4.1.1"
 
+"eslint-utils@^1.3.1":
+  "integrity" "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q=="
+  "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz"
+  "version" "1.4.3"
+  dependencies:
+    "eslint-visitor-keys" "^1.1.0"
+
+"eslint-visitor-keys@^1.0.0", "eslint-visitor-keys@^1.1.0":
+  "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ=="
+  "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz"
+  "version" "1.3.0"
+
+"eslint@^5.6.0":
+  "integrity" "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg=="
+  "resolved" "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz"
+  "version" "5.16.0"
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    "ajv" "^6.9.1"
+    "chalk" "^2.1.0"
+    "cross-spawn" "^6.0.5"
+    "debug" "^4.0.1"
+    "doctrine" "^3.0.0"
+    "eslint-scope" "^4.0.3"
+    "eslint-utils" "^1.3.1"
+    "eslint-visitor-keys" "^1.0.0"
+    "espree" "^5.0.1"
+    "esquery" "^1.0.1"
+    "esutils" "^2.0.2"
+    "file-entry-cache" "^5.0.1"
+    "functional-red-black-tree" "^1.0.1"
+    "glob" "^7.1.2"
+    "globals" "^11.7.0"
+    "ignore" "^4.0.6"
+    "import-fresh" "^3.0.0"
+    "imurmurhash" "^0.1.4"
+    "inquirer" "^6.2.2"
+    "js-yaml" "^3.13.0"
+    "json-stable-stringify-without-jsonify" "^1.0.1"
+    "levn" "^0.3.0"
+    "lodash" "^4.17.11"
+    "minimatch" "^3.0.4"
+    "mkdirp" "^0.5.1"
+    "natural-compare" "^1.4.0"
+    "optionator" "^0.8.2"
+    "path-is-inside" "^1.0.2"
+    "progress" "^2.0.0"
+    "regexpp" "^2.0.1"
+    "semver" "^5.5.1"
+    "strip-ansi" "^4.0.0"
+    "strip-json-comments" "^2.0.1"
+    "table" "^5.2.3"
+    "text-table" "^0.2.0"
+
+"espree@^5.0.1":
+  "integrity" "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A=="
+  "resolved" "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz"
+  "version" "5.0.1"
+  dependencies:
+    "acorn" "^6.0.7"
+    "acorn-jsx" "^5.0.0"
+    "eslint-visitor-keys" "^1.0.0"
+
 "esprima@^2.7.1":
   "integrity" "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
   "resolved" "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz"
@@ -4402,6 +4588,13 @@
   "resolved" "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz"
   "version" "2.7.3"
 
+"esquery@^1.0.1":
+  "integrity" "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w=="
+  "resolved" "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz"
+  "version" "1.4.0"
+  dependencies:
+    "estraverse" "^5.1.0"
+
 "esrecurse@^4.1.0":
   "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="
   "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz"
@@ -4419,6 +4612,11 @@
   "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
   "version" "4.3.0"
 
+"estraverse@^5.1.0":
+  "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
+  "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
+  "version" "5.3.0"
+
 "estraverse@^5.2.0":
   "integrity" "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ=="
   "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz"
@@ -4897,7 +5095,7 @@
     "uuid" "2.0.1"
     "xmlhttprequest" "1.8.0"
 
-"ethers@^5.0.0", "ethers@^5.0.1", "ethers@^5.0.13", "ethers@^5.0.2", "ethers@^5.1.0", "ethers@^5.1.3", "ethers@^5.4.7", "ethers@^5.5.2":
+"ethers@^5.0.0", "ethers@^5.0.1", "ethers@^5.0.13", "ethers@^5.1.0", "ethers@^5.1.3", "ethers@^5.4.7", "ethers@^5.5.2":
   "integrity" "sha512-EF5W+6Wwcu6BqVwpgmyR5U2+L4c1FQzlM/02dkZOugN3KF0cG9bzHZP+TDJglmPm2/IzCEJDT7KBxzayk7SAHw=="
   "resolved" "https://registry.npmjs.org/ethers/-/ethers-5.5.2.tgz"
   "version" "5.5.2"
@@ -5151,6 +5349,11 @@
   "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
   "version" "3.1.3"
 
+"fast-diff@^1.1.2":
+  "integrity" "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w=="
+  "resolved" "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz"
+  "version" "1.2.0"
+
 "fast-glob@^3.0.3":
   "integrity" "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q=="
   "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz"
@@ -5189,6 +5392,13 @@
   "resolved" "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz"
   "version" "3.5.2"
 
+"figures@^2.0.0":
+  "integrity" "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI="
+  "resolved" "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz"
+  "version" "2.0.0"
+  dependencies:
+    "escape-string-regexp" "^1.0.5"
+
 "figures@^3.0.0":
   "integrity" "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg=="
   "resolved" "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz"
@@ -5196,6 +5406,13 @@
   dependencies:
     "escape-string-regexp" "^1.0.5"
 
+"file-entry-cache@^5.0.1":
+  "integrity" "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g=="
+  "resolved" "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz"
+  "version" "5.0.1"
+  dependencies:
+    "flat-cache" "^2.0.1"
+
 "file-uri-to-path@1.0.0":
   "integrity" "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
   "resolved" "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz"
@@ -5298,6 +5515,15 @@
   dependencies:
     "micromatch" "^4.0.2"
 
+"flat-cache@^2.0.1":
+  "integrity" "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA=="
+  "resolved" "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz"
+  "version" "2.0.1"
+  dependencies:
+    "flatted" "^2.0.0"
+    "rimraf" "2.6.3"
+    "write" "1.0.3"
+
 "flat@^4.1.0":
   "integrity" "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA=="
   "resolved" "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz"
@@ -5305,6 +5531,11 @@
   dependencies:
     "is-buffer" "~2.0.3"
 
+"flatted@^2.0.0":
+  "integrity" "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA=="
+  "resolved" "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz"
+  "version" "2.0.2"
+
 "flow-stoplight@^1.0.0":
   "version" "1.0.0"
 
@@ -5766,6 +5997,11 @@
     "min-document" "^2.19.0"
     "process" "^0.11.10"
 
+"globals@^11.7.0":
+  "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+  "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
+  "version" "11.12.0"
+
 "globals@^9.18.0":
   "version" "9.18.0"
 
@@ -6279,6 +6515,11 @@
   "resolved" "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz"
   "version" "0.1.5"
 
+"ignore@^4.0.6":
+  "integrity" "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
+  "resolved" "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz"
+  "version" "4.0.6"
+
 "ignore@^5.1.1":
   "integrity" "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ=="
   "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz"
@@ -6299,6 +6540,22 @@
   "resolved" "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz"
   "version" "4.0.0-rc.12"
 
+"import-fresh@^2.0.0":
+  "integrity" "sha1-2BNVwVYS04bGH53dOSLUMEgipUY="
+  "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz"
+  "version" "2.0.0"
+  dependencies:
+    "caller-path" "^2.0.0"
+    "resolve-from" "^3.0.0"
+
+"import-fresh@^3.0.0":
+  "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="
+  "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
+  "version" "3.3.0"
+  dependencies:
+    "parent-module" "^1.0.0"
+    "resolve-from" "^4.0.0"
+
 "imul@^1.0.0":
   "integrity" "sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk="
   "resolved" "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz"
@@ -6342,6 +6599,25 @@
   "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
   "version" "1.3.8"
 
+"inquirer@^6.2.2":
+  "integrity" "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ=="
+  "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz"
+  "version" "6.5.2"
+  dependencies:
+    "ansi-escapes" "^3.2.0"
+    "chalk" "^2.4.2"
+    "cli-cursor" "^2.1.0"
+    "cli-width" "^2.0.0"
+    "external-editor" "^3.0.3"
+    "figures" "^2.0.0"
+    "lodash" "^4.17.12"
+    "mute-stream" "0.0.7"
+    "run-async" "^2.2.0"
+    "rxjs" "^6.4.0"
+    "string-width" "^2.1.0"
+    "strip-ansi" "^5.1.0"
+    "through" "^2.3.6"
+
 "inquirer@^8.2.0":
   "integrity" "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ=="
   "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz"
@@ -6525,6 +6801,11 @@
     "is-data-descriptor" "^1.0.0"
     "kind-of" "^6.0.2"
 
+"is-directory@^0.3.1":
+  "integrity" "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+  "resolved" "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz"
+  "version" "0.3.1"
+
 "is-docker@^2.0.0":
   "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
   "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz"
@@ -6825,7 +7106,7 @@
   "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz"
   "version" "0.8.0"
 
-"js-tokens@^3.0.0 || ^4.0.0":
+"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0":
   "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
   "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
   "version" "4.0.0"
@@ -6833,7 +7114,7 @@
 "js-tokens@^3.0.2":
   "version" "3.0.2"
 
-"js-yaml@^3.14.0", "js-yaml@3.x":
+"js-yaml@^3.12.0", "js-yaml@^3.13.0", "js-yaml@^3.13.1", "js-yaml@^3.14.0", "js-yaml@3.x":
   "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="
   "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz"
   "version" "3.14.1"
@@ -6870,7 +7151,7 @@
   "resolved" "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz"
   "version" "0.5.7"
 
-"json-parse-better-errors@^1.0.2":
+"json-parse-better-errors@^1.0.1", "json-parse-better-errors@^1.0.2":
   "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
   "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz"
   "version" "1.0.2"
@@ -6903,6 +7184,11 @@
   "resolved" "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz"
   "version" "0.2.3"
 
+"json-stable-stringify-without-jsonify@^1.0.1":
+  "integrity" "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
+  "resolved" "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
+  "version" "1.0.1"
+
 "json-stable-stringify@^1.0.1":
   "version" "1.0.1"
   dependencies:
@@ -7214,7 +7500,7 @@
     "level-supports" "~1.0.0"
     "xtend" "~4.0.0"
 
-"levn@~0.3.0":
+"levn@^0.3.0", "levn@~0.3.0":
   "integrity" "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4="
   "resolved" "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz"
   "version" "0.3.0"
@@ -7325,7 +7611,7 @@
   "resolved" "https://registry.npmjs.org/lodash.sum/-/lodash.sum-4.0.2.tgz"
   "version" "4.0.2"
 
-"lodash@^4.17.11", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.20", "lodash@^4.17.21", "lodash@^4.17.3":
+"lodash@^4.17.11", "lodash@^4.17.12", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.20", "lodash@^4.17.21", "lodash@^4.17.3":
   "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
   "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
   "version" "4.17.21"
@@ -7929,6 +8215,11 @@
     "fmix" "^0.1.0"
     "imul" "^1.0.0"
 
+"mute-stream@0.0.7":
+  "integrity" "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
+  "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz"
+  "version" "0.0.7"
+
 "mute-stream@0.0.8":
   "integrity" "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
   "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz"
@@ -7976,6 +8267,11 @@
   "resolved" "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz"
   "version" "1.0.2"
 
+"natural-compare@^1.4.0":
+  "integrity" "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
+  "resolved" "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
+  "version" "1.4.0"
+
 "negotiator@0.6.2":
   "integrity" "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
   "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz"
@@ -8314,6 +8610,13 @@
   dependencies:
     "wrappy" "1"
 
+"onetime@^2.0.0":
+  "integrity" "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ="
+  "resolved" "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz"
+  "version" "2.0.1"
+  dependencies:
+    "mimic-fn" "^1.0.0"
+
 "onetime@^5.1.0":
   "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="
   "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
@@ -8329,7 +8632,7 @@
     "is-docker" "^2.0.0"
     "is-wsl" "^2.1.1"
 
-"optionator@^0.8.1":
+"optionator@^0.8.1", "optionator@^0.8.2":
   "integrity" "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA=="
   "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz"
   "version" "0.8.3"
@@ -8499,6 +8802,13 @@
   dependencies:
     "no-case" "^2.2.0"
 
+"parent-module@^1.0.0":
+  "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="
+  "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
+  "version" "1.0.1"
+  dependencies:
+    "callsites" "^3.0.0"
+
 "parse-asn1@^5.0.0", "parse-asn1@^5.1.5":
   "integrity" "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw=="
   "resolved" "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz"
@@ -8522,6 +8832,14 @@
   dependencies:
     "error-ex" "^1.2.0"
 
+"parse-json@^4.0.0":
+  "integrity" "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA="
+  "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz"
+  "version" "4.0.0"
+  dependencies:
+    "error-ex" "^1.3.1"
+    "json-parse-better-errors" "^1.0.1"
+
 "parse5-htmlparser2-tree-adapter@^6.0.1":
   "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="
   "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz"
@@ -8631,6 +8949,11 @@
   "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
   "version" "1.0.1"
 
+"path-is-inside@^1.0.2":
+  "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+  "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz"
+  "version" "1.0.2"
+
 "path-key@^2.0.0", "path-key@^2.0.1":
   "integrity" "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
   "resolved" "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz"
@@ -8848,15 +9171,32 @@
   "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz"
   "version" "2.0.0"
 
+"prettier-plugin-solidity@^1.0.0-beta.18":
+  "integrity" "sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g=="
+  "resolved" "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz"
+  "version" "1.0.0-beta.19"
+  dependencies:
+    "@solidity-parser/parser" "^0.14.0"
+    "emoji-regex" "^10.0.0"
+    "escape-string-regexp" "^4.0.0"
+    "semver" "^7.3.5"
+    "solidity-comments-extractor" "^0.0.7"
+    "string-width" "^4.2.3"
+
+"prettier@^1.14.3":
+  "integrity" "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew=="
+  "resolved" "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz"
+  "version" "1.19.1"
+
 "prettier@^1.18.2":
   "integrity" "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew=="
   "resolved" "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz"
   "version" "1.19.1"
 
-"prettier@^2.1.2":
-  "integrity" "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ=="
-  "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz"
-  "version" "2.3.2"
+"prettier@^2.1.2", "prettier@^2.3.0", "prettier@^2.4.1":
+  "integrity" "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg=="
+  "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz"
+  "version" "2.5.1"
 
 "pretty-error@^2.0.2":
   "integrity" "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw=="
@@ -8884,6 +9224,11 @@
   "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz"
   "version" "0.11.10"
 
+"progress@^2.0.0":
+  "integrity" "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
+  "resolved" "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz"
+  "version" "2.0.3"
+
 "promise-inflight@^1.0.1":
   "integrity" "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
   "resolved" "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz"
@@ -9283,6 +9628,11 @@
     "define-properties" "^1.1.3"
     "es-abstract" "^1.17.0-next.1"
 
+"regexpp@^2.0.1":
+  "integrity" "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw=="
+  "resolved" "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz"
+  "version" "2.0.1"
+
 "regexpu-core@^2.0.0":
   "version" "2.0.0"
   dependencies:
@@ -9385,6 +9735,16 @@
   "resolved" "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz"
   "version" "2.0.0"
 
+"resolve-from@^3.0.0":
+  "integrity" "sha1-six699nWiBvItuZTM17rywoYh0g="
+  "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz"
+  "version" "3.0.0"
+
+"resolve-from@^4.0.0":
+  "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
+  "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
+  "version" "4.0.0"
+
 "resolve-url@^0.2.1":
   "integrity" "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
   "resolved" "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz"
@@ -9414,6 +9774,14 @@
   dependencies:
     "lowercase-keys" "^1.0.0"
 
+"restore-cursor@^2.0.0":
+  "integrity" "sha1-n37ih/gv0ybU/RYpI9YhKe7g368="
+  "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz"
+  "version" "2.0.0"
+  dependencies:
+    "onetime" "^2.0.0"
+    "signal-exit" "^3.0.2"
+
 "restore-cursor@^3.1.0":
   "integrity" "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="
   "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz"
@@ -9451,6 +9819,13 @@
   dependencies:
     "glob" "^7.1.3"
 
+"rimraf@2.6.3":
+  "integrity" "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="
+  "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz"
+  "version" "2.6.3"
+  dependencies:
+    "glob" "^7.1.3"
+
 "ripemd160-min@0.0.6":
   "integrity" "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A=="
   "resolved" "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz"
@@ -9471,7 +9846,7 @@
   dependencies:
     "bn.js" "^4.11.1"
 
-"run-async@^2.4.0":
+"run-async@^2.2.0", "run-async@^2.4.0":
   "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="
   "resolved" "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz"
   "version" "2.4.1"
@@ -9495,6 +9870,13 @@
   "resolved" "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz"
   "version" "0.2.0"
 
+"rxjs@^6.4.0", "rxjs@6":
+  "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="
+  "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz"
+  "version" "6.6.7"
+  dependencies:
+    "tslib" "^1.9.0"
+
 "rxjs@^7.2.0":
   "integrity" "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w=="
   "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz"
@@ -9502,13 +9884,6 @@
   dependencies:
     "tslib" "~2.1.0"
 
-"rxjs@6":
-  "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="
-  "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz"
-  "version" "6.6.7"
-  dependencies:
-    "tslib" "^1.9.0"
-
 "safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@^5.1.1", "safe-buffer@^5.1.2", "safe-buffer@^5.2.0", "safe-buffer@^5.2.1", "safe-buffer@~5.2.0":
   "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
   "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
@@ -9625,6 +10000,11 @@
   "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
   "version" "5.7.1"
 
+"semver@^5.5.1":
+  "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+  "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
+  "version" "5.7.1"
+
 "semver@^5.7.0":
   "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
   "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
@@ -9831,6 +10211,15 @@
   "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
   "version" "3.0.0"
 
+"slice-ansi@^2.1.0":
+  "integrity" "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ=="
+  "resolved" "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz"
+  "version" "2.1.0"
+  dependencies:
+    "ansi-styles" "^3.2.0"
+    "astral-regex" "^1.0.0"
+    "is-fullwidth-code-point" "^2.0.0"
+
 "snake-case@^2.1.0":
   "integrity" "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8="
   "resolved" "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz"
@@ -9923,6 +10312,33 @@
     "semver" "^5.5.0"
     "tmp" "0.0.33"
 
+"solhint@^3.3.6":
+  "integrity" "sha512-HWUxTAv2h7hx3s3hAab3ifnlwb02ZWhwFU/wSudUHqteMS3ll9c+m1FlGn9V8ztE2rf3Z82fQZA005Wv7KpcFA=="
+  "resolved" "https://registry.npmjs.org/solhint/-/solhint-3.3.6.tgz"
+  "version" "3.3.6"
+  dependencies:
+    "@solidity-parser/parser" "^0.13.2"
+    "ajv" "^6.6.1"
+    "antlr4" "4.7.1"
+    "ast-parents" "0.0.1"
+    "chalk" "^2.4.2"
+    "commander" "2.18.0"
+    "cosmiconfig" "^5.0.7"
+    "eslint" "^5.6.0"
+    "fast-diff" "^1.1.2"
+    "glob" "^7.1.3"
+    "ignore" "^4.0.6"
+    "js-yaml" "^3.12.0"
+    "lodash" "^4.17.11"
+    "semver" "^6.3.0"
+  optionalDependencies:
+    "prettier" "^1.14.3"
+
+"solidity-comments-extractor@^0.0.7":
+  "integrity" "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw=="
+  "resolved" "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz"
+  "version" "0.0.7"
+
 "solidity-coverage@0.7.17":
   "integrity" "sha512-Erw2hd2xdACAvDX8jUdYkmgJlIIazGznwDJA5dhRaw4def2SisXN9jUjneeyOZnl/E7j6D3XJYug4Zg9iwodsg=="
   "resolved" "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.17.tgz"
@@ -10147,7 +10563,7 @@
     "is-fullwidth-code-point" "^1.0.0"
     "strip-ansi" "^3.0.0"
 
-"string-width@^1.0.2 || 2", "string-width@^2.0.0":
+"string-width@^1.0.2 || 2", "string-width@^2.0.0", "string-width@^2.1.0":
   "integrity" "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="
   "resolved" "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz"
   "version" "2.1.1"
@@ -10173,6 +10589,15 @@
     "is-fullwidth-code-point" "^3.0.0"
     "strip-ansi" "^6.0.1"
 
+"string-width@^4.2.3":
+  "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="
+  "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
+  "version" "4.2.3"
+  dependencies:
+    "emoji-regex" "^8.0.0"
+    "is-fullwidth-code-point" "^3.0.0"
+    "strip-ansi" "^6.0.1"
+
 "string.prototype.trim@~1.2.1":
   "version" "1.2.3"
   dependencies:
@@ -10265,7 +10690,7 @@
   "resolved" "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz"
   "version" "2.0.0"
 
-"strip-json-comments@~2.0.1", "strip-json-comments@2.0.1":
+"strip-json-comments@^2.0.1", "strip-json-comments@~2.0.1", "strip-json-comments@2.0.1":
   "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
   "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz"
   "version" "2.0.1"
@@ -10345,6 +10770,16 @@
     "tar" "^4.0.2"
     "xhr-request" "^1.0.1"
 
+"table@^5.2.3":
+  "integrity" "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug=="
+  "resolved" "https://registry.npmjs.org/table/-/table-5.4.6.tgz"
+  "version" "5.4.6"
+  dependencies:
+    "ajv" "^6.10.2"
+    "lodash" "^4.17.14"
+    "slice-ansi" "^2.1.0"
+    "string-width" "^3.0.0"
+
 "tapable@^0.2.7":
   "integrity" "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A=="
   "resolved" "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz"
@@ -10445,6 +10880,11 @@
   "resolved" "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz"
   "version" "0.0.1"
 
+"text-table@^0.2.0":
+  "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
+  "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
+  "version" "0.2.0"
+
 "through@^2.3.6":
   "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
   "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
@@ -12034,6 +12474,13 @@
   "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
   "version" "1.0.2"
 
+"write@1.0.3":
+  "integrity" "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig=="
+  "resolved" "https://registry.npmjs.org/write/-/write-1.0.3.tgz"
+  "version" "1.0.3"
+  dependencies:
+    "mkdirp" "^0.5.1"
+
 "ws@^3.0.0":
   "integrity" "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA=="
   "resolved" "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz"