Loopring Protocol introduced an innovative way of modeling orders, which I called the Unidirectional Order Model, or UDOM for short. As you can notice in our whitepaper, UDOM makes it easier to express order-rings in a clean and concise way. UDOM is not new though, as in 2014 when I founded Coinport Cryptocurrency Exchange, this model was coded into our match-engine which is open-sourced ever since. It might have been discussed, in other terms, by other researchers and engineers as well.

UDOM expresses orders as token-exchange requests, instead of buys(bids) and sells(asks). An order in a simplified version of UDOM can be denoted as a tuple of 5 elements:

Order(amountS, tokenS, amountB, tokenB, buyNoMoreThanTokenB)

where:

amountS : is the amount of tokenS to pay out (sell) to the counterpart

: is the amount of to pay out (sell) to the counterpart tokenS : represents the type of token/asset to payout

: represents the type of token/asset to payout amountB : is the amount of tokenB to get (buy) from the counterpart

: is the amount of to get (buy) from the counterpart tokenB : represents the type of token/asset to get (buy)

: represents the type of token/asset to get (buy) buyNoMoreThanTokenB : determine the stop criteria for a complete-fill, which will be explained later.

So where is the price? Well, UDOM doesn’t include a price (which must be a floating-point number by nature), instead, it uses a term rate which is expressed as amountS/amountB . The rate is not a floating-point number but an expression, it will only be evaluated with other unsigned integer numbers on demand, to keep all intermediate results as unsigned integers. This will make the calculation accurate.

About “buyNoMoreThanTokenB”

UDOM’s buyNoMoreThanTokenB parameter determines when an order is considered as completely filled. Take Order(12, ABC, 120, XYZ) (without the buyNoMoreThanTokenB parameter) as an example, this order expresses selling 12 token ABC for 120 token XYZ (rate = 0.1 ABC/XYZ). If there is a very large order that would like to pay 12 XYZ per ABC bought, these two orders can match each other. The problem is how much to match.

If we ignore fees, Loopring uses the middle rate as the fill rate — in this case, the fill rate would be 0.90909 ABC/XYZ.

In case buyNoMoreThanTokenB == true , the actual fill amounts for the order would be:

120/11=10.91 ABC sold

120 XYZ received

In case buyNoMoreThanTokenB == false , the actual fill amounts for the order would be:

ABC sold : 12

12 x 11 = 132 XYZ received

As you can notice: buyNoMoreThanTokenB applies a cap on either amountS or amountB .

Examples

Assuming there is an ETH/USD market in a traditional exchange.

If a user wants to sell 10 ETH at price 300 USD/ETH. This order can be expressed as Order(10, ETH, 3000, USD, false) . If a user wants to sell ETH at price 300 USD/ETH to get 3000 USD. This order can be expressed as Order(10, ETH, 3000, USD, true) . If a user wants to buy 10 ETH at price 300 USD/ETH, This order can be expressed as Order(3000, USD, 10, ETH, true) . If a user wants to spend 3000 USD to buy as many ETH as possible at price 300 USD/ETH, This order can be expressed as Order(3000, USD, 10, ETH, false) .

Traditional buy-sell modeling can express the 1st and the 3rd order, but not the other two.

UDOM’s Challenges

UDOM orders need to be translated into buy-sell orders back and forth so UI can display orders in an intuitive way for end-users.

Price and rate also need to convert both ways. A user may get confused when he/she provided a price but the system displays a slightly different price after the conversion.