This commit is contained in:
Greg Hysz
2020-11-28 00:51:50 -08:00
committed by GitHub
parent 012fff46f6
commit 3c1ab889dd
94 changed files with 4147 additions and 552 deletions

53
docs/basics/addresses.rst Normal file
View File

@@ -0,0 +1,53 @@
###############################
Addresses
###############################
.. note::
This page is auto-generated. See the `contract-addresses <https://github.com/0xProject/protocol/blob/development/packages/contract-addresses/addresses.json>`_ package for an exhaustive list of contracts across all networks.
Exchange V4
===================
.. csv-table::
exchangeProxy, `0xdef1c0ded9bec7f1a1670819833240f027b25eff <https://etherscan.io/address//0xdef1c0ded9bec7f1a1670819833240f027b25eff>`_
exchangeProxyAllowanceTarget, `0xf740b67da229f2f10bcbd38a7979992fcc71b8eb <https://etherscan.io/address//0xf740b67da229f2f10bcbd38a7979992fcc71b8eb>`_
exchangeProxyFlashWallet, `0x22f9dcf4647084d6c31b2765f6910cd85c178c18 <https://etherscan.io/address//0x22f9dcf4647084d6c31b2765f6910cd85c178c18>`_
exchangeProxyGovernor, `0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e <https://etherscan.io/address//0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e>`_
exchangeProxyLiquidityProviderSandbox, `0xdb971b18ea5075734cec1241732cc1b41031dfc9 <https://etherscan.io/address//0xdb971b18ea5075734cec1241732cc1b41031dfc9>`_
exchangeProxyTransformerDeployer, `0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb <https://etherscan.io/address//0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb>`_
Transformers
===================
.. csv-table::
wethTransformer, `0x68c0bb685099dc7cb5c5ce2b26185945b357383e <https://etherscan.io/address//0x68c0bb685099dc7cb5c5ce2b26185945b357383e>`_
payTakerTransformer, `0x49b9df2c58491764cf40cb052dd4243df63622c7 <https://etherscan.io/address//0x49b9df2c58491764cf40cb052dd4243df63622c7>`_
fillQuoteTransformer, `0xfbfb26935f15db6a319a43db5085245a6df1e408 <https://etherscan.io/address//0xfbfb26935f15db6a319a43db5085245a6df1e408>`_
affiliateFeeTransformer, `0x4581b59a05ba373b9f67676f66bdb5fcd67e7567 <https://etherscan.io/address//0x4581b59a05ba373b9f67676f66bdb5fcd67e7567>`_
ZRX / Staking
===================
.. csv-table::
staking, `0x2a17c35ff147b32f13f19f2e311446eeb02503f3 <https://etherscan.io/address//0x2a17c35ff147b32f13f19f2e311446eeb02503f3>`_
stakingProxy, `0xa26e80e7dea86279c6d778d702cc413e6cffa777 <https://etherscan.io/address//0xa26e80e7dea86279c6d778d702cc413e6cffa777>`_
zrxToken, `0xe41d2489571d322189246dafa5ebde1f4699f498 <https://etherscan.io/address//0xe41d2489571d322189246dafa5ebde1f4699f498>`_
zrxVault, `0xba7f8b5fb1b19c1211c5d49550fcd149177a5eaf <https://etherscan.io/address//0xba7f8b5fb1b19c1211c5d49550fcd149177a5eaf>`_
Miscellaneous
===================
.. csv-table::
devUtils, `0x74134cf88b21383713e096a5ecf59e297dc7f547 <https://etherscan.io/address//0x74134cf88b21383713e096a5ecf59e297dc7f547>`_
etherToken, `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 <https://etherscan.io/address//0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2>`_
erc20BridgeSampler, `0xd8c38704c9937ea3312de29f824b4ad3450a5e61 <https://etherscan.io/address//0xd8c38704c9937ea3312de29f824b4ad3450a5e61>`_

View File

@@ -5,8 +5,8 @@ Allowances
.. _Allowance Target Address: https://github.com/0xProject/protocol/blob/development/packages/contract-addresses/addresses.json#L40
After the official release, allowances will be set directly on the Exchange V4 Proxy contract.
Presently, while we are in beta, allowances should be set on the `Allowance Target Address`_.
Presently, while we are in beta, allowances should be set on the `Allowance Target <./addresses.html#exchange-v4>`_.
The motivation for eliminating the separate Allowance Target in the official release is
to reduce transaction costs. Depending on the operational overhead for our integrators,
we may support allowances on both the Exchange V4 & the Allowance Target after the officual relase.
we may support allowances on both the Exchange V4 & the Allowance Target after the official release, which is slated for January, 2021.

View File

@@ -1,3 +1,368 @@
###############################
Events
###############################
###############################
This is a complete catalogue of 0x events emitted when interacting with the Exchange Proxy system of contracts. The diagram below
illustrates how events are emitted when trading through the Exchange Proxy.
.. warning::
There are pending upgrades that impact these events. Please see the `Releases <../additional/releases.html>`_ page for more details.
.. image:: ../_static/img/events.png
:scale: 42%
.. note::
This catalogue does not include events emitted by tokens or other exchanges, like Uniswap. It also only lists 0x V3 events
that are emitted during a Fill; for an extensive list of V3 events, see the `V3 Spec <https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md#events>`_.
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| **Event** | **Description** | **Emitted By** |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `Deployed`_ | Emitted by the `Transformer Deployer <../architecture/transformer_deployer.html>`_ when a `Transformer <../architecture/transformers.html>`_ is deployed. | TransformerDeployer |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `ERC20BridgeTransfer`_ | Emitted when a trade occurs. | FlashWallet |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `Fill`_ | Emitted by Exchange V3 when an order is filled. | Exchange V3 |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `Killed`_ | Emitted by the `Transformer Deployer <../architecture/transformer_deployer.html>`_ when a `Transformer <../architecture/transformers.html>`_ is killed. | TransformerDeployer |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `MetaTransactionExecuted`_ | Emitted when a meta-transaction is executed on the Exchange Proxy. | ExchangeProxy |
| | Note that this differs from meta-transactions that are executed on Exchange V3. | |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `Migrated`_ | Emitted when `ExchangeProxy.migrate()` is called. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `ProtocolFeeUnfunded`_ | Emitted when an order is skipped due to a lack of funds to pay the 0x Protocol fee. | FlashWallet |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `ProxyFunctionUpdated`_ | Emitted when a function is upgraded via `extend()` or `rollback()` | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `QuoteSignerUpdated`_ | Emitted when `ExchangeProxy.setQuoteSigner()` is called. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `TransformedERC20`_ | Emitted when an `ERC20 Transformation <../advanced/erc20_transformations.html>`_ completes. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `TransformerDeployerUpdated`_ | Emitted when the Transformer Deployer is upgraded. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `TransformerMetadata`_ | A general, customizable event emitted that can be emitted by transformers as-needed. | FlashWallet |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| **Events in upcoming releases** |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `LimitOrderFilled`_ | Emitted when a `V4 Limit Order <./orders.html#limit-orders>`_ is filled. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `RfqOrderFilled`_ | Emitted when a `V4 RFQ Order <./orders.html#rfq-orders>`_ is filled. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `OrderCancelled`_ | Emitted when a V4 Limit or RFQ Order is cancelled. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `PairCancelledLimitOrders`_ | Emitted when a Market Pair is cancelled for Limit Orders (see `cancelPairLimitOrders <./functions.html#cancelpairlimitorders>`_). | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `PairCancelledRfqOrders`_ | Emitted when a Market Pair is cancelled for RFQ Orders (see `cancelPairRfqOrders <./functions.html#cancelpairrfqorders>`_). | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `RfqOrderOriginsAllowed`_ | Emitted when a tx.origin is added/removed for RFQ, via `registerAllowedRfqOrigins <./functions.html#registerallowedrfqorigins>`_ | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
| `LiquidityProviderSwap`_ | Emitted when a `PLP <../advanced/plp.html>`_ executes a swap. | ExchangeProxy |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
Deployed
--------
.. code-block:: solidity
/// @dev Emitted when a contract is deployed via `deploy()`.
/// @param deployedAddress The address of the deployed contract.
/// @param nonce The deployment nonce.
/// @param sender The caller of `deploy()`.
event Deployed(address deployedAddress, uint256 nonce, address sender);
ERC20BridgeTransfer
-------------------
.. code-block:: solidity
/// @dev Emitted when a trade occurs.
/// @param inputToken The token the bridge is converting from.
/// @param outputToken The token the bridge is converting to.
/// @param inputTokenAmount Amount of input token.
/// @param outputTokenAmount Amount of output token.
/// @param from The bridge address, indicating the underlying source of the fill.
/// @param to The `to` address, currrently `address(this)`
event ERC20BridgeTransfer(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
address from,
address to
);
Fill
----
.. code-block:: solidity
event Fill(
address indexed makerAddress, // Address that created the order.
address indexed feeRecipientAddress, // Address that received fees.
bytes makerAssetData, // Encoded data specific to makerAsset.
bytes takerAssetData, // Encoded data specific to takerAsset.
bytes makerFeeAssetData, // Encoded data specific to makerFeeAsset.
bytes takerFeeAssetData, // Encoded data specific to takerFeeAsset.
bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getTypedDataHash).
address takerAddress, // Address that filled the order.
address senderAddress, // Address that called the Exchange contract (msg.sender).
uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker.
uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker.
uint256 makerFeePaid, // Amount of makerFeeAssetData paid to feeRecipient by maker.
uint256 takerFeePaid, // Amount of takerFeeAssetData paid to feeRecipient by taker.
uint256 protocolFeePaid // Amount of eth or weth paid to the staking contract.
);
Killed
------
.. code-block:: solidity
/// @dev Emitted when a contract is killed via `kill()`.
/// @param target The address of the contract being killed..
/// @param sender The caller of `kill()`.
event Killed(address target, address sender);
LimitOrderFilled
----------------
.. code-block:: solidity
/// @dev Emitted whenever a `LimitOrder` is filled.
/// @param orderHash The canonical hash of the order.
/// @param maker The maker of the order.
/// @param taker The taker of the order.
/// @param feeRecipient Fee recipient of the order.
/// @param takerTokenFilledAmount How much taker token was filled.
/// @param makerTokenFilledAmount How much maker token was filled.
/// @param protocolFeePaid How much protocol fee was paid.
/// @param pool The fee pool associated with this order.
event LimitOrderFilled(
bytes32 orderHash,
address maker,
address taker,
address feeRecipient,
address makerToken,
address takerToken,
uint128 takerTokenFilledAmount,
uint128 makerTokenFilledAmount,
uint128 takerTokenFeeFilledAmount,
uint256 protocolFeePaid,
bytes32 pool
);
MetaTransactionExecuted
-----------------------
.. code-block:: solidity
/// @dev Emitted whenever a meta-transaction is executed via
/// `executeMetaTransaction()` or `executeMetaTransactions()`.
/// @param hash The meta-transaction hash.
/// @param selector The selector of the function being executed.
/// @param signer Who to execute the meta-transaction on behalf of.
/// @param sender Who executed the meta-transaction.
event MetaTransactionExecuted(
bytes32 hash,
bytes4 indexed selector,
address signer,
address sender
);
LiquidityProviderSwap
---------------------
.. code-block:: solidity
event LiquidityProviderSwap(
address inputToken,
address outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
address provider,
address recipient
);
Migrated
--------
.. code-block:: solidity
/// @dev Emitted when `migrate()` is called.
/// @param caller The caller of `migrate()`.
/// @param migrator The migration contract.
/// @param newOwner The address of the new owner.
event Migrated(address caller, address migrator, address newOwner);
OrderCancelled
--------------
.. code-block:: solidity
/// @dev Emitted whenever a limit or RFQ order is cancelled.
/// @param orderHash The canonical hash of the order.
/// @param maker The order maker.
event OrderCancelled(
bytes32 orderHash,
address maker
);
PairCancelledLimitOrders
------------------------
.. code-block:: solidity
/// @dev Emitted whenever limit or RFQ orders are cancelled by pair by a maker.
/// @param maker The maker of the order.
/// @param makerToken The maker token in a pair for the orders cancelled.
/// @param takerToken The taker token in a pair for the orders cancelled.
/// @param minValidSalt The new minimum valid salt an order with this pair must
/// have.
event PairCancelledLimitOrders(
address maker,
address makerToken,
address takerToken,
uint256 minValidSalt
);
PairCancelledRfqOrders
------------------------
.. code-block:: solidity
/// @dev Emitted whenever limit or RFQ orders are cancelled by pair by a maker.
/// @param maker The maker of the order.
/// @param makerToken The maker token in a pair for the orders cancelled.
/// @param takerToken The taker token in a pair for the orders cancelled.
/// @param minValidSalt The new minimum valid salt an order with this pair must
/// have.
event PairCancelledRfqOrders(
address maker,
address makerToken,
address takerToken,
uint256 minValidSalt
);
ProtocolFeeUnfunded
-------------------
.. code-block:: solidity
/// @dev Emitted when a trade is skipped due to a lack of funds
/// to pay the 0x Protocol fee.
/// @param orderHash The hash of the order that was skipped.
event ProtocolFeeUnfunded(bytes32 orderHash);
ProxyFunctionUpdated
--------------------
.. code-block:: solidity
/// @dev A function implementation was updated via `extend()` or `rollback()`.
/// @param selector The function selector.
/// @param oldImpl The implementation contract address being replaced.
/// @param newImpl The replacement implementation contract address.
event ProxyFunctionUpdated(bytes4 indexed selector, address oldImpl, address newImpl);
QuoteSignerUpdated
------------------
.. code-block:: solidity
/// @dev Raised when `setQuoteSigner()` is called.
/// @param quoteSigner The new quote signer.
event QuoteSignerUpdated(address quoteSigner);
RfqOrderFilled
--------------
.. code-block:: solidity
/// @dev Emitted whenever an `RfqOrder` is filled.
/// @param orderHash The canonical hash of the order.
/// @param maker The maker of the order.
/// @param taker The taker of the order.
/// @param takerTokenFilledAmount How much taker token was filled.
/// @param makerTokenFilledAmount How much maker token was filled.
/// @param pool The fee pool associated with this order.
event RfqOrderFilled(
bytes32 orderHash,
address maker,
address taker,
address makerToken,
address takerToken,
uint128 takerTokenFilledAmount,
uint128 makerTokenFilledAmount,
bytes32 pool
);
RfqOrderOriginsAllowed
-------------------------
.. code-block:: solidity
/// @dev Emitted when new addresses are allowed or disallowed to fill
/// orders with a given txOrigin.
/// @param origin The address doing the allowing.
/// @param addrs The address being allowed/disallowed.
/// @param allowed Indicates whether the address should be allowed.
event RfqOrderOriginsAllowed(
address origin,
address[] addrs,
bool allowed
);
TransformedERC20
----------------
.. code-block:: solidity
/// @dev Raised upon a successful `transformERC20`.
/// @param taker The taker (caller) address.
/// @param inputToken The token being provided by the taker.
/// If `0xeee...`, ETH is implied and should be provided with the call.`
/// @param outputToken The token to be acquired by the taker.
/// `0xeee...` implies ETH.
/// @param inputTokenAmount The amount of `inputToken` to take from the taker.
/// @param outputTokenAmount The amount of `outputToken` received by the taker.
event TransformedERC20(
address indexed taker,
address inputToken,
address outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount
);
TransformerDeployerUpdated
--------------------------
.. code-block:: solidity
/// @dev Raised when `setTransformerDeployer()` is called.
/// @param transformerDeployer The new deployer address.
event TransformerDeployerUpdated(address transformerDeployer);
TransformerMetadata
-------------------
.. code-block:: solidity
/// @dev A transformer that just emits an event with an arbitrary byte payload.
event TransformerMetadata(
bytes32 callDataHash,
address sender,
address taker,
bytes data
);

View File

@@ -1,3 +1,584 @@
###############################
Functions
###############################
Basic Functionality
###############################
Below is a catalog of basic Exchange functionality. For more advanced usage, like meta-transactions and dex aggregation, see the Advanced section.
+---------------------------------+--------------------------------------------------------------------------+
| **Limit Orders** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `fillLimitOrder`_ | Fills a Limit Order up to the amount requested. |
+---------------------------------+--------------------------------------------------------------------------+
| `fillOrKillLimitOrder`_ | Fills exactly the amount requested or reverts. |
+---------------------------------+--------------------------------------------------------------------------+
| `cancelLimitOrder`_ | Cancels an order so that it can no longer be filled. |
+---------------------------------+--------------------------------------------------------------------------+
| `batchCancelLimitOrders`_ | A batch call to `cancelLimitOrder`. |
+---------------------------------+--------------------------------------------------------------------------+
| `cancelPairLimitOrders`_ | Cancels Limit orders in a specific market pair. |
| | Ex: Cancel all Limit Orders selling WETH for USDC. |
+---------------------------------+--------------------------------------------------------------------------+
| `batchCancelLimitPairOrders`_ | A batch call to `cancelLimitPairOrders`. |
+---------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderInfo`_ | Returns the state of a given order. |
+---------------------------------+--------------------------------------------------------------------------+
| `getLimitOrderHash`_ | Returns the EIP-712 hash for an order. |
+---------------------------------+--------------------------------------------------------------------------+
| **RFQ Orders** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `fillRfqOrder`_ | These are analogous to the above LimitOrder functions. |
+---------------------------------+ |
| `fillOrKillRfqOrder`_ | |
+---------------------------------+ |
| `cancelRfqOrder`_ | |
+---------------------------------+ |
| `batchCancelRfqOrders`_ | |
+---------------------------------+ |
| `cancelPairRfqOrders`_ | |
+---------------------------------+ |
| `batchCancelPairRfqOrders`_ | |
+---------------------------------+ |
| `getRfqOrderInfo`_ | |
+---------------------------------+ |
| `getRfqOrderHash`_ | |
+---------------------------------+--------------------------------------------------------------------------+
| `registerAllowedRfqOrigins`_ | Register tx.origin addresses that are allowed to fill an RFQ order. |
+---------------------------------+--------------------------------------------------------------------------+
| **Protocol Fees** | **Overview** |
+---------------------------------+--------------------------------------------------------------------------+
| `getProtocolFeeMultiplier`_ | Takers of limit orders pay a protocol fee of `Multiplier * tx.gasprice`. |
| | This returns the `Multiplier`. |
+---------------------------------+--------------------------------------------------------------------------+
| `transferProtocolFeesForPools`_ | Transfers protocol fees from escrow to the 0x Staking System. |
| | This should be called near the end of each epoch. |
+---------------------------------+--------------------------------------------------------------------------+
Limit Orders
============
These are the basic functions for using a `Limit Order <../basics/orders.html#limit-orders>`_.
fillLimitOrder
--------------
Limit orders can be filled with the ``fillLimitOrder()`` or ``fillOrKillLimitOrder()`` functions on the Exchange Proxy. The address calling these function will be considered the "taker" of the order.
``fillLimitOrder()`` fills a single limit order for **up to** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillLimitOrder(
// The order
LimitOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
If the trade is successful a `LimitOrderFilled <../basics/events.html#limitorderfilled>`_ will be emitted. This function reverts under any of the following conditions:
- The order is fully filled: taker amount sold greater or equal to ``order.takerAmount``.
- The order has expired.
- The order was cancelled.
- The market pair (Ex, ``WETH/USDT``) was cancelled (``order.salt`` is less than the value passed to ``cancelPairLimitOrders``.
- Either the maker or taker has an insufficient allowance/balance.
- The order's ``taker`` field is non-zero and does not match the actual taker. This is ``msg.sender``, unless used with `meta-transactions <../advanced/mtx.rst>`_ in which case it is the signer.
- The order's ``sender`` field is non-zero and does not match ``msg.sender``.
- The maker's signature is invalid.
- The order's ``takerTokenFeeAmount`` is non-zero but the fee cannot be paid due to insufficient allowance/balance.
- Not enough ETH was sent with the transaction to cover the `Protocol Fee <../basics/protocol_fees.html>`_.
fillOrKillLimitOrder
--------------------
``fillOrKillLimitOrder()`` fills a single limit order for **exactly** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillOrKillLimitOrder(
// The order
LimitOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 makerTokenFillAmount);
If the trade is successful a `LimitOrderFilled <../basics/events.html#limitorderfilled>`_ will be emitted. This function reverts under any of the conditions outlined above for ``fillLimitOrder``. Additionally, it will revert if the amount filled is less than ``takerTokenFillAmount``.
cancelLimitOrder
----------------
This function cancels a single limit order created by the caller:
.. code-block:: solidity
function cancelLimitOrder(
// The order
LimitOrder calldata order
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
batchCancelLimitOrders
----------------------
This function cancels multiple limit orders created by the caller:
.. code-block:: solidity
function batchCancelLimitOrders(
// The orders
LimitOrder[] calldata orders
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
cancelPairLimitOrders
---------------------
This function cancels all limit orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
.. code-block:: solidity
function cancelPairRfqOrders(
address makerToken,
address takerToken,
uint256 salt;
)
external;
This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event, or reverts in one of the following scenarios:
- ``msg.sender != order.maker``
- The ``salt`` parameter is ≤ to a previous ``salt``.
batchCancelLimitPairOrders
--------------------------
This function performs multiple ``cancelLimitPairOrders()`` at once. Each respective index across arrays is equivalent to a single call.
.. code-block:: solidity
function batchCancelLimitPairOrders(
address[] makerTokens,
address[] takerTokens,
uint256[] salts;
)
external;
This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
getLimitOrderInfo
-----------------
The Exchange Proxy exposes a function ``getLimitOrderInfo()`` to query information about a limit order, such as its fillable state and how much it has been filled by.
.. code-block:: solidity
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
struct OrderInfo {
// The order hash.
bytes32 orderHash;
// Current state of the order.
OrderStatus status;
// How much taker token has been filled in the order.
uint128 takerTokenFilledAmount;
}
function getLimitOrderInfo(
// The order
LimitOrder calldata order
)
external
view
returns (OrderInfo memory orderInfo);
getLimitOrderHash
-----------------
The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md>`_ standard. In solidity, the hash is computed as:
.. code-block:: solidity
/// @dev Get the canonical hash of a limit order.
/// @param order The limit order.
/// @return orderHash The order hash.
function getLimitOrderHash(LibNativeOrder.LimitOrder calldata order)
external
view
returns (bytes32 orderHash);
The simplest way to generate an order hash is by calling this function, ex:
.. code-block:: solidity
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
The hash can be manually generated using the following code:
.. code-block:: solidity
bytes32 orderHash = keccak256(abi.encodePacked(
'\x19\x01',
// The domain separator.
keccak256(abi.encode(
// The EIP712 domain separator type hash.
keccak256(abi.encodePacked(
'EIP712Domain(',
'string name,',
'string version,',
'uint256 chainId,',
'address verifyingContract)'
)),
// The EIP712 domain separator values.
'ZeroEx',
'1.0.0',
1, // For mainnet
0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
)),
// The struct hash.
keccak256(abi.encode(
// The EIP712 type hash.
keccak256(abi.encodePacked(
'LimitOrder(',
'address makerToken,',
'address takerToken,',
'uint128 makerAmount,',
'uint128 takerAmount,',
'uint128 takerTokenFeeAmount,',
'address taker,',
'address maker,',
'address sender,',
'address feeRecipient,',
'bytes32 pool,',
'uint64 expiry,',
'uint256 salt)'
)),
// The struct values.
order.makerToken,
order.takerToken,
order.makerAmount,
order.takerAmount,
order.takerTokenFeeAmount,
order.maker,
order.taker,
order.sender,
order.feeRecipient,
order.pool,
order.expiry,
order.salt
))
));
RFQ Orders
==========
These are the basic functions for using an `RFQ Order <../basics/orders.html#rfq-orders>`_.
fillRfqOrder
------------
RFQ orders can be filled with the ``fillRfqOrder()`` or ``fillOrKillRfqOrder()`` functions on the Exchange Proxy. The address calling this function will be considered the "taker" of the order.
``fillRfqOrder()`` fills a single RFQ order for **up to** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillRfqOrder(
// The order
RfqOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
If the trade is successful a `RfqOrderFilled <../basics/events.html#rfqorderfilled>`_ will be emitted. This function reverts under any of the following conditions:
- The order is fully filled: taker amount sold greater or equal to ``order.takerAmount``.
- The order has expired.
- The order was cancelled.
- The market pair (Ex, ``WETH/USDT``) was cancelled (``order.salt`` is less than the value passed to ``cancelPairLimitOrders``.
- Either the maker or taker has an insufficient allowance/balance.
- The order's ``taker`` field is non-zero and does not match the actual taker. This is ``msg.sender``, unless used with `meta-transactions <../advanced/mtx.rst>`_ in which case it is the signer.
- The order's ``origin`` field is non-zero and does not match ``tx.origin`` or a valid origin (see `registerAllowedRfqOrigins <../basics/functions.html#id11>`_).
- The maker's signature is invalid.
fillOrKillRfqOrder
------------------
``fillOrKillRfqOrder()`` fills a single RFQ order for **exactly** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillOrKillRfqOrder(
// The order
RfqOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 makerTokenFillAmount);
If the trade is successful a `RfqOrderFilled <../basics/events.html#rfqorderfilled>`_ will be emitted. This function reverts under any of the conditions outlined above for ``fillRfqOrder``. Additionally, it will revert if the amount filled is less than ``takerTokenFillAmount``.
cancelRfqOrder
--------------
Similar to limit orders, RFQ orders can be cancelled on-chain through a variety of functions, which can only be called by the order's maker.
``cancelRfqOrder()`` cancels a single RFQ order created by the caller:
.. code-block:: solidity
function cancelRfqOrder(
// The order
RfqOrder calldata order
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
batchCancelRfqOrders
--------------------
This function cancels multiple RFQ orders created by the caller:
.. code-block:: solidity
function batchCancelRfqOrders(
// The orders
RfqOrder[] calldata orders
)
external;
This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
cancelPairRfqOrders
-------------------
This function cancels all RFQ orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
.. code-block:: solidity
function cancelPairRfqOrders(
address makerToken,
address takerToken,
uint256 salt;
)
external;
This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event, or reverts in one of the following scenarios:
- ``msg.sender != order.maker``
- The ``salt`` parameter is ≤ to a previous ``salt``.
batchCancelPairRfqOrders
------------------------
``batchCancelPairRfqOrders()`` performs multiple ``cancelPairRfqOrders()`` at once. Each respective index across arrays is equivalent to a single call.
.. code-block:: solidity
function batchCancelPairRfqOrders(
address[] makerTokens,
address[] takerTokens,
uint256[] salts;
)
external;
This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
getRfqOrderInfo
---------------
The Exchange Proxy exposes a function ``getRfqOrderInfo()`` to query information about an RFQ order, such as its fillable state and how much it has been filled by.
.. code-block:: solidity
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
struct OrderInfo {
// The order hash.
bytes32 orderHash;
// Current state of the order.
OrderStatus status;
// How much taker token has been filled in the order.
uint128 takerTokenFilledAmount;
}
function getRfqOrderInfo(
// The order
RfqOrder calldata order
)
external
view
returns (OrderInfo memory orderInfo);
getRfqOrderHash
---------------
The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md>`_ standard. In solidity, the hash is computed using:
.. code-block:: solidity
/// @dev Get the canonical hash of an RFQ order.
/// @param order The RFQ order.
/// @return orderHash The order hash.
function getRfqOrderHash(LibNativeOrder.RfqOrder calldata order)
external
view
returns (bytes32 orderHash);
The simplest way to generate an order hash is by calling this function, ex:
.. code-block:: solidity
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getRfqOrderHash(order);
The hash can be manually generated using the following code:
.. code-block:: solidity
bytes32 orderHash = keccak256(abi.encodePacked(
'\x19\x01',
// The domain separator.
keccak256(abi.encode(
// The EIP712 domain separator type hash.
keccak256(abi.encodePacked(
'EIP712Domain(',
'string name,',
'string version,',
'uint256 chainId,',
'address verifyingContract)'
)),
// The EIP712 domain separator values.
'ZeroEx',
'1.0.0',
1, // For mainnet
0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
)),
// The struct hash.
keccak256(abi.encode(
// The EIP712 type hash.
keccak256(abi.encodePacked(
'RfqOrder(',
'address makerToken,',
'address takerToken,',
'uint128 makerAmount,',
'uint128 takerAmount,',
'address maker,'
'address taker,'
'address txOrigin,'
'bytes32 pool,',
'uint64 expiry,',
'uint256 salt)'
)),
// The struct values.
order.makerToken,
order.takerToken,
order.makerAmount,
order.takerAmount,
order.maker,
order.taker,
order.txOrigin,
order.pool,
order.expiry,
order.salt
))
));
registerAllowedRfqOrigins
-------------------------
The RFQ order includes a ``txOrigin`` field, which a maker can use to restrict which EOA's can submit the Ethereum transaction that fills their order. There are two ways a maker can use this field.
1. Set to the EOA that will submit the transaction (ex, the Taker or a Meta-Transaction relayer).
2. Set to an EOA owned by the maker, which acts as a registry key to lookup valid tx origins.
Looking at the 2nd use case, a maker can register valid tx origins using this function. They would then set ``order.origin`` to be the address they used to call ``registerAllowedRfqOrigins``.
.. code-block:: solidity
/// @dev Mark what tx.origin addresses are allowed to fill an order that
/// specifies the message sender as its txOrigin.
/// @param origins An array of origin addresses to update.
/// @param allowed True to register, false to unregister.
function registerAllowedRfqOrigins(address[] memory origins, bool allowed)
external;
This function emits a `RfqOrderOriginsAllowed <../basics/events.html#rfqorderoriginsallowed>`_ event.
Protocol Fees
=============
There is a fixed protocol fee paid by the Taker each time they fill a `Limit Order <orders.html#limit-orders>`_. Learn more in the `Protocol Fees Section <./protocol_fees.html>`_. Also check out our research in the `Tokenomics Section <../tokenomics/research.html>`_.
getProtocolFeeMultiplier
------------------------
Takers of limit orders pay a protocol fee of Multiplier * tx.gasprice. This returns the Multiplier.
.. code-block:: solidity
/// @dev Get the protocol fee multiplier. This should be multiplied by the
/// gas price to arrive at the required protocol fee to fill a native order.
/// @return multiplier The protocol fee multiplier.
function getProtocolFeeMultiplier()
external
view
returns (uint32 multiplier);
transferProtocolFeesForPools
----------------------------
This function transfers protocol fees from `Fee Collectors <../architecture/fee_collectors.html>`_ to the `Staking System <../tokenomics/staking.html>`_.
.. code-block:: solidity
/// @dev Transfers protocol fees from the `FeeCollector` pools into
/// the staking contract.
/// @param poolIds Staking pool IDs
function transferProtocolFeesForPools(bytes32[] calldata poolIds)
external;

View File

@@ -11,113 +11,88 @@ An order is a message passed into the 0x Protocol to facilitate an ERC20->ERC20
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 ``fillOrder()`` function on the Exchange Proxy.
Structure
---------
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. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``takerTokenFeeAmount`` | ``uint128`` | Amount of takerToken paid by the taker to the feeRecipient. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``maker`` | ``address`` | The address of the maker, and signer, of this order. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``sender`` | ``address`` | Allowed address to directly call ``fillLimitOrder()`` (``msg.sender``). |
| | | This is distinct from ``taker`` in meta-transactions. |
| | | Set to zero to allow any caller. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``feeRecipient`` | ``address`` | Recipient of maker token or taker token fees (if non-zero). |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``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. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order's hash. |
+--------------------------+-------------+-----------------------------------------------------------------------------+
+-------------------------+-------------+------------------------------------------------------------------------------------------+
| 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] |
+-------------------------+-------------+------------------------------------------------------------------------------------------+
Hashing limit orders
--------------------
RFQ Orders
==========
The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md>`_ standard. In solidity, the hash is computed as:
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.
.. code-block:: solidity
Some notable differences from regular limit orders are:
bytes32 orderHash = keccak256(abi.encodePacked(
'\x19\x01',
// The domain separator.
keccak256(abi.encode(
// The EIP712 domain separator type hash.
keccak256(abi.encodePacked(
'EIP712Domain(',
'string name,',
'string version,',
'uint256 chainId,',
'address verifyingContract)'
)),
// The EIP712 domain separator values.
'ZeroEx',
'1.0.0',
1, // For mainnet
0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
)),
// The struct hash.
keccak256(abi.encode(
// The EIP712 type hash.
keccak256(abi.encodePacked(
'LimitOrder(',
'address makerToken,',
'address takerToken,',
'uint128 makerAmount,',
'uint128 takerAmount,',
'uint128 takerTokenFeeAmount,',
'address taker,',
'address maker,',
'address sender,',
'address feeRecipient,',
'bytes32 pool,',
'uint64 expiry,',
'uint256 salt)'
)),
// The struct values.
order.makerToken,
order.takerToken,
order.makerAmount,
order.takerAmount,
order.takerTokenFeeAmount,
order.maker,
order.taker,
order.sender,
order.feeRecipient,
order.pool,
order.expiry,
order.salt
))
));
* There is no ``sender`` field.
* There is no taker fee.
* Must restrict ``transaction.origin`` via the `order.txOrigin` field.
* There is currently no protocol fee paid when filling an RFQ order.
Alternatively, the Exchange Proxy contract can be used to retrieve the hash given an order.
The ``RFQOrder`` struct has the following fields:
.. code-block:: solidity
+-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
| 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 <./functions.html#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] |
+-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
Signing limit orders
--------------------
How To Sign
==============
Limit orders must be signed by the maker of the order. This signature must be passed into the fill function by the taker in order to fill the order.
Both Limit & RFQ orders must be signed by the `maker`. This signature is needed to fill an order, see `Basic Functionality <./functions.rst>`_.
The protocol accepts signatures defined by the following struct:
@@ -137,10 +112,13 @@ There are two types of signatures supported: ``EIP712`` and ``EthSign``.
In both cases, the ``@0x/protocol-utils`` package simplifies generating these signatures.
.. note::
The Protocol Utils package is still under development. This message will be removed once the package is published. - 11/24/2020.
.. code-block:: javascript
const utils = require('@0x/protocol-utils');
const order = new utils.LimitOrder({
const order = new utils.LimitOrder({ // or utils.RfqOrder
makerToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
... // Other fields
@@ -156,369 +134,7 @@ In both cases, the ``@0x/protocol-utils`` package simplifies generating these si
makerAddress,
);
Filling limit orders
--------------------
Limit orders can be filled with the ``fillLimitOrder()`` or ``fillOrKillLimitOrder()`` functions on the Exchange Proxy. The address calling these function will be considered the "taker" of the order.
``fillLimitOrder()`` fills a single limit order for **up to** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillLimitOrder(
// The order
LimitOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
``fillOrKillLimitOrder()`` fills a single limit order for **exactly** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillOrKillLimitOrder(
// The order
LimitOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
payable
// How much maker token from the order the taker received.
returns (uint128 makerTokenFillAmount);
Cancelling a limit order
------------------------
Because there is no way to un-sign an order that has been distributed, limit orders must be cancelled on-chain through one of several functions. They can only be called by the order's maker.
``cancelLimitOrder()`` cancels a single limit order created by the caller:
.. code-block:: solidity
function cancelLimitOrder(
// The order
LimitOrder calldata order
)
external;
``batchCancelLimitOrders()`` cancels multiple limit orders created by the caller:
.. code-block:: solidity
function batchCancelLimitOrders(
// The orders
LimitOrder[] calldata orders
)
external;
``cancelLimitPairOrders()`` will cancel all limit orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
.. code-block:: solidity
function cancelLimitPairLimitOrders(
address makerToken,
address takerToken,
uint256 salt;
)
external;
``batchCancelLimitPairOrders()`` performs multiple ``cancelLimitPairOrders()`` at once. Each respective index across arrays is equivalent to a single call.
.. code-block:: solidity
function batchCancelLimitPairOrders(
address[] makerTokens,
address[] takerTokens,
uint256[] salts;
)
external;
Getting the status of a limit order
-----------------------------------
The Exchange Proxy exposes a function ``getLimitOrderInfo()`` to query information about a limit order, such as its fillable state and how much it has been filled by.
.. code-block:: solidity
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
struct OrderInfo {
// The order hash.
bytes32 orderHash;
// Current state of the order.
OrderStatus status;
// How much taker token has been filled in the order.
uint128 takerTokenFilledAmount;
}
function getLimitOrderInfo(
// The order
LimitOrder calldata order
)
external
view
returns (OrderInfo memory orderInfo);
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:
* The only fill restrictions that can be placed on an RFQ order is on the ``tx.origin`` and ``taker`` of the transaction.
* There are no taker token fees.
Structure
----------
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. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``maker`` | ``address`` | The address of the maker, and signer, of this order. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``txOrigin`` | ``address`` | The allowed address of the EOA that submitted the Ethereum transaction. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``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. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. |
+-----------------+-------------+-----------------------------------------------------------------------------+
| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order's hash. |
+-----------------+-------------+-----------------------------------------------------------------------------+
Hashing RFQ orders
------------------
The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md>`_ standard. In solidity, the hash is computed as:
.. code-block:: solidity
bytes32 orderHash = keccak256(abi.encodePacked(
'\x19\x01',
// The domain separator.
keccak256(abi.encode(
// The EIP712 domain separator type hash.
keccak256(abi.encodePacked(
'EIP712Domain(',
'string name,',
'string version,',
'uint256 chainId,',
'address verifyingContract)'
)),
// The EIP712 domain separator values.
'ZeroEx',
'1.0.0',
1, // For mainnet
0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
)),
// The struct hash.
keccak256(abi.encode(
// The EIP712 type hash.
keccak256(abi.encodePacked(
'RfqOrder(',
'address makerToken,',
'address takerToken,',
'uint128 makerAmount,',
'uint128 takerAmount,',
'address maker,'
'address taker,'
'address txOrigin,'
'bytes32 pool,',
'uint64 expiry,',
'uint256 salt)'
)),
// The struct values.
order.makerToken,
order.takerToken,
order.makerAmount,
order.takerAmount,
order.maker,
order.taker,
order.txOrigin,
order.pool,
order.expiry,
order.salt
))
));
Alternatively, the Exchange Proxy contract can be used to retrieve the hash given an order.
.. code-block:: solidity
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
Signing RFQ orders
------------------
RFQ orders must be signed by the maker of the order. This signature must be passed into the fill function by the taker in order to fill the order.
The protocol accepts signatures defined by the following struct:
.. code-block:: solidity
struct {
uint8 v; // Signature data.
bytes32 r; // Signature data.
bytes32 s; // Signature data.
}
The ``@0x/protocol-utils`` node package simplifies the process of creating a valid signature object.
.. code-block:: javascript
const utils = require('@0x/protocol-utils');
const order = new utils.RfqOrder({
makerToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
... // Other fields
});
// Generate an EthSign signature
const signature = await order.ethSignHashWithProviderAsync(
web3.currentProvider,
makerAddress,
);
Filling RFQ Orders
------------------
RFQ orders can be filled with the ``fillRfqOrder()`` or ``fillOrKillRfqOrder()`` functions on the Exchange Proxy. The address calling this function will be considered the "taker" of the order.
``fillRfqOrder()`` fills a single RFQ order for **up to** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillRfqOrder(
// The order
RfqOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
// How much maker token from the order the taker received.
returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
``fillOrKillRfqOrder()`` fills a single RFQ order for **exactly** ``takerTokenFillAmount``:
.. code-block:: solidity
function fillOrKillRfqOrder(
// The order
RfqOrder calldata order,
// The signature
Signature calldata signature,
// How much taker token to fill the order with
uint128 takerTokenFillAmount
)
external
// How much maker token from the order the taker received.
returns (uint128 makerTokenFillAmount);
Cancelling an RFQ order
-----------------------
Similar to limit orders, RFQ orders can be cancelled on-chain through a variety of functions, which can only be called by the order's maker.
``cancelRfqOrder()`` cancels a single RFQ order created by the caller:
.. code-block:: solidity
function cancelRfqOrder(
// The order
RfqOrder calldata order
)
external;
``batchCancelRfqOrders()`` cancels multiple RFQ orders created by the caller:
.. code-block:: solidity
function batchCancelRfqOrders(
// The orders
RfqOrder[] calldata orders
)
external;
``cancelPairRfqOrders()`` will cancel all RFQ orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
.. code-block:: solidity
function cancelPairRfqOrders(
address makerToken,
address takerToken,
uint256 salt;
)
external;
``batchCancelPairRfqOrders()`` performs multiple ``cancelPairRfqOrders()`` at once. Each respective index across arrays is equivalent to a single call.
.. code-block:: solidity
function batchCancelPairRfqOrders(
address[] makerTokens,
address[] takerTokens,
uint256[] salts;
)
external;
Getting the status of an RFQ order
----------------------------------
The Exchange Proxy exposes a function ``getRfqOrderInfo()`` to query information about an RFQ order, such as its fillable state and how much it has been filled by.
.. code-block:: solidity
enum OrderStatus {
INVALID,
FILLABLE,
FILLED,
CANCELLED,
EXPIRED
}
struct OrderInfo {
// The order hash.
bytes32 orderHash;
// Current state of the order.
OrderStatus status;
// How much taker token has been filled in the order.
uint128 takerTokenFilledAmount;
}
function getRfqOrderInfo(
// The order
RfqOrder calldata order
)
external
view
returns (OrderInfo memory orderInfo);
The Orderbook
=======================
Orders are shared through a decentralized and permissionless network, called `0x Mesh <https://0x.org/mesh>`_. The simplest way to post and discover orders is through `0x API <https://0x.org/api>`_. See `this guide <https://0x.org/docs/guides/market-making-on-0x>`_ tailored for Market Makers.

View File

@@ -0,0 +1,18 @@
###############################
Protocol Fees
###############################
An ETH protocol fee is paid by the Taker each time a `Limit Order <./orders.html#limit-orders>`_ is `filled <./functions.html>`_.
The fee is proportional to the gas cost of filling an order and scales linearly with gas price. The cost is currently ``70k * tx.gasprice``.
Every 10 days, these fees are aggregated and distributed to the makers as a liquidity reward: the reward is proportional to the maker's collected fees and staked ZRX relative to other makers.
To learn more about protocol fees and liquidity incentives, see the `Official Spec <https://github.com/0xProject/0x-protocol-specification/blob/master/staking/staking-specification.md>`_.
.. note::
`RFQ Orders <./orders.html#rfq-orders>`_ are introduced in Exchange V4, and there is currently no protocol fee for filling this type of order.
The existing fee mechanics work well for limit orders, where arb bots pay to compete for liquidity; however, it does not translate well to RFQ where makers are matched with a specific taker.
We are researching fee models that could be used for RFQ and will keep the community up-to-date on our `Forum <https://forum.0x.org/>`_.
.. warning::
In Exchange V3, protocol fees could be paid in ETH or WETH. As of V4, they can only be paid in ETH.