Loopring’s Uni-Directional Order Model (UDOM)
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)
amountS: is the amount of
tokenSto pay out (sell) to the counterpart
tokenS: represents the type of token/asset to pay out
amountB: is the amount of
tokenBto get (buy) from the counterpart
tokenB: 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 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 calculation accurate.
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.
buyNoMoreThanTokenB == true, the actual fill amounts for the order would be:
120/11=10.91 ABC sold
120 XYZ received
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
Assuming there is a ETH/USD market in a traditional exchange .
- If a user wants to sell 10 ETH at price 300 USD/ETH. This order can 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 expressed as
Order(10, ETH, 3000, USD, true).
- If a user wants to buy 10 ETH at price 300 USD/ETH, This order can 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 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 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 converted both ways. A user may get confused when he/she provided a price but the system displays a slightly different price after the conversion.