Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
2 contributors

Users who have contributed to this file

@buck54321 @chappjc
1754 lines (1412 sloc) 62.1 KB

Decred DEX

This is the repository for the Decred Distributed Exchange (DEX), for which this document provides the DRAFT specification.

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 disincentivizes 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.

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.

Message Protocol

DEX messaging is JSON-formatted [6]. All messages, regardless of originating party, use a common top-level structure called a Message.

JSON Message object

field type description
type int message type
payload any the data being transmitted
route string the route identifier. requests and notifications only
id int > 0 the request ID. requests and responses only

There are three anticipated message types.

Message types

type id description
request 1 a request is typically an uninitiated message the seeks a response
response 2 a response to a request
notification 3 usually part of a data feed. requires no response

Example request

The payload for a request can be of any type.

{
	"type": 1,
	"id": 123,
	"route" "sendnum",
	"payload": 5
}

Response payload

The payload for a response has a structure that enables quick error checking.

field type description
result any the result. field is missing or null if an error was encountered
error string or null the error. field is null or missing if no error was encountered

Example response

{
	"type": 2,
	"id": 123,
	"payload": { "result": true }
}

Example notification

{
	"type": 3,
	"route": "notifynums"
	"payload": [1, 5, 3, 9]
}

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:images/lot-sizes.png

Every asset is assigned a unique integer ID that will be used to identify the asset in serialized structures. Whenever possible, the ID is the same as the BIP-0044 registered coin type index [7].

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: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 has two distinct minimum numbers of confirmations. The fundconf is the number of confirmations required for backing UTXOs. The swapconf is the number of confirmations 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 swapconfth confirmation.

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

Request route: config, originator: client

The config request payload can be null. The DEX will respond with its current configuration.

result

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
id int a unique per-asset ID
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)
swapconf int minimum confirmations for swap transactions
fundconf int minimum confirmations for backing UTXOs
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 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 ensure that an individual client cannot obtain a deterministic latency advantage over other clients when executing trades. 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: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 is the 64-bit integer corresponding to the little-endian byte order interpretation of the first 8 bytes of the hash. The hash is computed as

File: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 from the queue matches a standing limit order on the book, the match is assigned the price rate of the maker's order (the standing order's price rate).

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 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 wallets that support atomic swaps 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 not identify themselves with their pubkey directly. Instead, the account is identified by an account ID, which is the double Blake-256 hash of the client's pubkey, blake256(blake256(pubkey)), provided as a hex-encoded string in API messages.

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.

Request route: register, originator: client

payload

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

Registration serialization

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

DEX response

result

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 33 the server's public key
client pubkey 33 the client's public account key
timestamp 8 the server's UNIX timestamp
fee 8 registration fee (atoms)
address varies UTF-8 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.

Request route: notifyfee, originator: client

payload

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

result

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 swapconf 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.

Request route: connect, originator: client

payload

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.

result

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.

Request route: orderbook, originator: client

payload

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.

result

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 order book will be received from the DEX as a stream of updates. These updates use the notification message type, so omit an id attribute.

Notification route: remove_order, originator: DEX

payload

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

Notification route: add_limit & add_market, originator: DEX

payload

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.

Notification route: match_data, originator: DEX

payload

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.

Request route: unsub_orderbook, originator: client

payload

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: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: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, swapconf, is an asset variable 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: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
pubkeys [string] array of hex-encoded pubkeys which satisfy the pubkey script
sigs [string] array of signatures of Blake-256 hashes of the serialized UTXO. serialization described below
redeem string hex-encoded redeem script for P2SH. empty for P2PKH

In order to enable multi-signature support, more than one pubkey can be submitted. If more than one pubkey is submitted, there should be a signature for each one. The data is signed with the private key(s) corresponding to the pubkeys. The pubkeys themselves must correspond with addresses in the UTXO's pubkey script (or corresponding redeem script).

UTXO serialization

field size (bytes) description
tx hash asset-dependent 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 4 the base asset ID
quote asset 4 the quote asset ID
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 Blake-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.

Request route: limit, originator: client

payload

field type description
accountid string client's account ID
timestamp int UNIX 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

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
quantity 8 quantity to buy or sell (atoms)
address varies client's receiving address
rate 8 price rate
time in force 1 0 for standing, 1 for immediate

result

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

Market Order

A market order is an order to buy or sell an asset at the best available market price. The request payload 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.

Request route: market, originator: client

payload

field type description
accountid string client's account ID
timestamp int UNIX 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. 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

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)
address varies client's receiving address

result

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 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.

Request route: cancel, originator: client

payload

field type description
accountid string client's account ID
timestamp int UNIX 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

Cancel order serialization

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

result

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

Match negotiation

Swap negotiation details will be relayed through the DEX with a series of notifications or progress reports. Both the DEX and the clients will need to serialize and sign the notification data. The originator includes their signature with the request, while the recipient will return an acknowledgement, or a list of acknowledgements, as the result of their response payload.

Acknowledgement

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

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. The maker is the first to act, so after sending their acknowledgement, they should broadcast their initialization transaction and inform the server with an init notification (described after).

Request route: match, originator: DEX

payload (array)

field type description
orderid string order ID
matchid string 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)
timestamp int server's UNIX timestamp
address string the counterparty's receiving address
sig string DEX's hex-encoded signature of the serialized notification data. serialization described below

Match serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 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
timestamp 8 server's UNIX timestamp
address varies UTF-8 encoded receiving address for the match

The client will respond with a list of signed match acknowledgements.

After a client broadcasts their initialization transaction, they are expected to report the transaction details to the server for verification and relay to the matching party.

Request route: init, originator: client

payload

field type description
orderid string the order ID
matchid string the matchid, retrieved from the match notification
txid string the hex-encoded transaction ID
vout int the output index
timestamp int client's UNIX timestamp
contract string hex-encoded swap redeem script
sig string client signature of the serialized notification. serialization described below

Init serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the ID assigned to this match
tx hash asset-dependent the transaction hash
vout 4 the output index
timestamp 8 the client's UNIX timestamp
contract asset-dependent swap redeem script

The DEX will respond with an acknowledgement.

The DEX will send each client a notification when the counterparty has broadcast their initialization transaction. When the taker receives the audit notification, they will audit the contract and broadcast their own initialization. When the maker receives the audit notification, they will audit the contract and issue their redemption.

Request route: audit, originator: DEX

payload

field type description
orderid string the order ID
matchid string the match ID
timestamp int server's UNIX timestamp
contract string hex-encoded swap redeem script
sig string DEX's signature of the serialized notification. serialization described below

Audit serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
timestamp 8 server's UNIX timestamp
contract asset-dependent swap redeem script

The client responds with an acknowledgement.

When a client has redeemed their contract, they will notify the server.

Request route: redeem, originator: client

payload

field type description
orderid string the order ID
matchid string the match ID
txid string the hex-encoded transaction ID
vout int the output index
timestamp int client's UNIX timestamp
sig string client signature of the serialized notification. serialization described below

Redeem serialization

result

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
tx hash asset-dependent the transaction hash
vout 4 the output index
timestamp 8 the client's UNIX timestamp

The DEX responds with an acknowledgement.

The DEX informs the taker when the maker has redeemed.

Request route: redemption, originator: DEX

payload

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
tx hash asset-dependent the transaction hash
vout 4 the output index
timestamp int server's UNIX timestamp
sig string DEX's signature of the serialized notification. serialization described below

Redemption serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID
tx hash asset-dependent the transaction hash
vout 4 the output index
timestamp 8 server's UNIX timestamp

The client will respond with an acknowledgement.

The taker will get the key from the maker's redemption and broadcast their own redemption transaction.

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 order book in any form.

Request route: revoke_match, originator: DEX

payload

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

Revocation serialization

field size (bytes) description
orderid 32 the order ID
matchid 32 the match ID

The client will respond with an acknowledgement.

Trade Suspension

There are a number of scenarios where the server may suspend operations, intentionally or not. During trade suspension, standing limit orders 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.

Request route: suspension, originator: DEX

payload

field type description
epoch int the epoch in which the suspension will start
persist bool whether standing limit orders will persist through the suspension

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 swap contract 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 contract 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 and sends the lock, which the DEX relays to Bob. Alice does not reveal the key that she created.

A5: Bob inspects Alice's transaction. After the requisite number of confirmations, Bob prepares his initialization transaction. He uses Alice's lock here as well, and creates a swap contract 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 maker 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 breaches 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 a non-trivial amount of administrative labor. Clients will expect near-perfect uptime and long-term operation.

Operators must 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 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.
utxo confirmations count The Minimum confirmations for backing UTXOs
swap confirmations count The Minimum confirmations before acting on a swap transaction

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

[7] BIP-0044 Registered Coins

You can’t perform that action at this time.