Skip to content

Repository files navigation

On-Chain Order Book DEX

A decentralised exchange implementing a full central limit order book on chain — price-time priority matching, limit and market orders, and custodial balance management — in ~630 lines of Solidity, with a React front end.

Most DEXs of this era were automated market makers precisely because an on-chain order book is hard: every resting order costs storage, and every match costs gas. Building one directly is the interesting part of this project, and the constraints it runs into are the substance of it.


Matching

Orders match on price first, then time of arrival — the same priority rule a traditional exchange uses.

   SELL SIDE (asks)                 BUY SIDE (bids)
   ┌────────────────┐               ┌────────────────┐
   │ 105  ×  50     │               │  99  ×  30     │
   │ 103  ×  20     │               │ 100  ×  75     │  ← best bid
   │ 101  ×  10     │ ← best ask    │  98  ×  40     │
   └────────────────┘               └────────────────┘
            ▲                                ▲
            └────── incoming order crosses ───┘
                    the spread and fills
                    at the resting price,
                    oldest order first

An incoming buy walks the ask queue upward while its limit price allows, filling resting orders oldest-first at each level; a sell walks the bid queue downward. Any unfilled remainder rests as a new order.

Each side is a queue of order indices with a mapping from index to order, so cancelling is a mapping delete rather than an array shift — an array shift would be O(n) in gas and would let a deep book price out its own cancellations.

Contracts

Contract Role
contracts/Exchange.sol Order books, matching, balances, deposits and withdrawals (627 lines)
contracts/Token.sol ERC-20 implementation
contracts/Token2.sol, contracts/Token3.sol Additional listings for multi-pair testing
contracts/owned.sol Ownership modifier gating token listing
contracts/Migrations.sol Truffle deployment bookkeeping

Balances are held in the exchange (tokenBalanceForAddress, etherBalanceForAddress) rather than pulled per trade. Settling every fill against external ERC-20 transfers would multiply gas cost by the number of fills — a single order crossing five resting orders would trigger five external calls, each with its own re-entrancy surface.


Security notes

This is an educational project on Solidity 0.5.1, and it should be read with that in mind. Documenting the issues honestly rather than quietly is the point of this section.

Unchecked multiplication — contracts/Exchange.sol:533.

uint total_ether_needed = priceInWei * amount;
require(total_ether_needed <= getEtherBalanceInWei());

Solidity did not add built-in overflow checks until 0.8.0. Under 0.5.1 this product wraps silently, so a sufficiently large priceInWei × amount can produce a small total_ether_needed, pass the balance check, and create a large buy order backed by almost no ether. On a modern compiler this reverts automatically; here it needs an explicit guard or SafeMath. depositEther does use a manual overflow require, so the pattern is applied inconsistently rather than absent.

Other observations:

  • msg.sender.transfer() forwards a fixed 2300 gas. This was the recommended pattern in 2019 but breaks for smart-contract recipients after gas repricing; the modern equivalent is call with a re-entrancy guard.
  • Withdrawals do decrement state before transferring, so checks-effects- interactions is correctly observed against re-entrancy.
  • test/ is empty. A matching engine holding custody of user funds with no test suite is the single largest gap here — an order book has enough edge cases (partial fills, self-crossing, cancel-during-match, empty book) that they cannot be verified by inspection.

Running it

Requires Ganache on 127.0.0.1:7545.

npm install
truffle compile
truffle migrate --reset

cd frontend
npm install
npm start

frontend/.env holds the deployed exchange address and the Ganache RPC URL — local development values only.

Stack

Solidity 0.5.1 · Truffle · React · web3.js / ethers.js · Ganache

Full write-up: DEX Documentation.pdf.

About

Decentralised exchange with a full on-chain central limit order book: price-time priority matching in Solidity, with a React frontend.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages