contract ExchangeOrdersHolderV1 {

    mapping(bytes32 => OrderParams) internal orders;

    struct OrderParams {
        /* how much has owner (in wei, or UINT256_MAX if ERC-721) */
        uint selling;
        /* how much wants owner (in wei, or UINT256_MAX if ERC-721) */
        uint buying;

        /* fee for selling */
        uint sellerFee;
    }

    /// @notice This function can be called to add the order to the contract, so it can be exchanged without signature.
    ///         Can be called only by the order owner.
    /// @param order - The order struct to add.
    function add(ExchangeDomainV1.Order calldata order) external {
        require(msg.sender == order.key.owner, "order could be added by owner only");
        bytes32 key = prepareKey(order);
        orders[key] = OrderParams(order.selling, order.buying, order.sellerFee);
    }

    /// @notice This function checks if order was added to the orders holder contract.
    /// @param order - The order struct to check.
    /// @return true if order is present in the contract's data.
    function exists(ExchangeDomainV1.Order calldata order) external view returns (bool) {
        bytes32 key = prepareKey(order);
        OrderParams memory params = orders[key];
        return params.buying == order.buying && params.selling == order.selling && params.sellerFee == order.sellerFee;
    }

    function prepareKey(ExchangeDomainV1.Order memory order) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                order.key.sellAsset.token,
                order.key.sellAsset.tokenId,
                order.key.owner,
                order.key.buyAsset.token,
                order.key.buyAsset.tokenId,
                order.key.salt
            ));
    }
}
/// @title ExchangeOrdersHolderV1
/// @notice Optionally holds orders, which can be exchanged without order's holder signature.
function exists(ExchangeDomainV1.Order calldata order) external view returns (bool) {
    bytes32 key = prepareKey(order);
    OrderParams memory params = orders[key];
    return params.buying == order.buying && params.selling == order.selling && params.sellerFee == order.sellerFee;
}

/// @notice This function checks if order was added to the orders holder contract.
/// @param order - The order struct to check.
/// @return true if order is present in the contract's data.