ZenDex is a true decentralised exchange, with no operator or fees.
ZenDex stores orders as utxos that it locks to itself. In this manner, we avoid having a shared state, allowing great parallelism.
When an order is made, the order parameters are hashed together. ZenDex mints a single token with that hash as it’s subidentifier (the ‘order asset’), and locks that to itself.
When an order is taken or cancelled, that token is destroyed. In the case of a partial fill, ZenDex will create a new order with reduced quantities of the underlying and order total. The previous order is still destroyed.
When cancelling or taking an order, one must supply all of the order parameters directly to ZenDex in the messageBody, because ZenDex does not store this information, and only possesses a hash of the order.
Order books can be constructed by folding over the blockchain, and looking for transactions involving ZenDex.
ZenDex accepts three commands: "Make"
, "Cancel"
, and "Take"
.
Use the command "Make"
. You must sign with a public key  if the sender is Anonymous
or Contract contractID
, then the transaction will fail.
The messageBody must consist of a dictionary which includes the following fields:
Field Name  Type  Description 

 The identifier of the underlying asset 

 The amount of the underlying asset used to make the order 

 The identifier of the pair asset 

 The total amount of the pair being ordered 

 The public key of the order maker 
The amount of the underlying made available to ZenDex in the transaction must be equal to "UnderlyingAmount"
. The public key used to sign the transaction must be the same as "MakerPubKey"
.
Use the command "Cancel"
. You must sign with the public key that was used to create the order.
The messageBody must consist of a dictionary which includes the following fields:
Field Name  Type  Description 

 The identifier of the underlying asset of the order 

 The amount of the underlying asset used to make the order 

 The identifier of the pair asset in the order 

 The total amount of the pair that was ordered 

 The public key of the order maker 
The transaction must place the order asset in ZenDex’s contract wallet, as well as a sufficient quantity of the underlying.
Use the command "Take"
.
The messageBody must consist of a dictionary which includes the following fields:
Field Name  Type  Description 

 The identifier of the underlying asset of the order 

 The amount of the underlying asset used to make the order 

 The identifier of the pair asset in the order 

 The total amount of the pair that was ordered in the order being taken 

 The public key of the order maker 

 The amount of the underlying to pay out 

 The amount of the pair supplied 
The transaction must place the order asset being taken and a sufficient amount of the underlying in ZenDex’s contract wallet, and must lock an amount α of the order’s pair asset to the contract, where
Orders are expressed in terms of underlying amount and pair amount to allow for rational price ratios  eg. a trade of 5α for 7β, or 13β for 11γ. This is not easily expressed as a ‘price per’ with only integer arithmetic. The payout for a partial fill should, assuming arbitrarily divisible assets, be calculated as
However, since we do not have arbitrarily divisible assets, we denote orders in the smallest unit of each asset and compute the floor, so that
The underlying amount, order total, and payment amount are all 64 bit unsigned integers. Version 0 ZF* contracts lack integer representations larger than this, and so we are tasked with implementing doubleword arithmetic in order to calculate the payoff. In order to avoid the complexity and potential for error in implementing doubleword division, we instead ask the user to provide the payoff, and validate that it is correct. Validating that a user’s RequestedPayout
is correct is simpler than computing the payout, and requires only doubleword multiplication and comparison, both relatively simple compared to doubleword division.
Note that
Each parameter is hashed separately and then aggregated to a single hash with updateHash
[[ [[ underlyingAsset ]] ; [[ underlyingAmount ]] ; [[ pairAsset ]] ; [[ orderTotal ]] ; [[ makerPubKey ]] ]]