± TESTNET · UNAUDITED · EXPERIMENTAL. Every token here is a test token worth nothing, and nothing has been audited.
The exchange has not opened and does not settle on the Liqua chain yet. That wiring comes first, then an outside audit and a bug bounty.
What exists today is the contracts and their tests. Your keys never leave your wallet. A match settles on-chain, or it does not happen.
§1
▸ BOOK + POOL = ONE COMBO
limit orders meet a price curve
Most DEXes pick one lane. A pool-only DEX is easy to swap on, but it has no limit orders and it leaks value from LPs when price runs. A book-only DEX prices to the tick, then goes quiet the moment makers log off. LIQUA runs both lanes and lets them trade with each other.
◆ THE BOOK
Every maker signs an EIP-712 order off-chain, so resting it costs zero gas. The relayer lists them. The contract settles each match in one shot, using the ERC-20 permits you already granted.
- Set a limit · take partial matches · pick an expiry
- Pull one order, or wipe them all with a single epoch bump
- Old-epoch orders get bounced at intake and again on-chain
- Your tokens stay put in your wallet until settlement
⇄MATCHMAKER
one-move cross
◆ THE POOL
A constant-product pool (x·y=k) anyone can swap through or add liquidity to. The 0.30% swap cost stays inside the pool, growing k for every LP.
- A price is always on the board, at any size
- Flash-swap callback: tokens go out first, k gets checked last
- InfinityFactory makes exactly one pool per sorted pair
- The pool is its own LP token (ERC-20)
The secret move is the Matchmaker. When a resting order is priced past the pool's effective quote, any keeper can call executeMatch. It flash-borrows takerToken from the pool, fills the order with it, pays the pool back in makerToken and hands the remainder to the caller. No bankroll needed. The caller covers gas. If the numbers do not work, the whole call unwinds.
§2
▸ THE STACK · FOUR FLOORS
settlement lives on-chain · everything else stays light
One rule shapes the build: settlement goes on-chain, everything else stays off. The contracts are the only piece that asks for no trust. The relayer can hide or skip an order. It can never touch funds, and every signature is checked again on-chain when a match settles.
F1 · SETTLE
Exchange (book settlement · EIP-712 · epochs · fee switch), InfinityPool (x·y=k + flash), InfinityFactory, Matchmaker, MockERC20, EmptyCallback.
trustless · not audited yet
▲ lands on ▲
F2 · RELAY
Express relayer built the molecular way (v3.2) · 6 fleets and 16 cells · watches the chain for Fill, Cancel and CancelAll · LEDGER + kernel saves · hormones you can read live.
takes orders · serves the book
▲ talks to ▲
F3 · BOTS
Quoter rests bids and asks ±50 bps around the pool price. Crosser calls the matchmaker when a cross covers its gas. Each has its own hot wallet, NonceManager-wrapped, so transactions go out side by side.
keep the book warm
▲ quote · cross · sign ▲
F4 · SCREEN
Plain HTML pages, zero build step. Wallet link · sign and send · partial matches · wipe-all · live match tape · vitals watermark · testnet stamp. House style by the drewless.
where you click
§3
▸ THE CROSS · ONE TRANSACTION, NO BANKROLL
how the pool snaps up a resting order
One transaction borrows, fills and repays. If any step comes up short, the whole call reverts. This is how the pool grabs an order it can reach:
// any keeper can call this · nothing up front:
matchmaker.executeMatch(order, signature, takerFillAmount, pool)
// 1 · flash-borrow from the pool
pool.swap(0, takerFillAmount, matchmaker, encodedCallback)
// the pool sends takerToken first, then rings back:
matchmaker.infinityCall(...)
// 2 · take the resting order: pay takerToken, collect makerToken
exchange.fillOrder(order, signature, takerFillAmount)
// 3 · work out what the pool is owed and pay it in makerToken
uint need = pool.getAmountIn(takerFillAmount, takerToken)
if (need > makerReceived) revert NotProfitable
makerToken.transfer(pool, need)
// any makerToken left over waits inside the matchmaker
// on the way out the pool re-checks k · break it and everything reverts
// 4 · send the leftover to the keeper
makerToken.transfer(msg.sender, profit)
If the pool's price is worse than the order, need > makerReceived and the call reverts. A keeper only moves on a real gap. That is the moment the book and the pool ought to meet.
§4
▸ PICK YOUR CLASS
six classes · one shared pool
CLASS · 01
TRADER
Sign limit orders for free, or swap straight through the pool. Nobody takes custody of your tokens.
- Gas-free EIP-712 signatures
- Partial matches, expiry, pull any single order
- Wipe every order with one epoch bump
- No deposit step. Nothing is held for you
- The pool steps in when the book runs thin
CLASS · 02
LIQUIDITY PROVIDER
Drop both tokens into InfinityPool and hold the LP token. The 0.30% swap cost stays in the pool you own a slice of. Matchmaker crosses count too.
- Classic x·y=k · easy to reason about
- Swap costs land by growing k, not as payouts
- MIN_LIQUIDITY is locked on the first deposit to block a drain trick
- Pool swaps and matchmaker paybacks both count
CLASS · 03
MARKET MAKER
Run the bundled Quoter bot, or bring your own. Rest bids and asks for free. Refresh them whenever the pool price wanders.
- Reads the pool mid → quotes a spread around it
- Refreshes with
cancelAllBefore when price drifts
- Dials: spread · drift · size · expiry
- Hot wallet only needs ETH for gas
CLASS · 04
KEEPER
Run the bundled Crosser bot (the mm-arber script). It watches the book and the pool and calls the Matchmaker when a cross covers its costs.
- No bankroll. The pool lends for one call
- Leftover makerToken lands in the keeper wallet
- NonceManager · several crosses per tick
- Set the floor with MIN_PROFIT_BPS
CLASS · 05
BUILDER
Fork the whole thing. Every floor is small and covered by tests, and the molecular labels tell you where to look.
- Solidity 0.8.28 (cancun) · OpenZeppelin 5
- ethers 6 · Hardhat 2.22
- 86 contract tests + 24 routing tests passing
- Plain HTML pages, zero build step
CLASS · 06
OPERATOR
Host a relayer for your crew. It cannot move a token. The worst it can do is hide orders.
- R6 INSTANCE=AUTH · boots from a seed
- A fresh LEDGER chain every boot (jsonl)
- Kernel saves the book, the tape and the lobby
- Health endpoint streams live hormones
§5
▸ VITALS · THE RELAYER HAS A PULSE
MDCP v3.2 · the drewless way
Every cell in the relayer wears a label, every commander carries a version, and every branch records the transition it took. Read it like a living thing. When something acts up, the trail names the fleet and the cell. Live hormones show the mood before you open a dashboard.
R0ASYNC SYSTEM · no master clock · each fleet ticks at its own speed
R1CELL_TYPE stamped on every sub-agent · APC · KILLER_T · MEMORY_T · TREG · HELPER_T
R2DNA_VERSION stamped on every commander · diff it, replay it
R3BE(fn, label) wraps every branch · a tracer of named transitions
R4GRADUATION events fire when something crosses a line (signature checked, cross landed)
R5SELF deep-store + prune · stale orders dropped, the tape kept short
R6INSTANCE = AUTH · nothing serves until the seed boots it
R7BOOT IS GENESIS · each start writes a fresh LEDGER block
R8COMMIT EVERY VERSION · ledger.jsonl only ever grows
R9DETECT-AND-ROLLBACK · a chain reorg rewinds that stretch of the tape
▸ HORMONES ON AIRasleep
measured, never rolled · failures per minute · matches per minute · book condition · does the watcher match the chain
§6
▸ THE FULL LOADOUT
86 contract tests · 24 routing tests · all green
Every item below is backed by a unit test or an end-to-end check. Nothing here is decoration.
F1EXCHANGE.SOL20 + 6 tests
- Orders signed with EIP-712, eight fields: maker, makerToken, takerToken, makerAmount, takerAmount, expiry, salt, epoch
fillOrder: partial or full · both legs in one shot · pro-rata · rounding leans toward the maker
cancelOrder: kills one order
cancelAllBefore: WIPE ALL by pushing your epoch forward, never back
remaining + remainingBatch: size up the whole book in one call
- FEE SWITCH: takerFeeBps + recipient · hard ceiling of 100 bps
- Owner powers:
setFee · transferOwnership
- Custom errors + events ·
ReentrancyGuard · SafeERC20
F1INFINITYPOOL.SOL + FACTORY9 tests
- x · y = k constant product, the classic curve
- The pool doubles as its own ERC-20 LP token
- token0 / token1 always sorted
mint: the first deposit locks 1000 MIN_LIQUIDITY for good · later deposits mint pro-rata
burn: hands back your slice of both reserves
swap with a flash callback (IInfinityCallback)
- 0.30% swap cost stays in the pool and grows k
- Price checks:
getAmountOut / getAmountIn
- Housekeeping:
skim · sync
- Factory · exactly one pool per sorted pair · look it up either way round
F1MATCHMAKER.SOL5 tests
executeMatch: book and pool meet in one atomic call
- Speaks
IInfinityCallback so the flash route works
- Flash-borrows takerToken from the pool
- Takes the resting order on Exchange
- Works out the payback with
pool.getAmountIn
- Sends whatever is left to the keeper
- Refuses with: PoolMismatch · NothingToFill · NotProfitable · UnauthorizedCallback
- Fires
Matched carrying every settlement detail
F2RELAYER · MOLECULAR v3.2e2e checked
- 6 organs and 16 cells, each wearing a
cell_type (KILLER_T · APC · MEMORY_T · TREG · HELPER_T)
- Versioned DNA commanders · intake · watcher · self · lobby
BE(fn,label) tracer keeps the newest 200 transitions
- R4 GRADUATION fires for every accepted order and every landed cross
- R5 SELF clears stale orders and trims the tape
- R6 INSTANCE=AUTH · stays dark until deployment.json loads
- R7/R8 every boot is a genesis written to LEDGER (ledger.jsonl, grow-only)
- R9 spots reorgs and rewinds the tape
- KERNEL saves the book · the tape · the lobby · epochs · lastBlock
- Watches Fill / Cancel / CancelAll on-chain and tidies up by itself
F2HTTP ROUTESthe core ten
GET /api/config: where it is deployed, the EIP-712 domain, the tokens
GET /api/orders: the resting book, checked by the watcher
POST /api/orders: gas-free intake behind four gates
DELETE /api/orders/:hash: soft pull (the chain always has the last word)
GET /api/trades: the tape of on-chain Fill events
GET /api/health: hormones · mood · LEDGER · fleets · DNA
GET /api/transitions: R3 tracer, newest 100
GET /api/chat: the lobby ring, 200 lines max
POST /api/chat: signed line + a timestamp within ±300 s
POST /api/reload: fresh genesis after a new deploy
F2HORMONES + MOODmeasured
- Four hormones computed from real state, never random
- cortisol = failures per minute (RPC, signature, schema)
- serotonin = book condition · resting vs total
- adrenaline = matches per minute
- oxytocin = does the watcher agree with the in-memory book
- Six moods: CALM · VIGILANT · ELATED · STRESSED · ALARMED · FATIGUED
- Set by MDCP's E1 (oracle thresholds) and E2 (somatic marker)
F3BOT #1 · QUOTERrests orders
- Own hot wallet. Hardhat account #5 unless you set
MM_QUOTER_KEY
cell_type APC · pinned DNA
- Reads pool depth to find a fair middle
- Rests a bid and an ask ±50 bps out (tunable)
- Wipes and re-quotes with
cancelAllBefore once price drifts past 25 bps
- Dials (env): SPREAD_BPS · DRIFT_BPS · REFRESH_SEC · ORDER_BASE · EXPIRY_SEC
- Every transition labelled in the logs
- Start it:
npm run mm:quoter
F3BOT #2 · CROSSERfires crosses
- Own hot wallet. Hardhat account #6 unless you set
MM_ARBER_KEY
cell_type KILLER_T · pinned DNA
- Checks /api/orders every 3 s
- Prices each resting order against
pool.getAmountIn
- Calls
Matchmaker.executeMatch once the gap clears MIN_PROFIT_BPS
- NonceManager wallet · several crosses per tick
- No bankroll · the leftover lands in makerToken
- Start it:
npm run mm:arber
F4SCREEN · index.htmlone page
- Browser-wallet link · chain hop (Base Sepolia · Arbitrum Sepolia · Hardhat on your machine)
- What you hold + the permits you've granted
- Order ticket: bid or ask · amount · limit · expiry · running total
- Permit check runs before your wallet pops up
- The book, live · click any row to take it
- Your resting orders · pull any one
- WIPE ALL button (on-chain epoch bump)
- Match tape (Fill events pulled from the relayer)
- Vitals LEDs + mood tag in the header
- Lobby chat (every line signed)
- Testnet · unaudited · experimental stamp
- Drewless house style · Holo Night Class skin · zero build step
OPSOPERATOR TOOLBOXthe essentials
deploy.js: ships the contracts, seeds the pool, funds the bots, writes shared/deployment.json
e2e-check.js: a headless smoke run, end to end
rogue-order.js: reads the pool mid and rests an order 2% off so the Crosser pounces
mm-quoter.js · mm-arber.js · the two bots
- npm scripts:
chain · deploy:local · deploy:baseSepolia · deploy:arbitrumSepolia · relayer · mm:quoter · mm:arber · test · compile
§7
▸ GEAR · WHAT IT'S BUILT WITH
open-source parts · nothing exotic
SOLIDITY 0.8.28
CANCUN EVM
OPENZEPPELIN 5.1
ETHERS 6.13
HARDHAT 2.22
HARDHAT-TOOLBOX 5
EXPRESS 4
CORS + DOTENV
EIP-712
EIP-1271 (LATER)
ANY EIP-1193 BROWSER WALLET
Networks wired in today: Hardhat on your own machine (31337), Base Sepolia (84532) and Arbitrum Sepolia (421614). All of them test networks. Settling on the Liqua chain is being built, and mainnet waits on an outside audit and a bug bounty.
§8
▸ RUN IT ON YOUR OWN MACHINE
one computer · five terminals · about a minute
1
BOOT A PRIVATE TEST CHAIN
A clean Hardhat node with 20 pre-loaded test accounts. Everything lives in memory, so closing it wipes the slate.
npm run chain
2
SHIP THE CONTRACTS
Deploys Exchange, two mock tokens, InfinityFactory, the pool and the Matchmaker. Seeds the pool with 100 mWETH and 200,000 mUSDC, tops up the bot wallets and writes shared/deployment.json.
npm run deploy:local
3
WAKE THE RELAYER
Express on port 8080 serves every page and hooks the watcher to the chain. This page sits at /liqua.html. The desk is /.
npm run relayer
4
LET THE BOTS LOOSE
The Quoter starts resting orders around the pool price while the Crosser hunts for gaps. Both narrate every move in labelled logs.
npm run mm:quoter npm run mm:arber
5
BAIT A CROSS (BONUS ROUND)
Rest a deliberately off-price order and watch the Crosser grab it inside one tick.
node scripts/rogue-order.js
Load the desk with a browser wallet pointed at your Hardhat chain. Step 1 prints its address, and the chainId is 31337. Import the Hardhat deployer key, which holds the seeded test tokens. Grant a permit, then rest an order or swap. Anything that crosses the pool gets scooped up by the Crosser.
§9
▸ STRAIGHT TALK · WHAT IS MISSING
testnet truth · zero hype
This is LIQUA's exchange, built end to end and covered by tests. It has not been audited, and it has not opened. Line by line:
- ✗ ZERO AUDITS SO FAR. Nobody should put it on mainnet before a professional review.
- ✗ The tokens are play-money ERC-20s with an open mint function, so they carry zero value.
- ✗ Fee-on-transfer or rebasing tokens wreck the pro-rata math. Every 0x-style or classic-pool DEX lives with the same catch.
- ✗ Plain wallet signatures only. EIP-1271 (contract wallets like Safe) sits on the later list.
- ✗ The desk shows one market, mWETH/mUSDC. The contracts accept any ERC-20 pair.
- ✗ The Quoter ignores its own inventory. Its spread is plain and symmetric.
- ✗ The Crosser doesn't sweep its leftovers back into one token.
- ✗ A concentrated-liquidity pool is parked for later. It was set aside when the build changed course.
This section stays. A project that shouts "production-ready" without listing what is missing is bluffing. The stamp sits in plain sight: testnet · unaudited · experimental. Real contracts, test tokens, and a door that has not opened.