Skip to content
/ dcrdex Public
forked from decred/dcrdex

The Decred Decentralized Exchange (DEX), powered by atomic-swaps.

Notifications You must be signed in to change notification settings

chappjc/dcrdex

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Table of Contents

Abstract

We propose here a decentralized, non-custodial, trustless, and intermediary-free cryptocurrency exchange platform.

The primary service provided by the decentralized exchange (DEX) is to match clients who would like to trade an asset of one type for an asset of another type. Trades are facilitated by a trustless atomic swap negotiation process carried out with all the cryptographic security guarantees of the respective blockchains.

A custom order matching procedure is offered to mitigate common abusive trading patterns associated with high-frequency trading (HFT) algorithms and other bot-driven trading. Elimination of per-trade fees disincintevizes deceptive bookkeeping practices commonly observed in centralized exchanges.

To encourage open and active development, descriptions of critical protocol components and a full client-server API definition are provided.

Introduction

Existing cryptocurrency exchange platforms fall into 4 overlapping categories: custodial corporate entities, services, tokens, and blockchains. The vast majority of cryptocurrency trading is currently performed via centralized, custodial exchanges. Since trades at these exchanges take place off-chain, they generally settle instantly to make funds available for further trading. This is a nice feature, but it practically guarantees that the market will be a target of HFT and algorithmic traders, which can be unpredictable and malicious. Additionally, such exchanges earn revenue by collecting trading fees. Such a model creates incentives for an exchange to artificially inflate their volume by wash trading [1]. By one study, it has been estimated that more than 95% of reported exchange volume is faked [2].

Several DEX projects have been created to address some of these issues by replacing the exchange with a blockchain or a token, and they have met with varying degrees of success. While they remove the trusted third party (TTP), they insert their own products as a means to capture the trading fees, which replaces the TTP friction with a new platform friction. The simple act of collecting trading fees serves to act as an incentive to centralize on a given solution, which runs counter to a system of open voluntary exchange. While a chain or token serves to remove the TTP, it also creates challenges with order matching, which typically occurs via the intermediate chain or token.

The DEX described in this document is based on atomic swaps [3], signed and transmitted by the clients. Thus, the exchange of funds is trustless and secure. The purpose of the DEX is to facilitate such peer-to-peer trades, while disincentivizing manipulative or abusive trading patterns, and utilizing an independently verifiable order matching algorithm that is difficult to game by traders and operators alike. The proposed DEX is not: an escrow service, an arbitration service, or a platform for HFT.

While trades are fully trustless, steps are taken to discourage malicious clients from hindering normal trade activity. Registered clients are bound by the rules of community conduct, violation of which typically results in loss of trading privileges. Serious violations may result in a permanent ban, in which case the affected user must pay another registration fee to continue using the DEX.

The following list of non-negotiable, fundamental, DEX properties served as a basis for design.

  1. Non-custodial. Assets must be traded directly between clients, without the exchange being in control of assets at any time.
  2. Intermediary-free. Trades must be executed in a secure and trustless manner.
  3. Resistant to malicious or manipulative trading. Deliberately disruptive behavior should be disincentivized, and volume manipulation mitigated by pseudo-random epoch-based order matching.
The remainder of this document details the design of the proposed DEX. It is intended as a first resource when implementing servers and clients. Continuing client-server interoperability will likely depend on subtle aspects of the specification laid out in this document, especially the following critical sections.

Communication Protocols describes the messaging protocols and communication layer technologies that are to be used in for the DEX API.

Distributed Exchange Design Fundamentals describes the notable design aspects that facilitate an exchange service with the features described above.

Client Order Management details the different order types and the client/server workflows required to synchronize the order book and place orders.

Atomic Settlement walks through the settlement process with a couple of examples to provide a high-level overview.

Community Conduct describes the system of rules to which clients interacting with the DEX must adhere.

Communication Protocols

WebSockets

Trustless negotiation of trades requires considerable messaging. Transaction details must be reported and relayed at appropriate times, sometimes with substantial delays between subsequent actions. Match notification via HTTP polling or other request interval-based methods are thus not suitable for the DEX system. Persistent, full-duplex communication is critical to minimizing communication latencies and wasted bandwidth. Websockets ([4]) are chosen as the default and preferred communications protocol for the DEX exchange API. In addition to fulfilling the aforementioned needs, Websockets are now a well-established technology with client software available for integration in virtually all popular programming languages.

Websocket messages are secured by encryption on Transport Layer Security (TLS) [5] connections.

JSON-RPC

JavaScript Object Notation - Remote Procedure Call v2.0 (JSON-RPC 2.0) is a message formatting protocol for client-server communications [6]. The DEX API uses JSON-RPC exclusively for both inbound and outbound client communications. The JSON-RPC structure is simple and flexible.

{
	"method": "string",
	"id": int,
	"params": {} || [];
}

{
	"result": {...} || null,
	"error": {...} || null,
	"id": int
}

The method is the "remote procedure" being called, analogous to calling a function. Most parameters are passed as part of a params object or array. Parameters will vary with method. The id field links a response to a request, and is optional for notifications which require no response.

JSON-RPC 2.0 specifies that in the case of an error, the response's error field will be non-null and the result field will be null. The opposite is true in the case of a success.

HTTP

An API using HTTP for message transport may be provided for basic account management and server status queries, however websocket connections are to be the sole means for placing, monitoring, and executing orders. The primary reason for limiting the scope of the HTTP API is to eliminate client polling for rapidly changing resources, such as order status API endpoints.

Distributed Exchange Design Fundamentals

There are several notable aspects of the DEX design that were chosen to permit peer-to-peer trades with the mechanics of order execution existing entirely on the separate blockchains via atomic swaps. These are:

  • Asset-specific order quantity increments and transaction fee rates
  • Epoch-based pseudorandom order matching
  • Client identities based on public key infrastructure (PKI)
  • An open and rigidly-defined interface for integration of arbitrary assets
This section describes each of these design aspects.

Exchange Variables

There are a number of asset-specific variables that must be known by the client.

The lot size for an asset serves as both the minimum order quantity and the order quantity increment for limit orders and market buy orders, which are quantified in the market's base asset. In particular, for lot size l, the requested order quantity, Q, must satisfy

File:spec/images/lot-sizes.png

When the asset is the quote asset, a price increment is enforced. The rate, r, of a limit order must be an integer multiple of the price increment, p.

File:spec/images/price-increment.png

The DEX operator specifies an on-chain transaction fee rate (units atoms/byte) used when calculating the fees for initialization transactions.

Each asset will also have a minimum number of confirmations. This is the number of confirmations that are required for backing UTXOs as well as the number required during settlement on the first swap transaction before the second swap transaction is broadcast.

The minimum confirmation rule is waived for a change output from a transaction involved in a DEX-monitored trade.

The broadcast timeout is the amount of time a client has to broadcast a transaction. For the maker, the broadcast time is measured from the time of match notification. For the taker, timeout is measured from the time when the maker's swap receives its minconfth confirmation.

Asset info should be requested by the user immediately after connecting.

JSON-RPC method: assets, originator: client

field type description
epochlen int the epoch duration (seconds)
buybuffer float the market buy buffer
cancelmax float the cancellation threshold
assets [object] list of Asset objects (definition below)
btimeout int the broadcast timeout

Asset object

field type description
symbol string ticker symbol
lotsize int lot size (atoms)
ratestep int the price rate increment (atoms)
feerate int the fee rate for transactions (atoms/byte)
swapsize int the size of the initialization transaction (bytes)
minconf int minimum confirmations for backing UTXOs and swap transactions
scripts [string] acceptable backing UTXO script types. minimum ["P2PKH"]

Fees

The DEX collects no trading fees. Collecting fees from trades executed via atomic swaps (where the server is never in control of funds and settlement occurs directly on-chain) would add considerable complexity to the swap process and incentivize DEX operators to facilitate wash trading. Instead, a one-time fee is collected by the pool during registration. Registration fees discourage certain spam attacks, enable punitive actions when conduct rules are violated, and help to cover DEX operating expenses. Registration fees will be configurable by the exchange operator.

Transaction Fees

The clients will cover on-chain transaction fees at a minimum fee rate set by the DEX operator. Failure to provide the specified fee rate in a transaction will result in a conduct violation.

As part of any submitted order, a client is required to demonstrate control of funds that will back the atomic swap, and ensure that the backing funds are sufficient to create the swap contract transactions transferring the full order quantity as well as covering the network's transaction fees at the specified rate.

Total on-chain fees associated with an order will increase as the number of swap transactions required to settle the order increases. Maximum fees paid vary linearly with order size, but the actual fees realized can be significantly less than the maximum. See the atomic settlement section for examples of simple and complex matches and how that affects the swap transaction sizes.

Fee rates can vary greatly between assets. For many assets, low fees are possible without increasing the time until mined. Transaction fees tend to rise as an asset pushes the limits of on-chain scaling. For high-fee assets, the DEX operator must find a balance between lower fees, which are preferable from an accounting standpoint, and higher fees, which can decrease settlement time by increasing the speed at which a transactions are mined.

See also: Calculating Transaction Fees

Epoch-based Order Matching

In order to devalue predatory behavior exhibited by certain high-frequency trading algorithms, received orders are not processed continuously, but rather after a shuffling step with all other orders received in a fixed duration period called an epoch. The goal of this algorithm is to reduce the probability that an individual or collaborating pair can submit two orders that match with each other. Limiting this possibility mitigates advantages gained from front-running, spoofing, and other manipulative trading practices.

Epoch Time

For a given epoch duration d > 0 , and current UNIX epoch time stamp t (in seconds since Jan 01 00:00:00 1970 UTC), the current order matching epoch index, i, and epoch range are computed as

File:spec/images/epoch-index.png

where / is integer division. For example, at the time of writing, t = 1562008475 , which for d = 60 corresponds to epoch number i = 26033474 spanning [1562008440, 1562008500). This convention allows epoch times to be known without querying the server.

A clock synchronization protocol such as NTP will be used to ensure server and client clocks are synchronized within acceptable tolerances.

Pseudorandom Order Matching

When the epoch ends, a match cycle begins.

First, the order pool is shuffled. Shuffling is deterministic, using the Fisher-Yates algorithm where the random number generator seed is derived from the hash of the concatenated order ID hashes. Specifically for hash function f, the seed hash, Hseed is computed as

File:spec/images/seed-eq.png

where orderi represents the order ID of the ith order in a lexicographically sorted list of order IDs and || indicates concatenation.

The order IDs and final hash are published at the start of the matching process. This is done so that the shuffling may be independently computed for external verification and to facilitate server mesh operation.

Orders are processed one at a time. Each order is matched according to its type.

1. If the order is a cancel order, any corresponding standing limit order is removed from the list and the cancel order is considered filled. If a cancellation is processed before the order that it cancels, the cancellation will fail, and will need to be re-submitted. That is, cancel orders do not affect down-queue orders, only standing orders.

2. If the order is a limit order with time in force standing that cannot match immediately (a maker), it is added to the standing orders. It is immediately able to match orders further down the queue.

3. If the order is a taker, it is matched against the best available standing order. Clients for both orders are notified and the settlement process begins. The orders are set aside for monitoring. If a limit order with time in force standing on either side of the match is only partially filled, it is added to the standing orders with the appropriate modifications and is immediately available for matching again.

Any unmatched quantity on a limit order with time in force immediate is left unfilled. Market orders and immediate limit orders cannot match orders further down the queue.

When a limit order matches a limit order, the price assigned to the match is the average of the two orders, with a split atom going to the maker.

The process continues with the next order in the list and iterates until all orders have been processed.

Identities based on Public Key Infrastructure (PKI) Key Pairs

The server and the clients are identified and authenticated using public keys, with matching private keys used to sign and authorize orders and other messages. Establishing client identity with public keys keeps the notion of client identity to a minimum, while providing a number of other security benefits throughout the order placement and execution processes.

All data submitted to the exchange server from a client must be signed with the client's private key and authenticated by the server using the corresponding public key, so using client public keys directly for identity purposes is a natural simplification that obviates the need for client user names and passwords.

Further, since Politeia, Decred's governance platform, also employs a PKI, the same identities may be used on both services to facilitate time-stamping exchange data via Politeia. For example, given common identities between the DEX and Politeia, anchoring data related to DEX client and server conduct on the Decred blockchain may be useful for establishing a reputation system.

Blockchain Interaction

Clients need atomic-swap enabled wallets and the ability to broadcast transactions to each of the blockchain networks involved in the swap.

DEX operators need access to trusted full nodes for each of the assets supported. While operation via a surrogate blockchain data service such as a block explorer is potentially feasible, it would entail significant security risks. Initial development will require a direct connection to full nodes of each asset's blockchain.

Adding support for an asset is accomplished by implementing a particular Go interface. The interface is exported and compiled with -buildmode=plugin to enable dynamic importing by the exchange operator. The operator will decide which plugins to import via configuration file. As the expected interface is expected to evolve greatly during initial implementation, the specifics of interface structure will be released at a later time.

With the exception of Decred and Bitcoin, which will be implemented during initial phases of DEX development, it is expected that development communities will release their own appropriately vetted plugins.

Account Creation

An account is uniquely identified by the client's public account key (pubkey), which the client provides during registration. After registration, the client does identify themselves with their pubkey directly. Instead, the account is identified by an account ID, which is the double SHA-256 hash of the client's pubkey, sha256(sha256(pubkey)), provided as a hex-encoded string in JSON-RPC calls.

Step 1: Registration

The user creates a websocket connection and sends their public account key. The message is signed with the corresponding private account key. The response includes the server's public key. The server's public key will also be pre-published for further validation.

JSON-RPC method: register, originator: client

field type description
pubkey string hex-encoded public account key
timestamp int UTC timestamp
sig string hex-encoded signature of serialized registration. serialization described below

Registration serialization

field size (bytes) description
pubkey 32 the user's public account key
timestamp 8 the client's UNIX timestamp

Response parameters

field type description
pubkey string hex-encoded server public key.
address string fee address
fee int fee (atoms)
timestamp int UNIX timestamp
sig string hex-encoded signature of the serialized response. serialization described below

Response serialization

field size (bytes) description
DEX pubkey 32 the server's public key
client pubkey 32 the client's public account key
timestamp 8 the server's UNIX timestamp
fee 8 registration fee (atoms)
address varies ASCII-encoded fee address

Step 2: Fee Notification

The client pays the fee on-chain and notifies the DEX of the transaction detail. The fee is paid with a standard P2PKH output to the address received in step 1. The server immediately sends their receipt and then closes the connection.

JSON-RPC method: notifyfee, originator: client

field type description
accountid string client's account ID
txid string transaction ID
vout int the transaction output index which pays the fee
timestamp int UNIX timestamp
sig string hex-encoded signature of serialized fee notification. serialization described below

Notification serialization

field size (bytes) description
account ID 16 client account ID
tx ID 32 the transaction ID
vout 4 transaction output index

Response parameters

field type description
sig string server hex-encoded signature of client's serialized notification

Step 3: Await Confirmation

Once the transaction is mined and has the requisite number of confirmations, the client should create a new authenticated connection. If the client attempts to connect before minconf confirmations, the DEX should reject the connection outright.

Client Order Management

This section describes the steps required of the client to place an order, and the interactions between the client and server to execute an order once a match has been found. See the atomic settlement section for a high-level overview of the settlement process.

There are three available types of order.

  • Limit orders are used to buy or sell a specified amount of an asset at a rate no higher (buy) or lower (sell) than a specified price.
  • Market orders are used to buy or sell a specified amount of an asset at the best price available.
  • Cancel orders are used to remove standing limit orders from the order book.
The order book holds only limit orders with time in force standing that have not completely filled or been cancelled. All other orders are only valid for one epoch match cycle.

Session Authentication

Orders must be placed on an authenticated connection. Once a websocket connection is established, the client will supply their account ID and signature.

JSON-RPC method: connect, originator: client

field type description
accountid string account ID
apiver int requested API version
timestamp int UNIX timestamp
sig string hex-encoded signature of serialized connection data. serialization described below

Connect serialization

field size (bytes) description
account ID 16 client account ID
API version 2 requested API version
timestamp 8 the client's UNIX timestamp

Connect response

If the client connects shortly after a trade suspension, it's possible that trading will not commence until a future epoch. The DEX response will indicate when trade did or will begin.

If a client unexpectedly disconnects with active orders, the orders may match in the client's absence. A list of any pending matches is included in the response.

field type description
startepoch int the epoch at which trading did or will commence. May be in the future e.g. after maintenance
matches [object] list of Match objects

Connection Persistence

If a connection is lost after placing an order, the client must reconnect and complete settlement on any matches made in their absence. Regardless of connection status, once a match is made, a client is always subject to violation of rule 1 via the broadcast timeout. This is true regardless of connection status.

If a client is disconnected for a full epoch duration, any standing limit orders may be auto-cancelled by the server. These cancellations will count toward the client's cancellation ratio, so could potentially result in penalties. The client should manage their orders carefully to ensure that this doesn't occur.

Market orders and limit orders with time in force immediate are not cancelled under disconnection. Once submitted, these orders will always go through a single match cycle.

If a client is in the settlement phase when a connection is dropped, the client will be expected to reconnect and complete settlement.

Order Book Subscriptions

An order book can be viewed and tracked by subscribing to a market.

JSON-RPC method: orderbook, originator: client

field type description
base string currency code for the market's base asset
quote string currency code for the market's quote asset

The response will contain the complete market order book. The order book and all updates include a sequence ID, which increments by +1 whenever the DEX accepts, removes, or modifies an order. The client is responsible for tracking the sequence ID to ensure all order updates are received. If an update appears to be missing, the client should re-subscribe to the market to synchronize the order book from scratch.

Response

field type description
book object An OrderBook object
seq int A sequence ID

JSON OrderBook object

field type description
marketid int the market ID. included with order book updates.
epoch int the current epoch
orders [object] A list of Order objects

JSON Order object

field type description
oid string the order ID
otype string "l" for limit, "m" for market
side string "b" for buy, "s" for sell
osize int order size (atoms)
rate int price rate (quote asset per unit base asset, atoms). only set on limit orders
tif string time in force. one of "i" for immediate or "s" for standing. only set on limit orders
epoch int the epoch in which the order was received

Changes to the orderbook will be received from the DEX as a stream of updates. These updates take the JSON-RPC notification format, so omit an id attribute.

JSON-RPC method: remove_order, originator: DEX

field type description
marketid int the market ID
orderid string hex-encoded order ID
seq int A sequence ID

JSON-RPC method: add_limit & add_market, originator: DEX

field type description
marketid int the market ID
order object the Order object
seq int A sequence ID

At the beginning of the matching cycle, the DEX will publish a list of order IDs and the seed hash used for order sequencing.

JSON-RPC method: match_data, originator: DEX

field type description
marketid int the market ID
epoch int the epoch for which the cycle occurs
orderids [string] list of order IDs for the epoch
seed string hex-encoded sorting key

A client can unsubscribe from order book updates without closing the websocket connection.

JSON-RPC method: unsub_orderbook, originator: client

field type description
marketid int the market ID

Order Preparation

As part of the order, the client must demonstrate control of funds. This is accomplished by supplying information and a signature for each previous output (UTXO) that will be spent. The client covers the backing fees associated with the inputs spending their own UTXOs.

In addition, the client must show the ability to cover base fees for any initialization transactions that will be generated. The client must show that they have the funds to cover all fees for the worst-case-scenario, which is single-lot matches for the entire order. In practice, large orders will rarely pay the total of the base fees because many of the matches will be more than a single-lot.

Calculating Transaction Fees

The base fees cover transaction fees associated with making initialization transactions for every match in the order.

For asset Z, a base fee ratio, Rz is calculated based on the lot size, l (units Z), a fee rate, r (Z/byte), and a transaction size, s (bytes). s is pre-calculated based on an initialization transaction with 1 standard P2PKH input, 1 standard P2PKH output, and 1 swap output.

File:spec/images/fee_max_ratio.png

The base fee ratio is a constant until the DEX operator changes one of its factors.

The base fees, fbase (units Z) can be calculated from Rz and the order quantity, Q.

File:spec/images/base_fees.png

The base fees scale linearly with order size, but the actual realized portion of the base fees, ffin, can only be known to fall within a range r s ≤ ffin ≤ fbase .

The client also covers the backing fees associated with spending their backing UTXOs, futxo. The client must know how to calculate the script sizes to assess fees. The DEX will verify the UTXO sum before accepting the order.

UTXO Preparation

All backing UTXOs must have a minimum number of confirmations. The exact number is set by the DEX operator.

With the exception of market buy orders, which are detailed below, for an order of quantity Q, the sum value of the selected UTXOs, V, must satisfy the relation

File:spec/images/utxo-sum.png

There may be types of pubkey script which are not implemented. As a rule, P2PKH will always be available.

As part of the order, the client will submit a list of UTXO objects.

JSON UTXO object

field type description
txid string hex-encoded transaction ID
vout int the transaction output index
pubkey string hex-encoded public key
sig string hex-encoded signature of serialized UTXO data. serialization described below
extradata string hex-encoded data. the script for P2SH. empty for P2PKH

The sig is a signature of the UTXO data serialized according to the table below. The data is signed with the private key corresponding to pubkey. The pubkey must hash to a receiving address in the UTXO's pubkey script.

UTXO serialization

field size (bytes) description
tx hash 32 the transaction hash
vout 4 the UTXO's transaction output index

Order Signing

All orders must be signed by the client and the server. The basic signing procedure will involve serializing order data into a byte array following a specific procedure that can be replicated on the server. The serialized data is then signed using the client's private account key.

All integer encoding for all serialized structures is big endian.

All order serializations have a common prefix structure.

Prefix serialization

field size (bytes) description
account ID 16 client account ID
base asset 5 the base asset for the market. ASCII-encoded ticker symbol, with leading zeros for 3- and 4-letter tickers
quote asset 5 the quote asset for the market. ASCII-encoded ticker symbol, with leading zeros for 3- and 4-letter tickers
order type 1 the type of order. limit = 0, market=2, cancel=3
client time 8 the client's UNIX timestamp
server time 8 the server's UNIX timestamp. zeros for client-size serialization

Order ID

The order serialization is used to create a unique order ID. The ID is defined as the SHA-256 hash of the serialized order. It is represented in messaging as a hex-encoded string.

Limit Order

Limit orders are for the trade of assets at a rate no higher (buy) or lower (sell) than a specified price. The client may specify the time in force of a limit order as one of: (a) standing, which remains on the books until filled or cancelled, or (b) immediate, which can complete execution wholly or partially unfilled. As such, the immediate option is intended for limit orders with a price that crosses the spread (i.e. a taker rather than a maker). The ordersize must be an integer multiple of the asset's lot size.

JSON-RPC method: limit, originator: client

field type description
accountid string client's account ID
timestamp int UTC timestamp generated at the time of order submission of trades requires a fair amount of messaging between the 2 clients, via the DEX trade API.
tradepair string market. trading pair. e.g. DCR/BTC
ordertype string "limit" for a limit order
side string one of "buy" or "sell"
ordersize int order size (atoms)
rate int price rate (quote asset per unit base asset, atoms)
timeinforce string one of standing or immediate
utxos [UTXO] list of backing UTXOs
orderid string hex-encoded order ID
sig string client hex-encoded signature of the serialized order data. serialization described below
address string address where the matched client will send funds

Response parameters

field type description
sig string server hex-encoded signature of the serialized order, after adding the DEX timestamp
server time int the server's UNIX timestamp

Limit order serialization

field size (bytes) description
prefix 65 the order prefix
UTXO count 1 The number of backing UTXOs
UTXO data 36 x count sequence of UTXO data
side 1 0 for buy, 1 for sell
rate 8 price rate
quantity 8 quanity to buy or sell (atoms)
time in force 1 0 for standing, 1 for immediate
address varies client's receiving address

Market Order

A market order is an order to buy or sell an asset at the best available market price. The JSON-RPC params fields are similar to a limit order, but without the rate field.

Market orders cannot be cancelled. Any portion of the requested quantity that does not match immediately (during the epoch match cycle) is left unfilled.

JSON-RPC method: market, originator: client

field type description
accountid string client's account ID
timestamp int UTC timestamp. order broadcast time
tradepair string market. trading pair. e.g. DCR/BTC
ordertype string "market" for a market order
side string one of "buy" or "sell"
ordersize int order size, in atoms (*1e8). See notes on market buy orders below.
utxos [UTXO] list of backing UTXOs
orderid string hex-encoded order ID
sig string client hex-encoded signature of the serialized order data. serialization described below
address string address where the matched client will send funds

Response parameters

field type description
sig string server hex-encoded signature of the order by server, after adding the DEX timestamp
server time int the server's UNIX timestamp

Market order serialization

field size (bytes) description
prefix 65 the order prefix
UTXO count 1 The number of backing UTXOs
UTXO data 36 x count sequence of UTXO data
side 1 0 for buy, 1 for sell
quantity 8 quantity to buy or sell (atoms)
time in force 1 0 for standing, 1 for immediate
address varies client's receiving address

Market Buy Orders

Market buy orders have a slightly different ruleset than market sell orders or limit orders. First, the ordersize is not denominated in the base asset, but in the quote asset. As an example, on the DCR/BTC market, where DCR is the base asset, market sell orders and both types of limit orders' ordersize are quantified in the base asset, DCR, but the market buy order's ordersize is in BTC. The order is essentially a statement of "buy as much DCR as you can with this much BTC".

The ordersize is also not bound to the integral lot size constraints of other types of orders.

Since the market may move before the order is matched, at the time of submission it is not known with certainty how many lots will match. For orders that are nearly 1 lot, it is possible for no matching to occur because by the time the order is matched it cannot afford a single lot. The DEX server maintains an interest in ensuring that only valid orders that can match are accepted, so market buy orders must be handled carefully to make sure they remain valid.

To prevent orders becoming invalid (too small to match) due to a price increase, the DEX operator chooses a market buy buffer, bm > 1. For a market with lot size l, and for which there is a best known standing sell order price rate, r, the ordersize, Q must satisfy the relation Q > bm l r. If the best rate increases before the order is matched, the order will still result in a fill as long as the price does not surpass ~bm r. If the market buy buffer is set too low or the market is particularly volatile and the price exceeds bm r, an order that was accepted but is now too small to match is considered executed but unfilled and there is no change to the account's cancellation statistics.

Cancel Order

Cancel orders remove standing limit orders from the order book. A client cannot cancel a market order or a limit order with time in force immediate. Further, due to the epoch-based pseudorandom matching process, a cancel order submitted in the same epoch as it's corresponding limit order has a 50% chance of being processed before the order it cancels, resulting in an error. This is by design and discourages certain types of spoofing.

JSON-RPC method: cancel, originator: client

field type description
accountid string client's account ID
timestamp int UTC timestamp. order broadcast time
tradepair string market. trading pair. e.g. DCR/BTC
orderid string hex-encoded order ID
sig string client hex-encoded signature of the serialized order data. serialization described below

Response parameters

field type description
sig string server hex-encoded signature of the serialize order data, after adding the DEX timestamp
server time int the server's UNIX timestamp

Cancel order serialization

field size (bytes) description
prefix 65 the order prefix
orderid 16 the order ID

Match notifications

If the client's order has one or more matches at the end of a match cycle, the DEX will send a list of Match objects.

JSON-RPC method: match, originator: DEX

field type description
orderid string order ID
matchid int the match ID to use for progress notifications
quantity int the matched amount, in atoms of the base asset
rate int the rate that the order matched at (as quote asset per unit base asset, atoms)
address string the client's receiving address
timestamp int UTC timestamp. order broadcast time
sig string server hex-encoded signature of the serialized notification data. serialization described below

The client will be responsible for serializing the notification and checking the signature. In turn, the client should themselves sign the notification data and return an acknowledgement to the DEX.

Client Acknowledgement

The client will return a list of signed match acknowledgements.

field type description
matchid int the match ID
sig string client hex-encoded signature of the serialized notification data.

Match notification serialization

field size (bytes) description
orderid 32 the order ID
matchid 8 the ID assigned to this match
quantity 8 the matched amount, in atoms of the base asset
rate 8 the rate that the order matched at
address varies ASCII encoded receiving address for the match

Progress Notifications

After the client broadcasts both their initialization and redemption transactions, they are expected to report the transaction details to the server for verification and relay to the counterparty.

JSON-RPC method: progress, originator: client

field type description
swap stage string one of "init" or "redeem"
matchid int the matchid, retrieved from the match notification
txid string the hex-encoded transaction ID
vout int the output index
timestamp int UTC timestamp. order broadcast time
sig string client signature of the serialized progress notification. serialization described below

DEX Acknowledgement

field type description
matchid int the match ID
swap stage string one of "init" or "redeem"
sig string client hex-encoded signature of the serialized progress notification. serialization described below

Progress notification serialization

field size (bytes) description
orderid 16 the order ID
matchid 8 the ID assigned to this match
swap stage 1 0 for initialization transaction, 1 for redemption
tx hash 32 the transaction hash
vout 4 the output index
timestamp 8 the client's UNIX timestamp

Match revocation

A match can be revoked by the server if a client fails to act within the broadcast timeout. A match revocation will result in penalties for the violating party only. The revoked match quantity is not added back to the orderbook in any form.

JSON-RPC method: revoke_match, originator: DEX

field type description
orderid string order ID
matchid int the match ID
sig string server hex-encoded signature of serialized revocation. serialization described below

Revocation serialization

field size (bytes) description
orderid 32 the order ID
matchid 8 the ID assigned to this match

Trade Suspension

There are a number of scenarios where the server may suspend operations, intentionally or not. During trade suspension, standing limit are not necessarily revoked.

If the server intentionally suspends operations, they should provide a notification to connected clients as early as possible, ideally with several epochs for the client to get their orders situated before matching ceases. The epoch specified in the suspension notification is the first epoch for which orders will no longer be accepted. Users should expect to lose connection during suspension. When possible, the server should settle all existing matches before closing connections. If that is not possible, clients will need to reconnect and complete settlement when the server comes back online.

If the server disconnects without notice, it is expected that orders placed during the current epoch are revoked at no penalty to the client and that standing limit orders are persisted.

The suspension notification may indicate that standing limit orders will not be persisted. This would be the case if the DEX needs to change an asset variable such as the lot size or minimum transaction fee rate.

If standing limit orders are persisted, they will be auto-revoked if the client does not reconnect before the next startepoch.

JSON-RPC method: suspension, originator: DEX

field type description
epoch int the epoch in which the suspension will start
persist bool

Atomic Settlement

In order to facilitate trustless, non-custodial exchange, the DEX leverages an atomic swap process that enables all parties to maintain full control over their assets at every step. The DEX primarily acts as a matchmaker, connecting two orders and relaying messages between the two clients. Additionally, the DEX performs some trade monitoring to ensure that parties are acting in good faith. Clients who fail to act on their trades appropriately will be issued a penalty in accordance with the rules of community conduct.

The following cases are meant to provide a high-level overview of the trade process, and to illustrate how to handle a perfect match, a partial fill, and multiple matches within an epoch. For the sake of illustration, the following simplifications are made.

  1. The lot size for the market is 1 DCR.
  2. All backing funds for the orders are in the form of a single UTXO.
  3. There are no fees.
The examples involve a participant named Alice, who holds some DCR and would like to exchange it for some BTC. The market is a DCR/BTC market, where DCR is the “base asset” and BTC is the “quote asset”. Order quantities are in units of DCR, and the rate offered in a limit order is denominated in BTC.

Case A: Perfect match

In the most basic case, Alice and a trader named Bob are the only participants and their orders match perfectly.

A1: Alice places a limit order to sell 3 DCR at 0.1 BTC per DCR for a total of 0.3 BTC. As a limit order, Alice must specify both the quantity and the price, as a rate, as well as her BTC address. Alice signs the order information. The signature provides proof of the order and justifies any penalties imposed on Alice should she fail to follow through on a trade.

A2: During some later epoch, Bob places a market order to buy DCR with BTC at the best available price. Bob’s order will contain both an address and a signature. As a market order, Bob’s order must match in this epoch. Any unfilled portion is immediately cancelled.

A3: At the end of the epoch, the DEX performs a match cycle, recognizes the match, and informs both Alice and Bob that a match has occurred. Because the order quantities are identical, the orders are simply removed from the book and set aside for monitoring. The DEX informs both clients that a match has been made and provides Bob with Alice’s address.

A4: Because Alice is the maker, she will broadcast her initialization transaction first. She will be expected to broadcast and report her transaction to the DEX within a specified amount of time.

Before Alice can prepare her initialization transaction, she must generate a key known only to herself. From the key, Alice generates a “lock” and constructs an output script such that if someone can provide both Alice’s key and the pubkey for Bob’s specified address, they can spend the output. In practice, the key is simply a random 32-byte number, and the lock is its hash.

In addition, Alice constructs the output script with a second, alternative lock that allows her to spend the output herself, but only if the output remains unspent for a specified amount of time. Alice sets her timelock to 48 hours.

Alice broadcasts her initialization transaction to the Decred network. She informs the DEX of the transaction details, which the DEX relays to Bob. Alice does not reveal the key that she created.

A5: Bob inspects Alice's transaction and retrieves the lock. After the requisite number of confirmations, Bob prepares his initialization transaction. He uses Alice's lock here as well, and creates an output script satisfied by Alice’s key and the pubkey for Alice’s address.

Bob sets his timelock to 24 hours. Bob should also check that the timelock in Alice's initialization is set to 48 hours. If Alice’s timelock duration is set near or below Bob’s timelock duration, Alice could potentially spend the DCR output before Bob.

Bob broadcasts his initialization transaction to the Bitcoin network. He informs the DEX of the transaction details, and the DEX relays the information to Alice.

A6: Alice prepares a redemption transaction that spends the output from Bob’s initialization transaction to her own address. In order to spend the Bitcoin from Bob’s transaction, she needs to provide the key created in step 4.

Alice broadcasts her redemption transaction to the Bitcoin network. Though both the DEX and Bob are capable of monitoring for the transaction, it is expected that Alice informs the DEX server of the transaction details anyway. The DEX server will notify Bob of the details.

A7: Bob prepares his redemption transaction using the key gleaned from Alice’s redemption transaction and the output from Alice’s initialization transaction.

Bob broadcasts his redemption transaction to the Decred network, completing the atomic swap.

Case B: Multi-taker with partial fill

In case B, Alice is similarly trying to sell 3 DCR for 0.3 BTC, but the match found by the DEX is not perfect this time.

B1: Same as A1. Alice submits her signed order to the DEX.

B2: Bob places a market order for 0.1 BTC worth of DCR at market price. A new client, Carl, places an identical market order for 0.1 BTC worth of DCR.

B3: The DEX finds the match and informs all parties, providing Alice with Bob and Carl's addresses. The DEX cannot simply remove Alice’s order, because it is only partially filled. In this case, the DEX does not remove the order from the order book, instead just marking it partially filled and calculating the remaining quantity. The order is returned to the order book and is immediately able to match again.

B4: As the maker, Alice goes first again. She groups her matches from the epoch and creates two different keys, one for Bob and one for Carl. She sets her timelocks to 48 hours. Alice broadcasts her initialization transaction to the Decred network and informs the DEX about the transaction details, which the DEX relays to Bob and Carl.

B5 After waiting the requisite number of confirmations, Bob and Carl prepare their initialization transactions using the locks from Alice's transaction. They broadcast their transactions.

B6 and B7 follow naturally from case A, with Alice creating two redemption transactions, one for Bob and one for Carl. Bob and Carl then follow up with their own redemptions.

Community Conduct

By registering, clients agree to abide by the rules described here. These rules are designed to ensure that clients are acting in good faith and maintaining behaviors that contribute to a smooth DEX experience for humans.

Rules of Community Conduct

Rule 1: Every match must be fully settled

Swap transactions must be created at the correct times (see broadcast timeout).

In the event that the maker fails to start the atomic swap process with their initialization transaction, the taker will be notified that order execution is terminated due to failure of the taker to accept the order. The Maker's limit order will not go back on the order book, but they may be given the option to replace the order.

In the event that the taker fails to respond to the maker's initialization transaction, the maker will incur no violation.

Rule 2: An account's cancellation ratio must remain below the threshold

The cancellation ratio is the ratio of the count of cancelled orders to the count of completed orders. The cancellation threshold is set by the DEX operator. An order is considered completed when all matches have fully settled. An order is considered cancelled when a cancel order is matched to a standing limit order. The server may also cancel an order if the client's connection is dropped and the client fails to reconnect for more than 1 epoch duration. Cancellation of a partially filled order is counted as a full cancellation. The cancellation ratio is evaluated on a 25-order rolling window.

Rule 3: Transaction outputs must be properly sized

The swap output value must be sized to exactly the matched amount. The fee rate must be at least the minimum value set by the DEX. It is the client's responsibility to ensure that fees on a partial fill are not overpaid to a level that results in a violation of rules 1 or 3 when the remaining portion is matched.

Penalties

The primary penalty for breeches of conduct is a ban, which includes loss of trading privileges, forfeiture of registration fee, and immediate revocation of any unfilled orders.

Less drastic punitive measures such as a cool-down period may be considered for minor, first-time or infrequent conduct violations.

Data API

Trade history will be made available to both websocket and HTTP clients.

Exchange Administration

Operation of the DEX will require substantial administrative labor. High throughput and low latency networking and high performance hardware are expected requirements. Historical trade data should be archived for some reasonable amount of time, if not forever. Clients will expect near-perfect uptime and long-term operation.

Additionally, operators will need to manage exchange settings properly to keep markets liquid and to balance fees and settlement speed. That said, changes to exchange or asset variables will often entail server revocation of all existing orders on a market, so should be done as infrequently as possible.

Exchange Variables

variable relevant section units default
epoch duration Epoch-based Order Matching seconds 60
market buy buffer Market Buy Orders unitless ratio 1.25
registration fees Fees atoms 1e8 (1 DCR)
cancellation threshold Rule 2 unitless ratio 0.6

Per-asset Variables

variable units description
lot size atoms The minimum order quantity and the order quantity increment when an asset is the base asset.
rate step atoms The minimum price rate and the price rate increment when an asset is the quote asset.
fee rate atoms/byte The minimum fee rate for swap transactions.
minimum confirmations count The Minimum confirmations for backing UTXOs and swap transactions.

See also Exchange Variables.

...

References

[1] Teall, John L., Financial Trading and Investing, p. 336 (2013)

[2] Bitwise Presentation to the U.S. Securities and Exchange Commission (2019)

[3] Atomic Swaps

[4] The WebSocket Protocol

[5] Transport Layer Security 1.3

[6] JSON-RPC 2.0 Specification

About

The Decred Decentralized Exchange (DEX), powered by atomic-swaps.

Resources

Stars

Watchers

Forks

Packages

No packages published