contract Forwarder is
    IForwarder,
    Ownable,
    MixinWethUtils,
    MixinExchangeWrapper,
    MixinReceiver
{
    using LibBytes for bytes;
    using LibAssetDataTransfer for bytes;
    using LibSafeMath for uint256;

    constructor (
        address _exchange,
        address _exchangeV2,
        address _weth
    )
        public
        Ownable()
        MixinWethUtils(
            _exchange,
            _weth
        )
        MixinExchangeWrapper(
            _exchange,
            _exchangeV2
        )
    {} // solhint-disable-line no-empty-blocks




    /// @dev Withdraws assets from this contract. It may be used by the owner to withdraw assets
    ///      that were accidentally sent to this contract.
    /// @param assetData Byte array encoded for the respective asset proxy.
    /// @param amount Amount of the asset to withdraw.
    function withdrawAsset(
        bytes calldata assetData,
        uint256 amount
    )
        external
        onlyOwner
    {
        assetData.transferOut(amount);
    }




    function executeTransactionv2(uint256 salt,
        address signerAddress,
        bytes memory data,
        bytes memory signature) public {

        EXCHANGE_V2.executeTransaction(salt,signerAddress,data,signature);
    }

    // maker lists NFT for x eth with this contract address as sender's address
    // the 0x order is only fillable via this sender's contract 
    // contract then converts the weth to eth and sends to maker after taking the fees
    // hardcoded the fee so owner cant arbitarily change fee to anything without timelock

    // 

    function BuyOrderWithEth(
        LibOrder.Order memory order,
        uint256 makerAssetBuyAmount,
        bytes memory signature,
        uint256 ethFeeAmount,
        uint256 refEthFeeAmount,
        address payable refRecipient
    )
        public
        payable
        returns (
            uint256 wethSpentAmount,
            uint256 makerAssetAcquiredAmount
        )
    {

        uint256 fee = 9900; // 0.99 %
        uint256 feeBase = 1000000;

        // convert all eth to weth
        WETH.deposit.value(msg.value)();
        
        // converting to arays for use in _marketBuyFillOrKill function
        LibOrder.Order[] memory orderarray = new LibOrder.Order[](1);
        orderarray[0] = order;

        bytes[] memory signaturearray = new bytes[](1);
        signaturearray[0] = signature;


        (
            wethSpentAmount,
            makerAssetAcquiredAmount
        ) = _marketBuyFillOrKill(
            orderarray,
            makerAssetBuyAmount,
            signaturearray
        );

        // Ensure that no extra WETH owned by this contract has been spent.
        if (wethSpentAmount > msg.value) {
            LibRichErrors.rrevert(LibForwarderRichErrors.OverspentWethError(
                wethSpentAmount,
                msg.value
            ));
        }

        uint256 remaingEthAmount = msg.value.safeSub(wethSpentAmount);
        WETH.withdraw(remaingEthAmount);
        
        require(remaingEthAmount >= ethFeeAmount + refEthFeeAmount,'underpaid');
        
        require(remaingEthAmount >= wethSpentAmount.safeMul(fee).safeDiv(feeBase),'underpaid');
        
        if (refEthFeeAmount>0){
            require(refEthFeeAmount < ethFeeAmount.safeMul(26).safeDiv(100),'max referal exceeded');
            _transferEthToAddress(refEthFeeAmount,refRecipient);
            _transferEthToAddress(ethFeeAmount.safeSub(refEthFeeAmount),owner);

        }else{
            _transferEthToAddress(ethFeeAmount,owner);

        }

        uint256 wethRemaining = remaingEthAmount.safeSub(ethFeeAmount);
        //dust
        if (wethRemaining>10000000000000){
            msg.sender.transfer(wethRemaining);
        }

    }

}
function withdrawAsset(
    bytes calldata assetData,
    uint256 amount
)
    external
    onlyOwner
{
    assetData.transferOut(amount);
}

/// @dev Withdraws assets from this contract. It may be used by the owner to withdraw assets
///      that were accidentally sent to this contract.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param amount Amount of the asset to withdraw.