From 30eb39378fb32da235e1a294cd7007d74d43271e Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 24 Aug 2021 14:04:17 -0500
Subject: [PATCH 01/28] implement uniswap v3 staker

---
 .../connectors/uniswapStaker/events.sol       |  34 +++
 .../connectors/uniswapStaker/helpers.sol      | 230 ++++++++++++++++
 .../connectors/uniswapStaker/interface.sol    | 183 +++++++++++++
 .../mainnet/connectors/uniswapStaker/main.sol | 237 +++++++++++++++++
 test/uniswapStake/uniswapStake.test.js        | 245 ++++++++++++++++++
 5 files changed, 929 insertions(+)
 create mode 100644 contracts/mainnet/connectors/uniswapStaker/events.sol
 create mode 100644 contracts/mainnet/connectors/uniswapStaker/helpers.sol
 create mode 100644 contracts/mainnet/connectors/uniswapStaker/interface.sol
 create mode 100644 contracts/mainnet/connectors/uniswapStaker/main.sol
 create mode 100644 test/uniswapStake/uniswapStake.test.js

diff --git a/contracts/mainnet/connectors/uniswapStaker/events.sol b/contracts/mainnet/connectors/uniswapStaker/events.sol
new file mode 100644
index 00000000..8618e151
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswapStaker/events.sol
@@ -0,0 +1,34 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+    event LogDeposit(
+        uint256 indexed tokenId,
+        uint256 liquidity,
+        uint256 amountA,
+        uint256 amountB
+    );
+
+    event LogWithdraw(
+        uint256 indexed tokenId,
+        uint256 liquidity,
+        uint256 amountA,
+        uint256 amountB
+    );
+
+    event LogStake(uint256 tokenId, address refundee);
+
+    event LogUnstake(uint256 tokenId, bytes32 incentiveId);
+
+    event LogRewardClaimed(
+        address rewardToken,
+        address receiver,
+        uint256 amount
+    );
+
+    event LogIncentiveCreated(
+        uint256 tokenId,
+        uint256 startTime,
+        uint256 endTime,
+        uint256 reward
+    );
+}
diff --git a/contracts/mainnet/connectors/uniswapStaker/helpers.sol b/contracts/mainnet/connectors/uniswapStaker/helpers.sol
new file mode 100644
index 00000000..e7b8e7af
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswapStaker/helpers.sol
@@ -0,0 +1,230 @@
+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 "./interface.sol";
+import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
+import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
+import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
+
+abstract contract Helpers is DSMath, Basic {
+    /**
+     * @dev uniswap v3 NFT Position Manager & Swap Router
+     */
+    INonfungiblePositionManager constant nftManager =
+        INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
+    IUniswapV3Staker constant staker =
+        IUniswapV3Staker(0x1f98407aaB862CdDeF78Ed252D6f557aA5b0f00d);
+
+    /**
+     * @dev Get Last NFT Index
+     * @param user: User address
+     */
+    function _getLastNftId(address user)
+        internal
+        view
+        returns (uint256 tokenId)
+    {
+        uint256 len = nftManager.balanceOf(user);
+        tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1);
+    }
+
+    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 getNftTokenPairAddresses(uint256 _tokenId)
+        internal
+        view
+        returns (address token0, address token1)
+    {
+        (bool success, bytes memory data) = address(nftManager).staticcall(
+            abi.encodeWithSelector(nftManager.positions.selector, _tokenId)
+        );
+        require(success, "fetching positions failed");
+        {
+            (, , token0, token1, , , , ) = abi.decode(
+                data,
+                (
+                    uint96,
+                    address,
+                    address,
+                    address,
+                    uint24,
+                    int24,
+                    int24,
+                    uint128
+                )
+            );
+        }
+    }
+
+    function getPoolAddress(uint256 _tokenId)
+        internal
+        view
+        returns (address pool)
+    {
+        (bool success, bytes memory data) = address(nftManager).staticcall(
+            abi.encodeWithSelector(nftManager.positions.selector, _tokenId)
+        );
+        require(success, "fetching positions failed");
+        {
+            (, , address token0, address token1, uint24 fee, , , ) = abi.decode(
+                data,
+                (
+                    uint96,
+                    address,
+                    address,
+                    address,
+                    uint24,
+                    int24,
+                    int24,
+                    uint128
+                )
+            );
+
+            pool = PoolAddress.computeAddress(
+                nftManager.factory(),
+                PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee})
+            );
+        }
+    }
+
+    /**
+     * @dev Check if token address is etherAddr and convert it to weth
+     */
+    function _checkETH(
+        address _token0,
+        address _token1,
+        uint256 _amount0,
+        uint256 _amount1
+    ) internal {
+        bool isEth0 = _token0 == wethAddr;
+        bool isEth1 = _token1 == wethAddr;
+        convertEthToWeth(isEth0, TokenInterface(_token0), _amount0);
+        convertEthToWeth(isEth1, TokenInterface(_token1), _amount1);
+        approve(TokenInterface(_token0), address(nftManager), _amount0);
+        approve(TokenInterface(_token1), address(nftManager), _amount1);
+    }
+
+    /**
+     * @dev addLiquidityWrapper function wrapper of _addLiquidity
+     */
+    function _addLiquidityWrapper(
+        uint256 tokenId,
+        uint256 amountA,
+        uint256 amountB,
+        uint256 slippage
+    )
+        internal
+        returns (
+            uint256 liquidity,
+            uint256 amtA,
+            uint256 amtB
+        )
+    {
+        (address token0, address token1) = getNftTokenPairAddresses(tokenId);
+
+        (liquidity, amtA, amtB) = _addLiquidity(
+            tokenId,
+            token0,
+            token1,
+            amountA,
+            amountB,
+            slippage
+        );
+    }
+
+    /**
+     * @dev addLiquidity function which interact with Uniswap v3
+     */
+    function _addLiquidity(
+        uint256 _tokenId,
+        address _token0,
+        address _token1,
+        uint256 _amount0,
+        uint256 _amount1,
+        uint256 _slippage
+    )
+        internal
+        returns (
+            uint128 liquidity,
+            uint256 amount0,
+            uint256 amount1
+        )
+    {
+        _checkETH(_token0, _token1, _amount0, _amount1);
+        uint256 _amount0Min = getMinAmount(
+            TokenInterface(_token0),
+            _amount0,
+            _slippage
+        );
+        uint256 _amount1Min = getMinAmount(
+            TokenInterface(_token1),
+            _amount1,
+            _slippage
+        );
+        INonfungiblePositionManager.IncreaseLiquidityParams
+            memory params = INonfungiblePositionManager.IncreaseLiquidityParams(
+                _tokenId,
+                _amount0,
+                _amount1,
+                _amount0Min,
+                _amount1Min,
+                block.timestamp
+            );
+
+        (liquidity, amount0, amount1) = nftManager.increaseLiquidity(params);
+    }
+
+    /**
+     * @dev decreaseLiquidity function which interact with Uniswap v3
+     */
+    function _decreaseLiquidity(
+        uint256 _tokenId,
+        uint128 _liquidity,
+        uint256 _amount0Min,
+        uint256 _amount1Min
+    ) internal returns (uint256 amount0, uint256 amount1) {
+        INonfungiblePositionManager.DecreaseLiquidityParams
+            memory params = INonfungiblePositionManager.DecreaseLiquidityParams(
+                _tokenId,
+                _liquidity,
+                _amount0Min,
+                _amount1Min,
+                block.timestamp
+            );
+        (amount0, amount1) = nftManager.decreaseLiquidity(params);
+    }
+
+    function _stake(
+        uint256 _tokenId,
+        IUniswapV3Staker.IncentiveKey memory _incentiveId
+    ) internal {
+        staker.stakeToken(_incentiveId, _tokenId);
+    }
+
+    function _unstake(
+        IUniswapV3Staker.IncentiveKey memory _key,
+        uint256 _tokenId
+    ) internal {
+        staker.unstakeToken(_key, _tokenId);
+    }
+
+    function _claimRewards(
+        IERC20Minimal _rewardToken,
+        address _to,
+        uint256 _amountRequested
+    ) internal returns (uint256 rewards) {
+        rewards = staker.claimReward(_rewardToken, _to, _amountRequested);
+    }
+}
diff --git a/contracts/mainnet/connectors/uniswapStaker/interface.sol b/contracts/mainnet/connectors/uniswapStaker/interface.sol
new file mode 100644
index 00000000..5c537e43
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswapStaker/interface.sol
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+pragma solidity =0.7.6;
+pragma abicoder v2;
+
+import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
+
+import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
+import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
+import '@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol';
+
+import '@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol';
+import '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol';
+
+/// @title Uniswap V3 Staker Interface
+/// @notice Allows staking nonfungible liquidity tokens in exchange for reward tokens
+interface IUniswapV3Staker is IERC721Receiver, IMulticall {
+    /// @param rewardToken The token being distributed as a reward
+    /// @param pool The Uniswap V3 pool
+    /// @param startTime The time when the incentive program begins
+    /// @param endTime The time when rewards stop accruing
+    /// @param refundee The address which receives any remaining reward tokens when the incentive is ended
+    struct IncentiveKey {
+        IERC20Minimal rewardToken;
+        IUniswapV3Pool pool;
+        uint256 startTime;
+        uint256 endTime;
+        address refundee;
+    }
+
+    /// @notice The Uniswap V3 Factory
+    function factory() external view returns (IUniswapV3Factory);
+
+    /// @notice The nonfungible position manager with which this staking contract is compatible
+    function nonfungiblePositionManager() external view returns (INonfungiblePositionManager);
+
+    /// @notice The max duration of an incentive in seconds
+    function maxIncentiveDuration() external view returns (uint256);
+
+    /// @notice The max amount of seconds into the future the incentive startTime can be set
+    function maxIncentiveStartLeadTime() external view returns (uint256);
+
+    /// @notice Represents a staking incentive
+    /// @param incentiveId The ID of the incentive computed from its parameters
+    /// @return totalRewardUnclaimed The amount of reward token not yet claimed by users
+    /// @return totalSecondsClaimedX128 Total liquidity-seconds claimed, represented as a UQ32.128
+    /// @return numberOfStakes The count of deposits that are currently staked for the incentive
+    function incentives(bytes32 incentiveId)
+        external
+        view
+        returns (
+            uint256 totalRewardUnclaimed,
+            uint160 totalSecondsClaimedX128,
+            uint96 numberOfStakes
+        );
+
+    /// @notice Returns information about a deposited NFT
+    /// @return owner The owner of the deposited NFT
+    /// @return numberOfStakes Counter of how many incentives for which the liquidity is staked
+    /// @return tickLower The lower tick of the range
+    /// @return tickUpper The upper tick of the range
+    function deposits(uint256 tokenId)
+        external
+        view
+        returns (
+            address owner,
+            uint48 numberOfStakes,
+            int24 tickLower,
+            int24 tickUpper
+        );
+
+    /// @notice Returns information about a staked liquidity NFT
+    /// @param tokenId The ID of the staked token
+    /// @param incentiveId The ID of the incentive for which the token is staked
+    /// @return secondsPerLiquidityInsideInitialX128 secondsPerLiquidity represented as a UQ32.128
+    /// @return liquidity The amount of liquidity in the NFT as of the last time the rewards were computed
+    function stakes(uint256 tokenId, bytes32 incentiveId)
+        external
+        view
+        returns (uint160 secondsPerLiquidityInsideInitialX128, uint128 liquidity);
+
+    /// @notice Returns amounts of reward tokens owed to a given address according to the last time all stakes were updated
+    /// @param rewardToken The token for which to check rewards
+    /// @param owner The owner for which the rewards owed are checked
+    /// @return rewardsOwed The amount of the reward token claimable by the owner
+    function rewards(IERC20Minimal rewardToken, address owner) external view returns (uint256 rewardsOwed);
+
+    /// @notice Creates a new liquidity mining incentive program
+    /// @param key Details of the incentive to create
+    /// @param reward The amount of reward tokens to be distributed
+    function createIncentive(IncentiveKey memory key, uint256 reward) external;
+
+    /// @notice Ends an incentive after the incentive end time has passed and all stakes have been withdrawn
+    /// @param key Details of the incentive to end
+    /// @return refund The remaining reward tokens when the incentive is ended
+    function endIncentive(IncentiveKey memory key) external returns (uint256 refund);
+
+    /// @notice Transfers ownership of a deposit from the sender to the given recipient
+    /// @param tokenId The ID of the token (and the deposit) to transfer
+    /// @param to The new owner of the deposit
+    function transferDeposit(uint256 tokenId, address to) external;
+
+    /// @notice Withdraws a Uniswap V3 LP token `tokenId` from this contract to the recipient `to`
+    /// @param tokenId The unique identifier of an Uniswap V3 LP token
+    /// @param to The address where the LP token will be sent
+    /// @param data An optional data array that will be passed along to the `to` address via the NFT safeTransferFrom
+    function withdrawToken(
+        uint256 tokenId,
+        address to,
+        bytes memory data
+    ) external;
+
+    /// @notice Stakes a Uniswap V3 LP token
+    /// @param key The key of the incentive for which to stake the NFT
+    /// @param tokenId The ID of the token to stake
+    function stakeToken(IncentiveKey memory key, uint256 tokenId) external;
+
+    /// @notice Unstakes a Uniswap V3 LP token
+    /// @param key The key of the incentive for which to unstake the NFT
+    /// @param tokenId The ID of the token to unstake
+    function unstakeToken(IncentiveKey memory key, uint256 tokenId) external;
+
+    /// @notice Transfers `amountRequested` of accrued `rewardToken` rewards from the contract to the recipient `to`
+    /// @param rewardToken The token being distributed as a reward
+    /// @param to The address where claimed rewards will be sent to
+    /// @param amountRequested The amount of reward tokens to claim. Claims entire reward amount if set to 0.
+    /// @return reward The amount of reward tokens claimed
+    function claimReward(
+        IERC20Minimal rewardToken,
+        address to,
+        uint256 amountRequested
+    ) external returns (uint256 reward);
+
+    /// @notice Calculates the reward amount that will be received for the given stake
+    /// @param key The key of the incentive
+    /// @param tokenId The ID of the token
+    /// @return reward The reward accrued to the NFT for the given incentive thus far
+    function getRewardInfo(IncentiveKey memory key, uint256 tokenId)
+        external
+        returns (uint256 reward, uint160 secondsInsideX128);
+
+    /// @notice Event emitted when a liquidity mining incentive has been created
+    /// @param rewardToken The token being distributed as a reward
+    /// @param pool The Uniswap V3 pool
+    /// @param startTime The time when the incentive program begins
+    /// @param endTime The time when rewards stop accruing
+    /// @param refundee The address which receives any remaining reward tokens after the end time
+    /// @param reward The amount of reward tokens to be distributed
+    event IncentiveCreated(
+        IERC20Minimal indexed rewardToken,
+        IUniswapV3Pool indexed pool,
+        uint256 startTime,
+        uint256 endTime,
+        address refundee,
+        uint256 reward
+    );
+
+    /// @notice Event that can be emitted when a liquidity mining incentive has ended
+    /// @param incentiveId The incentive which is ending
+    /// @param refund The amount of reward tokens refunded
+    event IncentiveEnded(bytes32 indexed incentiveId, uint256 refund);
+
+    /// @notice Emitted when ownership of a deposit changes
+    /// @param tokenId The ID of the deposit (and token) that is being transferred
+    /// @param oldOwner The owner before the deposit was transferred
+    /// @param newOwner The owner after the deposit was transferred
+    event DepositTransferred(uint256 indexed tokenId, address indexed oldOwner, address indexed newOwner);
+
+    /// @notice Event emitted when a Uniswap V3 LP token has been staked
+    /// @param tokenId The unique identifier of an Uniswap V3 LP token
+    /// @param liquidity The amount of liquidity staked
+    /// @param incentiveId The incentive in which the token is staking
+    event TokenStaked(uint256 indexed tokenId, bytes32 indexed incentiveId, uint128 liquidity);
+
+    /// @notice Event emitted when a Uniswap V3 LP token has been unstaked
+    /// @param tokenId The unique identifier of an Uniswap V3 LP token
+    /// @param incentiveId The incentive in which the token is staking
+    event TokenUnstaked(uint256 indexed tokenId, bytes32 indexed incentiveId);
+
+    /// @notice Event emitted when a reward token has been claimed
+    /// @param to The address where claimed rewards were sent to
+    /// @param reward The amount of reward tokens claimed
+    event RewardClaimed(address indexed to, uint256 reward);
+}
diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswapStaker/main.sol
new file mode 100644
index 00000000..da0db209
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswapStaker/main.sol
@@ -0,0 +1,237 @@
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+/**
+ * @title Uniswap v3.
+ * @dev Decentralized Exchange.
+ */
+
+import {TokenInterface} from "../../common/interfaces.sol";
+import "./interface.sol";
+import {Helpers} from "./helpers.sol";
+import {Events} from "./events.sol";
+
+abstract contract UniswapResolver is Helpers, Events {
+    /**
+     * @dev Increase Liquidity
+     * @notice Increase Liquidity of NFT Position
+     * @param tokenId NFT LP Token ID.
+     * @param amountA tokenA amounts.
+     * @param amountB tokenB amounts.
+     * @param slippage slippage.
+     * @param getIds IDs to retrieve token amounts
+     * @param setId stores the liquidity amount
+     */
+    function deposit(
+        uint256 tokenId,
+        uint256 amountA,
+        uint256 amountB,
+        uint256 slippage,
+        uint256[] calldata getIds,
+        uint256 setId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        if (tokenId == 0) tokenId = _getLastNftId(address(this));
+        amountA = getUint(getIds[0], amountA);
+        amountB = getUint(getIds[1], amountB);
+        (
+            uint256 _liquidity,
+            uint256 _amtA,
+            uint256 _amtB
+        ) = _addLiquidityWrapper(tokenId, amountA, amountB, slippage);
+        setUint(setId, _liquidity);
+
+        _eventName = "LogDeposit(uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+    }
+
+    /**
+     * @dev Decrease Liquidity
+     * @notice Decrease Liquidity of NFT Position
+     * @param tokenId NFT LP Token ID.
+     * @param liquidity LP Token amount.
+     * @param amountAMin Min amount of tokenA.
+     * @param amountBMin Min amount of tokenB.
+     * @param getId ID to retrieve LP token amounts
+     * @param setIds stores the amount of output tokens
+     */
+    function withdraw(
+        uint256 tokenId,
+        uint256 liquidity,
+        uint256 amountAMin,
+        uint256 amountBMin,
+        uint256 getId,
+        uint256[] calldata setIds
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        if (tokenId == 0) tokenId = _getLastNftId(address(this));
+        uint128 _liquidity = uint128(getUint(getId, liquidity));
+
+        (uint256 _amtA, uint256 _amtB) = _decreaseLiquidity(
+            tokenId,
+            _liquidity,
+            amountAMin,
+            amountBMin
+        );
+
+        setUint(setIds[0], _amtA);
+        setUint(setIds[1], _amtB);
+
+        _eventName = "LogWithdraw(uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+    }
+
+    /**
+     * @dev Stake NFT LP token
+     * @notice Stake NFT LP Position
+     * @param _rewardToken _rewardToken address
+     * @param _startTime stake start time
+     * @param _endTime stake end time
+     * @param _refundee refundee address
+     * @param _tokenId NFT LP token id
+     */
+    function stake(
+        address _rewardToken,
+        uint256 _startTime,
+        uint256 _endTime,
+        address _refundee,
+        uint256 _tokenId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        nftManager.safeTransferFrom(
+            address(this),
+            address(staker),
+            _tokenId,
+            ""
+        );
+        address poolAddr = getPoolAddress(_tokenId);
+
+        IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
+        IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker
+            .IncentiveKey(
+                IERC20Minimal(_rewardToken),
+                pool,
+                _startTime,
+                _endTime,
+                _refundee
+            );
+        _stake(_tokenId, _key);
+
+        _eventName = "LogStake(uint256, address)";
+        _eventParam = abi.encode(_tokenId, _refundee);
+    }
+
+    /**
+     * @dev Unstake NFT LP token
+     * @notice Unstake NFT LP Position
+     * @param _rewardToken _rewardToken address
+     * @param _startTime stake start time
+     * @param _endTime stake end time
+     * @param _refundee refundee address
+     * @param _tokenId NFT LP token id
+     */
+    function unstake(
+        address _rewardToken,
+        uint256 _startTime,
+        uint256 _endTime,
+        address _refundee,
+        uint256 _tokenId
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        address poolAddr = getPoolAddress(_tokenId);
+
+        IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
+        IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker
+            .IncentiveKey(
+                IERC20Minimal(_rewardToken),
+                pool,
+                _startTime,
+                _endTime,
+                _refundee
+            );
+        _unstake(_key, _tokenId);
+        _eventName = "LogUnstake(uint256,bytes32)";
+        _eventParam = abi.encode(_tokenId, _key);
+    }
+
+    /**
+     * @dev Claim rewards
+     * @notice Claim rewards
+     * @param _rewardToken _rewardToken address
+     * @param _to address to receive
+     * @param _amountRequested requested amount
+     */
+    function claimRewards(
+        address _rewardToken,
+        address _to,
+        uint256 _amountRequested
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        uint256 rewards = _claimRewards(
+            IERC20Minimal(_rewardToken),
+            _to,
+            _amountRequested
+        );
+
+        _eventName = "LogRewardClaimed(address,address,uint256)";
+        _eventParam = abi.encode(_rewardToken, _to, rewards);
+    }
+
+    /**
+     * @dev Create incentive
+     * @notice Create incentive
+     * @param _rewardToken _rewardToken address
+     * @param _length incentive length
+     * @param _refundee refundee address
+     * @param _tokenId NFT LP token id
+     * @param _reward reward amount
+     */
+    function createIncentive(
+        address _rewardToken,
+        uint256 _length,
+        address _refundee,
+        uint256 _tokenId,
+        uint256 _reward
+    )
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        address poolAddr = getPoolAddress(_tokenId);
+
+        IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
+        uint256 _startTime = block.timestamp;
+        uint256 _endTime = _startTime + _length;
+        IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker
+            .IncentiveKey(
+                IERC20Minimal(_rewardToken),
+                pool,
+                _startTime,
+                _endTime,
+                _refundee
+            );
+        staker.createIncentive(_key, _reward);
+
+        _eventName = "LogIncentiveCreated(uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(_tokenId, _startTime, _endTime, _reward);
+    }
+}
+
+contract ConnectV2UniswapV3Staker is UniswapResolver {
+    string public constant name = "UniswapStaker-v1";
+}
diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
new file mode 100644
index 00000000..0ca88ae0
--- /dev/null
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -0,0 +1,245 @@
+const { expect } = require("chai");
+const hre = require("hardhat");
+const { waffle, ethers } = hre;
+const { provider, deployContract } = waffle
+
+const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
+const buildDSAv2 = require("../../scripts/buildDSAv2")
+const encodeSpells = require("../../scripts/encodeSpells.js")
+const getMasterSigner = require("../../scripts/getMasterSigner")
+const addLiquidity = require("../../scripts/addLiquidity");
+
+const addresses = require("../../scripts/constant/addresses");
+const abis = require("../../scripts/constant/abis");
+const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json")
+
+const connectV2UniswapStakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswapStaker/main.sol/ConnectV2UniswapV3Staker.json");
+const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswapV3/main.sol/ConnectV2UniswapV3.json");
+
+const FeeAmount = {
+    LOW: 500,
+    MEDIUM: 3000,
+    HIGH: 10000,
+}
+
+const TICK_SPACINGS = {
+    500: 10,
+    3000: 60,
+    10000: 200
+}
+
+const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"
+const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+
+let tokenIds = []
+const abiCoder = ethers.utils.defaultAbiCoder
+
+describe("UniswapV3", function () {
+    const connectorStaker = "UniswapStaker-v1"
+    const connectorUniswap = "UniswapV3-v1"
+
+    let dsaWallet0
+    let masterSigner;
+    let instaConnectorsV2;
+    let connector;
+    let startTime, endTime;
+
+    const wallets = provider.getWallets()
+    const [wallet0, wallet1, wallet2, wallet3] = wallets
+    before(async () => {
+        masterSigner = await getMasterSigner(wallet3)
+        instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+        nftManager = await ethers.getContractAt(nftManagerAbi, "0xC36442b4a4522E871399CD717aBDD847Ab11FE88");
+        connector = await deployAndEnableConnector({
+            connectorName: connectorStaker,
+            contractArtifact: connectV2UniswapStakerArtifacts,
+            signer: masterSigner,
+            connectors: instaConnectorsV2
+        })
+        console.log("Connector address", connector.address)
+
+        uniswapConnector = await deployAndEnableConnector({
+            connectorName: connectorUniswap,
+            contractArtifact: connectV2UniswapV3Artifacts,
+            signer: masterSigner,
+            connectors: instaConnectorsV2
+        });
+    })
+
+    it("Should have contracts deployed.", async function () {
+        expect(!!instaConnectorsV2.address).to.be.true;
+        expect(!!connector.address).to.be.true;
+        expect(!!masterSigner.address).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("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
+            await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000"));
+        });
+    });
+
+    describe("Main", function () {
+        const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH
+        const daiAmount = ethers.utils.parseEther("400") // 1 ETH
+
+        it("Should mint successfully", async function () {
+            const getIds = ["0", "0"]
+            const setId = "0"
+
+            const spells = [
+                {
+                    connector: connectorUniswap,
+                    method: "mint",
+                    args: [
+                        DAI_ADDR,
+                        ethAddress,
+                        FeeAmount.MEDIUM,
+                        getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
+                        getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
+                        daiAmount,
+                        ethAmount,
+                        "500000000000000000",
+                        getIds,
+                        setId
+                    ],
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+
+            let castEvent = new Promise((resolve, reject) => {
+                dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
+                    const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]);
+                    tokenIds.push(params[0]);
+                    event.removeListener();
+
+                    resolve({
+                        eventNames,
+                    });
+                });
+
+                setTimeout(() => {
+                    reject(new Error('timeout'));
+                }, 60000)
+            });
+
+            let event = await castEvent
+        });
+
+        it("Should create incentive successfully", async function () {
+            const spells = [
+                {
+                    connector: connectorStaker,
+                    method: "createIncentive",
+                    args: [
+                        ethAddress,
+                        "1000",
+                        dsaWallet0.address,
+                        tokenIds[0],
+                        ethers.utils.parseEther("0.01")
+                    ],
+                }]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+
+            let castEvent = new Promise((resolve, reject) => {
+                dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
+                    const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[0]);
+                    event.removeListener();
+
+                    resolve({ start: params[1], end: params[2] });
+                });
+
+                setTimeout(() => {
+                    reject(new Error('timeout'));
+                }, 60000)
+            });
+
+            let event = await castEvent
+            startTime = event.start;
+            endTime = event.end;
+        });
+
+        it("Should stake successfully", async function () {
+            const spells = [
+                {
+                    connector: connectorStaker,
+                    method: "stake",
+                    args: [
+                        ethAddress,
+                        startTime,
+                        endTime,
+                        dsaWallet0.address,
+                        tokenIds[0]
+                    ],
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+        });
+
+        it("Should claim rewards successfully", async function () {
+            const spells = [
+                {
+                    connector: connectorStaker,
+                    method: "claimRewards",
+                    args: [
+                        ethAddress,
+                        dsaWallet0.address,
+                        "1000",
+                    ],
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+        });
+
+        it("Should unstake successfully", async function () {
+            const spells = [
+                {
+                    connector: connectorStaker,
+                    method: "unstake",
+                    args: [
+                        ethAddress,
+                        startTime,
+                        endTime,
+                        dsaWallet0.address,
+                        tokenIds[0]
+                    ],
+                }
+            ]
+
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            let receipt = await tx.wait()
+        });
+    })
+})
+
+const getMinTick = (tickSpacing) => Math.ceil(-887272 / tickSpacing) * tickSpacing
+const getMaxTick = (tickSpacing) => Math.floor(887272 / tickSpacing) * tickSpacing

From 509d2cf3bda90d6ee8a1a4769b5373d7a363ed6b Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 24 Aug 2021 14:56:55 -0500
Subject: [PATCH 02/28] refactor: fix deposit/withdraw function

---
 .../connectors/uniswapStaker/events.sol       |  16 +--
 .../connectors/uniswapStaker/helpers.sol      | 107 ------------------
 .../mainnet/connectors/uniswapStaker/main.sol |  99 +++++++---------
 test/uniswapStake/uniswapStake.test.js        |   7 ++
 4 files changed, 49 insertions(+), 180 deletions(-)

diff --git a/contracts/mainnet/connectors/uniswapStaker/events.sol b/contracts/mainnet/connectors/uniswapStaker/events.sol
index 8618e151..b5b2e8b0 100644
--- a/contracts/mainnet/connectors/uniswapStaker/events.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/events.sol
@@ -1,19 +1,11 @@
 pragma solidity ^0.7.0;
 
 contract Events {
-    event LogDeposit(
-        uint256 indexed tokenId,
-        uint256 liquidity,
-        uint256 amountA,
-        uint256 amountB
-    );
+    event LogDeposit(uint256 tokenId);
 
-    event LogWithdraw(
-        uint256 indexed tokenId,
-        uint256 liquidity,
-        uint256 amountA,
-        uint256 amountB
-    );
+    event LogWithdraw(uint256 indexed tokenId, address to);
+
+    event LogDepositTransfer(uint256 indexed tokenId, address to);
 
     event LogStake(uint256 tokenId, address refundee);
 
diff --git a/contracts/mainnet/connectors/uniswapStaker/helpers.sol b/contracts/mainnet/connectors/uniswapStaker/helpers.sol
index e7b8e7af..71926302 100644
--- a/contracts/mainnet/connectors/uniswapStaker/helpers.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/helpers.sol
@@ -99,113 +99,6 @@ abstract contract Helpers is DSMath, Basic {
         }
     }
 
-    /**
-     * @dev Check if token address is etherAddr and convert it to weth
-     */
-    function _checkETH(
-        address _token0,
-        address _token1,
-        uint256 _amount0,
-        uint256 _amount1
-    ) internal {
-        bool isEth0 = _token0 == wethAddr;
-        bool isEth1 = _token1 == wethAddr;
-        convertEthToWeth(isEth0, TokenInterface(_token0), _amount0);
-        convertEthToWeth(isEth1, TokenInterface(_token1), _amount1);
-        approve(TokenInterface(_token0), address(nftManager), _amount0);
-        approve(TokenInterface(_token1), address(nftManager), _amount1);
-    }
-
-    /**
-     * @dev addLiquidityWrapper function wrapper of _addLiquidity
-     */
-    function _addLiquidityWrapper(
-        uint256 tokenId,
-        uint256 amountA,
-        uint256 amountB,
-        uint256 slippage
-    )
-        internal
-        returns (
-            uint256 liquidity,
-            uint256 amtA,
-            uint256 amtB
-        )
-    {
-        (address token0, address token1) = getNftTokenPairAddresses(tokenId);
-
-        (liquidity, amtA, amtB) = _addLiquidity(
-            tokenId,
-            token0,
-            token1,
-            amountA,
-            amountB,
-            slippage
-        );
-    }
-
-    /**
-     * @dev addLiquidity function which interact with Uniswap v3
-     */
-    function _addLiquidity(
-        uint256 _tokenId,
-        address _token0,
-        address _token1,
-        uint256 _amount0,
-        uint256 _amount1,
-        uint256 _slippage
-    )
-        internal
-        returns (
-            uint128 liquidity,
-            uint256 amount0,
-            uint256 amount1
-        )
-    {
-        _checkETH(_token0, _token1, _amount0, _amount1);
-        uint256 _amount0Min = getMinAmount(
-            TokenInterface(_token0),
-            _amount0,
-            _slippage
-        );
-        uint256 _amount1Min = getMinAmount(
-            TokenInterface(_token1),
-            _amount1,
-            _slippage
-        );
-        INonfungiblePositionManager.IncreaseLiquidityParams
-            memory params = INonfungiblePositionManager.IncreaseLiquidityParams(
-                _tokenId,
-                _amount0,
-                _amount1,
-                _amount0Min,
-                _amount1Min,
-                block.timestamp
-            );
-
-        (liquidity, amount0, amount1) = nftManager.increaseLiquidity(params);
-    }
-
-    /**
-     * @dev decreaseLiquidity function which interact with Uniswap v3
-     */
-    function _decreaseLiquidity(
-        uint256 _tokenId,
-        uint128 _liquidity,
-        uint256 _amount0Min,
-        uint256 _amount1Min
-    ) internal returns (uint256 amount0, uint256 amount1) {
-        INonfungiblePositionManager.DecreaseLiquidityParams
-            memory params = INonfungiblePositionManager.DecreaseLiquidityParams(
-                _tokenId,
-                _liquidity,
-                _amount0Min,
-                _amount1Min,
-                block.timestamp
-            );
-        (amount0, amount1) = nftManager.decreaseLiquidity(params);
-    }
-
     function _stake(
         uint256 _tokenId,
         IUniswapV3Staker.IncentiveKey memory _incentiveId
diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswapStaker/main.sol
index da0db209..72872a5e 100644
--- a/contracts/mainnet/connectors/uniswapStaker/main.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/main.sol
@@ -13,78 +13,61 @@ import {Events} from "./events.sol";
 
 abstract contract UniswapResolver is Helpers, Events {
     /**
-     * @dev Increase Liquidity
-     * @notice Increase Liquidity of NFT Position
-     * @param tokenId NFT LP Token ID.
-     * @param amountA tokenA amounts.
-     * @param amountB tokenB amounts.
-     * @param slippage slippage.
-     * @param getIds IDs to retrieve token amounts
-     * @param setId stores the liquidity amount
+     * @dev Deposit NFT token
+     * @notice Transfer deposited NFT token
+     * @param _tokenId NFT LP Token ID
      */
-    function deposit(
-        uint256 tokenId,
-        uint256 amountA,
-        uint256 amountB,
-        uint256 slippage,
-        uint256[] calldata getIds,
-        uint256 setId
-    )
+    function deposit(uint256 _tokenId)
         external
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        if (tokenId == 0) tokenId = _getLastNftId(address(this));
-        amountA = getUint(getIds[0], amountA);
-        amountB = getUint(getIds[1], amountB);
-        (
-            uint256 _liquidity,
-            uint256 _amtA,
-            uint256 _amtB
-        ) = _addLiquidityWrapper(tokenId, amountA, amountB, slippage);
-        setUint(setId, _liquidity);
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
+        nftManager.safeTransferFrom(
+            address(this),
+            address(staker),
+            _tokenId,
+            ""
+        );
 
-        _eventName = "LogDeposit(uint256,uint256,uint256,uint256)";
-        _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+        _eventName = "LogDeposit(uint256)";
+        _eventParam = abi.encode(_tokenId);
     }
 
     /**
-     * @dev Decrease Liquidity
-     * @notice Decrease Liquidity of NFT Position
-     * @param tokenId NFT LP Token ID.
-     * @param liquidity LP Token amount.
-     * @param amountAMin Min amount of tokenA.
-     * @param amountBMin Min amount of tokenB.
-     * @param getId ID to retrieve LP token amounts
-     * @param setIds stores the amount of output tokens
+     * @dev Deposit Transfer
+     * @notice Transfer deposited NFT token
+     * @param _tokenId NFT LP Token ID
+     * @param _to address to transfer
      */
-    function withdraw(
-        uint256 tokenId,
-        uint256 liquidity,
-        uint256 amountAMin,
-        uint256 amountBMin,
-        uint256 getId,
-        uint256[] calldata setIds
-    )
+    function transferDeposit(uint256 _tokenId, address _to)
         external
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        if (tokenId == 0) tokenId = _getLastNftId(address(this));
-        uint128 _liquidity = uint128(getUint(getId, liquidity));
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
+        staker.transferDeposit(_tokenId, _to);
 
-        (uint256 _amtA, uint256 _amtB) = _decreaseLiquidity(
-            tokenId,
-            _liquidity,
-            amountAMin,
-            amountBMin
-        );
+        _eventName = "LogDepositTransfer(uint256,address)";
+        _eventParam = abi.encode(_tokenId, _to);
+    }
 
-        setUint(setIds[0], _amtA);
-        setUint(setIds[1], _amtB);
+    /**
+     * @dev Withdraw NFT LP token
+     * @notice Withdraw NFT LP token from staking pool
+     * @param _tokenId NFT LP Token ID
+     * @param _to address to transfer
+     */
+    function withdraw(uint256 _tokenId, address _to)
+        external
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
+        staker.withdrawToken(_tokenId, _to, "");
 
-        _eventName = "LogWithdraw(uint256,uint256,uint256,uint256)";
-        _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+        _eventName = "LogWithdraw(uint256,address)";
+        _eventParam = abi.encode(_tokenId, _to);
     }
 
     /**
@@ -107,12 +90,6 @@ abstract contract UniswapResolver is Helpers, Events {
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        nftManager.safeTransferFrom(
-            address(this),
-            address(staker),
-            _tokenId,
-            ""
-        );
         address poolAddr = getPoolAddress(_tokenId);
 
         IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
index 0ca88ae0..923b673a 100644
--- a/test/uniswapStake/uniswapStake.test.js
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -186,6 +186,13 @@ describe("UniswapV3", function () {
 
         it("Should stake successfully", async function () {
             const spells = [
+                {
+                    connector: connectorStaker,
+                    method: "deposit",
+                    args: [
+                        tokenIds[0]
+                    ],
+                },
                 {
                     connector: connectorStaker,
                     method: "stake",

From f4b4cbfc5eca24b31842222577fc1f2951afe194 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Wed, 25 Aug 2021 10:09:52 -0500
Subject: [PATCH 03/28] feat/implement ERC721 deposit/withdraw

---
 .../connectors/basic-ERC721/events.sol        | 14 +++++
 .../mainnet/connectors/basic-ERC721/main.sol  | 58 +++++++++++++++++++
 2 files changed, 72 insertions(+)
 create mode 100644 contracts/mainnet/connectors/basic-ERC721/events.sol
 create mode 100644 contracts/mainnet/connectors/basic-ERC721/main.sol

diff --git a/contracts/mainnet/connectors/basic-ERC721/events.sol b/contracts/mainnet/connectors/basic-ERC721/events.sol
new file mode 100644
index 00000000..ebe059e5
--- /dev/null
+++ b/contracts/mainnet/connectors/basic-ERC721/events.sol
@@ -0,0 +1,14 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+    event LogDepositERC721(
+        address indexed erc721,
+        address from,
+        uint256 tokenId
+    );
+    event LogWithdrawERC721(
+        address indexed erc721,
+        uint256 tokenId,
+        address indexed to
+    );
+}
diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
new file mode 100644
index 00000000..98878ada
--- /dev/null
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -0,0 +1,58 @@
+pragma solidity ^0.7.0;
+
+/**
+ * @title Basic.
+ * @dev Deposit & Withdraw from DSA.
+ */
+import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
+
+import {DSMath} from "../../common/math.sol";
+import {Basic} from "../../common/basic.sol";
+import {Events} from "./events.sol";
+
+abstract contract BasicResolver is Events, DSMath, Basic {
+    /**
+     * @dev Deposit Assets To Smart Account.
+     * @notice Deposit a ERC721 token to DSA
+     * @param token The address of the token to deposit.
+     * @param tokenId The id of token to deposit.
+     */
+    function depositERC721(address token, uint256 tokenId)
+        public
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        IERC721 tokenContract = IERC721(token);
+        tokenContract.safeTransferFrom(msg.sender, address(this), tokenId);
+
+        _eventName = "LogDepositERC721(address,address,uint256)";
+        _eventParam = abi.encode(token, msg.sender, tokenId);
+    }
+
+    /**
+     * @dev Withdraw Assets To Smart Account.
+     * @notice Withdraw a ERC721 token from DSA
+     * @param token The address of the token to deposit.
+     * @param tokenId The id of token to deposit.
+     * @param to The address to receive the token upon withdrawal
+     */
+    function withdrawERC721(
+        address token,
+        uint256 tokenId,
+        address payable to
+    )
+        public
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        IERC721 tokenContract = IERC721(token);
+        tokenContract.safeTransferFrom(address(this), to, tokenId);
+
+        _eventName = "LogWithdrawERC721(address,uint256,address)";
+        _eventParam = abi.encode(token, tokenId, to);
+    }
+}
+
+contract ConnectV2Basic is BasicResolver {
+    string public constant name = "BASIC-ERC721-A";
+}

From cc6da0c75822b22293487b0f5620725b9e9445f0 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Wed, 25 Aug 2021 11:18:31 -0500
Subject: [PATCH 04/28] refactor/implement getId/setId

---
 .../connectors/basic-ERC721/events.sol        |  8 +++--
 .../mainnet/connectors/basic-ERC721/main.sol  | 32 +++++++++++++------
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/contracts/mainnet/connectors/basic-ERC721/events.sol b/contracts/mainnet/connectors/basic-ERC721/events.sol
index ebe059e5..7b367145 100644
--- a/contracts/mainnet/connectors/basic-ERC721/events.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/events.sol
@@ -4,11 +4,15 @@ contract Events {
     event LogDepositERC721(
         address indexed erc721,
         address from,
-        uint256 tokenId
+        uint256 tokenId,
+        uint256 getId,
+        uint256 setId
     );
     event LogWithdrawERC721(
         address indexed erc721,
         uint256 tokenId,
-        address indexed to
+        address indexed to,
+        uint256 getId,
+        uint256 setId
     );
 }
diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
index 98878ada..9e6f86b2 100644
--- a/contracts/mainnet/connectors/basic-ERC721/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -17,16 +17,25 @@ abstract contract BasicResolver is Events, DSMath, Basic {
      * @param token The address of the token to deposit.
      * @param tokenId The id of token to deposit.
      */
-    function depositERC721(address token, uint256 tokenId)
+    function depositERC721(
+        address token,
+        uint256 tokenId,
+        uint256 getId,
+        uint256 setId
+    )
         public
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        IERC721 tokenContract = IERC721(token);
-        tokenContract.safeTransferFrom(msg.sender, address(this), tokenId);
+        uint256 _tokenId = getUint(getId, tokenId);
 
-        _eventName = "LogDepositERC721(address,address,uint256)";
-        _eventParam = abi.encode(token, msg.sender, tokenId);
+        IERC721 tokenContract = IERC721(token);
+        tokenContract.safeTransferFrom(msg.sender, address(this), _tokenId);
+
+        setUint(setId, _tokenId);
+
+        _eventName = "LogDepositERC721(address,address,uint256,uint256,uint256)";
+        _eventParam = abi.encode(token, msg.sender, _tokenId, getId, setId);
     }
 
     /**
@@ -39,17 +48,22 @@ abstract contract BasicResolver is Events, DSMath, Basic {
     function withdrawERC721(
         address token,
         uint256 tokenId,
-        address payable to
+        address payable to,
+        uint256 getId,
+        uint256 setId
     )
         public
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
+        uint256 _tokenId = getUint(getId, tokenId);
         IERC721 tokenContract = IERC721(token);
-        tokenContract.safeTransferFrom(address(this), to, tokenId);
+        tokenContract.safeTransferFrom(address(this), to, _tokenId);
 
-        _eventName = "LogWithdrawERC721(address,uint256,address)";
-        _eventParam = abi.encode(token, tokenId, to);
+        setUint(setId, _tokenId);
+
+        _eventName = "LogWithdrawERC721(address,uint256,address,uint256,uint256)";
+        _eventParam = abi.encode(token, _tokenId, to, getId, setId);
     }
 }
 

From 7f8e13af0cf4e19133b119c80112caf40986187b Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Wed, 25 Aug 2021 12:48:08 -0500
Subject: [PATCH 05/28] refactor:  fix small issue

---
 contracts/mainnet/connectors/basic-ERC721/main.sol | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
index 9e6f86b2..e7680b51 100644
--- a/contracts/mainnet/connectors/basic-ERC721/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -16,6 +16,8 @@ abstract contract BasicResolver is Events, DSMath, Basic {
      * @notice Deposit a ERC721 token to DSA
      * @param token The address of the token to deposit.
      * @param tokenId The id of token to deposit.
+     * @param getId ID to retrieve tokenId.
+     * @param setId ID stores the tokenId.
      */
     function depositERC721(
         address token,
@@ -44,6 +46,8 @@ abstract contract BasicResolver is Events, DSMath, Basic {
      * @param token The address of the token to deposit.
      * @param tokenId The id of token to deposit.
      * @param to The address to receive the token upon withdrawal
+     * @param getId ID to retrieve tokenId.
+     * @param setId ID stores the tokenId.
      */
     function withdrawERC721(
         address token,

From 59870142d10817ac2b11656b98f77b6b3070b566 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Wed, 25 Aug 2021 12:54:44 -0500
Subject: [PATCH 06/28] refactor: fix small issues

---
 contracts/mainnet/connectors/uniswapStaker/main.sol | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswapStaker/main.sol
index 72872a5e..b33e0734 100644
--- a/contracts/mainnet/connectors/uniswapStaker/main.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/main.sol
@@ -90,6 +90,7 @@ abstract contract UniswapResolver is Helpers, Events {
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
         address poolAddr = getPoolAddress(_tokenId);
 
         IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
@@ -127,6 +128,7 @@ abstract contract UniswapResolver is Helpers, Events {
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
         address poolAddr = getPoolAddress(_tokenId);
 
         IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
@@ -189,6 +191,7 @@ abstract contract UniswapResolver is Helpers, Events {
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
+        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
         address poolAddr = getPoolAddress(_tokenId);
 
         IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
@@ -210,5 +213,5 @@ abstract contract UniswapResolver is Helpers, Events {
 }
 
 contract ConnectV2UniswapV3Staker is UniswapResolver {
-    string public constant name = "UniswapStaker-v1";
+    string public constant name = "Uniswap-V3-Staker-v1";
 }

From c26e01a72b755ad3fee52624122281ca1c2faa9b Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Wed, 25 Aug 2021 16:26:43 -0500
Subject: [PATCH 07/28] refactor: improve test case

---
 test/uniswapStake/uniswapStake.test.js | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
index 923b673a..be684b6a 100644
--- a/test/uniswapStake/uniswapStake.test.js
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -147,6 +147,9 @@ describe("UniswapV3", function () {
             });
 
             let event = await castEvent
+
+            let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
+            console.log("Balane", balance)
         });
 
         it("Should create incentive successfully", async function () {
@@ -208,6 +211,9 @@ describe("UniswapV3", function () {
 
             const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
             let receipt = await tx.wait()
+
+            let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
+            console.log("Balane", balance)
         });
 
         it("Should claim rewards successfully", async function () {
@@ -239,11 +245,22 @@ describe("UniswapV3", function () {
                         dsaWallet0.address,
                         tokenIds[0]
                     ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "withdraw",
+                    args: [
+                        tokenIds[0],
+                        dsaWallet0.address,
+                    ],
                 }
             ]
 
             const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
             let receipt = await tx.wait()
+
+            let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
+            console.log("Balane", balance)
         });
     })
 })

From cff2edda79ecacf41764e1e023de77abbb5d8af9 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Sat, 28 Aug 2021 14:35:36 -0500
Subject: [PATCH 08/28] refactor: fix minor issue

---
 contracts/mainnet/connectors/uniswapStaker/main.sol | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswapStaker/main.sol
index b33e0734..18ca0916 100644
--- a/contracts/mainnet/connectors/uniswapStaker/main.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/main.sol
@@ -104,7 +104,7 @@ abstract contract UniswapResolver is Helpers, Events {
             );
         _stake(_tokenId, _key);
 
-        _eventName = "LogStake(uint256, address)";
+        _eventName = "LogStake(uint256,address)";
         _eventParam = abi.encode(_tokenId, _refundee);
     }
 

From cce38fec6d8bd054ea11f1415d57f6d4316b4338 Mon Sep 17 00:00:00 2001
From: Thrilok kumar <thrilok2000@gmail.com>
Date: Sun, 29 Aug 2021 23:03:05 +0530
Subject: [PATCH 09/28] Added new connectors

Connector Name: "B-COMPOUND-A"
Connector Address: 0xa3EeFDc2de9DFA59968bEcff3E15b53E6162460f

Connector Name: "B-MAKERDAO-A"
Connector Address: 0xB0A1f10FeEfECf25064CE7cdF0a65042F7dE7bF0

Connector Name: "B-LIQUITY-A"
Connector Address: 0x19574E5Dfb40bbD63A4F3bdcF27ed662b329b2ff

Connector Name: "UNISWAP-V3-A"
Connector Address: 0x25B0c76dE86C3457b9B8b9ee3775F5a7b8D4c475
---
 docs/connectors.json | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/docs/connectors.json b/docs/connectors.json
index 28c96123..75db30dc 100644
--- a/docs/connectors.json
+++ b/docs/connectors.json
@@ -25,7 +25,11 @@
       "REFINANCE-A": "0x6f22931423e8ffC8d51f6E5aF73118fC64b27856",
       "INST-A": "0x52C2C4a0db049255fF345EB9D3Fb1f555b7a924A",
       "REFLEXER-A": "0xaC6dc28a6251F49Bbe5755E630107Dccde9ae2C8",
-      "LIQUITY-A": "0x3643bA40B8e2bd8F77233BDB6abe38c218f31bFe"
+      "LIQUITY-A": "0x3643bA40B8e2bd8F77233BDB6abe38c218f31bFe",
+      "UNISWAP-V3-A": "0x25B0c76dE86C3457b9B8b9ee3775F5a7b8D4c475",
+      "B-COMPOUND-A": "0xa3EeFDc2de9DFA59968bEcff3E15b53E6162460f",
+      "B-MAKERDAO-A": "0xB0A1f10FeEfECf25064CE7cdF0a65042F7dE7bF0",
+      "B-LIQUITY-A": "0x19574E5Dfb40bbD63A4F3bdcF27ed662b329b2ff"
     },
     "137" : {
       "1INCH-A": "0xC0d9210496afE9763F5d8cEb8deFfBa817232A9e",

From 73ed99993b6cd3f86dd4b05ed10db0688336628a Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Mon, 30 Aug 2021 03:23:54 -0500
Subject: [PATCH 10/28] reactor: fix minor issue

---
 contracts/mainnet/connectors/basic-ERC721/main.sol | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
index e7680b51..849aebba 100644
--- a/contracts/mainnet/connectors/basic-ERC721/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -14,8 +14,8 @@ abstract contract BasicResolver is Events, DSMath, Basic {
     /**
      * @dev Deposit Assets To Smart Account.
      * @notice Deposit a ERC721 token to DSA
-     * @param token The address of the token to deposit.
-     * @param tokenId The id of token to deposit.
+     * @param token Address of token.
+     * @param tokenId ID of token.
      * @param getId ID to retrieve tokenId.
      * @param setId ID stores the tokenId.
      */
@@ -43,8 +43,8 @@ abstract contract BasicResolver is Events, DSMath, Basic {
     /**
      * @dev Withdraw Assets To Smart Account.
      * @notice Withdraw a ERC721 token from DSA
-     * @param token The address of the token to deposit.
-     * @param tokenId The id of token to deposit.
+     * @param token Address of the token.
+     * @param tokenId ID of token.
      * @param to The address to receive the token upon withdrawal
      * @param getId ID to retrieve tokenId.
      * @param setId ID stores the tokenId.
@@ -71,6 +71,6 @@ abstract contract BasicResolver is Events, DSMath, Basic {
     }
 }
 
-contract ConnectV2Basic is BasicResolver {
+contract ConnectV2BasicERC721 is BasicResolver {
     string public constant name = "BASIC-ERC721-A";
 }

From 6f7f14c235bb4b27e7eb51d0da8bc34bbe0f94b9 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Mon, 30 Aug 2021 03:25:28 -0500
Subject: [PATCH 11/28] refactor: fix version string

---
 contracts/mainnet/connectors/basic-ERC721/main.sol | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
index 849aebba..a6962b47 100644
--- a/contracts/mainnet/connectors/basic-ERC721/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -72,5 +72,5 @@ abstract contract BasicResolver is Events, DSMath, Basic {
 }
 
 contract ConnectV2BasicERC721 is BasicResolver {
-    string public constant name = "BASIC-ERC721-A";
+    string public constant name = "BASIC-ERC721-v1.0";
 }

From 7905b01a85d43d08bec88139135328e1553f513b Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Mon, 30 Aug 2021 10:33:08 -0500
Subject: [PATCH 12/28] feat: support ERC1155 deposit/withdraw

---
 .../connectors/basic-ERC1155/events.sol       | 20 ++++
 .../mainnet/connectors/basic-ERC1155/main.sol | 93 +++++++++++++++++++
 2 files changed, 113 insertions(+)
 create mode 100644 contracts/mainnet/connectors/basic-ERC1155/events.sol
 create mode 100644 contracts/mainnet/connectors/basic-ERC1155/main.sol

diff --git a/contracts/mainnet/connectors/basic-ERC1155/events.sol b/contracts/mainnet/connectors/basic-ERC1155/events.sol
new file mode 100644
index 00000000..2ef9f79a
--- /dev/null
+++ b/contracts/mainnet/connectors/basic-ERC1155/events.sol
@@ -0,0 +1,20 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+    event LogDepositERC1155(
+        address indexed erc1155,
+        address from,
+        uint256 tokenId,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    );
+    event LogWithdrawERC1155(
+        address indexed erc1155,
+        uint256 tokenId,
+        address indexed to,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    );
+}
diff --git a/contracts/mainnet/connectors/basic-ERC1155/main.sol b/contracts/mainnet/connectors/basic-ERC1155/main.sol
new file mode 100644
index 00000000..c71b7805
--- /dev/null
+++ b/contracts/mainnet/connectors/basic-ERC1155/main.sol
@@ -0,0 +1,93 @@
+pragma solidity ^0.7.0;
+
+/**
+ * @title Basic.
+ * @dev Deposit & Withdraw from DSA.
+ */
+import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
+
+import {DSMath} from "../../common/math.sol";
+import {Basic} from "../../common/basic.sol";
+import {Events} from "./events.sol";
+
+abstract contract BasicResolver is Events, DSMath, Basic {
+    /**
+     * @dev Deposit Assets To Smart Account.
+     * @notice Deposit a ERC721 token to DSA
+     * @param token Address of token.
+     * @param tokenId ID of token.
+     * @param amount Amount to deposit.
+     * @param getId ID to retrieve amount.
+     * @param setId ID stores the amount.
+     */
+    function depositERC1155(
+        address token,
+        uint256 tokenId,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    )
+        public
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        uint256 _amount = getUint(getId, tokenId);
+
+        IERC1155 tokenContract = IERC1155(token);
+        tokenContract.safeTransferFrom(
+            msg.sender,
+            address(this),
+            tokenId,
+            _amount,
+            ""
+        );
+
+        setUint(setId, _amount);
+
+        _eventName = "LogDepositERC1155(address,address,uint256,uint256,uint256,uint256)";
+        _eventParam = abi.encode(
+            token,
+            msg.sender,
+            tokenId,
+            _amount,
+            getId,
+            setId
+        );
+    }
+
+    /**
+     * @dev Withdraw Assets To Smart Account.
+     * @notice Withdraw a ERC721 token from DSA
+     * @param token Address of the token.
+     * @param tokenId ID of token.
+     * @param to The address to receive the token upon withdrawal
+     * @param amount Amount to withdraw.
+     * @param getId ID to retrieve amount.
+     * @param setId ID stores the amount.
+     */
+    function withdrawERC721(
+        address token,
+        uint256 tokenId,
+        address payable to,
+        uint256 amount,
+        uint256 getId,
+        uint256 setId
+    )
+        public
+        payable
+        returns (string memory _eventName, bytes memory _eventParam)
+    {
+        uint256 _amount = getUint(getId, amount);
+        IERC1155 tokenContract = IERC1155(token);
+        tokenContract.safeTransferFrom(address(this), to, tokenId, _amount, "");
+
+        setUint(setId, _amount);
+
+        _eventName = "LogWithdrawERC1155(address,uint256,address,uint256,uint256,uint256)";
+        _eventParam = abi.encode(token, tokenId, to, _amount, getId, setId);
+    }
+}
+
+contract ConnectV2BasicERC1155 is BasicResolver {
+    string public constant name = "BASIC-ERC1155-v1.0";
+}

From 7ad2a53364049f139223816633dc34dbe6ae465e Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Mon, 30 Aug 2021 10:34:52 -0500
Subject: [PATCH 13/28] refactor: fix minor issue

---
 contracts/mainnet/connectors/basic-ERC1155/main.sol | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contracts/mainnet/connectors/basic-ERC1155/main.sol b/contracts/mainnet/connectors/basic-ERC1155/main.sol
index c71b7805..b6ab4af8 100644
--- a/contracts/mainnet/connectors/basic-ERC1155/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC1155/main.sol
@@ -65,7 +65,7 @@ abstract contract BasicResolver is Events, DSMath, Basic {
      * @param getId ID to retrieve amount.
      * @param setId ID stores the amount.
      */
-    function withdrawERC721(
+    function withdrawERC1155(
         address token,
         uint256 tokenId,
         address payable to,

From 453848c7f516c90f5a12fb0b8e66c3b7f9557d7a Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 31 Aug 2021 09:41:31 -0500
Subject: [PATCH 14/28] feat: ERC721 test case

---
 test/basic-ERC721/nftTransfer.test.js | 107 ++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)
 create mode 100644 test/basic-ERC721/nftTransfer.test.js

diff --git a/test/basic-ERC721/nftTransfer.test.js b/test/basic-ERC721/nftTransfer.test.js
new file mode 100644
index 00000000..9735d51e
--- /dev/null
+++ b/test/basic-ERC721/nftTransfer.test.js
@@ -0,0 +1,107 @@
+const { expect } = require("chai");
+const hre = require("hardhat");
+const { web3, deployments, waffle, ethers } = hre;
+const { provider, deployContract } = waffle
+
+const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
+const buildDSAv2 = require("../../scripts/buildDSAv2")
+const encodeSpells = require("../../scripts/encodeSpells.js")
+const getMasterSigner = require("../../scripts/getMasterSigner")
+
+const addresses = require("../../scripts/constant/addresses");
+const abis = require("../../scripts/constant/abis");
+const constants = require("../../scripts/constant/constant");
+const tokens = require("../../scripts/constant/tokens");
+
+const connectV2BasicERC721Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC721/main.sol/ConnectV2BasicERC721.json")
+const erc721Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json")
+
+const TOKEN_CONTRACT_ADDR = "0x4d695c615a7aacf2d7b9c481b66045bb2457dfde";
+const TOKEN_OWNER_ADDR = "0x8c6b10d42ff08e56133fca0dac75e1931b1fcc23";
+const TOKEN_ID = "38";
+
+describe("BASIC-ERC721", function () {
+    const connectorName = "BASIC-ERC721-A"
+
+    let dsaWallet0
+    let masterSigner;
+    let instaConnectorsV2;
+    let connector;
+    let nftContract;
+    let tokenOwner;
+
+
+    const wallets = provider.getWallets()
+    const [wallet0, wallet1, wallet2, wallet3] = wallets
+    before(async () => {
+        await hre.network.provider.request({
+            method: "hardhat_impersonateAccount",
+            params: [TOKEN_OWNER_ADDR],
+        });
+
+        await network.provider.send("hardhat_setBalance", [
+            TOKEN_OWNER_ADDR,
+            "0x1000000000000000",
+        ]);
+
+        // get tokenOwner
+        tokenOwner = await ethers.getSigner(
+            TOKEN_OWNER_ADDR
+        );
+        nftContract = await ethers.getContractAt(erc721Artifacts.abi, TOKEN_CONTRACT_ADDR)
+        masterSigner = await getMasterSigner(wallet3)
+        instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+        connector = await deployAndEnableConnector({
+            connectorName,
+            contractArtifact: connectV2BasicERC721Artifacts,
+            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(!!masterSigner.address).to.be.true;
+    });
+
+    describe("DSA wallet setup", function () {
+        it("Should build DSA v2", async function () {
+            dsaWallet0 = await buildDSAv2(tokenOwner.address)
+            expect(!!dsaWallet0.address).to.be.true;
+        });
+
+        it("Deposit ETH into DSA wallet", async function () {
+            await wallet0.sendTransaction({
+                to: dsaWallet0.address,
+                value: ethers.utils.parseEther("10")
+            });
+            expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+        });
+    });
+
+    describe("Main", function () {
+        it("should deposit successfully", async () => {
+            console.log("DSA wallet address", dsaWallet0.address)
+            await nftContract.connect(tokenOwner).setApprovalForAll(dsaWallet0.address, true);
+            const spells = [
+                {
+                    connector: connectorName,
+                    method: "depositERC721",
+                    args: [
+                        TOKEN_CONTRACT_ADDR,
+                        TOKEN_ID,
+                        "0",
+                        "0"
+                    ]
+                }
+            ];
+
+            const tx = await dsaWallet0
+                .connect(tokenOwner)
+                .cast(...encodeSpells(spells), tokenOwner.address);
+            const receipt = await tx.wait();
+        });
+    })
+})

From d39dc1d5091b49b4f14bf2f620a309d64665bff5 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 31 Aug 2021 11:17:03 -0500
Subject: [PATCH 15/28] feat: implement ERC721/1155 testcase

---
 contracts/test/implementation_default.sol     | 114 ++++++++++
 contracts/test/variables.sol                  |   6 +
 .../abi/core/InstaImplementations.json        | 206 ++++++++++++++++++
 test/basic-ERC1155/ERC1155-transfer.js        | 127 +++++++++++
 ...nftTransfer.test.js => ERC721-transfer.js} |  19 ++
 5 files changed, 472 insertions(+)
 create mode 100644 contracts/test/implementation_default.sol
 create mode 100644 contracts/test/variables.sol
 create mode 100644 scripts/constant/abi/core/InstaImplementations.json
 create mode 100644 test/basic-ERC1155/ERC1155-transfer.js
 rename test/basic-ERC721/{nftTransfer.test.js => ERC721-transfer.js} (79%)

diff --git a/contracts/test/implementation_default.sol b/contracts/test/implementation_default.sol
new file mode 100644
index 00000000..e897433b
--- /dev/null
+++ b/contracts/test/implementation_default.sol
@@ -0,0 +1,114 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+import { Variables } from "./variables.sol";
+
+interface IndexInterface {
+    function list() external view returns (address);
+}
+
+interface ListInterface {
+    function addAuth(address user) external;
+
+    function removeAuth(address user) external;
+}
+
+contract Constants is Variables {
+    uint256 public constant implementationVersion = 1;
+    // InstaIndex Address.
+    address public immutable instaIndex;
+    // The Account Module Version.
+    uint256 public constant version = 2;
+
+    constructor(address _instaIndex) {
+        instaIndex = _instaIndex;
+    }
+}
+
+contract Record is Constants {
+    constructor(address _instaIndex) Constants(_instaIndex) {}
+
+    event LogEnableUser(address indexed user);
+    event LogDisableUser(address indexed user);
+
+    /**
+     * @dev Check for Auth if enabled.
+     * @param user address/user/owner.
+     */
+    function isAuth(address user) public view returns (bool) {
+        return _auth[user];
+    }
+
+    /**
+     * @dev Enable New User.
+     * @param user Owner address
+     */
+    function enable(address user) public {
+        require(
+            msg.sender == address(this) || msg.sender == instaIndex,
+            "not-self-index"
+        );
+        require(user != address(0), "not-valid");
+        require(!_auth[user], "already-enabled");
+        _auth[user] = true;
+        ListInterface(IndexInterface(instaIndex).list()).addAuth(user);
+        emit LogEnableUser(user);
+    }
+
+    /**
+     * @dev Disable User.
+     * @param user Owner address
+     */
+    function disable(address user) public {
+        require(msg.sender == address(this), "not-self");
+        require(user != address(0), "not-valid");
+        require(_auth[user], "already-disabled");
+        delete _auth[user];
+        ListInterface(IndexInterface(instaIndex).list()).removeAuth(user);
+        emit LogDisableUser(user);
+    }
+
+    /**
+     * @dev ERC721 token receiver
+     */
+    function onERC721Received(
+        address,
+        address,
+        uint256,
+        bytes calldata
+    ) external returns (bytes4) {
+        return 0x150b7a02; // bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))
+    }
+
+    /**
+     * @dev ERC1155 token receiver
+     */
+    function onERC1155Received(
+        address,
+        address,
+        uint256,
+        uint256,
+        bytes memory
+    ) external returns (bytes4) {
+        return 0xf23a6e61; // bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))
+    }
+
+    /**
+     * @dev ERC1155 token receiver
+     */
+    function onERC1155BatchReceived(
+        address,
+        address,
+        uint256[] calldata,
+        uint256[] calldata,
+        bytes calldata
+    ) external returns (bytes4) {
+        return 0xbc197c81; // bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
+    }
+}
+
+contract InstaDefaultImplementation is Record {
+    constructor(address _instaIndex) public Record(_instaIndex) {}
+
+    receive() external payable {}
+}
diff --git a/contracts/test/variables.sol b/contracts/test/variables.sol
new file mode 100644
index 00000000..86853496
--- /dev/null
+++ b/contracts/test/variables.sol
@@ -0,0 +1,6 @@
+pragma solidity ^0.7.0;
+
+contract Variables {
+    // Auth Module(Address of Auth => bool).
+    mapping (address => bool) internal _auth;
+}
\ No newline at end of file
diff --git a/scripts/constant/abi/core/InstaImplementations.json b/scripts/constant/abi/core/InstaImplementations.json
new file mode 100644
index 00000000..c1bae964
--- /dev/null
+++ b/scripts/constant/abi/core/InstaImplementations.json
@@ -0,0 +1,206 @@
+{
+  "_format": "hh-sol-artifact-1",
+  "contractName": "InstaImplementations",
+  "sourceName": "contracts/v2/registry/implementations.sol",
+  "abi": [
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_instaIndex",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "nonpayable",
+      "type": "constructor"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "implementation",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes4[]",
+          "name": "sigs",
+          "type": "bytes4[]"
+        }
+      ],
+      "name": "LogAddImplementation",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "implementation",
+          "type": "address"
+        },
+        {
+          "indexed": false,
+          "internalType": "bytes4[]",
+          "name": "sigs",
+          "type": "bytes4[]"
+        }
+      ],
+      "name": "LogRemoveImplementation",
+      "type": "event"
+    },
+    {
+      "anonymous": false,
+      "inputs": [
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "oldImplementation",
+          "type": "address"
+        },
+        {
+          "indexed": true,
+          "internalType": "address",
+          "name": "newImplementation",
+          "type": "address"
+        }
+      ],
+      "name": "LogSetDefaultImplementation",
+      "type": "event"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_implementation",
+          "type": "address"
+        },
+        {
+          "internalType": "bytes4[]",
+          "name": "_sigs",
+          "type": "bytes4[]"
+        }
+      ],
+      "name": "addImplementation",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "defaultImplementation",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes4",
+          "name": "_sig",
+          "type": "bytes4"
+        }
+      ],
+      "name": "getImplementation",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_impl",
+          "type": "address"
+        }
+      ],
+      "name": "getImplementationSigs",
+      "outputs": [
+        {
+          "internalType": "bytes4[]",
+          "name": "",
+          "type": "bytes4[]"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "bytes4",
+          "name": "_sig",
+          "type": "bytes4"
+        }
+      ],
+      "name": "getSigImplementation",
+      "outputs": [
+        {
+          "internalType": "address",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [],
+      "name": "instaIndex",
+      "outputs": [
+        {
+          "internalType": "contract IndexInterface",
+          "name": "",
+          "type": "address"
+        }
+      ],
+      "stateMutability": "view",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_implementation",
+          "type": "address"
+        }
+      ],
+      "name": "removeImplementation",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    },
+    {
+      "inputs": [
+        {
+          "internalType": "address",
+          "name": "_defaultImplementation",
+          "type": "address"
+        }
+      ],
+      "name": "setDefaultImplementation",
+      "outputs": [],
+      "stateMutability": "nonpayable",
+      "type": "function"
+    }
+  ],
+  "bytecode": "0x60a060405234801561001057600080fd5b506040516116383803806116388339818101604052602081101561003357600080fd5b8101908080519060200190929190505050808073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050505060805160601c61158e6100aa6000398061039f528061085b5280610c5d5280610dfb525061158e6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063b39c45931161005b578063b39c4593146101e2578063dc9cc64514610216578063ef7e5c7b1461028d578063f0c01b421461030457610088565b806322175a321461008d5780637c16ffc4146100d157806389396dc814610115578063a41098bf146101ae575b600080fd5b6100cf600480360360208110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061039d565b005b610113600480360360208110156100e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610859565b005b6101576004803603602081101561012b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b82565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019a57808201518184015260208101905061017f565b505050509050019250505060405180910390f35b6101b6610c5b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ea610c7f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102616004803603602081101561022c57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610ca3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102d8600480360360208110156102a357600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610d7e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6004803603604081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035757600080fd5b82018360208201111561036957600080fd5b8035906020019184602083028401116401000000008311171561038b57600080fd5b9091929391929390505050610df9565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b15801561040357600080fd5b505afa158015610417573d6000803e3d6000fd5b505050506040513d602081101561042d57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501415610600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114f8602b913960400191505060405180910390fd5b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156106cd57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161067a5790505b5050505050905060005b815181101561077a5760008282815181106106ee57fe5b6020026020010151905060016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555080806001019150506106d7565b50600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006107c69190611305565b8173ffffffffffffffffffffffffffffffffffffffff167fb7d759e6cdda23e8a1749bce345fc77355b8a22eeaf92c6e4e7257d959c162c7826040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610842578082015181840152602081019050610827565b505050509050019250505060405180910390a25050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d60208110156108e957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001806114656039913960400191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ac5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806115236036913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f3b337225b8d68d037e0c721876335a3832bd08162c943fe5f88e8d428597ca8f60405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610c4f57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411610bfc5790505b50505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d545780610d76565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b915050919050565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d6020811015610e8957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501461105b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061149e602f913960400191505060405180910390fd5b60005b8282905081101561123357600083838381811061107757fe5b905060200201357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169050600073ffffffffffffffffffffffffffffffffffffffff1660016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114426023913960400191505060405180910390fd5b8460016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050808060010191505061105e565b508181600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020919061128292919061132d565b508273ffffffffffffffffffffffffffffffffffffffff167ff9c512a86be00aaec236065d0a439f064133f367de889c782448c3578a3f30c5838360405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b50805460008255600701600890049060005260206000209081019061132a91906113f9565b50565b828054828255906000526020600020906007016008900481019282156113e85791602002820160005b838211156113b65783357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548163ffffffff021916908360e01c02179055509260200192600401602081600301049283019260010302611356565b80156113e65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026113b6565b505b5090506113f59190611416565b5090565b5b808211156114125760008160009055506001016113fa565b5090565b5b8082111561143d57600081816101000a81549063ffffffff021916905550600101611417565b509056fe496d706c656d656e746174696f6e733a205f73696720616c7265616479206164646564496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2061646472657373206e6f742076616c6964496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e20616c72656164792061646465642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f742076616c69642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f7420666f756e642e496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2063616e6e6f742062652073616d65a2646970667358221220d42dcb568934728d15f318f76a6028fe848a484b097ea24581f45425fcde152864736f6c63430007000033",
+  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063b39c45931161005b578063b39c4593146101e2578063dc9cc64514610216578063ef7e5c7b1461028d578063f0c01b421461030457610088565b806322175a321461008d5780637c16ffc4146100d157806389396dc814610115578063a41098bf146101ae575b600080fd5b6100cf600480360360208110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061039d565b005b610113600480360360208110156100e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610859565b005b6101576004803603602081101561012b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b82565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019a57808201518184015260208101905061017f565b505050509050019250505060405180910390f35b6101b6610c5b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ea610c7f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102616004803603602081101561022c57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610ca3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102d8600480360360208110156102a357600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610d7e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6004803603604081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035757600080fd5b82018360208201111561036957600080fd5b8035906020019184602083028401116401000000008311171561038b57600080fd5b9091929391929390505050610df9565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b15801561040357600080fd5b505afa158015610417573d6000803e3d6000fd5b505050506040513d602081101561042d57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501415610600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114f8602b913960400191505060405180910390fd5b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156106cd57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161067a5790505b5050505050905060005b815181101561077a5760008282815181106106ee57fe5b6020026020010151905060016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555080806001019150506106d7565b50600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006107c69190611305565b8173ffffffffffffffffffffffffffffffffffffffff167fb7d759e6cdda23e8a1749bce345fc77355b8a22eeaf92c6e4e7257d959c162c7826040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610842578082015181840152602081019050610827565b505050509050019250505060405180910390a25050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d60208110156108e957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001806114656039913960400191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ac5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806115236036913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f3b337225b8d68d037e0c721876335a3832bd08162c943fe5f88e8d428597ca8f60405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610c4f57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411610bfc5790505b50505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d545780610d76565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b915050919050565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d6020811015610e8957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501461105b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061149e602f913960400191505060405180910390fd5b60005b8282905081101561123357600083838381811061107757fe5b905060200201357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169050600073ffffffffffffffffffffffffffffffffffffffff1660016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114426023913960400191505060405180910390fd5b8460016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050808060010191505061105e565b508181600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020919061128292919061132d565b508273ffffffffffffffffffffffffffffffffffffffff167ff9c512a86be00aaec236065d0a439f064133f367de889c782448c3578a3f30c5838360405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b50805460008255600701600890049060005260206000209081019061132a91906113f9565b50565b828054828255906000526020600020906007016008900481019282156113e85791602002820160005b838211156113b65783357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548163ffffffff021916908360e01c02179055509260200192600401602081600301049283019260010302611356565b80156113e65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026113b6565b505b5090506113f59190611416565b5090565b5b808211156114125760008160009055506001016113fa565b5090565b5b8082111561143d57600081816101000a81549063ffffffff021916905550600101611417565b509056fe496d706c656d656e746174696f6e733a205f73696720616c7265616479206164646564496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2061646472657373206e6f742076616c6964496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e20616c72656164792061646465642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f742076616c69642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f7420666f756e642e496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2063616e6e6f742062652073616d65a2646970667358221220d42dcb568934728d15f318f76a6028fe848a484b097ea24581f45425fcde152864736f6c63430007000033",
+  "linkReferences": {},
+  "deployedLinkReferences": {}
+}
diff --git a/test/basic-ERC1155/ERC1155-transfer.js b/test/basic-ERC1155/ERC1155-transfer.js
new file mode 100644
index 00000000..cd2f2b12
--- /dev/null
+++ b/test/basic-ERC1155/ERC1155-transfer.js
@@ -0,0 +1,127 @@
+const { expect } = require("chai");
+const hre = require("hardhat");
+const { web3, deployments, waffle, ethers } = hre;
+const { provider, deployContract } = waffle
+const {abi: implementationsABI} = require("../../scripts/constant/abi/core/InstaImplementations.json")
+
+const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
+const buildDSAv2 = require("../../scripts/buildDSAv2")
+const encodeSpells = require("../../scripts/encodeSpells.js")
+const getMasterSigner = require("../../scripts/getMasterSigner")
+
+const addresses = require("../../scripts/constant/addresses");
+const abis = require("../../scripts/constant/abis");
+const constants = require("../../scripts/constant/constant");
+const tokens = require("../../scripts/constant/tokens");
+
+const connectV2BasicERC1155Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC1155/main.sol/ConnectV2BasicERC1155.json")
+const erc1155Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC1155/IERC1155.sol/IERC1155.json")
+
+const TOKEN_CONTRACT_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa";
+const TOKEN_OWNER_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa";
+const TOKEN_ID = "1";
+
+const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D"
+
+describe("BASIC-ERC1155", function () {
+    const connectorName = "BASIC-ERC1155-A"
+
+    let dsaWallet0
+    let masterSigner;
+    let instaConnectorsV2;
+    let connector;
+    let nftContract;
+    let tokenOwner;
+    let instaImplementationsMapping;
+
+
+    const wallets = provider.getWallets()
+    const [wallet0, wallet1, wallet2, wallet3] = wallets
+    before(async () => {
+        await hre.network.provider.request({
+            method: "hardhat_impersonateAccount",
+            params: [TOKEN_OWNER_ADDR],
+        });
+
+        await network.provider.send("hardhat_setBalance", [
+            TOKEN_OWNER_ADDR,
+            "0x1000000000000000",
+        ]);
+
+        // get tokenOwner
+        tokenOwner = await ethers.getSigner(
+            TOKEN_OWNER_ADDR
+        );
+        nftContract = await ethers.getContractAt(erc1155Artifacts.abi, TOKEN_CONTRACT_ADDR)
+        masterSigner = await getMasterSigner(wallet3)
+        instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+
+        instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr);
+        InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation")
+        instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex);
+        await instaAccountV2DefaultImpl.deployed()
+        connector = await deployAndEnableConnector({
+            connectorName,
+            contractArtifact: connectV2BasicERC1155Artifacts,
+            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(!!masterSigner.address).to.be.true;
+    });
+
+    describe("Implementations", function () {
+
+        it("Should add default implementation to mapping.", async function () {
+            const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address);
+            await tx.wait()
+            expect(await instaImplementationsMapping.defaultImplementation()).to.be.equal(instaAccountV2DefaultImpl.address);
+        });
+
+    });
+
+    describe("DSA wallet setup", function () {
+        it("Should build DSA v2", async function () {
+            dsaWallet0 = await buildDSAv2(tokenOwner.address)
+            expect(!!dsaWallet0.address).to.be.true;
+        });
+
+        it("Deposit ETH into DSA wallet", async function () {
+            await wallet0.sendTransaction({
+                to: dsaWallet0.address,
+                value: ethers.utils.parseEther("10")
+            });
+            expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
+        });
+    });
+
+    describe("Main", function () {
+        it("should deposit successfully", async () => {
+            console.log("DSA wallet address", dsaWallet0.address)
+            await nftContract.connect(tokenOwner).setApprovalForAll(dsaWallet0.address, true);
+            const spells = [
+                {
+                    connector: connectorName,
+                    method: "depositERC1155",
+                    args: [
+                        TOKEN_CONTRACT_ADDR,
+                        TOKEN_ID,
+                        1,
+                        "0",
+                        "0"
+                    ]
+                }
+            ];
+
+            const tx = await dsaWallet0
+                .connect(tokenOwner)
+                .cast(...encodeSpells(spells), tokenOwner.address);
+            const receipt = await tx.wait();
+        });
+    })
+})
diff --git a/test/basic-ERC721/nftTransfer.test.js b/test/basic-ERC721/ERC721-transfer.js
similarity index 79%
rename from test/basic-ERC721/nftTransfer.test.js
rename to test/basic-ERC721/ERC721-transfer.js
index 9735d51e..01a5de0b 100644
--- a/test/basic-ERC721/nftTransfer.test.js
+++ b/test/basic-ERC721/ERC721-transfer.js
@@ -2,6 +2,7 @@ const { expect } = require("chai");
 const hre = require("hardhat");
 const { web3, deployments, waffle, ethers } = hre;
 const { provider, deployContract } = waffle
+const {abi: implementationsABI} = require("../../scripts/constant/abi/core/InstaImplementations.json")
 
 const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
 const buildDSAv2 = require("../../scripts/buildDSAv2")
@@ -20,6 +21,8 @@ const TOKEN_CONTRACT_ADDR = "0x4d695c615a7aacf2d7b9c481b66045bb2457dfde";
 const TOKEN_OWNER_ADDR = "0x8c6b10d42ff08e56133fca0dac75e1931b1fcc23";
 const TOKEN_ID = "38";
 
+const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D"
+
 describe("BASIC-ERC721", function () {
     const connectorName = "BASIC-ERC721-A"
 
@@ -29,6 +32,7 @@ describe("BASIC-ERC721", function () {
     let connector;
     let nftContract;
     let tokenOwner;
+    let instaImplementationsMapping;
 
 
     const wallets = provider.getWallets()
@@ -51,6 +55,11 @@ describe("BASIC-ERC721", function () {
         nftContract = await ethers.getContractAt(erc721Artifacts.abi, TOKEN_CONTRACT_ADDR)
         masterSigner = await getMasterSigner(wallet3)
         instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
+
+        instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr);
+        InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation")
+        instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex);
+        await instaAccountV2DefaultImpl.deployed()
         connector = await deployAndEnableConnector({
             connectorName,
             contractArtifact: connectV2BasicERC721Artifacts,
@@ -66,6 +75,16 @@ describe("BASIC-ERC721", function () {
         expect(!!masterSigner.address).to.be.true;
     });
 
+    describe("Implementations", function () {
+
+        it("Should add default implementation to mapping.", async function () {
+            const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address);
+            await tx.wait()
+            expect(await instaImplementationsMapping.defaultImplementation()).to.be.equal(instaAccountV2DefaultImpl.address);
+        });
+
+    });
+
     describe("DSA wallet setup", function () {
         it("Should build DSA v2", async function () {
             dsaWallet0 = await buildDSAv2(tokenOwner.address)

From 7d45c6ad8fc2ae256bfcde30b9e1eb6f0d1f7e99 Mon Sep 17 00:00:00 2001
From: Ishan Jain <contact@ishanjain.me>
Date: Thu, 2 Sep 2021 13:00:48 +0530
Subject: [PATCH 16/28] Updated pr status check gh action config

---
 .github/workflows/status.yml | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml
index 9dd6986c..0470aa1e 100644
--- a/.github/workflows/status.yml
+++ b/.github/workflows/status.yml
@@ -9,18 +9,24 @@ jobs:
       matrix:
         node-version: [16.x]
     steps:
-    - uses: actions/checkout@v1
-      with:
-        # Checkout the head ref instead of the PR branch that github creates.
-        ref: ${{ github.head_ref }}
-    - name: Use Node.js ${{ matrix.node-version }}
-      uses: actions/setup-node@v1
-      with:
-        node-version: ${{ matrix.node-version }}
-    - name: Install and build
-      run: |
-        npm install
-    - name: Run status checks
-      run: node ./status-checks
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - uses: actions/checkout@v2
+        with:
+          ref: ${{ github.event.pull_request.head.sha }}
+      - name: Use Node.js ${{ matrix.node-version }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ matrix.node-version }}
+      - name: Use Cache
+        uses: actions/cache@v2
+        with:
+          path: |
+            node_modules
+            */*/node_modules
+          key: ${{ runner.os }}-${{ matrix.node_version }}-${{ hashFiles('**/package-lock.json') }}
+      - name: Install and build
+        run: |
+          npm install
+      - name: Run status checks
+        run: node ./status-checks
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

From 1252c0f4279601459e4878faf27bc55856de1d96 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Thu, 2 Sep 2021 03:09:09 -0500
Subject: [PATCH 17/28] refactor: minor fixes and implement ETH-INST pool test

---
 .../connectors/uniswapStaker/events.sol       |  2 +-
 .../mainnet/connectors/uniswapStaker/main.sol | 16 ++--
 scripts/addLiquidity.js                       |  9 ++
 test/uniswapStake/uniswapStake.test.js        | 94 +++++++++++++++++--
 4 files changed, 104 insertions(+), 17 deletions(-)

diff --git a/contracts/mainnet/connectors/uniswapStaker/events.sol b/contracts/mainnet/connectors/uniswapStaker/events.sol
index b5b2e8b0..0406b33c 100644
--- a/contracts/mainnet/connectors/uniswapStaker/events.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/events.sol
@@ -18,7 +18,7 @@ contract Events {
     );
 
     event LogIncentiveCreated(
-        uint256 tokenId,
+        address poolAddr,
         uint256 startTime,
         uint256 endTime,
         uint256 reward
diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswapStaker/main.sol
index 18ca0916..e65f44d9 100644
--- a/contracts/mainnet/connectors/uniswapStaker/main.sol
+++ b/contracts/mainnet/connectors/uniswapStaker/main.sol
@@ -177,24 +177,21 @@ abstract contract UniswapResolver is Helpers, Events {
      * @param _rewardToken _rewardToken address
      * @param _length incentive length
      * @param _refundee refundee address
-     * @param _tokenId NFT LP token id
+     * @param _poolAddr Uniswap V3 Pool address
      * @param _reward reward amount
      */
     function createIncentive(
         address _rewardToken,
         uint256 _length,
         address _refundee,
-        uint256 _tokenId,
+        address _poolAddr,
         uint256 _reward
     )
         external
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
-        address poolAddr = getPoolAddress(_tokenId);
-
-        IUniswapV3Pool pool = IUniswapV3Pool(poolAddr);
+        IUniswapV3Pool pool = IUniswapV3Pool(_poolAddr);
         uint256 _startTime = block.timestamp;
         uint256 _endTime = _startTime + _length;
         IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker
@@ -205,10 +202,13 @@ abstract contract UniswapResolver is Helpers, Events {
                 _endTime,
                 _refundee
             );
+        if (_rewardToken != ethAddr) {
+            IERC20Minimal(_rewardToken).approve(address(staker), _reward);
+        }
         staker.createIncentive(_key, _reward);
 
-        _eventName = "LogIncentiveCreated(uint256,uint256,uint256,uint256)";
-        _eventParam = abi.encode(_tokenId, _startTime, _endTime, _reward);
+        _eventName = "LogIncentiveCreated(address,uint256,uint256,uint256)";
+        _eventParam = abi.encode(_poolAddr, _startTime, _endTime, _reward);
     }
 }
 
diff --git a/scripts/addLiquidity.js b/scripts/addLiquidity.js
index 0fb51156..c461a775 100644
--- a/scripts/addLiquidity.js
+++ b/scripts/addLiquidity.js
@@ -50,6 +50,15 @@ const tokenMapping = {
       await mineTx(contract.mint(address, amt));
     },
   },
+  inst: {
+    impersonateSigner: "0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88",
+    address: "0x6f40d4a6237c257fff2db00fa0510deeecd303eb",
+    abi: ["function transfer(address to, uint value)"],
+    process: async function(owner, address, amt) {
+      const contract = new ethers.Contract(this.address, this.abi, owner);
+      await mineTx(contract.transfer(address, amt));
+    },
+  }
 };
 
 module.exports = async (tokenName, address, amt) => {
diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
index be684b6a..67b523a0 100644
--- a/test/uniswapStake/uniswapStake.test.js
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -30,6 +30,7 @@ const TICK_SPACINGS = {
 
 const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"
 const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+const INST_ADDR = "0x6f40d4a6237c257fff2db00fa0510deeecd303eb"
 
 let tokenIds = []
 const abiCoder = ethers.utils.defaultAbiCoder
@@ -88,7 +89,7 @@ describe("UniswapV3", function () {
             await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
         });
 
-        it("Deposit ETH & USDT into DSA wallet", async function () {
+        it("Deposit ETH & USDT & INST into DSA wallet", async function () {
             await wallet0.sendTransaction({
                 to: dsaWallet0.address,
                 value: ethers.utils.parseEther("10")
@@ -97,12 +98,14 @@ describe("UniswapV3", function () {
 
             await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000"));
             await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000"));
+            await addLiquidity("inst", dsaWallet0.address, ethers.utils.parseEther("10000"));
         });
     });
 
     describe("Main", function () {
         const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH
         const daiAmount = ethers.utils.parseEther("400") // 1 ETH
+        const instAmount = ethers.utils.parseEther("50")
 
         it("Should mint successfully", async function () {
             const getIds = ["0", "0"]
@@ -124,6 +127,22 @@ describe("UniswapV3", function () {
                         getIds,
                         setId
                     ],
+                },
+                {
+                    connector: connectorUniswap,
+                    method: "mint",
+                    args: [
+                        INST_ADDR,
+                        ethAddress,
+                        FeeAmount.MEDIUM,
+                        getMinTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
+                        getMaxTick(TICK_SPACINGS[FeeAmount.MEDIUM]),
+                        instAmount,
+                        ethAmount,
+                        "500000000000000000",
+                        getIds,
+                        setId
+                    ],
                 }
             ]
 
@@ -133,7 +152,9 @@ describe("UniswapV3", function () {
             let castEvent = new Promise((resolve, reject) => {
                 dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
                     const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]);
+                    const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[1]);
                     tokenIds.push(params[0]);
+                    tokenIds.push(params1[0]);
                     event.removeListener();
 
                     resolve({
@@ -153,6 +174,7 @@ describe("UniswapV3", function () {
         });
 
         it("Should create incentive successfully", async function () {
+            console.log("TokenIds", tokenIds[1]);
             const spells = [
                 {
                     connector: connectorStaker,
@@ -161,20 +183,32 @@ describe("UniswapV3", function () {
                         ethAddress,
                         "1000",
                         dsaWallet0.address,
-                        tokenIds[0],
+                        "0xc2e9f25be6257c210d7adf0d4cd6e3e881ba25f8",
+                        ethers.utils.parseEther("0.01")
+                    ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "createIncentive",
+                    args: [
+                        INST_ADDR,
+                        "50",
+                        dsaWallet0.address,
+                        "0xcba27c8e7115b4eb50aa14999bc0866674a96ecb",
                         ethers.utils.parseEther("0.01")
                     ],
                 }]
 
-            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
+            const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address)
             let receipt = await tx.wait()
 
             let castEvent = new Promise((resolve, reject) => {
                 dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
                     const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[0]);
+                    const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[1]);
                     event.removeListener();
 
-                    resolve({ start: params[1], end: params[2] });
+                    resolve({ start: [params[1], params1[1]], end: [params[2], params1[2]] });
                 });
 
                 setTimeout(() => {
@@ -201,11 +235,29 @@ describe("UniswapV3", function () {
                     method: "stake",
                     args: [
                         ethAddress,
-                        startTime,
-                        endTime,
+                        startTime[0],
+                        endTime[0],
                         dsaWallet0.address,
                         tokenIds[0]
                     ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "deposit",
+                    args: [
+                        tokenIds[1]
+                    ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "stake",
+                    args: [
+                        INST_ADDR,
+                        startTime[1],
+                        endTime[1],
+                        dsaWallet0.address,
+                        tokenIds[1]
+                    ],
                 }
             ]
 
@@ -222,7 +274,14 @@ describe("UniswapV3", function () {
                     connector: connectorStaker,
                     method: "claimRewards",
                     args: [
-                        ethAddress,
+                        DAI_ADDR,
+                        dsaWallet0.address,
+                        "1000",
+                    ],
+                    connector: connectorStaker,
+                    method: "claimRewards",
+                    args: [
+                        INST_ADDR,
                         dsaWallet0.address,
                         "1000",
                     ],
@@ -239,7 +298,7 @@ describe("UniswapV3", function () {
                     connector: connectorStaker,
                     method: "unstake",
                     args: [
-                        ethAddress,
+                        DAI_ADDR,
                         startTime,
                         endTime,
                         dsaWallet0.address,
@@ -253,6 +312,25 @@ describe("UniswapV3", function () {
                         tokenIds[0],
                         dsaWallet0.address,
                     ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "unstake",
+                    args: [
+                        INST_ADDR,
+                        startTime,
+                        endTime,
+                        dsaWallet0.address,
+                        tokenIds[1]
+                    ],
+                },
+                {
+                    connector: connectorStaker,
+                    method: "withdraw",
+                    args: [
+                        tokenIds[1],
+                        dsaWallet0.address,
+                    ],
                 }
             ]
 

From 0da788cdb2f3d8ab8c4af2ab66fbe58b3a542673 Mon Sep 17 00:00:00 2001
From: Ishan Jain <contact@ishanjain.me>
Date: Thu, 2 Sep 2021 22:56:29 +0530
Subject: [PATCH 18/28] auto check pr gh action: Add output of status checks as
 a comment in the thread

---
 .github/workflows/status.yml | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml
index 0470aa1e..fc6ede0a 100644
--- a/.github/workflows/status.yml
+++ b/.github/workflows/status.yml
@@ -27,6 +27,22 @@ jobs:
         run: |
           npm install
       - name: Run status checks
-        run: node ./status-checks
+        id: status_check
+        run: |
+          output=$(node ./status-checks)
+          # Escape newlines so _all_ the output is included in the set-output
+          output="${output//'%'/'%25'}"
+          output="${output//$'\n'/'%0A'}"
+          output="${output//$'\r'/'%0D'}"
+          echo "::set-output name=status_check_output::$output"
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - name: Auto Comment Status Check Result
+        # Use with caution
+        uses: bubkoo/auto-comment@v1
+        with:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          pullRequestSynchronize: "${{ steps.status_check.outputs.output }}"
+          pullRequestAssigned: "${{ steps.status_check.outputs.output }}"
+          pullRequestOpened: "${{ steps.status_check.outputs.output }}"
+          pullRequestReopened: "${{ steps.status_check.outputs.output }}"

From cf504594be9a99e628dd1ba6a7ae8cae46830e9f Mon Sep 17 00:00:00 2001
From: Ishan Jain <contact@ishanjain.me>
Date: Thu, 2 Sep 2021 23:31:58 +0530
Subject: [PATCH 19/28] Updated pull request check gh action

---
 .github/workflows/status.yml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml
index fc6ede0a..2e72f099 100644
--- a/.github/workflows/status.yml
+++ b/.github/workflows/status.yml
@@ -42,7 +42,7 @@ jobs:
         uses: bubkoo/auto-comment@v1
         with:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          pullRequestSynchronize: "${{ steps.status_check.outputs.output }}"
-          pullRequestAssigned: "${{ steps.status_check.outputs.output }}"
-          pullRequestOpened: "${{ steps.status_check.outputs.output }}"
-          pullRequestReopened: "${{ steps.status_check.outputs.output }}"
+          pullRequestSynchronize: "${{ steps.status_check.outputs.status_check_output }}"
+          pullRequestAssigned: "${{ steps.status_check.outputs.status_check_output }}"
+          pullRequestOpened: "${{ steps.status_check.outputs.status_check_output }}"
+          pullRequestReopened: "${{ steps.status_check.outputs.status_check_output }}"

From 6c5460fac2745e722438330124f9c8010a2adb3c Mon Sep 17 00:00:00 2001
From: Aleksandr S <ardhead@gmail.com>
Date: Sun, 5 Sep 2021 11:32:18 +0300
Subject: [PATCH 20/28] cl args to set check path

---
 README.md              |  6 ++++++
 package.json           |  1 +
 status-checks/check.js | 13 ++++++++-----
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index e9a60cd8..39b78357 100644
--- a/README.md
+++ b/README.md
@@ -54,3 +54,9 @@ Few things to consider while writing the connector:
 
 If you can't find something you're looking for or have any questions, ask them at our developers community on [Discord](https://discord.gg/83vvrnY) or simply send an [Email](mailto:info@instadapp.io).
 
+## Check run
+
+use
+`npm run check`
+to check `connectors` directory. Use `connector=$` argument to check specific connector:
+`npm run check connector=contracts/mainnet/common`
diff --git a/package.json b/package.json
index 589d093e..22fdaec2 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
   "scripts": {
     "test": "hardhat test",
     "coverage": "./node_modules/.bin/solidity-coverage",
+    "check": "node status-checks/huskyCheck.js",
     "check-husky": "node status-checks/huskyCheck.js",
     "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build"
   },
diff --git a/status-checks/check.js b/status-checks/check.js
index a76d81ae..c0848d77 100644
--- a/status-checks/check.js
+++ b/status-checks/check.js
@@ -3,13 +3,11 @@ const path = require('path')
 
 const forbiddenStrings = ['selfdestruct']
 
-const getConnectorsList = async () => {
+const getConnectorsList = async (connectorsRootsDirs) => {
   try {
     const connectors = []
-    const connectorsRootsDirs = ['mainnet', 'polygon']
     for (let index = 0; index < connectorsRootsDirs.length; index++) {
-      const root = `contracts/${connectorsRootsDirs[index]}/connectors`
-      const dirs = [root]
+      const dirs = [connectorsRootsDirs[index]]
       while (dirs.length) {
         const currentDir = dirs.pop()
         const subs = fs.readdirSync(currentDir, { withFileTypes: true })
@@ -326,9 +324,14 @@ const checkHeadComments = async (connector) => {
 
 async function checkMain () {
   try {
+    const connectorsRootsDirsDefault = ['mainnet', 'polygon'].map(v=> `contracts/${v}/connectors`)
+    const customPathArg = process.argv.find(a => a.startsWith('connector='))
+    const connectorsRootsDirs = customPathArg 
+      ? [customPathArg.slice(10)]
+      : connectorsRootsDirsDefault
     const errors = []
     const warnings = []
-    const connectors = await getConnectorsList()
+    const connectors = await getConnectorsList(connectorsRootsDirs)
     for (let index = 0; index < connectors.length; index++) {
       const { forbiddenErrors, code } = await checkForbidden(connectors[index].path)
       connectors[index].code = code

From 7b2dd953b1575ff885773e2a79883edc1c4f0b01 Mon Sep 17 00:00:00 2001
From: Aleksandr S <ardhead@gmail.com>
Date: Sun, 5 Sep 2021 19:53:23 +0300
Subject: [PATCH 21/28] readme update

---
 README.md               | 7 -------
 status-checks/readme.md | 7 +++++++
 2 files changed, 7 insertions(+), 7 deletions(-)
 create mode 100644 status-checks/readme.md

diff --git a/README.md b/README.md
index 39b78357..be1b4893 100644
--- a/README.md
+++ b/README.md
@@ -53,10 +53,3 @@ Few things to consider while writing the connector:
 ### Support
 
 If you can't find something you're looking for or have any questions, ask them at our developers community on [Discord](https://discord.gg/83vvrnY) or simply send an [Email](mailto:info@instadapp.io).
-
-## Check run
-
-use
-`npm run check`
-to check `connectors` directory. Use `connector=$` argument to check specific connector:
-`npm run check connector=contracts/mainnet/common`
diff --git a/status-checks/readme.md b/status-checks/readme.md
new file mode 100644
index 00000000..ed376c25
--- /dev/null
+++ b/status-checks/readme.md
@@ -0,0 +1,7 @@
+
+# Check run
+
+use
+`npm run check`
+to check `connectors` directory. Use `connector=$` argument to check specific connector:
+`npm run check connector=contracts/mainnet/common`

From b64791d984d68958613d6c65b2e016702a0ad0b7 Mon Sep 17 00:00:00 2001
From: Thrilok Kumar <thrilok2000@gmail.com>
Date: Tue, 7 Sep 2021 16:44:59 +0530
Subject: [PATCH 22/28] Minor comment fixes

---
 contracts/mainnet/connectors/basic-ERC1155/main.sol | 8 ++++----
 contracts/mainnet/connectors/basic-ERC721/main.sol  | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/contracts/mainnet/connectors/basic-ERC1155/main.sol b/contracts/mainnet/connectors/basic-ERC1155/main.sol
index b6ab4af8..0aef5cd7 100644
--- a/contracts/mainnet/connectors/basic-ERC1155/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC1155/main.sol
@@ -2,7 +2,7 @@ pragma solidity ^0.7.0;
 
 /**
  * @title Basic.
- * @dev Deposit & Withdraw from DSA.
+ * @dev Deposit & Withdraw from ERC1155 DSA.
  */
 import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
 
@@ -13,7 +13,7 @@ import {Events} from "./events.sol";
 abstract contract BasicResolver is Events, DSMath, Basic {
     /**
      * @dev Deposit Assets To Smart Account.
-     * @notice Deposit a ERC721 token to DSA
+     * @notice Deposit a ERC1155 token to DSA
      * @param token Address of token.
      * @param tokenId ID of token.
      * @param amount Amount to deposit.
@@ -31,7 +31,7 @@ abstract contract BasicResolver is Events, DSMath, Basic {
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
-        uint256 _amount = getUint(getId, tokenId);
+        uint256 _amount = getUint(getId, amount);
 
         IERC1155 tokenContract = IERC1155(token);
         tokenContract.safeTransferFrom(
@@ -57,7 +57,7 @@ abstract contract BasicResolver is Events, DSMath, Basic {
 
     /**
      * @dev Withdraw Assets To Smart Account.
-     * @notice Withdraw a ERC721 token from DSA
+     * @notice Withdraw a ERC1155 token from DSA
      * @param token Address of the token.
      * @param tokenId ID of token.
      * @param to The address to receive the token upon withdrawal
diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol
index a6962b47..410c6342 100644
--- a/contracts/mainnet/connectors/basic-ERC721/main.sol
+++ b/contracts/mainnet/connectors/basic-ERC721/main.sol
@@ -2,7 +2,7 @@ pragma solidity ^0.7.0;
 
 /**
  * @title Basic.
- * @dev Deposit & Withdraw from DSA.
+ * @dev Deposit & Withdraw ERC721 from DSA.
  */
 import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
 

From 3c800b82accee88a1888107b8c60c96107270651 Mon Sep 17 00:00:00 2001
From: Thrilok Kumar <thrilok2000@gmail.com>
Date: Tue, 7 Sep 2021 23:48:07 +0530
Subject: [PATCH 23/28] restructured uniswap folders

---
 contracts/mainnet/connectors/uniswap/{ => v2}/events.sol          | 0
 contracts/mainnet/connectors/uniswap/{ => v2}/helpers.sol         | 0
 contracts/mainnet/connectors/uniswap/{ => v2}/interface.sol       | 0
 contracts/mainnet/connectors/uniswap/{ => v2}/main.sol            | 0
 contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/events.sol | 0
 .../mainnet/connectors/{uniswapV3 => uniswap/v3}/helpers.sol      | 0
 .../mainnet/connectors/{uniswapV3 => uniswap/v3}/interface.sol    | 0
 contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/main.sol   | 0
 .../connectors/{uniswapStaker => uniswap/v3_staker}/events.sol    | 0
 .../connectors/{uniswapStaker => uniswap/v3_staker}/helpers.sol   | 0
 .../connectors/{uniswapStaker => uniswap/v3_staker}/interface.sol | 0
 .../connectors/{uniswapStaker => uniswap/v3_staker}/main.sol      | 0
 12 files changed, 0 insertions(+), 0 deletions(-)
 rename contracts/mainnet/connectors/uniswap/{ => v2}/events.sol (100%)
 rename contracts/mainnet/connectors/uniswap/{ => v2}/helpers.sol (100%)
 rename contracts/mainnet/connectors/uniswap/{ => v2}/interface.sol (100%)
 rename contracts/mainnet/connectors/uniswap/{ => v2}/main.sol (100%)
 rename contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/events.sol (100%)
 rename contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/helpers.sol (100%)
 rename contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/interface.sol (100%)
 rename contracts/mainnet/connectors/{uniswapV3 => uniswap/v3}/main.sol (100%)
 rename contracts/mainnet/connectors/{uniswapStaker => uniswap/v3_staker}/events.sol (100%)
 rename contracts/mainnet/connectors/{uniswapStaker => uniswap/v3_staker}/helpers.sol (100%)
 rename contracts/mainnet/connectors/{uniswapStaker => uniswap/v3_staker}/interface.sol (100%)
 rename contracts/mainnet/connectors/{uniswapStaker => uniswap/v3_staker}/main.sol (100%)

diff --git a/contracts/mainnet/connectors/uniswap/events.sol b/contracts/mainnet/connectors/uniswap/v2/events.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswap/events.sol
rename to contracts/mainnet/connectors/uniswap/v2/events.sol
diff --git a/contracts/mainnet/connectors/uniswap/helpers.sol b/contracts/mainnet/connectors/uniswap/v2/helpers.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswap/helpers.sol
rename to contracts/mainnet/connectors/uniswap/v2/helpers.sol
diff --git a/contracts/mainnet/connectors/uniswap/interface.sol b/contracts/mainnet/connectors/uniswap/v2/interface.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswap/interface.sol
rename to contracts/mainnet/connectors/uniswap/v2/interface.sol
diff --git a/contracts/mainnet/connectors/uniswap/main.sol b/contracts/mainnet/connectors/uniswap/v2/main.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswap/main.sol
rename to contracts/mainnet/connectors/uniswap/v2/main.sol
diff --git a/contracts/mainnet/connectors/uniswapV3/events.sol b/contracts/mainnet/connectors/uniswap/v3/events.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapV3/events.sol
rename to contracts/mainnet/connectors/uniswap/v3/events.sol
diff --git a/contracts/mainnet/connectors/uniswapV3/helpers.sol b/contracts/mainnet/connectors/uniswap/v3/helpers.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapV3/helpers.sol
rename to contracts/mainnet/connectors/uniswap/v3/helpers.sol
diff --git a/contracts/mainnet/connectors/uniswapV3/interface.sol b/contracts/mainnet/connectors/uniswap/v3/interface.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapV3/interface.sol
rename to contracts/mainnet/connectors/uniswap/v3/interface.sol
diff --git a/contracts/mainnet/connectors/uniswapV3/main.sol b/contracts/mainnet/connectors/uniswap/v3/main.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapV3/main.sol
rename to contracts/mainnet/connectors/uniswap/v3/main.sol
diff --git a/contracts/mainnet/connectors/uniswapStaker/events.sol b/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapStaker/events.sol
rename to contracts/mainnet/connectors/uniswap/v3_staker/events.sol
diff --git a/contracts/mainnet/connectors/uniswapStaker/helpers.sol b/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapStaker/helpers.sol
rename to contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
diff --git a/contracts/mainnet/connectors/uniswapStaker/interface.sol b/contracts/mainnet/connectors/uniswap/v3_staker/interface.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapStaker/interface.sol
rename to contracts/mainnet/connectors/uniswap/v3_staker/interface.sol
diff --git a/contracts/mainnet/connectors/uniswapStaker/main.sol b/contracts/mainnet/connectors/uniswap/v3_staker/main.sol
similarity index 100%
rename from contracts/mainnet/connectors/uniswapStaker/main.sol
rename to contracts/mainnet/connectors/uniswap/v3_staker/main.sol

From 73969113c5a67d4bac2260354df5b7dfcc08bd48 Mon Sep 17 00:00:00 2001
From: Thrilok Kumar <thrilok2000@gmail.com>
Date: Tue, 7 Sep 2021 23:50:58 +0530
Subject: [PATCH 24/28] minor fixes

---
 contracts/mainnet/connectors/uniswap/v2/helpers.sol        | 6 +++---
 contracts/mainnet/connectors/uniswap/v2/main.sol           | 2 +-
 contracts/mainnet/connectors/uniswap/v3/helpers.sol        | 6 +++---
 contracts/mainnet/connectors/uniswap/v3/main.sol           | 2 +-
 contracts/mainnet/connectors/uniswap/v3_staker/events.sol  | 1 +
 contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol | 6 +++---
 6 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/contracts/mainnet/connectors/uniswap/v2/helpers.sol b/contracts/mainnet/connectors/uniswap/v2/helpers.sol
index f435a78b..f0a8a6da 100644
--- a/contracts/mainnet/connectors/uniswap/v2/helpers.sol
+++ b/contracts/mainnet/connectors/uniswap/v2/helpers.sol
@@ -1,8 +1,8 @@
 pragma solidity ^0.7.0;
 
-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 { IUniswapV2Router02, IUniswapV2Factory } from "./interface.sol";
 
 abstract contract Helpers is DSMath, Basic {
diff --git a/contracts/mainnet/connectors/uniswap/v2/main.sol b/contracts/mainnet/connectors/uniswap/v2/main.sol
index a8ee9959..e0daa6a9 100644
--- a/contracts/mainnet/connectors/uniswap/v2/main.sol
+++ b/contracts/mainnet/connectors/uniswap/v2/main.sol
@@ -5,7 +5,7 @@ pragma solidity ^0.7.0;
  * @dev Decentralized Exchange.
  */
 
-import { TokenInterface } from "../../common/interfaces.sol";
+import { TokenInterface } from "../../../common/interfaces.sol";
 import { Helpers } from "./helpers.sol";
 import { Events } from "./events.sol";
 
diff --git a/contracts/mainnet/connectors/uniswap/v3/helpers.sol b/contracts/mainnet/connectors/uniswap/v3/helpers.sol
index 8585f84f..2fc42f8b 100644
--- a/contracts/mainnet/connectors/uniswap/v3/helpers.sol
+++ b/contracts/mainnet/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";
diff --git a/contracts/mainnet/connectors/uniswap/v3/main.sol b/contracts/mainnet/connectors/uniswap/v3/main.sol
index 7fd058a6..c40f871f 100644
--- a/contracts/mainnet/connectors/uniswap/v3/main.sol
+++ b/contracts/mainnet/connectors/uniswap/v3/main.sol
@@ -6,7 +6,7 @@ pragma abicoder v2;
  * @dev Decentralized Exchange.
  */
 
-import {TokenInterface} from "../../common/interfaces.sol";
+import {TokenInterface} from "../../../common/interfaces.sol";
 import {Helpers} from "./helpers.sol";
 import {Events} from "./events.sol";
 
diff --git a/contracts/mainnet/connectors/uniswap/v3_staker/events.sol b/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
index 0406b33c..1582d7d2 100644
--- a/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
+++ b/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
@@ -19,6 +19,7 @@ contract Events {
 
     event LogIncentiveCreated(
         address poolAddr,
+        address refundee,
         uint256 startTime,
         uint256 endTime,
         uint256 reward
diff --git a/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol b/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
index 71926302..f6ff4e16 100644
--- a/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
+++ b/contracts/mainnet/connectors/uniswap/v3_staker/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";

From e62e0cfea84be9d908d274faba8041dbab5bd1b9 Mon Sep 17 00:00:00 2001
From: Thrilok Kumar <thrilok2000@gmail.com>
Date: Wed, 8 Sep 2021 00:00:48 +0530
Subject: [PATCH 25/28] Minor changes

---
 .../connectors/uniswap/v3_staker/events.sol   | 10 +++---
 .../connectors/uniswap/v3_staker/helpers.sol  | 36 -------------------
 .../connectors/uniswap/v3_staker/main.sol     | 35 +++++++++---------
 3 files changed, 21 insertions(+), 60 deletions(-)

diff --git a/contracts/mainnet/connectors/uniswap/v3_staker/events.sol b/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
index 1582d7d2..fa8bbebf 100644
--- a/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
+++ b/contracts/mainnet/connectors/uniswap/v3_staker/events.sol
@@ -3,21 +3,21 @@ pragma solidity ^0.7.0;
 contract Events {
     event LogDeposit(uint256 tokenId);
 
-    event LogWithdraw(uint256 indexed tokenId, address to);
+    event LogWithdraw(uint256 indexed tokenId);
 
     event LogDepositTransfer(uint256 indexed tokenId, address to);
 
-    event LogStake(uint256 tokenId, address refundee);
+    event LogStake(uint256 indexed tokenId, bytes32 incentiveId);
 
-    event LogUnstake(uint256 tokenId, bytes32 incentiveId);
+    event LogUnstake(uint256 indexed tokenId, bytes32 incentiveId);
 
     event LogRewardClaimed(
-        address rewardToken,
-        address receiver,
+        address indexed rewardToken,
         uint256 amount
     );
 
     event LogIncentiveCreated(
+        bytes32 incentiveId,
         address poolAddr,
         address refundee,
         uint256 startTime,
diff --git a/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol b/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
index f6ff4e16..258d0961 100644
--- a/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
+++ b/contracts/mainnet/connectors/uniswap/v3_staker/helpers.sol
@@ -32,42 +32,6 @@ abstract contract Helpers is DSMath, Basic {
         tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1);
     }
 
-    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 getNftTokenPairAddresses(uint256 _tokenId)
-        internal
-        view
-        returns (address token0, address token1)
-    {
-        (bool success, bytes memory data) = address(nftManager).staticcall(
-            abi.encodeWithSelector(nftManager.positions.selector, _tokenId)
-        );
-        require(success, "fetching positions failed");
-        {
-            (, , token0, token1, , , , ) = abi.decode(
-                data,
-                (
-                    uint96,
-                    address,
-                    address,
-                    address,
-                    uint24,
-                    int24,
-                    int24,
-                    uint128
-                )
-            );
-        }
-    }
-
     function getPoolAddress(uint256 _tokenId)
         internal
         view
diff --git a/contracts/mainnet/connectors/uniswap/v3_staker/main.sol b/contracts/mainnet/connectors/uniswap/v3_staker/main.sol
index e65f44d9..2da11c59 100644
--- a/contracts/mainnet/connectors/uniswap/v3_staker/main.sol
+++ b/contracts/mainnet/connectors/uniswap/v3_staker/main.sol
@@ -6,7 +6,7 @@ pragma abicoder v2;
  * @dev Decentralized Exchange.
  */
 
-import {TokenInterface} from "../../common/interfaces.sol";
+import {TokenInterface} from "../../../common/interfaces.sol";
 import "./interface.sol";
 import {Helpers} from "./helpers.sol";
 import {Events} from "./events.sol";
@@ -56,18 +56,17 @@ abstract contract UniswapResolver is Helpers, Events {
      * @dev Withdraw NFT LP token
      * @notice Withdraw NFT LP token from staking pool
      * @param _tokenId NFT LP Token ID
-     * @param _to address to transfer
      */
-    function withdraw(uint256 _tokenId, address _to)
+    function withdraw(uint256 _tokenId)
         external
         payable
         returns (string memory _eventName, bytes memory _eventParam)
     {
         if (_tokenId == 0) _tokenId = _getLastNftId(address(this));
-        staker.withdrawToken(_tokenId, _to, "");
+        staker.withdrawToken(_tokenId, address(this), "");
 
-        _eventName = "LogWithdraw(uint256,address)";
-        _eventParam = abi.encode(_tokenId, _to);
+        _eventName = "LogWithdraw(uint256)";
+        _eventParam = abi.encode(_tokenId);
     }
 
     /**
@@ -104,8 +103,8 @@ abstract contract UniswapResolver is Helpers, Events {
             );
         _stake(_tokenId, _key);
 
-        _eventName = "LogStake(uint256,address)";
-        _eventParam = abi.encode(_tokenId, _refundee);
+        _eventName = "LogStake(uint256,bytes32)";
+        _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key)));
     }
 
     /**
@@ -142,20 +141,18 @@ abstract contract UniswapResolver is Helpers, Events {
             );
         _unstake(_key, _tokenId);
         _eventName = "LogUnstake(uint256,bytes32)";
-        _eventParam = abi.encode(_tokenId, _key);
+        _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key)));
     }
 
     /**
      * @dev Claim rewards
      * @notice Claim rewards
      * @param _rewardToken _rewardToken address
-     * @param _to address to receive
-     * @param _amountRequested requested amount
+     * @param _amount requested amount
      */
     function claimRewards(
         address _rewardToken,
-        address _to,
-        uint256 _amountRequested
+        uint256 _amount
     )
         external
         payable
@@ -163,12 +160,12 @@ abstract contract UniswapResolver is Helpers, Events {
     {
         uint256 rewards = _claimRewards(
             IERC20Minimal(_rewardToken),
-            _to,
-            _amountRequested
+            address(this),
+            _amount
         );
 
-        _eventName = "LogRewardClaimed(address,address,uint256)";
-        _eventParam = abi.encode(_rewardToken, _to, rewards);
+        _eventName = "LogRewardClaimed(address,uint256)";
+        _eventParam = abi.encode(_rewardToken, rewards);
     }
 
     /**
@@ -207,8 +204,8 @@ abstract contract UniswapResolver is Helpers, Events {
         }
         staker.createIncentive(_key, _reward);
 
-        _eventName = "LogIncentiveCreated(address,uint256,uint256,uint256)";
-        _eventParam = abi.encode(_poolAddr, _startTime, _endTime, _reward);
+        _eventName = "LogIncentiveCreated(bytes32,address,address,uint256,uint256,uint256)";
+        _eventParam = abi.encode(keccak256(abi.encode(_key)), _poolAddr, _refundee, _startTime, _endTime, _reward);
     }
 }
 

From df7becce200ee6b1d4fefe7044e0422b00acf638 Mon Sep 17 00:00:00 2001
From: Ishan Jain <contact@ishanjain.me>
Date: Wed, 8 Sep 2021 00:31:20 +0530
Subject: [PATCH 26/28] Pretty print status check output in comments, Remove
 the colors

---
 .github/workflows/status.yml | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml
index 2e72f099..3382de78 100644
--- a/.github/workflows/status.yml
+++ b/.github/workflows/status.yml
@@ -29,7 +29,8 @@ jobs:
       - name: Run status checks
         id: status_check
         run: |
-          output=$(node ./status-checks)
+          # Run status checks, Remove ANSI colors from the text
+          output=$(node ./status-checks | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g')
           # Escape newlines so _all_ the output is included in the set-output
           output="${output//'%'/'%25'}"
           output="${output//$'\n'/'%0A'}"
@@ -42,7 +43,7 @@ jobs:
         uses: bubkoo/auto-comment@v1
         with:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          pullRequestSynchronize: "${{ steps.status_check.outputs.status_check_output }}"
-          pullRequestAssigned: "${{ steps.status_check.outputs.status_check_output }}"
-          pullRequestOpened: "${{ steps.status_check.outputs.status_check_output }}"
-          pullRequestReopened: "${{ steps.status_check.outputs.status_check_output }}"
+          pullRequestSynchronize: "```${{ steps.status_check.outputs.status_check_output }}```"
+          pullRequestAssigned: "```${{ steps.status_check.outputs.status_check_output }}```"
+          pullRequestOpened: "```${{ steps.status_check.outputs.status_check_output }}```"
+          pullRequestReopened: "```${{ steps.status_check.outputs.status_check_output }}```"

From a2717f0853ca6e422800188f9bdcb22799e092dc Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 7 Sep 2021 14:35:46 -0500
Subject: [PATCH 27/28] refactor: minor fixes

---
 hardhat.config.js                      |  2 +-
 test/uniswapStake/uniswapStake.test.js | 19 +++++++++----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/hardhat.config.js b/hardhat.config.js
index 3320c333..44456a48 100644
--- a/hardhat.config.js
+++ b/hardhat.config.js
@@ -57,7 +57,7 @@ module.exports = {
     hardhat: {
       forking: {
         url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
-        blockNumber: 13005785,
+        blockNumber: 13180514,
       },
       blockGasLimit: 12000000,
       gasPrice: parseInt(utils.parseUnits("300", "gwei"))
diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
index 67b523a0..b11a5927 100644
--- a/test/uniswapStake/uniswapStake.test.js
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -170,11 +170,10 @@ describe("UniswapV3", function () {
             let event = await castEvent
 
             let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
-            console.log("Balane", balance)
+            console.log("Balance", balance)
         });
 
         it("Should create incentive successfully", async function () {
-            console.log("TokenIds", tokenIds[1]);
             const spells = [
                 {
                     connector: connectorStaker,
@@ -265,7 +264,7 @@ describe("UniswapV3", function () {
             let receipt = await tx.wait()
 
             let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
-            console.log("Balane", balance)
+            console.log("Balance", balance)
         });
 
         it("Should claim rewards successfully", async function () {
@@ -274,7 +273,7 @@ describe("UniswapV3", function () {
                     connector: connectorStaker,
                     method: "claimRewards",
                     args: [
-                        DAI_ADDR,
+                        ethAddress,
                         dsaWallet0.address,
                         "1000",
                     ],
@@ -298,9 +297,9 @@ describe("UniswapV3", function () {
                     connector: connectorStaker,
                     method: "unstake",
                     args: [
-                        DAI_ADDR,
-                        startTime,
-                        endTime,
+                        ethAddress,
+                        startTime[0],
+                        endTime[0],
                         dsaWallet0.address,
                         tokenIds[0]
                     ],
@@ -318,8 +317,8 @@ describe("UniswapV3", function () {
                     method: "unstake",
                     args: [
                         INST_ADDR,
-                        startTime,
-                        endTime,
+                        startTime[1],
+                        endTime[1],
                         dsaWallet0.address,
                         tokenIds[1]
                     ],
@@ -338,7 +337,7 @@ describe("UniswapV3", function () {
             let receipt = await tx.wait()
 
             let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
-            console.log("Balane", balance)
+            console.log("Balance", balance)
         });
     })
 })

From cf53215d13a40193ba11e91a254c6cdb2822fba6 Mon Sep 17 00:00:00 2001
From: cryptoDev222 <genius.developer.63@gmail.com>
Date: Tue, 7 Sep 2021 15:20:19 -0500
Subject: [PATCH 28/28] refactor: minor fixes

---
 test/uniswapStake/uniswapStake.test.js | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/test/uniswapStake/uniswapStake.test.js b/test/uniswapStake/uniswapStake.test.js
index b11a5927..043bd07f 100644
--- a/test/uniswapStake/uniswapStake.test.js
+++ b/test/uniswapStake/uniswapStake.test.js
@@ -13,8 +13,8 @@ const addresses = require("../../scripts/constant/addresses");
 const abis = require("../../scripts/constant/abis");
 const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json")
 
-const connectV2UniswapStakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswapStaker/main.sol/ConnectV2UniswapV3Staker.json");
-const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswapV3/main.sol/ConnectV2UniswapV3.json");
+const connectV2UniswapStakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/v3_staker/main.sol/ConnectV2UniswapV3Staker.json");
+const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/v3/main.sol/ConnectV2UniswapV3.json");
 
 const FeeAmount = {
     LOW: 500,
@@ -203,11 +203,11 @@ describe("UniswapV3", function () {
 
             let castEvent = new Promise((resolve, reject) => {
                 dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
-                    const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[0]);
-                    const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256"], eventParams[1]);
+                    const params = abiCoder.decode(["bytes32","address","address","uint256","uint256","uint256"], eventParams[0]);
+                    const params1 = abiCoder.decode(["bytes32","address","address","uint256","uint256","uint256"], eventParams[1]);
                     event.removeListener();
 
-                    resolve({ start: [params[1], params1[1]], end: [params[2], params1[2]] });
+                    resolve({ start: [params[3], params1[3]], end: [params[4], params1[4]] });
                 });
 
                 setTimeout(() => {
@@ -274,14 +274,12 @@ describe("UniswapV3", function () {
                     method: "claimRewards",
                     args: [
                         ethAddress,
-                        dsaWallet0.address,
                         "1000",
                     ],
                     connector: connectorStaker,
                     method: "claimRewards",
                     args: [
                         INST_ADDR,
-                        dsaWallet0.address,
                         "1000",
                     ],
                 }
@@ -309,7 +307,6 @@ describe("UniswapV3", function () {
                     method: "withdraw",
                     args: [
                         tokenIds[0],
-                        dsaWallet0.address,
                     ],
                 },
                 {
@@ -327,8 +324,7 @@ describe("UniswapV3", function () {
                     connector: connectorStaker,
                     method: "withdraw",
                     args: [
-                        tokenIds[1],
-                        dsaWallet0.address,
+                        tokenIds[1]
                     ],
                 }
             ]