Skip to content

Providing Liquidity

Provide liquidity to the DEX by placing limit orders or flip orders in the onchain orderbook.

When your orders are filled, you earn the spread between bid and ask prices while helping facilitate trades for other users.

You can only place orders on pairs between a token and its designated quote token. All TIP-20 tokens specify a quote token for trading pairs. PathUSD can be used as a simple choice for a quote token.

Overview

The DEX uses an onchain orderbook where you can place orders at specific price ticks. Orders are matched using price-time priority, meaning better-priced orders fill first, and within the same price, earlier orders fill first.

Unlike traditional AMMs, you specify exact prices where you want to buy or sell, giving you more precise control over your liquidity provision strategy.

Order Types

Limit Orders

Standard orders that remain in the book at a specific price until filled or cancelled.

function place(
    address token,
    uint128 amount,
    bool isBid,
    int16 tick
) external returns (uint128 orderId)
Parameters:
  • token - The token address you're trading (must trade against its quote token)
  • amount - The amount of the token denominated in token
  • isBid - true for a buy order, false for a sell order
  • tick - The price tick: (price - 1) * 100_000 where price is in quote token per token
Returns:
  • orderId - Unique identifier for this order
Example: Place a bid to buy 1000 USDC at $0.9990
// tick = (0.9990 - 1) * 100_000 = -10
uint128 orderId = exchange.place(
    USDC_ADDRESS,
    1000e6,      // Amount: 1000 USDC
    true,        // isBid: buying USDC
    -10          // tick: price = $0.9990
);
Example: Place an ask to sell 1000 USDC at $1.0010
// tick = (1.0010 - 1) * 100_000 = 10
uint128 orderId = exchange.place(
    USDC_ADDRESS,
    1000e6,      // Amount: 1000 USDC
    false,       // isBid: selling USDC
    10           // tick: price = $1.0010
);

Flip Orders

Special orders that automatically reverse to the opposite side when completely filled, creating perpetual liquidity similar to an automated market maker pool.

function placeFlip(
    address token,
    uint128 amount,
    bool isBid,
    int16 tick,
    int16 flipTick
) external returns (uint128 orderId)
Parameters:
  • All parameters from place(), plus:
  • flipTick - The price where the order will flip to when filled
    • Must be greater than tick if isBid is true
    • Must be less than tick if isBid is false
Returns:
  • orderId - Unique identifier for this flip order
Example: Place a flip order providing liquidity on both sides
// Place a bid at $0.9990 that flips to an ask at $1.0010
uint128 orderId = exchange.placeFlip(
    USDC_ADDRESS,
    1000e6,      // Amount: 1000 USDC
    true,        // isBid: start as a buy order
    -10,         // tick: buy at $0.9990
    10           // flipTick: sell at $1.0010 after filled
);

When this order is completely filled:

  1. You buy 1000 USDC at $0.9990
  2. A new order automatically sells 1000 USDC at $1.0010
  3. When that fills, it flips back to a bid at $0.9990
  4. This continues indefinitely, earning the spread each time

Understanding Ticks

Prices are specified using ticks with 0.1 basis point (0.001%) precision:

Tick Formula: tick = (price - 1) × 100_000

Price Formula: price = 1 + (tick / 100_000)

Where price is the token price in quote token units.

Example Tick Calculations

PriceTickCalculation
$0.9990-100(0.9990 - 1) × 100_000 = -100
$0.9998-20(0.9998 - 1) × 100_000 = -20
$1.00000(1.0000 - 1) × 100_000 = 0
$1.000220(1.0002 - 1) × 100_000 = 20
$1.0010100(1.0010 - 1) × 100_000 = 100

Bid vs Ask

  • Bid (isBid = true): An order to buy the token using its quote token
  • Ask (isBid = false): An order to sell the token for its quote token

For a USDC/USD pair where USD is the quote:

  • A bid buys USDC with USD at your specified price
  • An ask sells USDC for USD at your specified price

Order Execution Timeline

Orders follow a specific lifecycle:

  1. Placement: When you call place() or placeFlip():

    • Tokens are debited from your DEX balance (or transferred if insufficient)
    • Order is queued but not yet visible to other contracts
    • Returns an order ID immediately
  2. End of Block: All queued orders are added to the book:

    • Processed in the order they were placed
    • Filled flip orders from this block are added first
    • Orders become visible and matchable
  3. Filling: As market orders execute against your order:

    • Your order fills partially or completely
    • Proceeds are credited to your DEX balance
    • If a flip order fills completely, it creates a new order on the opposite side

Cancelling Orders

Remove an order from the book before it's filled:

function cancel(
    uint128 orderId
) external
Example:
// Cancel order #12345
exchange.cancel(12345);

Cancellations execute immediately, and any unfilled portion of your order is refunded to your DEX balance.