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.valueon native pools), thenplaceOrder, 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:
- Discover available markets via the HTTP API or by calling
getPoolParams()on a SpotPool contract. - (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. - Place a limit or market order via
placeOrder()— it auto-pulls the input from your wallet and delivers proceeds back to it. - 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, andreduceOrderstake 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).
amendOrderatomically 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.amendOrdersre-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, usereduceOrderinstead.
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:
- Best price first - the incoming buy takes the lowest ask (or the incoming sell hits the highest bid) available.
- 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:
| Stage | Event | Notes |
|---|---|---|
| Accepted | OrderPlaced | Emitted for every accepted order, filled or not. |
| Rests on book | OrderRested | Only when residual quantity actually enters the priority index (maker orders). |
| Matches | OrderFilled | One event per fill leg; carries filled quantity and remaining quantities for both taker and maker. |
| Removed | OrderCancelled / OrderExpired / OrderReduced | Cancel returns locked funds; orders past expireTimestampNs are expired (permissionlessly cleanable). |
| Amended | OrderAmended | Atomic 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):
- The pool auto-pulls the worst-case cost (
principal + max(makerFee, takerFee) + builderFee) from your wallet - read it first withgetAutoPullRequirement. (Builder fee is0while builder codes are disabled at v1.0.) - PTP fills
0.4 WETHat2,500.00(best price), then0.6 WETHat2,501.00- twoOrderFilledlegs. You pay each maker's price, not your limit. - The
1.0 WETHis 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. - Nothing rests, because the order fully filled. Had only
0.4 WETHbeen available and your order been GTC, the remaining0.6 WETHwould rest at2,501.00and emitOrderRested.
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.