mirror of
				https://github.com/Instadapp/dsa-connectors.git
				synced 2024-07-29 22:37:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			309 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
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);
 | 
						|
    ISwapRouter constant swapRouter =
 | 
						|
        ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
 | 
						|
 | 
						|
    struct MintParams {
 | 
						|
        address tokenA;
 | 
						|
        address tokenB;
 | 
						|
        uint24 fee;
 | 
						|
        int24 tickLower;
 | 
						|
        int24 tickUpper;
 | 
						|
        uint256 amtA;
 | 
						|
        uint256 amtB;
 | 
						|
        uint256 slippage;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @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 sortTokenAddress(address _token0, address _token1)
 | 
						|
        internal
 | 
						|
        view
 | 
						|
        returns (address token0, address token1)
 | 
						|
    {
 | 
						|
        if (_token0 > _token1) {
 | 
						|
            (token0, token1) = (_token1, _token0);
 | 
						|
        } else {
 | 
						|
            (token0, token1) = (_token0, _token1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    function _createAndInitializePoolIfNecessary (
 | 
						|
        address tokenA,
 | 
						|
        address tokenB,
 | 
						|
        uint24 fee,
 | 
						|
        int24 initialTick
 | 
						|
    ) internal returns (address pool) {
 | 
						|
        (TokenInterface token0Contract_, TokenInterface token1Contract_) = changeMaticAddress(
 | 
						|
            tokenA,
 | 
						|
            tokenB
 | 
						|
        );
 | 
						|
        
 | 
						|
        (address token0_, address token1_) =  sortTokenAddress(address(token0Contract_), address(token1Contract_));
 | 
						|
 | 
						|
        return nftManager.createAndInitializePoolIfNecessary(
 | 
						|
            token0_,
 | 
						|
            token1_,
 | 
						|
            fee,
 | 
						|
            TickMath.getSqrtRatioAtTick(initialTick)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Mint function which interact with Uniswap v3
 | 
						|
     */
 | 
						|
    function _mint(MintParams memory params)
 | 
						|
        internal
 | 
						|
        returns (
 | 
						|
            uint256 tokenId,
 | 
						|
            uint128 liquidity,
 | 
						|
            uint256 amountA,
 | 
						|
            uint256 amountB
 | 
						|
        )
 | 
						|
    {
 | 
						|
        (TokenInterface _token0, TokenInterface _token1) = changeMaticAddress(
 | 
						|
            params.tokenA,
 | 
						|
            params.tokenB
 | 
						|
        );
 | 
						|
 | 
						|
        uint256 _amount0 = params.amtA == uint256(-1)
 | 
						|
            ? getTokenBal(TokenInterface(params.tokenA))
 | 
						|
            : params.amtA;
 | 
						|
        uint256 _amount1 = params.amtB == uint256(-1)
 | 
						|
            ? getTokenBal(TokenInterface(params.tokenB))
 | 
						|
            : params.amtB;
 | 
						|
 | 
						|
        convertMaticToWmatic(address(_token0) == wmaticAddr, _token0, _amount0);
 | 
						|
        convertMaticToWmatic(address(_token1) == wmaticAddr, _token1, _amount1);
 | 
						|
 | 
						|
        approve(_token0, address(nftManager), _amount0);
 | 
						|
        approve(_token1, address(nftManager), _amount1);
 | 
						|
 | 
						|
        {
 | 
						|
            (address token0, ) = sortTokenAddress(
 | 
						|
                address(_token0),
 | 
						|
                address(_token1)
 | 
						|
            );
 | 
						|
 | 
						|
            if (token0 != address(_token0)) {
 | 
						|
                (_token0, _token1) = (_token1, _token0);
 | 
						|
                (_amount0, _amount1) = (_amount1, _amount0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        uint256 _minAmt0 = getMinAmount(_token0, _amount0, params.slippage);
 | 
						|
        uint256 _minAmt1 = getMinAmount(_token1, _amount1, params.slippage);
 | 
						|
 | 
						|
        INonfungiblePositionManager.MintParams
 | 
						|
            memory params = INonfungiblePositionManager.MintParams(
 | 
						|
                address(_token0),
 | 
						|
                address(_token1),
 | 
						|
                params.fee,
 | 
						|
                params.tickLower,
 | 
						|
                params.tickUpper,
 | 
						|
                _amount0,
 | 
						|
                _amount1,
 | 
						|
                _minAmt0,
 | 
						|
                _minAmt1,
 | 
						|
                address(this),
 | 
						|
                block.timestamp
 | 
						|
            );
 | 
						|
 | 
						|
        (tokenId, liquidity, amountA, amountB) = nftManager.mint(params);
 | 
						|
    }
 | 
						|
 | 
						|
    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
 | 
						|
                )
 | 
						|
            );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Check if token address is maticAddr and convert it to wmatic
 | 
						|
     */
 | 
						|
    function _checkMATIC(
 | 
						|
        address _token0,
 | 
						|
        address _token1,
 | 
						|
        uint256 _amount0,
 | 
						|
        uint256 _amount1
 | 
						|
    ) internal {
 | 
						|
        bool isMatic0 = _token0 == wmaticAddr;
 | 
						|
        bool isMatic1 = _token1 == wmaticAddr;
 | 
						|
        convertMaticToWmatic(isMatic0, TokenInterface(_token0), _amount0);
 | 
						|
        convertMaticToWmatic(isMatic1, 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
 | 
						|
        )
 | 
						|
    {
 | 
						|
        _checkMATIC(_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);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev collect function which interact with Uniswap v3
 | 
						|
     */
 | 
						|
    function _collect(
 | 
						|
        uint256 _tokenId,
 | 
						|
        uint128 _amount0Max,
 | 
						|
        uint128 _amount1Max
 | 
						|
    ) internal returns (uint256 amount0, uint256 amount1) {
 | 
						|
        INonfungiblePositionManager.CollectParams
 | 
						|
            memory params = INonfungiblePositionManager.CollectParams(
 | 
						|
                _tokenId,
 | 
						|
                address(this),
 | 
						|
                _amount0Max,
 | 
						|
                _amount1Max
 | 
						|
            );
 | 
						|
        (amount0, amount1) = nftManager.collect(params);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Burn Function
 | 
						|
     */
 | 
						|
    function _burn(uint256 _tokenId) internal {
 | 
						|
        nftManager.burn(_tokenId);
 | 
						|
    }
 | 
						|
}
 |