Matching & Settlement
How orders are matched on-chain and the three settlement paths — Normal Fill, Mint-to-Fill, and Merge-to-Fill.
OddMaki runs a fully on-chain central limit order book (CLOB). Orders are matched through a permissionless matchOrders function that anyone can call to earn the operator fee (10 bps per fill).
Order Types
| Type | Behavior | Settlement Paths |
|---|---|---|
| Limit | Rests on the book at a specified price until filled, cancelled, or expired | Normal, Mint, Merge |
| Fill-Or-Kill (FOK) | Must fill completely or the entire transaction reverts | Normal only |
| Fill-And-Kill (FAK) | Fills as much as available, returns remaining collateral | Normal only |
Limit Orders
const tx = await client.trade.placeOrderSimple({
marketId: 1n,
outcomeId: 0n, // YES
side: 0, // BUY
price: '0.65', // $0.65
quantity: '100', // 100 tokens
expiry: '24h', // expires in 24 hours
});Collateral locking:
- BUY orders lock USDC (pulled via ERC-20 transfer)
- SELL orders lock outcome tokens (pulled via CTF
safeTransferFrom)
Market Orders
const tx = await client.trade.placeMarketOrderSimple({
marketId: 1n,
outcomeId: 0n, // YES
amount: '50', // spend up to 50 USDC
maxPrice: '0.80', // slippage protection
orderType: 'FAK', // fill what's available
});Market orders execute immediately against resting sell-side liquidity. They only use the Normal Fill path.
Settlement Paths
The matching engine evaluates paths in a fixed priority order each step:
| Priority | Path | Condition | What Crosses |
|---|---|---|---|
| 1 | Normal Fill (YES) | YES bestBid >= YES bestAsk | Same-outcome BUY/SELL |
| 2 | Normal Fill (NO) | NO bestBid >= NO bestAsk | Same-outcome BUY/SELL |
| 3 | Mint-to-Fill | yesBid + noBid >= 1.0 + fees | Cross-outcome BUY/BUY |
| 4 | Merge-to-Fill | yesAsk + noAsk <= 1.0 - fees | Cross-outcome SELL/SELL |
The first path that successfully executes a fill consumes one step. If no path fills, the loop terminates.
Normal Fill
Standard buyer-seller matching within the same outcome. A BUY order crosses with a SELL order when bestBid >= bestAsk. Execution price is always at the ask price.
The seller receives collateral minus fees. The buyer receives outcome tokens from the vault.
Mint-to-Fill
When both a YES buyer and a NO buyer exist and their combined bids cover the full token price (1.0) plus fees, the protocol mints new YES and NO tokens from collateral via the CTF's splitPosition.
- YES buyer receives YES tokens
- NO buyer receives NO tokens
- Fees are taken from the surplus collateral
This path creates new liquidity — it doesn't require existing sellers.
Merge-to-Fill
When both a YES seller and a NO seller exist and their combined asks are below the full token price (1.0) minus fees, the protocol merges outcome tokens back into collateral via the CTF's mergePositions.
- YES seller receives collateral for their ask price
- NO seller receives collateral for their ask price
- Fees are taken from remaining collateral
This path removes liquidity — it doesn't require existing buyers. Volume is not recorded for Merge-to-Fill.
Triggering Matching
Anyone can call matchOrders to earn the operator fee:
const tx = await client.trade.matchOrders({
marketId: 1n,
maxSteps: 10n, // max fill iterations
});Each step processes one fill. The caller receives the operator fee (10 bps fixed) on every fill executed. Gas usage scales linearly with maxSteps.
Order Cancellation
Only the order owner can cancel. Remaining quantity is fully refunded (no penalty):
const tx = await client.trade.cancelOrder(42n);Orders with a nonzero expiry are automatically cleaned up during matching when expired.
What's Next
- Orderbook → — how the on-chain CLOB works
- Token Mechanics → — split, merge, and position tokens
- Fee Structure → — fee calculation per settlement path