Published on

Understanding What Side of the Trade a 0x Order Refers to

Authors

0x is a protocol that defines various components that can be created to roll out a decentralized exchange (AKA DEX). The idea behind it is that any number of new tokens can be released over time. Trying to create a DEX to cater for all of them would be impossible. Instead, rather define a protocol that lets anyone expose any currency pairs they want using the prescribed protocol.

Companies/entities that implement this protocol and manage an offchain order book are known as relayers. Conforming to the 0x protocol allows anyone to interact with a relayer's order book. Unlike many DEX's, 0x does not require the order book to be stored onchain.

The general process is someone wishing to sell ERC20/ERC721 tokens creates the order, signs it using their private key and has that order stored on a relayer's offchain order book. When there is a match for that order the matched order is executed on chain.

0x provides a number of tools and smart contracts to facilitate the order creation and execution process. But 0x does not handle matching and management of the order book for you.

0x defines what is called the Standard Relayer API or SRA for short. As mentioned earlier a relayer is an entity that manages and hosts an offchain order book. This company chooses to support one or more ERC20 or/and ERC721 pairs using the 0x protocol. Implementing this API involves exposing a REST service as described here and exposing information over web sockets as described here.

After reading through the spec one thing that is not clear is how do you indicate what side an order is on? I.e. is it a BUY ( AKA BID - which is usually green) or SELL (AKA ASK - which is usually red) order?

To better understand this lets look at an example of a 0x order:

{
  "order": {
    "makerAddress": "0x9e56625509c2f60af937f23b7b532600390e8c8b",
    "takerAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
    "feeRecipientAddress": "0xb046140686d052fff581f63f8136cce132e857da",
    "senderAddress": "0xa2b31dacf30a9c50ca473337c01d8a201ae33e32",
    "makerAssetAmount": "10000000000000000",
    "takerAssetAmount": "20000000000000000",
    "makerFee": "100000000000000",
    "takerFee": "200000000000000",
    "expirationTimeSeconds": "1532560590",
    "salt": "1532559225",
    "makerAssetData": "0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498",
    "takerAssetData": "0x02571792000000000000000000000000371b13d97f4bf77d724e78c16b7dc74099f40e840000000000000000000000000000000000000000000000000000000000000063",
    "exchangeAddress": "0x12459c951127e0c374ff9105dda097662a027093",
    "signature": "0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33"
  },
  "metaData": {}
}

To determine whether this is a buy or sell order depends on:

  • Order Book: What order book this is being posted to or worded differently what currency pair this is for.
    • So for example if the above is a ZRX/ETH order then in this pair the base is ZRX and the quote is ETH.
  • makerAssetData and takerAssetData: In a 0x order the makeAssetData and takerAssetData are encoded pieces of data which contain the following details:
    • The 0x ERC20 or ERC721 proxy contract address which is used to interact with the given token's smart contract.
    • The token's smart contract address.

Asset data can be decoded using assetDataUtils and the decodeERC20AssetData(assetData) method or decodeERC721AssetData(assetData) method for ERC20 and ERC721 respectively. These return an object that contains the proxy address and token address of one side of the pair.

Using the token address we can get the ticker for the taker and maker asset data respectively. In the above if this order is for the ZRX/ETH order book then the base is ZRX and the quote is ETH.

For this pair there are 2 possible permutations:

  • The maker asset data is for ZRX while the taker asset data is for ETH.
    • In this case it is an ASK or SELL order.
  • The taker asset data is for ZRX while the maker asset data is for ETH.
    • In this case it is an ASK or SELL order.

Simple pseudocode for this would be:

(taker == base) && (maker == quote) -> BID
(maker == base) && (taker == quote) -> ASK

0x has plenty of documentation but this also makes it hard to find information. This process to determine the side to an order is one of these instances.

After some digging the above approach to determining the side for the order was found in the example SRA in the 0x starter project here where an order list is taken and split up into two separate lists for bids and asks:

const bidOrders = orders.filter((order) => {
  return (
    order.takerAssetData === baseAssetData &&
    order.makerAssetData === quoteAssetData &&
    order.expirationTimeSeconds.isGreaterThan(getCurrentUnixTimestampSec())
  )
})
const askOrders = orders.filter((order) => {
  return (
    order.takerAssetData === quoteAssetData &&
    order.makerAssetData === baseAssetData &&
    order.expirationTimeSeconds.isGreaterThan(getCurrentUnixTimestampSec())
  )
})