library GPv2TradeExecution {
    using GPv2SafeERC20 for IERC20;

    /// @dev Executed trade data.
    struct Data {
        address owner;
        address receiver;
        IERC20 sellToken;
        IERC20 buyToken;
        uint256 sellAmount;
        uint256 buyAmount;
    }

    /// @dev Ether marker address used to indicate an order is buying Ether.
    address internal constant BUY_ETH_ADDRESS =
        0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    /// @dev Executes the trade's sell amount, transferring it from the trade's
    /// owner to the specified recipient.
    function transferSellAmountToRecipient(
        Data calldata trade,
        address recipient
    ) internal {
        require(
            address(trade.sellToken) != BUY_ETH_ADDRESS,
            "GPv2: cannot transfer native ETH"
        );
        trade.sellToken.safeTransferFrom(
            trade.owner,
            recipient,
            trade.sellAmount
        );
    }

    /// @dev Executes the trade's buy amount, transferring it to the trade's
    /// receiver from the caller's address.
    function transferBuyAmountToOwner(Data memory trade) internal {
        if (address(trade.buyToken) == BUY_ETH_ADDRESS) {
            payable(trade.receiver).transfer(trade.buyAmount);
        } else {
            trade.buyToken.safeTransfer(trade.receiver, trade.buyAmount);
        }
    }
}
/// @title Gnosis Protocol v2 Trade Execution
/// @author Gnosis Developers
function transferBuyAmountToOwner(Data memory trade) internal {
    if (address(trade.buyToken) == BUY_ETH_ADDRESS) {
        payable(trade.receiver).transfer(trade.buyAmount);
    } else {
        trade.buyToken.safeTransfer(trade.receiver, trade.buyAmount);
    }
}

/// @dev Executes the trade's buy amount, transferring it to the trade's
/// receiver from the caller's address.