---
id: TIP-1002
title: Prevent crossed orders and allow same-tick flip orders
description: Changes to the Stablecoin DEX that prevent placing orders that would cross existing orders on the opposite side of the book, and allow flip orders to flip to the same tick.
authors: Dan Robinson
status: Draft
---

# TIP-1002: Prevent crossed orders and allow same-tick flip orders

## Abstract

This TIP makes two related changes to the Stablecoin DEX:

1. **Prevent crossed orders**: Modify `place` and `placeFlip` to reject orders that would cross existing orders on the opposite side of the book. An order "crosses" when a bid is placed at a tick higher than the best ask, or an ask is placed at a tick lower than the best bid.

2. **Allow same-tick flip orders**: Relax the `placeFlip` validation to allow `flipTick` to equal `tick`, enabling flip orders that flip to the same price.

## Motivation

### Preventing crossed orders

Currently, the Stablecoin DEX allows orders to be placed at any valid tick, even if they would cross existing orders. Since matching only occurs during swaps (not during order placement), crossed orders can accumulate in the order book. This is unusual behavior and could confuse market makers who are accustomed to books that do not allow crossing.

By preventing crossed orders at placement time, the order book maintains a clean invariant: `best_bid_tick <= best_ask_tick`.

### Allowing same-tick flip orders

Currently, `placeFlip` requires `flipTick` to be strictly on the opposite side of `tick` (e.g., for a bid, `flipTick > tick`). This prevents use cases like instant token convertibility, where an issuer wants to place flip orders on both sides at the same tick to create a stable two-sided market that automatically replenishes when orders are filled.

---

# Specification

## Modified behavior

The `place` and `placeFlip` functions (including the `bookKey` overloads from TIP-1001) are modified to check for crossing before accepting an order:

- **For bids**: Revert if `tick > best_ask_tick` (when `best_ask_tick` exists)
- **For asks**: Revert if `tick < best_bid_tick` (when `best_bid_tick` exists)

### Same-tick orders

Orders at the same tick as the best order on the opposite side are **allowed**. This means:

- A bid at `tick == best_ask_tick` is allowed
- An ask at `tick == best_bid_tick` is allowed

While this is non-standard behavior for most order books (which would immediately match same-tick orders), it is intentionally permitted to support flip orders that flip to the same tick (see below).

## Same-tick flip orders

The `placeFlip` validation is relaxed to allow `flipTick == tick`:

- **Current behavior**: For bids, `flipTick > tick` required; for asks, `flipTick < tick` required
- **New behavior**: For bids, `flipTick >= tick` required; for asks, `flipTick <= tick` required

This enables use cases like instant token convertibility, where an issuer places flip orders on both sides at the same tick to create a stable two-sided market that automatically replenishes when orders are filled.

## Interaction with TIP-1001

If TIP-1001 is accepted, the crossing check only applies when the pair is **active**—that is, when the pair's quote token equals the base token's current `quoteToken()`.

For pairs created via `createNextPair` (where the quote token is the base token's `nextQuoteToken()`), the crossing check is skipped. This allows orders to accumulate freely during "place-only mode" before the quote token update is finalized. Such orders would likely be arbitraged nearly instantly once the pair launches, but this prevents someone from causing a denial-of-service to one side of the book by placing an extremely aggressive order on the other side.

## New error

```solidity
/// @notice The order would cross existing orders on the opposite side
error ORDER_WOULD_CROSS();
```

## Events

No new events.

---

# Invariants

- On active pairs, `best_bid_tick <= best_ask_tick` after any successful `place` or `placeFlip` call
- On inactive pairs (per TIP-1001), no crossing check is enforced
- Flip orders may create orders at the same tick as the opposite side, potentially resulting in `best_bid_tick == best_ask_tick`
