Files
protocol/docs/basics/orders.md
2021-05-20 10:57:31 -07:00

8.9 KiB

title
title
Orders

An order is a message passed into the 0x Protocol to facilitate an ERC20->ERC20 trade. There are currently two types of orders in 0x V4: Limit and RFQ.

::: {.note} ::: {.title} Note :::

0x Orders currently support the exchange of ERC20 Tokens. Other asset classes, like ERC721, will be added in the future based on community demand. :::

Limit Orders

Limit orders are the standard 0x Order, which encodes a possible trade between a maker and taker at a fixed price. These orders are typically distributed via Mesh/SRA (open orderbook) or OTC, and can be filled through the functions on the Exchange Proxy.

The LimitOrder struct has the following fields:


Field Type Description

makerToken address The ERC20 token the maker is selling and the maker is selling to the taker. [required]

takerToken address The ERC20 token the taker is selling and the taker is selling to the maker. [required]

makerAmount uint128 The amount of makerToken being sold by the maker. [required]

takerAmount uint128 The amount of takerToken being sold by the taker. [required]

takerTokenFeeAmount uint128 Amount of takerToken paid by the taker to the feeRecipient. [optional; default 0]

maker address The address of the maker, and signer, of this order. [required]

taker address Allowed taker address. Set to zero to allow any taker. [optional; default 0]

sender address Allowed address to call fillLimitOrder() (msg.sender). This is the same as taker, expect when using meta-transactions. Set to zero to allow any caller. [optional; default 0]

feeRecipient address Recipient of maker token or taker token fees (if non-zero). [optional; default 0]

pool bytes32 The staking pool to attribute the 0x protocol fee from this order. Set to zero to attribute to the default pool, not owned by anyone. [optional; default 0]

expiry uint64 The Unix timestamp in seconds when this order expires. [required]

salt uint256 Arbitrary number to enforce uniqueness of the order hash. [required]


RFQ Orders

RFQ orders are a stripped down version of standard limit orders, supporting fewer fields and a leaner settlement process. These orders are fielded just-in-time, directly from market makers, during the construction of a swap quote on 0x API, and can be filled through the fillRfqOrder() function on the Exchange Proxy.

Some notable differences from regular limit orders are:

  • There is no sender field.
  • There is no taker fee.
  • Must restrict transaction.origin via the [order.txOrigin]{.title-ref} field.
  • There is currently no protocol fee paid when filling an RFQ order.

The RFQOrder struct has the following fields:


Field Type Description

makerToken address The ERC20 token the maker is selling and the maker is selling to the taker. [required]

takerToken address The ERC20 token the taker is selling and the taker is selling to the maker. [required]

makerAmount uint128 The amount of makerToken being sold by the maker. [required]

takerAmount uint128 The amount of takerToken being sold by the taker. [required]

maker address The address of the maker, and signer, of this order. [required]

taker address Allowed taker address. Set to zero to allow any taker. [optional; default 0]

txOrigin address The allowed address of the EOA that submitted the Ethereum transaction. This must be set. Multiple addresses are supported via registerAllowedRfqOrigins. [required]

pool bytes32 The staking pool to attribute the 0x protocol fee from this order. Set to zero to attribute to the default pool, not owned by anyone. [optional; default 0]

expiry uint64 The Unix timestamp in seconds when this order expires. [required]

salt uint256 Arbitrary number to enforce uniqueness of the order hash. [required]


How To Sign

Both Limit & RFQ orders must be signed by the [maker]{.title-ref} or a registered order signer (registerAllowedOrderSigner). This signature is needed to fill an order, see Basic Functionality.

The protocol accepts signatures defined by the following struct:

struct {
     uint8 signatureType; // Either 2 or 3
     uint8 v; // Signature data.
     bytes32 r; // Signature data.
     bytes32 s; // Signature data.
}

There are two types of signatures supported: EIP712 and EthSign.

  • The EIP712 signature type is best for web frontends that present an order to be signed through Metamask in a human-readable format. It relies on the eth_signTypedData JSON-RPC method exposed by MetaMask. This signature has the signatureType of 2.
  • The EthSign signature is best for use with headless providers, such as when using a geth node. This relies on the eth_sign JSON-RPC method common to all nodes. This signature has the signatureType of 3.

In both cases, the @0x/protocol-utils package simplifies generating these signatures.

::: {.note} ::: {.title} Note :::

The Protocol Utils package is still under development. This message will be removed once the package is published. - 11/24/2020. :::

const utils = require('@0x/protocol-utils');
const order = new utils.LimitOrder({ // or utils.RfqOrder
    makerToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
    takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
    ... // Other fields
});
// Generate an EthSign signature with a provider.
const signature = await order.getSignatureWithProviderAsync(
    web3.currentProvider,
);
// Generate an EthSign signature with a private key.
const signature = await order.getSignatureWithKey(
    '0x123456...', // Maker's 32-byte private key, in hex.
);
// Generate an EIP712 signature with a provider (e.g., metamask).
const signature = await order.getSignatureWithProviderAsync(
    web3.currentProvider,
    utils.SignatureType.EIP712,
);
// Generate an EIP712 signature with a private key.
const signature = await order.getSignatureWithKey(
    '0x123456...', // Maker's 32-byte private key, in hex.
    utils.SignatureType.EIP712,
);

The Orderbook

Orders are shared through a decentralized and permissionless network, called 0x Mesh. The simplest way to post and discover orders is through 0x API. See this guide tailored for Market Makers.

Orders are usually represented as a JSON object off-chain. Below is a table represention and example of how orders should be formatted off-chain.

JSON representation of RFQ Orders

A RFQOrder should be serialized to JSON as following:

interface RfqOrderJson {
    "maker": string,
    "taker": string,
    "makerToken": string,
    "takerToken": string,
    "makerAmount": string,
    "takerAmount": string,
    "txOrigin": string,
    "pool": string,
    "expiry": number,
    "salt": string,
    "chainId": number,             // Ethereum Chain Id where the transaction is submitted.
    "verifyingContract": string,   // Address of the contract where the transaction should be sent.
    "signature": {
        "signatureType": number,
        "v": number,
        "s": string,
        "r": string,
    }
}