contract UniswapDapp is BrokerExtension {
    using SafeMath for uint256;

    UniswapFactory public factory;
    address private constant ETHER_ADDR = address(0);

    constructor(address _factoryAddress) public {
        factory = UniswapFactory(_factoryAddress);
    }

    function setFactory(address _factoryAddress) external onlyOwner nonReentrant {
        factory = UniswapFactory(_factoryAddress);
    }

    /// @notice See Utils._performNetworkTrade for method details
    function tokenReceiver(
        address[] memory /* _assetIds */,
        uint256[] memory /* _dataValues */,
        address[] memory /* _addresses */
    )
        public
        view
        returns(address)
    {
        return address(this);
    }

    /// @notice See Utils._performNetworkTrade for method details
    function trade(
        address[] memory _assetIds,
        uint256[] memory _dataValues,
        address[] memory /* _addresses */,
        address payable _recipient
    )
        public
        payable
        nonReentrant
    {
        // _dataValues[2] bits(24..56): delay
        uint256 deadline = now.add((_dataValues[2] & ~(~uint256(0) << 56)) >> 24);

        if (_assetIds[0] == ETHER_ADDR) {
            UniswapExchange exchange = UniswapExchange(factory.getExchange(_assetIds[1]));
            exchange.ethToTokenTransferInput.value(_dataValues[0])(
                _dataValues[1],
                deadline,
                _recipient
            );
            return;
        }

        UniswapExchange exchange = UniswapExchange(factory.getExchange(_assetIds[0]));

        Utils.transferTokensIn(msg.sender, _assetIds[0], _dataValues[0], _dataValues[0]);
        Utils.approveTokenTransfer(
            _assetIds[0],
            address(exchange),
            _dataValues[0]
        );

        if (_assetIds[1] == ETHER_ADDR) {
            exchange.tokenToEthTransferInput(
                _dataValues[0],
                _dataValues[1],
                deadline,
                _recipient
            );
            return;
        }

        // Use the minimum of 1 for minEth as the amount of intermediate eth
        // used for the trade is not important. It is only important that the
        // final received tokens is more than or equal to the wantAmount.
        exchange.tokenToTokenTransferInput(
            _dataValues[0],
            _dataValues[1],
            1,
            deadline,
            _recipient,
            _assetIds[1]
        );
    }
}
/// @title The DApp adapter contract for Uniswap
/// @author Switcheo Network
/// @notice This contract allows BrokerV2 offers to be filled by Uniswap
function trade(
        address[] memory _assetIds,
        uint256[] memory _dataValues,
        address[] memory /* _addresses */,
        address payable _recipient
    )
        public
        payable
        nonReentrant
    {
        // _dataValues[2] bits(24..56): delay
        uint256 deadline = now.add((_dataValues[2] & ~(~uint256(0) << 56)) >> 24);

        if (_assetIds[0] == ETHER_ADDR) {
            UniswapExchange exchange = UniswapExchange(factory.getExchange(_assetIds[1]));
            exchange.ethToTokenTransferInput.value(_dataValues[0])(
                _dataValues[1],
                deadline,
                _recipient
            );
            return;
        }

        UniswapExchange exchange = UniswapExchange(factory.getExchange(_assetIds[0]));

        Utils.transferTokensIn(msg.sender, _assetIds[0], _dataValues[0], _dataValues[0]);
        Utils.approveTokenTransfer(
            _assetIds[0],
            address(exchange),
            _dataValues[0]
        );

        if (_assetIds[1] == ETHER_ADDR) {
            exchange.tokenToEthTransferInput(
                _dataValues[0],
                _dataValues[1],
                deadline,
                _recipient
            );
            return;
        }

        // Use the minimum of 1 for minEth as the amount of intermediate eth
        // used for the trade is not important. It is only important that the
        // final received tokens is more than or equal to the wantAmount.
        exchange.tokenToTokenTransferInput(
            _dataValues[0],
            _dataValues[1],
            1,
            deadline,
            _recipient,
            _assetIds[1]
        );
    }
/// @notice See Utils._performNetworkTrade for method details