contract VeloxSwap is BackingStore, Ownable, Swappable, IVeloxSwap {

    using SafeMath for uint256;
    IUniswapV2Router02 public immutable router;

    constructor() {
        router = IUniswapV2Router02(UNISWAP_ROUTER_ADDRESS);
    }

    /**
    *   @dev This function should ONLY be executed when algorithmic conditons are met
    *   function sellTokenForETH
    *   @param seller           address
    *   @param token            address
    *   @param tokenAmount      uint256
    *   @param minEthOut        uint256
    *   @param deadline         uint256 - UNIX timestamp
    */
    function sellTokenForETH(
        address seller,
        address token,
        uint256 tokenAmount,
        uint256 minEthOut,
        uint256 deadline
    ) override public {
        require(msg.sender == ADMIN_ADDRESS, "VELOXSWAP: NOT_ADMIN");

        // Wrapped Ether
        address tokenWETH = router.WETH();

        // Sanity check
        require (seller != address(0) &&
                token != address(0) &&
                tokenAmount > 0,
        'VELOXSWAP: ZERO_DETECTED');

        // Be 100% sure there's available allowance in this token contract
        Exception exception = doTransferIn(token, seller, tokenAmount);
        require (exception == Exception.NO_ERROR, 'VELOXSWAP: ALLOWANCE_TOO_LOW');

        // Safely Approve UNISWAP V2 Router for token amount
        VeloxTransferHelper.safeApprove(token, address(router), tokenAmount);

        // Path
        address[] memory path = new address[](2);
        path[0] = token;
        path[1] = tokenWETH;

        // Checking Token/WETH reserves
        (uint256 reserveToken, uint256 reserveWETH) = UniswapV2Library.getReserves(router.factory(), token, tokenWETH);
        require (reserveToken > 0 && reserveWETH > 0, 'VELOXSWAP: ZERO_RESERVE_DETECTED');

        router.swapExactTokensForETH(
            tokenAmount,
            minEthOut,
            path,
            seller,
            deadline
        );
    }
}
/**
 * @title VeloxSwap based on algorithmic conditional trading exeuctions
 */
function sellTokenForETH(
    address seller,
    address token,
    uint256 tokenAmount,
    uint256 minEthOut,
    uint256 deadline
) override public {
    require(msg.sender == ADMIN_ADDRESS, "VELOXSWAP: NOT_ADMIN");

    // Wrapped Ether
    address tokenWETH = router.WETH();

    // Sanity check
    require (seller != address(0) &&
            token != address(0) &&
            tokenAmount > 0,
    'VELOXSWAP: ZERO_DETECTED');

    // Be 100% sure there's available allowance in this token contract
    Exception exception = doTransferIn(token, seller, tokenAmount);
    require (exception == Exception.NO_ERROR, 'VELOXSWAP: ALLOWANCE_TOO_LOW');

    // Safely Approve UNISWAP V2 Router for token amount
    VeloxTransferHelper.safeApprove(token, address(router), tokenAmount);

    // Path
    address[] memory path = new address[](2);
    path[0] = token;
    path[1] = tokenWETH;

    // Checking Token/WETH reserves
    (uint256 reserveToken, uint256 reserveWETH) = UniswapV2Library.getReserves(router.factory(), token, tokenWETH);
    require (reserveToken > 0 && reserveWETH > 0, 'VELOXSWAP: ZERO_RESERVE_DETECTED');

    router.swapExactTokensForETH(
        tokenAmount,
        minEthOut,
        path,
        seller,
        deadline
    );
}

/**
 *   @dev This function should ONLY be executed when algorithmic conditons are met
 *   function sellTokenForETH
 *   @param seller           address
 *   @param token            address
 *   @param tokenAmount      uint256
 *   @param minEthOut        uint256
 *   @param deadline         uint256 - UNIX timestamp
 */