Spot Trading

dreamDEX provides a high-performance spot market for trading crypto assets with zero protocol fees and atomic on-chain settlement.

Features

  • Zero Fees: 0% maker and 0% taker fees.
  • Deep Liquidity: Institutional-grade market makers providing tight spreads.
  • Atomic Settlement: Funds are swapped instantly and are fully non-custodial.
  • Simple Swap: One-click multi-hop swap surface routed through the SpotRouter; see Simple Swap for the user flow and testnet live preview.
  • Stop Orders: Conditional stop-loss and take-profit orders via the SpotStopOrderRegistry, triggered automatically by Somnia's on-chain reactivity against the SpotPool's EMA-smoothed mark price.
  • Batch Order Management: Place, cancel, or reduce many orders in a single transaction — fewer round trips, and atomic re-laddering for market makers.
  • Amend Orders: Atomically cancel and replace a resting order — or a whole ladder — in one call, returning a new order id.
  • On-Chain Matching Engine: Spot runs on dreamDEX's on-chain price-time-priority matching engine, with matching and settlement executed atomically on-chain.

Getting Started

Automated bots and agents: skip the vault entirely. Use the default wallet funding flow - a one-time ERC-20 approval to the pool (or msg.value on native pools), then placeOrder, which auto-pulls at execution and delivers proceeds back to your wallet. IOC / FOK suit taker loops; resting GTC / PostOnly are also supported from the wallet. See the Quick Start.

To trade on the spot market:

  1. Discover available markets via the HTTP API or by calling getPoolParams() on a SpotPool contract.
  2. (Optional) Pre-deposit tokens via deposit(). By default the pool auto-pulls funds from your wallet at order time, so a deposit is not required.
  3. Place a limit or market order via placeOrder() — it auto-pulls the input from your wallet and delivers proceeds back to it.
  4. Optionally set up stop orders for automated risk management.

See the Quick Start guide for a step-by-step walkthrough.

Batch Orders & Amend

Manage many orders in one transaction instead of one call at a time:

  • Batch place / cancel / reduce. placeOrders, cancelOrders, and reduceOrders take arrays and run in a single tx — one signature for a whole ladder and fewer round trips. Batch cancel is best-effort: a rung that filled or expired in the race window is skipped rather than reverting the rest of the pull. Batch reduce is atomic (all-or-nothing); batch place returns a per-order success flag.
  • Amend (cancel + replace). amendOrder atomically cancels a resting order and places a replacement in one call, returning a new order id — update your tracking, as the old id is dead. amendOrders re-ladders many quotes atomically, so re-quoting never leaves a gap. An amend re-enters the back of the price-time queue for its price; to only shrink an order while keeping its queue spot, use reduceOrder instead.

Operators can run all of these on your behalf via the ...For variants (placeOrdersFor, cancelOrdersFor, reduceOrdersFor, amendOrderFor, amendOrdersFor) — see Operators & Session Keys. Full signatures are on the Functions reference.

How Matching and Settlement Work

Every SpotPool runs an on-chain price-time-priority (PTP) matching engine. Matching and settlement happen atomically inside the placement transaction - there is no off-chain sequencer and no separate settlement step.

Price-time priority

When an incoming order crosses the book, it matches resting orders in strict order:

  1. Best price first - the incoming buy takes the lowest ask (or the incoming sell hits the highest bid) available.
  2. Then earliest first - among orders resting at the same price, the one that arrived first fills first.

An order that does not (or cannot) fully fill either rests on the book as a maker (GTC / PostOnly) or is discarded (IOC keeps the fill and cancels the rest; FOK reverts the whole order unless it fills completely). Self-trade prevention cancels one side if your order would match your own resting order.

Order lifecycle

An order moves through these states, each marked by an on-chain event:

StageEventNotes
AcceptedOrderPlacedEmitted for every accepted order, filled or not.
Rests on bookOrderRestedOnly when residual quantity actually enters the priority index (maker orders).
MatchesOrderFilledOne event per fill leg; carries filled quantity and remaining quantities for both taker and maker.
RemovedOrderCancelled / OrderExpired / OrderReducedCancel returns locked funds; orders past expireTimestampNs are expired (permissionlessly cleanable).
AmendedOrderAmendedAtomic cancel + replace; links oldOrderId to the replacement's new id (the cancel leg also emits OrderCancelled).

A receipt with an empty logs array means the order was not accepted - always check for OrderPlaced rather than assuming status: 1 implies a fill.

Worked example: a crossing limit buy

Book: best ask 2,500.00 USDso for 0.4 WETH, next ask 2,501.00 for 1.0 WETH.

You place a limit buy for 1.0 WETH at 2,501.00 (wallet-funded, GTC):

  1. The pool auto-pulls the worst-case cost (principal + max(makerFee, takerFee) + builderFee) from your wallet - read it first with getAutoPullRequirement. (Builder fee is 0 while builder codes are disabled at v1.0.)
  2. PTP fills 0.4 WETH at 2,500.00 (best price), then 0.6 WETH at 2,501.00 - two OrderFilled legs. You pay each maker's price, not your limit.
  3. The 1.0 WETH is credited and auto-delivered to your wallet; any quote pulled but unspent (your limit was above the fill price on the first leg) is returned. Fees are 0% maker / 0% taker at launch.
  4. Nothing rests, because the order fully filled. Had only 0.4 WETH been available and your order been GTC, the remaining 0.6 WETH would rest at 2,501.00 and emit OrderRested.

Settlement is complete when the transaction confirms - proceeds are already in your wallet (or vault, in manual mode). See Functions for the full call surface and Order Types for execution semantics.