Compare commits
2 Commits
feat/Multi
...
wip/markdo
Author | SHA1 | Date | |
---|---|---|---|
|
7f7d587974 | ||
|
7886d913fa |
46
docs/additional/audits.md
Normal file
46
docs/additional/audits.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: Audits
|
||||
---
|
||||
|
||||
Below are links to our third-party audit reports.
|
||||
|
||||
+---------+------------------------------------------------------------+
|
||||
| **Re | **Reports** |
|
||||
| lease** | |
|
||||
+---------+------------------------------------------------------------+
|
||||
| E | - [Consensys Diligence |
|
||||
| xchange | (December 2020)](https |
|
||||
| V4 | ://consensys.net/diligence/audits/2020/12/0x-exchange-v4/) |
|
||||
+---------+------------------------------------------------------------+
|
||||
| E | - [Trail of |
|
||||
| xchange | Bits](http://zeips.0x.org.s3-website. |
|
||||
| V3 | us-east-2.amazonaws.com/audits/56/trail-of-bits/audit.pdf) |
|
||||
| | - [Consensys Diligence |
|
||||
| | (Exchange)](https |
|
||||
| | ://diligence.consensys.net/audits/2019/09/0x-v3-exchange/) |
|
||||
| | - [Consensys Diligence |
|
||||
| | (Staking)](http |
|
||||
| | s://diligence.consensys.net/audits/2019/10/0x-v3-staking/) |
|
||||
+---------+------------------------------------------------------------+
|
||||
| E | - [First](https://docs.google.com/doc |
|
||||
| xchange | ument/d/1jYv6V21MfCSwCS5fxD6ZyaLWGzkpRSUO0lZpST94XsA/edit) |
|
||||
| V2.1 | - [Consensys |
|
||||
| | Diligence |
|
||||
| | ](https://github.com/ConsenSys/0x_audit_report_2018-07-23) |
|
||||
+---------+------------------------------------------------------------+
|
||||
| M | - [Consensys |
|
||||
| ultiAss | Dilige |
|
||||
| etProxy | nce](https://github.com/ConsenSys/0x-audit-report-2018-12) |
|
||||
+---------+------------------------------------------------------------+
|
||||
| ERC11 | - [Consensys |
|
||||
| 55Proxy | Dilige |
|
||||
| | nce](https://github.com/ConsenSys/0x-audit-report-2019-05) |
|
||||
+---------+------------------------------------------------------------+
|
||||
| S | - No third-party audit. |
|
||||
| taticCa | |
|
||||
| llProxy | |
|
||||
+---------+------------------------------------------------------------+
|
||||
| ER | - No third-party audit. |
|
||||
| C20Brid | |
|
||||
| geProxy | |
|
||||
+---------+------------------------------------------------------------+
|
252
docs/additional/bounties.md
Normal file
252
docs/additional/bounties.md
Normal file
@@ -0,0 +1,252 @@
|
||||
---
|
||||
title: Bounties
|
||||
---
|
||||
|
||||
We run an ongoing bug bounty for the 0x Protocol smart contracts! The
|
||||
program is open to anyone and rewards up to **\$100,000 for critical
|
||||
exploits**. The scope and disclosure instructions are below.
|
||||
|
||||
# Rewards
|
||||
|
||||
The severity of reported vulnerabilities will be graded according to the
|
||||
[CVSS](https://www.first.org/cvss/) (Common Vulnerability Scoring
|
||||
Standard). The following table will serve as a guideline for reward
|
||||
decisions:
|
||||
|
||||
---------------------------- ---------------------
|
||||
**Exploit Score** **Reward**
|
||||
|
||||
Critical (CVSS 9.0 - 10.0) \$10,000 - \$100,000
|
||||
|
||||
High (CVSS 7.0 - 8.9) \$2,500 - \$10,000
|
||||
|
||||
Medium (CVSS 4.0 - 6.9) \$1,000 - \$2,500
|
||||
|
||||
Low (CVSS 0.0 - 3.9) \$0 - \$1,000
|
||||
---------------------------- ---------------------
|
||||
|
||||
Please note that any rewards will ultimately be awarded at the
|
||||
discretion of ZeroEx Intl. All rewards will be paid out in ZRX.
|
||||
|
||||
# Areas of Interest
|
||||
|
||||
+----------+-----------------------------------------------------------+
|
||||
| **Area** | **Examples** |
|
||||
+----------+-----------------------------------------------------------+
|
||||
| Loss of | - A user loses funds in a way that they did not |
|
||||
| funds | explicitly authorize (e.g an account is able to gain |
|
||||
| | access to an `AssetProxy` and drain user funds). |
|
||||
| | - A user authorized a transaction or trade but spends |
|
||||
| | more assets than normally expected (e.g an order is |
|
||||
| | allowed to be over-filled). |
|
||||
+----------+-----------------------------------------------------------+
|
||||
| Un | - A user is able to update the state of a contract such |
|
||||
| intended | that it is no longer useable (e.g permanently lock a |
|
||||
| contract | mutex). |
|
||||
| state | - Any assets get unexpectedly \"stuck\" in a contract |
|
||||
| | with regular use of the contract\'s public methods. |
|
||||
| | - An action taken in the staking contracts is applied |
|
||||
| | to an incorrect epoch. |
|
||||
+----------+-----------------------------------------------------------+
|
||||
| B | - The `ZeroExGovernor` is allowed to bypass the |
|
||||
| ypassing | timelock for transactions where it is not explicitly |
|
||||
| time | allowed to do so. |
|
||||
| locks | - A user is allowed to bypass the `ZeroExGovernor`. |
|
||||
+----------+-----------------------------------------------------------+
|
||||
| I | - Overflows or underflow result in unexpected behavior. |
|
||||
| ncorrect | - The staking reward payouts are incorrect. |
|
||||
| math | |
|
||||
+----------+-----------------------------------------------------------+
|
||||
|
||||
# Scope
|
||||
|
||||
The following contracts are in scope of the bug bounty. Please note that
|
||||
any bugs already reported are considered out of scope. See the
|
||||
[Audits](./audits.html) page for 3rd party security reports.
|
||||
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| * | **Contracts** | **Commit Hash** |
|
||||
| * | | |
|
||||
| R | | |
|
||||
| e | | |
|
||||
| l | | |
|
||||
| e | | |
|
||||
| a | | |
|
||||
| s | | |
|
||||
| e | | |
|
||||
| * | | |
|
||||
| * | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - Documentation at | [72 |
|
||||
| x | <ht | a74e7c66](https:// |
|
||||
| c | tps://0xprotocol.readthedocs.io/en/latest/> | github.com/0xProje |
|
||||
| h | - [ZeroEx.sol | ct/protocol/tree/7 |
|
||||
| a | ](https://github.com/0xProject/protocol/blo | 2a74e7c66e27da02dd |
|
||||
| n | b/72a74e7c66e27da02dd9f4ce604ad057c740c304/ | 9f4ce604ad057c740c |
|
||||
| g | contracts/zero-ex/contracts/src/ZeroEx.sol) | 304/contracts/zero |
|
||||
| e | - [ZeroExOptimized.sol](https:/ | -ex/contracts/src) |
|
||||
| V | /github.com/0xProject/protocol/blob/72a74e7 | |
|
||||
| 4 | c66e27da02dd9f4ce604ad057c740c304/contracts | |
|
||||
| | /zero-ex/contracts/src/ZeroExOptimized.sol) | |
|
||||
| | - [external/\*.s | |
|
||||
| | ol](https://github.com/0xProject/protocol/t | |
|
||||
| | ree/72a74e7c66e27da02dd9f4ce604ad057c740c30 | |
|
||||
| | 4/contracts/zero-ex/contracts/src/external) | |
|
||||
| | - [features/\*\*.s | |
|
||||
| | ol](https://github.com/0xProject/protocol/t | |
|
||||
| | ree/72a74e7c66e27da02dd9f4ce604ad057c740c30 | |
|
||||
| | 4/contracts/zero-ex/contracts/src/features) | |
|
||||
| | - [fixins/\* | |
|
||||
| | .sol](https://github.com/0xProject/protocol | |
|
||||
| | /tree/72a74e7c66e27da02dd9f4ce604ad057c740c | |
|
||||
| | 304/contracts/zero-ex/contracts/src/fixins) | |
|
||||
| | - [migrations/\*.sol | |
|
||||
| | ](https://github.com/0xProject/protocol/tre | |
|
||||
| | e/72a74e7c66e27da02dd9f4ce604ad057c740c304/ | |
|
||||
| | contracts/zero-ex/contracts/src/migrations) | |
|
||||
| | - [storage/\*. | |
|
||||
| | sol](https://github.com/0xProject/protocol/ | |
|
||||
| | tree/72a74e7c66e27da02dd9f4ce604ad057c740c3 | |
|
||||
| | 04/contracts/zero-ex/contracts/src/storage) | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - [ERC20BridgeProxy.sol](https://github. | [f |
|
||||
| x | com/0xProject/0x-monorepo/blob/fb8360edfd4f | b8360edfd](https:/ |
|
||||
| c | 42f2d2b127b95c156eb1b0daa02b/contracts/asse | /github.com/0xProj |
|
||||
| h | t-proxy/contracts/src/ERC20BridgeProxy.sol) | ect/0x-monorepo/tr |
|
||||
| a | ([spec](https://github.c | ee/fb8360edfd4f42f |
|
||||
| n | om/0xProject/0x-protocol-specification/blob | 2d2b127b95c156eb1b |
|
||||
| g | /master/asset-proxy/erc20-bridge-proxy.md)) | 0daa02b/contracts) |
|
||||
| e | - [Exchange.sol](http | |
|
||||
| V | s://github.com/0xProject/0x-monorepo/blob/f | |
|
||||
| 3 | b8360edfd4f42f2d2b127b95c156eb1b0daa02b/con | |
|
||||
| | tracts/exchange/contracts/src/Exchange.sol) | |
|
||||
| | ([spec](https | |
|
||||
| | ://github.com/0xProject/0x-protocol-specifi | |
|
||||
| | cation/blob/master/v3/v3-specification.md)) | |
|
||||
| | - [ZeroExGovernor.sol](https://gi | |
|
||||
| | thub.com/0xProject/0x-monorepo/blob/fb8360e | |
|
||||
| | dfd4f42f2d2b127b95c156eb1b0daa02b/contracts | |
|
||||
| | /multisig/contracts/src/ZeroExGovernor.sol) | |
|
||||
| | ([spec](https | |
|
||||
| | ://github.com/0xProject/0x-protocol-specifi | |
|
||||
| | cation/blob/master/v3/zero-ex-governor.md)) | |
|
||||
| | - [Staking.sol](ht | |
|
||||
| | tps://github.com/0xProject/0x-monorepo/blob | |
|
||||
| | /fb8360edfd4f42f2d2b127b95c156eb1b0daa02b/c | |
|
||||
| | ontracts/staking/contracts/src/Staking.sol) | |
|
||||
| | ([spec](https://github. | |
|
||||
| | com/0xProject/0x-protocol-specification/blo | |
|
||||
| | b/master/staking/staking-specification.md)) | |
|
||||
| | - [StakingProxy.sol](https:/ | |
|
||||
| | /github.com/0xProject/0x-monorepo/blob/fb83 | |
|
||||
| | 60edfd4f42f2d2b127b95c156eb1b0daa02b/contra | |
|
||||
| | cts/staking/contracts/src/StakingProxy.sol) | |
|
||||
| | ([spec](https://github. | |
|
||||
| | com/0xProject/0x-protocol-specification/blo | |
|
||||
| | b/master/staking/staking-specification.md)) | |
|
||||
| | - [ZrxVault.sol](htt | |
|
||||
| | ps://github.com/0xProject/0x-monorepo/blob/ | |
|
||||
| | fb8360edfd4f42f2d2b127b95c156eb1b0daa02b/co | |
|
||||
| | ntracts/staking/contracts/src/ZrxVault.sol) | |
|
||||
| | ([spec](https://github. | |
|
||||
| | com/0xProject/0x-protocol-specification/blo | |
|
||||
| | b/master/staking/staking-specification.md)) | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - [src/2.0.0/protoc | [f |
|
||||
| x | ol](https://github.com/0xProject/0x-monorep | f70c5ecfe](https:/ |
|
||||
| c | o/tree/ff70c5ecfe28eff14e1a372c5e493b8f5363 | /github.com/0xProj |
|
||||
| h | e1d0/packages/contracts/src/2.0.0/protocol) | ect/0x-monorepo/tr |
|
||||
| a | - [src/2.0.0/ | ee/ff70c5ecfe28eff |
|
||||
| n | utils](https://github.com/0xProject/0x-mono | 14e1a372c5e493b8f5 |
|
||||
| g | repo/tree/ff70c5ecfe28eff14e1a372c5e493b8f5 | 363e1d0/contracts) |
|
||||
| e | 363e1d0/packages/contracts/src/2.0.0/utils) | |
|
||||
| V | | |
|
||||
| 2 | | |
|
||||
| . | | |
|
||||
| 1 | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| M | - [MultiAssetProxy.sol](https://github | [c |
|
||||
| u | .com/0xProject/0x-monorepo/blob/c4d9ef9f835 | 4d9ef9f83](https:/ |
|
||||
| l | 08154fe9db35796b6b86aeb0f2240/contracts/ass | /github.com/0xProj |
|
||||
| t | et-proxy/contracts/src/MultiAssetProxy.sol) | ect/0x-monorepo/tr |
|
||||
| i | | ee/c4d9ef9f8350815 |
|
||||
| A | | 4fe9db35796b6b86ae |
|
||||
| s | | b0f2240/contracts) |
|
||||
| s | | |
|
||||
| e | | |
|
||||
| t | | |
|
||||
| P | | |
|
||||
| r | | |
|
||||
| o | | |
|
||||
| x | | |
|
||||
| y | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - [ERC1155Proxy.sol](https://git | [7 |
|
||||
| R | hub.com/0xProject/0x-monorepo/blob/77484dc6 | 7484dc69e](https:/ |
|
||||
| C | 9eea1f4f1a8397590199f3f2489751d2/contracts/ | /github.com/0xProj |
|
||||
| 1 | asset-proxy/contracts/src/ERC1155Proxy.sol) | ect/0x-monorepo/tr |
|
||||
| 1 | | ee/77484dc69eea1f4 |
|
||||
| 5 | | f1a8397590199f3f24 |
|
||||
| 5 | | 89751d2/contracts) |
|
||||
| P | | |
|
||||
| r | | |
|
||||
| o | | |
|
||||
| x | | |
|
||||
| y | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| S | - [StaticCallProxy.sol](https://github | [5 |
|
||||
| t | .com/0xProject/0x-monorepo/blob/54f4727adc6 | 4f4727adc](https:/ |
|
||||
| a | da95f312e3721f44857110555d24c/contracts/ass | /github.com/0xProj |
|
||||
| t | et-proxy/contracts/src/StaticCallProxy.sol) | ect/0x-monorepo/tr |
|
||||
| i | | ee/54f4727adc6da95 |
|
||||
| c | | f312e3721f44857110 |
|
||||
| C | | 555d24c/contracts) |
|
||||
| a | | |
|
||||
| l | | |
|
||||
| l | | |
|
||||
| P | | |
|
||||
| r | | |
|
||||
| o | | |
|
||||
| x | | |
|
||||
| y | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - [ERC20BridgeProxy.sol](https://github. | [2 |
|
||||
| R | com/0xProject/0x-monorepo/blob/281658ba349a | 81658ba34](https:/ |
|
||||
| C | 2c5088b40b503998bea5020284a6/contracts/asse | /github.com/0xProj |
|
||||
| 2 | t-proxy/contracts/src/ERC20BridgeProxy.sol) | ect/0x-monorepo/tr |
|
||||
| 0 | | ee/281658ba349a2c5 |
|
||||
| B | | 088b40b503998bea50 |
|
||||
| r | | 20284a6/contracts) |
|
||||
| i | | |
|
||||
| d | | |
|
||||
| g | | |
|
||||
| e | | |
|
||||
| P | | |
|
||||
| r | | |
|
||||
| o | | |
|
||||
| x | | |
|
||||
| y | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
| E | - [contracts/src](https://github.com/ | [7 |
|
||||
| x | 0xProject/0x-monorepo/tree/7967a8416c76e34f | 967a8416c](https:/ |
|
||||
| c | f5a0a4eb80e7b33ff8c0e297/contracts/zero-ex) | /github.com/0xProj |
|
||||
| h | | ect/0x-monorepo/tr |
|
||||
| a | | ee/7967a8416c76e34 |
|
||||
| n | | ff5a0a4eb80e7b33ff |
|
||||
| g | | 8c0e297/contracts) |
|
||||
| e | | |
|
||||
| P | | |
|
||||
| r | | |
|
||||
| o | | |
|
||||
| x | | |
|
||||
| y | | |
|
||||
+---+---------------------------------------------+--------------------+
|
||||
|
||||
# Disclosures
|
||||
|
||||
Please e-mail all submissions to <security@0x.org> with the subject
|
||||
\"BUG BOUNTY\". Your submission should include any steps required to
|
||||
reproduce or exploit the vulnerability. Please allow time for the
|
||||
vulnerability to be fixed before discussing any findings publicly. After
|
||||
receiving a submission, we will contact you with expected timelines for
|
||||
a fix to be implemented.
|
15
docs/additional/contributing.md
Normal file
15
docs/additional/contributing.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Contributing
|
||||
---
|
||||
|
||||
We are an open source project and welcome contributions!
|
||||
|
||||
Learn more about 0x Labs at [0x.org](https://0x.org). Check out our code
|
||||
on [GitHub](https://github.com/0xProject/protocol). Connect with the
|
||||
community on our [Forum](https://forum.0x.org/) and
|
||||
[Reddit](https://www.reddit.com/r/0xProject/). Chat with our team
|
||||
privately on [Discord](https://discord.com/invite/d3FTX3M) or publicly
|
||||
on [Twitter](https://twitter.com/0xproject).
|
||||
|
||||
We\'re also hiring, see our open roles at
|
||||
[0x.org/jobs](https://0x.org/about/jobs).
|
131
docs/additional/emergency.md
Normal file
131
docs/additional/emergency.md
Normal file
File diff suppressed because one or more lines are too long
23
docs/additional/exceptional_erc20s.md
Normal file
23
docs/additional/exceptional_erc20s.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: Exceptional ERC20s
|
||||
---
|
||||
|
||||
Some ERC20s have unique behavior that may require extra handling. We
|
||||
document these here as they are discovered.
|
||||
|
||||
# Assert vs Require
|
||||
|
||||
These ERC20\'s use [assert]{.title-ref} instead of
|
||||
[require]{.title-ref}, which means that if the token reverts then
|
||||
(nearly) all of the gas from your transaction will be consumed.
|
||||
Specifically, you are left with 1/64 of the gas limit. Be mindful of
|
||||
this when implementing fallback logic; for example, if a call to
|
||||
[transferFrom]{.title-ref} reverts then note you will only have 1/64 of
|
||||
the gas limit to handle the exception.
|
||||
|
||||
Known tokens:
|
||||
|
||||
- KNC
|
||||
- LINK
|
||||
- sUSD
|
||||
- USDT
|
143
docs/additional/releases.md
Normal file
143
docs/additional/releases.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: Releases
|
||||
---
|
||||
|
||||
::: {.note}
|
||||
::: {.title}
|
||||
Note
|
||||
:::
|
||||
|
||||
These releases are approved by the 0x Community. Come out and vote
|
||||
[HERE](https://0x.org/zrx/vote/)!
|
||||
:::
|
||||
|
||||
This page outlines upcoming releases and expected changes.
|
||||
|
||||
--------------------------------------------- ------------------------------------------------- ---------- ------------- -------------------------------------------------------------------------------------------------------------------------
|
||||
**Name** **Overview** **Est **Status** **Additional**
|
||||
Release
|
||||
Date**
|
||||
|
||||
[Amaretto](#amaretto) Protocol 4.1: Efficiency + Batch Fills 03/15/21 Development
|
||||
|
||||
*The following releases have been deployed*
|
||||
|
||||
[Babooshka](#babooshka) Connect Exchange Proxy to Staking 02/08/21 Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/9_babooshka.md)
|
||||
|
||||
[Squire](#squire) Aggregation for [V4 02/04/21 Deployed N/A
|
||||
Orders](../basics/orders.html)
|
||||
|
||||
[big-pantsuit-energy](#big-pantsuit-energy) Patch batch `` `getOrderRelevantState() ``\` 01/25/21 Deployed [Release
|
||||
functions Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/8_big-pantsuit-energy.md)
|
||||
|
||||
[Panettone](#panettone) Minor patches from [Consensys 01/12/21 Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/7_panettone.md)
|
||||
Audit](./audits.html)
|
||||
|
||||
[cyberpants2077](#cyberpants2077) [V4 Orders](../basics/orders.html) 01/05/21 Deployed [Release
|
||||
Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/6_cyberpants2077.md)
|
||||
|
||||
[Hot-Pants](#hot-pants) Remove calldata signing / DeFi Saver Fix / 12/07/20 Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/5_hot_pants.md)
|
||||
Allowance on Proxy
|
||||
|
||||
[Plop](#plop) PLP VIP 12/01/20 Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/4_plop.md)
|
||||
|
||||
[Tinker](#tinker) Set allowances directly on Exchange Proxy 11/12/20 Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/3_tinker.md)
|
||||
|
||||
[Elphaba](#elphaba) Meta-Transactions + Uniswap VIP Deployed [Release Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/2_elphaba.md)
|
||||
|
||||
[Champagne-Problems](#champagne-problems) Signed Calldata Deployed [Release
|
||||
Notes](https://github.com/0xProject/0x-migrations/blob/main/src/exchange-proxy/migrations/log/1_champagne_problems.md)
|
||||
--------------------------------------------- ------------------------------------------------- ---------- ------------- -------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Upcoming
|
||||
|
||||
## Amaretto
|
||||
|
||||
- RFQ VIP (fallback to DEX if RFQ orders is unfillable)
|
||||
- Batch fills for native orders
|
||||
- Mooniswap VIP
|
||||
- Curve / Swerve VIP (via PLP Sandbox)
|
||||
|
||||
# Past
|
||||
|
||||
## Babooshka
|
||||
|
||||
- Register the 0x Exchange Proxy with the Staking Proxy, allowing
|
||||
protocol fees from V4 Orders to be paid to Staking Pools.
|
||||
|
||||
## Squire
|
||||
|
||||
- Deploy updated
|
||||
[FillQuoteTransformer](../architecture/transformers.html), which can
|
||||
fill [V4 Orders](../basics/orders.html). This transformer will no
|
||||
longer call Exchange V3.
|
||||
- This will replace the [ERC20BridgeTransfer
|
||||
Event](../basics/events.html#erc20bridgetransfer)
|
||||
|
||||
## big-pantsuit-energy
|
||||
|
||||
- Swallow reverts in [batchGetRfqOrderRelevantStates()]{.title-ref}
|
||||
and [batchGetLimitOrderRelevantStates()]{.title-ref} functions.
|
||||
|
||||
## Panettone
|
||||
|
||||
- Minor patches from the Consensys Audit. No breaking changes.
|
||||
- Decommissions the internal [\_executeMetaTransaction]{.title-ref}
|
||||
function.
|
||||
- Extends deployment timelock from 24h to 48h.
|
||||
- Decommission
|
||||
[SignatureValidationFeature](../architecture/features.html).
|
||||
- Decommission [TokenSpenderFeature](../architecture/features.html).
|
||||
|
||||
## cyberpants2077
|
||||
|
||||
- Deploy [NativeLiquidityFeature](../architecture/features.html). This
|
||||
incldues order validation that was previously in Dev-Utils.
|
||||
- Introduces [new events](../basics/events.html).
|
||||
|
||||
## Hot-Pants
|
||||
|
||||
- Removes calldata signing from `TransformERC20` Feature.
|
||||
- Redeploying all [Transformers](../architecture/transformers.html)
|
||||
(new interface w/o `calldataHash`)
|
||||
- Allowances can now be set on the
|
||||
[Proxy](../architecture/features/proxy.html). See more on the
|
||||
[Allowances Page](../basics/allowances.html). This involves
|
||||
redeploying the following [Features](../architecture/features.html):
|
||||
`MetaTransactionsFeature`, `TransformERC20Feature`,
|
||||
`UniswapFeature`.
|
||||
|
||||
## Plop
|
||||
|
||||
- Deploy the
|
||||
[LiquidityProviderFeature](../architecture/features.html), which
|
||||
enables optimized trades directly with [PLP](../advanced/plp.html)
|
||||
|
||||
## Tinker
|
||||
|
||||
::: {.note}
|
||||
::: {.title}
|
||||
Note
|
||||
:::
|
||||
|
||||
This release was partially rolled back due to breaking allowances for
|
||||
some [Exceptional ERC20 Tokens](./exceptional_erc20s.html). These
|
||||
features were fixed and re-deployed in the Hot-Pants release, above.
|
||||
:::
|
||||
|
||||
- Upgrade any features that transfer user funds to use allowances on
|
||||
the Proxy contract. Transfers will still fallback to the Allowance
|
||||
Target, but integrators will get reduced transaction costs from
|
||||
setting their allowance on the Proxy. This involves redeploying the
|
||||
following [Features](../architecture/features.html):
|
||||
`MetaTransactionsFeature`, `TransformERC20Feature`,
|
||||
`UniswapFeature`.
|
||||
|
||||
## Elphaba
|
||||
|
||||
- Updates for Meta-Transactions Feature
|
||||
- Uniswap VIP for efficient fills through Uniswap.
|
||||
|
||||
## Champagne-Problems
|
||||
|
||||
- Signed Calldata for Meta-Transactions
|
@@ -1,178 +0,0 @@
|
||||
###############################
|
||||
ERC20 Transformations
|
||||
###############################
|
||||
|
||||
|
||||
The 0x Protocol is able to perform a variety of atomic transformations on ERC20 tokens, in addition to simply executing trades. This is made possible through composable smart contracts, called `Transformers <../architecture/transformers.html>`_. These trustless modules extend the core Exchange logic, enabling workflows like converting between ETH<>WETH or aggregating liquidity across DEX's. These operations can be combined with trade exeuction to create a seamlesss trading experience.
|
||||
|
||||
Anyone can run transformations using the ``transformERC20`` Exchange function.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Executes a series of transformations to convert an ERC20 `inputToken`
|
||||
/// to an ERC20 `outputToken`.
|
||||
/// @param inputToken The token being provided by the sender.
|
||||
/// If `0xeee...`, ETH is implied and should be provided with the call.`
|
||||
/// @param outputToken The token to be acquired by the sender.
|
||||
/// `0xeee...` implies ETH.
|
||||
/// @param inputTokenAmount The amount of `inputToken` to take from the sender.
|
||||
/// If set to `uint256(-1)`, the entire spendable balance of the taker
|
||||
/// will be solt.
|
||||
/// @param minOutputTokenAmount The minimum amount of `outputToken` the sender
|
||||
/// must receive for the entire transformation to succeed. If set to zero,
|
||||
/// the minimum output token transfer will not be asserted.
|
||||
/// @param transformations The transformations to execute on the token balance(s)
|
||||
/// in sequence.
|
||||
/// @return outputTokenAmount The amount of `outputToken` received by the sender.
|
||||
function transformERC20(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 minOutputTokenAmount,
|
||||
Transformation[] memory transformations
|
||||
)
|
||||
public
|
||||
override
|
||||
payable
|
||||
returns (uint256 outputTokenAmount);
|
||||
|
||||
A Transformation is defined by a ``deploymentNonce`` (which identifies the contract that implements the transformation) and ``data`` for that contract.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Defines a transformation to run in `transformERC20()`.
|
||||
struct Transformation {
|
||||
// The deployment nonce for the transformer.
|
||||
// The address of the transformer contract will be derived from this
|
||||
// value.
|
||||
uint32 deploymentNonce;
|
||||
// Arbitrary data to pass to the transformer.
|
||||
bytes data;
|
||||
}
|
||||
|
||||
The transaction will revert if a transformation fails; the `inputTokenAmount` cannot be transferred from the sender; or the ``minOutputTokenAmount`` is not transferred to the sender. A single `TransformedERC20 <../basics/events.html#transformederc20>`_ event is be emitted upon successful execution of all transformations.
|
||||
|
||||
Liquidity Aggregation
|
||||
---------------------
|
||||
|
||||
Liquidity can be pulled from other Decentralized Exchanges (DEX) to supplement native liquidity (0x orders). This is currently used by 0x API to provide the aggregate the best prices across the entire DEX Ecosystem. Check out `https://matcha.xyz <https://matcha.xyz>`_ to see this in action!
|
||||
|
||||
Supported DEX's:
|
||||
|
||||
* Balancer
|
||||
* Curve
|
||||
* DoDo
|
||||
* Kyber
|
||||
* MStable
|
||||
* Mooniswap
|
||||
* Oasis
|
||||
* Shell
|
||||
* Sushiswap
|
||||
* Uniswap v1/v2
|
||||
|
||||
This transformation is implemented by the `FillQuoteTransformer <../architecture/transformers.html>`_. Abi-Encode the following struct to get the ``data``:
|
||||
|
||||
.. warning::
|
||||
An upgrade is pending to this transformation. This currently uses Exchange V3 Orders, but will soon be updated to use `V4 Orders <../basics/orders.html>`_. - 11/26/2020
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Transform data to ABI-encode and pass into `transform()`.
|
||||
struct TransformData {
|
||||
// Whether we are performing a market sell or buy.
|
||||
Side side;
|
||||
// The token being sold.
|
||||
// This should be an actual token, not the ETH pseudo-token.
|
||||
IERC20TokenV06 sellToken;
|
||||
// The token being bought.
|
||||
// This should be an actual token, not the ETH pseudo-token.
|
||||
IERC20TokenV06 buyToken;
|
||||
// The orders to fill.
|
||||
IExchange.Order[] orders;
|
||||
// Signatures for each respective order in `orders`.
|
||||
bytes[] signatures;
|
||||
// Maximum fill amount for each order. This may be shorter than the
|
||||
// number of orders, where missing entries will be treated as `uint256(-1)`.
|
||||
// For sells, this will be the maximum sell amount (taker asset).
|
||||
// For buys, this will be the maximum buy amount (maker asset).
|
||||
uint256[] maxOrderFillAmounts;
|
||||
// Amount of `sellToken` to sell or `buyToken` to buy.
|
||||
// For sells, this may be `uint256(-1)` to sell the entire balance of
|
||||
// `sellToken`.
|
||||
uint256 fillAmount;
|
||||
// Who to transfer unused protocol fees to.
|
||||
// May be a valid address or one of:
|
||||
// `address(0)`: Stay in flash wallet.
|
||||
// `address(1)`: Send to the taker.
|
||||
// `address(2)`: Send to the sender (caller of `transformERC20()`).
|
||||
address payable refundReceiver;
|
||||
// Required taker address for RFQT orders.
|
||||
// Null means any taker can fill it.
|
||||
address rfqtTakerAddress;
|
||||
}
|
||||
|
||||
This transformation currently executes a Market Sell or Market Buy on a series of `0x V3 Orders <https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md#orders>`_. The transaction will revert if the ``fillAmount`` is not reached; an individual order can fail without the entire transaction reverting. A `ProtocolFeeUnfunded <../basics/events.html#protocolfeeunfunded>`_ event will be emitted if an order failed to fill because the Taker did not send a sufficient protocol fee.
|
||||
|
||||
|
||||
WETH Wrapping
|
||||
-------------
|
||||
|
||||
This transformation is implemented by the `WethTransformer <../architecture/transformers.html>`_. Abi-Encode the following struct to get the ``data``:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Transform data to ABI-encode and pass into `transform()`.
|
||||
struct TransformData {
|
||||
// The token to wrap/unwrap. Must be either ETH or WETH.
|
||||
IERC20TokenV06 token;
|
||||
// Amount of `token` to wrap or unwrap.
|
||||
// `uint(-1)` will unwrap the entire balance.
|
||||
uint256 amount;
|
||||
}
|
||||
|
||||
If the supplied token address is `WETH (etherToken) <../basics/addresses.html>`_ then the supplied WETH will be unwrapped to ``ETH``. If any other address is supplied the any ETH passed in will be wrapped into ``WETH``. No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if ``allowances <../basics/allowances.html>_`` are not set or the available balance is less than ``amount``.
|
||||
|
||||
Affiliate Fees
|
||||
--------------
|
||||
|
||||
This transformation is implemented by the `AffiliateFeeTransformer <../architecture/transformers.html>`_. Abi-Encode the following struct to get the ``data``:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Information for a single fee.
|
||||
struct TokenFee {
|
||||
// The token to transfer to `recipient`.
|
||||
IERC20TokenV06 token;
|
||||
// Amount of each `token` to transfer to `recipient`.
|
||||
// If `amount == uint256(-1)`, the entire balance of `token` will be
|
||||
// transferred.
|
||||
uint256 amount;
|
||||
// Recipient of `token`.
|
||||
address payable recipient;
|
||||
}
|
||||
|
||||
This pays the ``recipient`` in the ``amount`` of ``token`` specified. This can be used by integrators who wish to add an additional fee on top of 0x Orders. No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if `allowances <../basics/allowances.html>`_ are not set or the available balance is less than ``amount``.
|
||||
|
||||
Pay Taker
|
||||
---------
|
||||
|
||||
This transformation is implemented by the `PayTakerTransformer <../architecture/transformers.html>`_. Abi-Encode the following struct to get the ``data``:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Transform data to ABI-encode and pass into `transform()`.
|
||||
struct TransformData {
|
||||
// The tokens to transfer to the taker.
|
||||
IERC20TokenV06[] tokens;
|
||||
// Amount of each token in `tokens` to transfer to the taker.
|
||||
// `uint(-1)` will transfer the entire balance.
|
||||
uint256[] amounts;
|
||||
}
|
||||
|
||||
This pays the ``taker`` in the ``amounts`` of each ``tokens`` specified. This is generally run at the end of all other transformations. For example, if you've swapped the taker's ETH for WETH then executed a trade through `Liquidity Aggregation`_, this transformation will can transfer the final output token back to the Taker.
|
||||
|
||||
No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if `allowances <../basics/allowances.html>`_ are not set or the available balance is less than ``amount``.
|
||||
|
||||
Adding Custom Transformations
|
||||
-----------------------------
|
||||
Transformations are trustless, but at this time they are permissioned so only 0x Labs can deploy new Transformers. If you are interested in deploying your own transformation logic, please reach out to us on `Discord <https://discord.com/invite/d3FTX3M>`_. Learn more about why this is permissioned in the `Transformer Deployer <../architecture/transformer_deployer.html>`_ section.
|
@@ -1,233 +0,0 @@
|
||||
###############################
|
||||
Meta-Transactions
|
||||
###############################
|
||||
|
||||
Meta-Transactions are signed messages that instruct the 0x Protocol to run function(s) in the context of the signer. This signed mtx can then be shared off-chain, allowing anyone to execute on-chain. This is useful for integrators who would like to subsidize the Ethereum Gas Fee, or add custom smart contract logic to run atomically a fill. A signed meta-transaction can only be executed once.
|
||||
|
||||
A common use case for this is in Request For Quote (RFQ) systems. The Maker creates an order; the Taker signs a mtx permitting 0x Protocol to fill the order on their behalf; the mtx is returned to the Maker who submits it on-chain.
|
||||
|
||||
.. image:: ../_static/img/rfqm.png
|
||||
:alt: Meta-Transaction Example
|
||||
:align: center
|
||||
|
||||
|
||||
|
||||
Constructing
|
||||
============
|
||||
|
||||
To construct a Meta-Transaction, abi-encode the following struct and sign it.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Describes an exchange proxy meta transaction.
|
||||
struct MetaTransactionData {
|
||||
// Signer of meta-transaction. On whose behalf to execute the MTX.
|
||||
address payable signer;
|
||||
// Required sender, or NULL for anyone.
|
||||
address sender;
|
||||
// Minimum gas price.
|
||||
uint256 minGasPrice;
|
||||
// Maximum gas price.
|
||||
uint256 maxGasPrice;
|
||||
// MTX is invalid after this time.
|
||||
uint256 expirationTimeSeconds;
|
||||
// Nonce to make this MTX unique.
|
||||
uint256 salt;
|
||||
// Encoded call data to a function on the exchange proxy.
|
||||
bytes callData;
|
||||
// Amount of ETH to attach to the call.
|
||||
uint256 value;
|
||||
// ERC20 fee `signer` pays `sender`.
|
||||
IERC20TokenV06 feeToken;
|
||||
// ERC20 fee amount.
|
||||
uint256 feeAmount;
|
||||
}
|
||||
|
||||
The ``calldata`` field is specific to the function you wish to execute. At this time, the following functions are supported:
|
||||
|
||||
- `fillLimitOrder <../basics/functions.html#filllimitorder>`_
|
||||
- `fillRfqOrder <../basics/functions.html#fillrfqorder>`_
|
||||
- `transformERC20 <../advanced/erc20_transformations.html>`_
|
||||
|
||||
Signing
|
||||
=======
|
||||
|
||||
Meta-Transactions use the same signing technique as 0x Orders; see the `How to Sign <../basics/orders.html#how-to-sign>`_ section of the Orders documentation. See `getMetaTransactionHash`_ for generating a unique hash for your mtx.
|
||||
|
||||
Functionality
|
||||
=============
|
||||
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| Function | Overview |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| `executeMetaTransaction`_ | Executes a single meta-transaction |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| `batchExecuteMetaTransactions`_ | Executes a batch of meta-transactions. |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| `getMetaTransactionExecutedBlock`_ | Returns the block that a meta-transaction was executed at. |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| `getMetaTransactionHashExecutedBlock`_ | Same as ``getMetaTransactionExecutedBlock``, only this function takes a meta-transaction hash. |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
| `getMetaTransactionHash`_ | Returns the hash of a meta-transaction. |
|
||||
+----------------------------------------+------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
executeMetaTransaction
|
||||
----------------------
|
||||
|
||||
A single Meta-Transaction is executed by calling ``executeMetaTransaction``. A batch of mtx's can be executed by calling ``batchExecuteMetaTransactions``.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Execute a single meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @param signature The signature by `mtx.signer`.
|
||||
/// @return returnResult The ABI-encoded result of the underlying call.
|
||||
function executeMetaTransaction(
|
||||
MetaTransactionData calldata mtx,
|
||||
LibSignature.Signature calldata signature
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (bytes memory returnResult);
|
||||
|
||||
A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted on succes. The ``returnResult`` contains the raw return data for the executed function. For example, if the function returns a ``uint256`` then the ``returnResult`` could be abi-decoded into a ``uint256``.
|
||||
|
||||
This call will revert in the following scenarios:
|
||||
|
||||
- The address in the ``mtx.sender`` field does not match ``msg.sender``.
|
||||
- The mtx has expired.
|
||||
- The Ethereum transaction's gas price (``tx.gasprice``) is outside of the range ``[mtx.minGasPrice..mtx.maxGasPrice]``
|
||||
- The ETH sent with the mtx is less than ``mtx.value``
|
||||
- The allowance/balance of ``signer`` is insufficient to pay ``feeAmount`` of ``feeToken`` to the ``sender`` (if specified)
|
||||
- The signature is invalid.
|
||||
- The mtx was already executed
|
||||
- The underlying function is not supported by meta-transactions (see list above).
|
||||
- The underlying function call reverts.
|
||||
|
||||
batchExecuteMetaTransactions
|
||||
----------------------------
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Execute multiple meta-transactions.
|
||||
/// @param mtxs The meta-transactions.
|
||||
/// @param signatures The signature by each respective `mtx.signer`.
|
||||
/// @return returnResults The ABI-encoded results of the underlying calls.
|
||||
function batchExecuteMetaTransactions(
|
||||
MetaTransactionData[] calldata mtxs,
|
||||
LibSignature.Signature[] calldata signatures
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (bytes[] memory returnResults);
|
||||
|
||||
A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted for each mtx on succes. The ``returnResult`` contains the raw return data for the executed function This call will revert if the one of the ``mtxs`` reverts. Any exceess Ether will be refunded to the ``msg.sender``.
|
||||
|
||||
|
||||
getMetaTransactionExecutedBlock
|
||||
-------------------------------
|
||||
|
||||
The ``block.number`` is stored on-chain when a mtx is executed. This value can be retrieved using the following function.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Get the block at which a meta-transaction has been executed.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionExecutedBlock(MetaTransactionData calldata mtx)
|
||||
external
|
||||
view
|
||||
returns (uint256 blockNumber);
|
||||
|
||||
getMetaTransactionHashExecutedBlock
|
||||
-----------------------------------
|
||||
|
||||
This is a more gas-efficient implementation of ``getMetaTransactionExecutedBlock``.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Get the block at which a meta-transaction hash has been executed.
|
||||
/// @param mtxHash The meta-transaction hash.
|
||||
/// @return blockNumber The block height when the meta-transactioin was executed.
|
||||
function getMetaTransactionHashExecutedBlock(bytes32 mtxHash)
|
||||
external
|
||||
view
|
||||
returns (uint256 blockNumber);
|
||||
|
||||
|
||||
getMetaTransactionHash
|
||||
----------------------
|
||||
|
||||
The hash of the mtx is used to uniquely identify it 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 EIP712 hash of a meta-transaction.
|
||||
/// @param mtx The meta-transaction.
|
||||
/// @return mtxHash The EIP712 hash of `mtx`.
|
||||
function getMetaTransactionHash(MetaTransactionData calldata mtx)
|
||||
external
|
||||
view
|
||||
returns (bytes32 mtxHash);
|
||||
|
||||
The simplest way to generate an order hash is by calling this function, ex:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getMetaTransactionHash(mtx);
|
||||
|
||||
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(
|
||||
"MetaTransactionData("
|
||||
"address signer,"
|
||||
"address sender,"
|
||||
"uint256 minGasPrice,"
|
||||
"uint256 maxGasPrice,"
|
||||
"uint256 expirationTimeSeconds,"
|
||||
"uint256 salt,"
|
||||
"bytes callData,"
|
||||
"uint256 value,"
|
||||
"address feeToken,"
|
||||
"uint256 feeAmount"
|
||||
")"
|
||||
)),
|
||||
// The struct values.
|
||||
mtx.signer,
|
||||
mtx.sender,
|
||||
mtx.minGasPrice,
|
||||
mtx.maxGasPrice,
|
||||
mtx.expirationTimeSeconds,
|
||||
mtx.salt,
|
||||
keccak256(mtx.callData),
|
||||
mtx.value,
|
||||
mtx.feeToken,
|
||||
mtx.feeAmount
|
||||
))
|
||||
));
|
||||
|
@@ -1,122 +0,0 @@
|
||||
###############################
|
||||
Pluggable Liquidity (PLP)
|
||||
###############################
|
||||
|
||||
PLP (Pluggable Liquidity PLP) enables anyone to extend the 0x Protocol with their own on-chain liquidity provider, like an AMM (Automated Market Maker). Liquidity providers are sandboxed so their code can be totally closed-source; they are executed via the `LiquidityProviderFeature <../architecture/features.html>`_
|
||||
|
||||
|
||||
Implementing a Liquidity Provider
|
||||
=================================
|
||||
The only requirement is that the provider implements the interface in `ILiquidityProvider <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/vendor/ILiquidityProvider.sol>`_.
|
||||
Note that ``sellEthForToken`` and ``sellTokenForEth`` do not need to be implemented if the liquidity provider does not trade ETH/WETH.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Trades `inputToken` for `outputToken`. The amount of `inputToken`
|
||||
/// to sell must be transferred to the contract prior to calling this
|
||||
/// function to trigger the trade.
|
||||
/// @param inputToken The token being sold.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function sellTokenForToken(
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
address recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Trades ETH for token. ETH must either be attached to this function
|
||||
/// call or sent to the contract prior to calling this function to
|
||||
/// trigger the trade.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function sellEthForToken(
|
||||
address outputToken,
|
||||
address recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Trades token for ETH. The token must be sent to the contract prior
|
||||
/// to calling this function to trigger the trade.
|
||||
/// @param inputToken The token being sold.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of ETH to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of ETH bought.
|
||||
function sellTokenForEth(
|
||||
address inputToken,
|
||||
address payable recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
returns (uint256 boughtAmount);
|
||||
|
||||
/// @dev Quotes the amount of `outputToken` that would be obtained by
|
||||
/// selling `sellAmount` of `inputToken`.
|
||||
/// @param inputToken Address of the taker token (what to sell). Use
|
||||
/// the wETH address if selling ETH.
|
||||
/// @param outputToken Address of the maker token (what to buy). Use
|
||||
/// the wETH address if buying ETH.
|
||||
/// @param sellAmount Amount of `inputToken` to sell.
|
||||
/// @return outputTokenAmount Amount of `outputToken` that would be obtained.
|
||||
function getSellQuote(
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
uint256 sellAmount
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (uint256 outputTokenAmount);
|
||||
|
||||
|
||||
Trading with a Liquidity Provider
|
||||
=================================
|
||||
|
||||
To trade with a liquidity provider use the ``sellToLiquidityProvider`` function.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Sells `sellAmount` of `inputToken` to the liquidity provider
|
||||
/// at the given `provider` address.
|
||||
/// @param inputToken The token being sold.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param provider The address of the on-chain liquidity provider
|
||||
/// to trade with.
|
||||
/// @param recipient The recipient of the bought tokens. If equal to
|
||||
/// address(0), `msg.sender` is assumed to be the recipient.
|
||||
/// @param sellAmount The amount of `inputToken` to sell.
|
||||
/// @param minBuyAmount The minimum acceptable amount of `outputToken` to
|
||||
/// buy. Reverts if this amount is not satisfied.
|
||||
/// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function sellToLiquidityProvider(
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
address payable provider,
|
||||
address recipient,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
override
|
||||
payable
|
||||
returns (uint256 boughtAmount);
|
||||
|
||||
This function transfers tokens from ``msg.sender`` to the liquidity provider then executes the trade through a sandboxed contract external to the Exchange Proxy. The sandbox then executes the trade through the provider. This function then transfers the output tokens to the ``recipient``.
|
||||
|
||||
This function will emit a `LiquidityProviderSwap <../basics/events.html#liquidityproviderswap>`_ event if the trade succeeds. It will revert if the amount of ``outputToken`` returned by the Liquidity Provider is less than ``minBuyAmount``.
|
@@ -1,32 +0,0 @@
|
||||
###############################
|
||||
Optimized Uniswap Router
|
||||
###############################
|
||||
|
||||
The 0x Protocol is equipped with a highly optimized `UniswapV2 Router <https://uniswap.org/docs/v2/smart-contracts/router02/>`_, which can reduce the transaction cost of trading with Uniswap. Call the ``sellToUniswap`` function to execute a trade on Uniswap through the 0x Protocol.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Efficiently sell directly to uniswap/sushiswap.
|
||||
/// @param tokens Sell path.
|
||||
/// @param sellAmount of `tokens[0]` Amount to sell.
|
||||
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
|
||||
/// @param isSushi Use sushiswap if true.
|
||||
/// @return buyAmount Amount of `tokens[-1]` bought.
|
||||
function sellToUniswap(
|
||||
IERC20TokenV06[] calldata tokens,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
bool isSushi
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 buyAmount);
|
||||
|
||||
This function sells ``sellAmount`` of ``tokens[0]`` for at least ``minBuyAmount`` of ``tokens[-1]``. The ``tokens`` array defines how to route the trade between Uniswap pools. This function does not emit any events, although Uniswap pools will emit their own events. This function reverts if amount bought from Uniswap is less than ``minBuyAmount``, or if Uniswap reverts.
|
||||
|
||||
See the source code for our router `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/UniswapFeature.sol>`_.
|
||||
|
||||
See the official `Uniswap V2 Documentation <https://uniswap.org/docs/v2/>`_ for information on events/reverts/allowances.
|
||||
|
||||
.. note::
|
||||
This function does not use allowances set on 0x. The ``msg.sender`` must have allowances set on Uniswap (or SushiSwap).
|
@@ -1,77 +0,0 @@
|
||||
###############################
|
||||
Features
|
||||
###############################
|
||||
|
||||
Features implement the core feature set of the 0x Protocol. They are trusted with user allowances and permissioned by the `0x Governor <./governor.html>`_. Features are run in the context of the `Proxy <../proxy.html>`_, via a ``delegatecall``.
|
||||
|
||||
Below is a catalog of Features.
|
||||
|
||||
.. table::
|
||||
:widths: 20 60 20
|
||||
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Feature** | **Description** | **Resources** |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| BootstrapFeature | Bootstraps the entire system. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/BootstrapFeature.sol>`__; `Usage <./proxy.html#bootstrapping>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| LiquidityProviderFeature | Connects the system to Pluggable Liquidity (PLP). | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/LiquidityProviderFeature.sol>`__; `Usage <../advanced/plp.html#trading-with-a-liquidity-provider>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| MetaTransactionsFeature | Executes Meta-Transactions. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/MetaTransactionsFeature.sol>`__; `Usage <../advanced/mtx.html>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| NativeLiquidityFeature | Functions for native 0x liquidity (see `Orders <../basics/orders.html>`_). | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/NativeOrdersFeature.sol>`__; `Usage <../basics/functions.html>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| OwnableFeature | An implementation of Ownable that is compatible with the delegate-call proxy pattern. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/OwnableFeature.sol>`__; `Usage <./architecture/proxy.html#ownership>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| SignatureValidationFeature | *This feature is deprecated. Its code will be removed after the contract is decommissioned.* | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/SignatureValidatorFeature.sol>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| SimpleFunctionRegistry | Implements the registry of functions/features available in the system. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/SimpleFunctionRegistryFeature.sol>`__; `Usage <./proxy.html#function-registry>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| TokenSpenderFeature | *This feature is deprecated. Its code will be removed after the contract is decommissioned.* | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/TokenSpenderFeature.sol>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| TransformERC20Feature | Executes `Transformers <./transformers.html>`_ to aggregate liquidity and operate on ERC20 tokens. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/TransformERC20Feature.sol>`__; `Usage <../advanced/erc20_transformations.html>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| UniswapFeature | A highly-optimized UniswapV2 router; used to source liquidity from Uniswap. | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/UniswapFeature.sol>`__; `Usage <../advanced/uniswap.html>`__ |
|
||||
+----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Implementing a Feature
|
||||
======================
|
||||
The only requirement is that the Feature implements the interface in `IFeature <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/IFeature.sol>`_. Review the `Proxy Section <./proxy.html>`_ for details on how to write a smart contract that is compatible with our architecture (ex, how to properly manage state).
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Basic interface for a feature contract.
|
||||
interface IFeature {
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
|
||||
/// @dev The name of this feature set.
|
||||
function FEATURE_NAME() external view returns (string memory name);
|
||||
|
||||
/// @dev The version of this feature set.
|
||||
function FEATURE_VERSION() external view returns (uint256 version);
|
||||
}
|
||||
|
||||
|
||||
Best Practices
|
||||
================
|
||||
|
||||
We use this checklist to review the safety of new Features.
|
||||
|
||||
::
|
||||
|
||||
- [ ] Feature has updated version information.
|
||||
- [ ] implements IFeature interface.
|
||||
- [ ] Feature contracts are stateless (including inherited contracts).
|
||||
- [ ] onlySelf feature functions are prefixed with _.
|
||||
- [ ] Feature functions are added to full_migration_tests.
|
||||
- [ ] No delegatecalls from inside a feature. Call other features through the router.
|
||||
- [ ] No self-destruct in features (except BootstrapFeature).
|
||||
- [ ] No intentionally persistent (non-atomic) balances on the Exchange Proxy.
|
||||
- [ ] No direct access to another feature’s storage bucket without strong justification.
|
||||
- [ ] No executing arbitrary calldata from the context of the Exchange Proxy.
|
||||
- [ ] No external calls to arbitrary contracts from within the Exchange Proxy.
|
||||
- [ ] Features use unique StorageIds.
|
||||
- [ ] Document functions with execution contexts outside of the Exchange Proxy.
|
||||
- [ ] Document feature dependencies in checklist doc.
|
||||
- [ ] Document reentrant functions in checklist doc.
|
||||
- [ ] Document temporary balances.
|
@@ -1,17 +0,0 @@
|
||||
###############################
|
||||
Fee Collectors
|
||||
###############################
|
||||
|
||||
The `Protocol Fees <../basics/protocol_fees.html>`_ are paid into special Fee Collector contracts at time-of-fill. There is one collector for each Staking Pool. The fees are paid in aggregate from the collector to the `Staking System <../tokenomics/staking.md>`_; this can happen at anytime, but is most optimal to run during finalization. This increases the cost of finalizing an epoch, but substantially reduces the transaction cost for takers executing trades.
|
||||
|
||||
Architecture
|
||||
============
|
||||
|
||||
1. There is one Fee Collector per staking pool. The fee collector serves as a repository for protocol fees attributed to a given pool. It automatically ``approve()s`` the staking contract so fees can be aggregated during finalization. It also contains functionality to convert ETH to WETH. Fee collectors are created using ``CREATE2``. This gives us predictable addresses.
|
||||
|
||||
2. When a `Limit Order <../basics/orders.html#limitorders>`_ is filled, the protocol fee is paid to the Fee Collector that corresponds to ``order.pool``.
|
||||
|
||||
3. The `transferProtocolFeesForPools() <../basics/functions.html#transferprotocolfeesforpools>` function can be called to transfer the fees for a set of pools from their respective Fee Collectors into the Staking system.
|
||||
|
||||
.. image:: ../_static/img/fee_collectors.png
|
||||
:align: center
|
@@ -1,47 +0,0 @@
|
||||
###############################
|
||||
Flash Wallet
|
||||
###############################
|
||||
|
||||
The Flash Wallet is a sandboxed escrow contract that holds funds for `Transformers <./transformers.html>`_ to operate on. A `Feature <./features.html>`_ contract transfers tokens to the Flash Wallet, which then delegate call's into a Transformer to run operations on the escrowed funds. Transformers are trustless and therefore only have access to the funds deposted into the Flash Wallet; they do not have access to user allowances.
|
||||
|
||||
The wallet is currently only used by the ``TransformERC20`` feature. It is deployed using the ``createTransformWallet()`` function on the feature, which is only callable by the owner/governor. This allows us to deploy a fresh wallet in case we somehow break the old one, like if we accidentally selfdestruct it or clobber its state.
|
||||
|
||||
.. note::
|
||||
The wallet is currently only used for ERC20 tokens, but can be extended to work with other standards, like ERC1155 and ERC223, by implementing the required fallbacks for those standards.
|
||||
|
||||
The Flash Wallet exposes two functions of interest: ``executeCall()`` and ``executeDelegateCall()``. The former executes a ``call`` and reverts if the callee reverts. The latter executes a ``delegatecall`` and reverts if the callee reverts.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Execute an arbitrary call. Only an authority can call this.
|
||||
/// @param target The call target.
|
||||
/// @param callData The call data.
|
||||
/// @param value Ether to attach to the call.
|
||||
/// @return resultData The data returned by the call.
|
||||
function executeCall(
|
||||
address payable target,
|
||||
bytes calldata callData,
|
||||
uint256 value
|
||||
)
|
||||
external
|
||||
payable
|
||||
override
|
||||
onlyOwner
|
||||
returns (bytes memory resultData);
|
||||
|
||||
/// @dev Execute an arbitrary delegatecall, in the context of this puppet.
|
||||
/// Only an authority can call this.
|
||||
/// @param target The call target.
|
||||
/// @param callData The call data.
|
||||
/// @return resultData The data returned by the call.
|
||||
function executeDelegateCall(
|
||||
address payable target,
|
||||
bytes calldata callData
|
||||
)
|
||||
external
|
||||
payable
|
||||
override
|
||||
onlyOwner
|
||||
returns (bytes memory resultData);
|
||||
|
||||
View the code for the Flash Wallet `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/external/FlashWallet.sol>`_.
|
@@ -1,90 +0,0 @@
|
||||
###############################
|
||||
Governor
|
||||
###############################
|
||||
|
||||
.. note::
|
||||
|
||||
This page is tailored for Exchange V4. For information on governance over past exhcange versions, see `this specification <https://github.com/0xProject/0x-protocol-specification/blob/master/v3/zero-ex-governor.md>`_.
|
||||
|
||||
The ``ZeroExGovernor`` is a time-locked multi-signature wallet that has permission to perform administrative functions within the protocol. Functions are timelocked (see below). Many functions that can be used to mitigate damage in case of emergencies (for example, if a vulnerability is discovered that puts user funds at risk) do not have a timelock.
|
||||
|
||||
The ``ZeroExGovernor`` is able to perform the following functions within the protocol:
|
||||
|
||||
Managing Ownership
|
||||
==================
|
||||
|
||||
The ``ZeroExGovernor`` can transfer ownership of any contract for which it is the ``owner`` by calling the following function:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Transfers ownership to a new address.
|
||||
/// @param newOwner Address of the new owner.
|
||||
function transferOwnership(address newOwner)
|
||||
public;
|
||||
|
||||
Managing Authorizations
|
||||
=======================
|
||||
|
||||
The ``ZeroExGovernor`` can also manage authorizations all permissioned contracts in the Exchange and Staking systems. While the ``ZeroExGovernor`` itself is currently the only authorized address in these contracts, this feature can be used to allow new contracts to perform admin functions under different conditions in the future (such as with an on-chain token vote).
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(
|
||||
address target,
|
||||
uint256 index
|
||||
)
|
||||
external;
|
||||
|
||||
|
||||
Administering Systems
|
||||
=======================
|
||||
|
||||
The governor owns all permissioned, trusted contracts under the 0x Protocol. Any ``onlyOwner`` function can be executed by the governor. The governor requires 2/3 signatures and is timelocked.
|
||||
|
||||
|
||||
Timelocks
|
||||
============
|
||||
Function timelocks are represented in days, where one day is equivalent to 86,400 seconds.
|
||||
|
||||
.. csv-table::
|
||||
:header: "Contract", "Function", "Selector", "Timelock"
|
||||
|
||||
AllowanceTarget, ``addAuthorizedAddress``, ``42f1181e``, 1 day
|
||||
AllowanceTarget, ``removeAuthorizedAddress``, ``70712939``, 0 days
|
||||
AllowanceTarget, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 0 days
|
||||
Governor, ``registerFunctionCall``, ``751ad560``, 1 day
|
||||
ExchangeProxy, ``extend``, ``6eb224cb``, 1 day
|
||||
ExchangeProxy, ``migrate``, ``261fe679``, 1 day
|
||||
ExchangeProxy, ``rollback``, ``9db64a40``, 0 days
|
||||
ExchangeProxy, ``setQuoteSigner``, ``<deprecation in progress>``, 1 day
|
||||
ExchangeProxy, ``setTransformerDeployer``, ``87c96419``, 1 day
|
||||
ExchangeProxy, ``transferOwnership``, ``f2fde38b``, 1 day
|
||||
StakingProxy, ``addExchangeAddress``, ``8a2e271a``, 14 days
|
||||
StakingProxy, ``removeExchangeAddress``, ``01e28d84``, 14 days
|
||||
StakingProxy, ``attachStakingContract``, ``66615d56``, 14 days
|
||||
StakingProxy, ``detachStakingContract``, ``37b006a6``, 14 days
|
||||
StakingProxy, ``setParams``, ``9c3ccc82``, 7 days
|
||||
StakingProxy, ``addAuthorizedAddress``, ``42f1181e``, 14 days
|
||||
StakingProxy, ``removeAuthorizedAddress``, ``70712939``, 14 days
|
||||
StakingProxy, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 14 days
|
||||
StakingProxy, ``transferOwnership``, ``f2fde38b``, 14 days
|
||||
ZrxVault, ``setStakingProxy``, ``6bf3f9e5``, 14 days
|
||||
ZrxVault, ``enterCatastrophicFailure``, ``c02e5a7f``, 0 days
|
||||
ZrxVault, ``setZrxProxy``, ``ca5b0218``, 14 days
|
||||
ZrxVault, ``addAuthorizedAddress``, ``42f1181e``, 14 days
|
||||
ZrxVault, ``removeAuthorizedAddress``, ``70712939``, 14 days
|
||||
ZrxVault, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 14 days
|
||||
ZrxVault, ``transferOwnership``, ``f2fde38b``, 14 days
|
@@ -1,36 +0,0 @@
|
||||
###############################
|
||||
Overview
|
||||
###############################
|
||||
|
||||
The 0x Exchange implements a delegate-call proxy pattern to create a system of composable smart contracts. This architecture enables 0x to innovate with minimal friction alongside the growing DeFi ecosystem.
|
||||
|
||||
The diagram below illustrates our system (click to enlarge).
|
||||
|
||||
.. image:: ../_static/img/architecture.png
|
||||
:scale: 70%
|
||||
|
||||
------------
|
||||
|
||||
The table below defines our smart contract nomenclature.
|
||||
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Term** | **Definition** |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Proxy <./proxy.html>`_ | The point of entry into the system. This contract delegate-calls into Features. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Features <./features.html>`_ | These contracts implement the core feature set of the 0x Protocol. They are trusted with user allowances and permissioned by the 0x Governor. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Transformers <./transformers.html>`_ | These contracts extend the core protocol. They are trustless and permissioned by the Transformer Deployer. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Flash Wallet <./flash_wallet.html>`_ | The Flash Wallet is a sandboxed escrow contract that holds funds for Transformers to operate on. For example, the ``WETHtransformer`` wraps any Ether in the Flash Wallet. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Allowance Target <../basics/allowances.html>`_ | Users set their allowances on this contract. It is scheduled to be deprecated after the official V4 release in January, 2021. After which point allowances will be set directly on the Proxy. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Governor <./governor.html>`_ | A MultiSig that governs trusted contracts in the system: Proxy, Features, Flash Wallet. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Transformer Deployer <./transformer_deployer.html>`_ | Deploys Transformers. A transformer is authenticated using a nonce of the Transformer Deployer. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `Fee Collectors <./fee_collectors.html>`_ | `Protocol fees <../basics/protocol_fees.html>`_ are paid into these contracts at time-of-fill. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| `PLP Sandbox <./plp_sandbox.html>`_ | `PLP <../advanced/plp.html>`_ liquidity providers are called from this sandbox. |
|
||||
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
@@ -1,14 +0,0 @@
|
||||
###############################
|
||||
PLP Sandbox
|
||||
###############################
|
||||
|
||||
`PLP <../advanced/plp.html>`_ are external, closed-source contracts that provide liquidity to the 0x Protocol. We want to limit the contracts called from the context of the `Proxy <./proxy.html>`_ contract because this contract has access to user funds. We must mitigate the attack vector where an ERC20 Token (or some other trusted contract) is passed in place of a legitimate PLP liquidity provider. We do this by routing trades through the PLP Sandbox.
|
||||
|
||||
The diagram below illustrates this workflow.
|
||||
|
||||
.. image:: ../_static/img/plp_sandbox.png
|
||||
:align: center
|
||||
|
||||
See the `PLP Section <../advanced/plp.html>`_ for usage. View the code for the PLP Sandbox is `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/external/LiquidityProviderSandbox.sol>`_.
|
||||
|
||||
|
@@ -1,257 +0,0 @@
|
||||
###############################
|
||||
Proxy
|
||||
###############################
|
||||
|
||||
The `ZeroEx <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_ contract implements a per-function proxy pattern. Every function registered to the proxy contract can have a distinct implementation contract. Implementation contracts are called “features” and can expose multiple, related functions. Since features can be upgraded independently, there will no longer be a collective “version” of the API, defaulting to a rolling release model. The ZeroEx contract’s only responsibility is to route (delegate) calls to per-function implementation contracts through its fallback.
|
||||
|
||||
.. image:: ../_static/img/proxy.png
|
||||
:align: center
|
||||
:scale: 100%
|
||||
|
||||
View the code for the Proxy `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroEx.sol>`_. There is also a `gas-optimized implementation <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/ZeroExOptimized.sol>`_ that may be put into production in the future (there is a lot of overhead for our integrators when redeploying this contract).
|
||||
|
||||
Bootstrapping
|
||||
=============
|
||||
The ZeroEx contract comes pre-loaded with only one Feature: `Bootstrap <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/features/BootstrapFeature.sol>`_. This exposes a ``bootstrap()`` function that can only be called by the deployer. This function does a few things:
|
||||
|
||||
1. De-register the bootstrap() function, which prevents it being called again.
|
||||
2. Self-destruct.
|
||||
3. Delegatecall the bootstrapper target contract and call data.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Execute a bootstrapper in the context of the proxy.
|
||||
function bootstrap(address target, bytes callData) external
|
||||
|
||||
Below is the bootstrap workflow (click to enlarge).
|
||||
|
||||
.. image:: ../_static/img/bootstrap.png
|
||||
:align: center
|
||||
:scale: 70%
|
||||
|
||||
Function Registry
|
||||
=================
|
||||
|
||||
One of the initial features InitialMigration bootstraps into the ZeroEx contract is the function registry feature, SimpleFunctionRegistry. This feature exposes the following function registry management features: ``extend()`` and ``rollback()``.
|
||||
|
||||
Call ``extend()`` to register a new function (selector) and implementation (address). This also maintains a history of past implementations so we can roll back to one, if needed.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Register or replace a function.
|
||||
function extend(bytes4 selector, address impl)
|
||||
external
|
||||
onlyOwner;
|
||||
|
||||
Call ``rollback()`` to revert a function implementation to a prior version in its history.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Roll back to a previousimplementation of a function.
|
||||
function rollback(bytes4 selector, address targetImpl)
|
||||
external
|
||||
onlyOwner;
|
||||
|
||||
Ownership
|
||||
=========
|
||||
Another Feature, ``InitialMigration``, bootstraps into the proxy is the Ownable feature. This exposes ownership management functions: ``transferOwnership()`` and ``getOwner()``. This feature also enables ubiquitous modifiers such as onlyOwner, so it is an implicit dependency of nearly every other feature.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// Change the owner of this contract.
|
||||
function transferOwnership(address newOwner)
|
||||
external
|
||||
onlyOwner;
|
||||
|
||||
// Get the owner of this contract.
|
||||
function getOwner()
|
||||
external
|
||||
view
|
||||
returns (address owner_);
|
||||
|
||||
Migrations
|
||||
==========
|
||||
Migrations are upgrade logic that run in the context of the proxy contract. To do this, the owner calls the ``migrate()`` function, provided by the ``Ownable`` Feature. This follows a similar sequence as the bootstrap process. Notably, it temporarily sets the owner of the contract to itself for the duration of the migration call, which allows the migrator to perform admin-level operations through other features, such as registering or rolling back new functions. Before exiting, the owner is set to the newOwner, which is passed in to the call.
|
||||
|
||||
One motivation for the existence of this function, as opposed to just having the make individual admin calls, is a shortcoming of the ZeroExGoverner contract, which is designed to perform one operation at a time, with no strict ordering of those operations.
|
||||
|
||||
This is a stripped down ``migrate()`` feature implementation:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
contract Ownable {
|
||||
|
||||
// Execute a migration function in the context of the proxy contract.
|
||||
function migrate(address target, bytes calldata data, address newOwner)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
// If the owner is already set to ourselves then we've reentered.
|
||||
require(OwnableStorage.owner != address(this));
|
||||
// Temporarily set the owner to ourselves.
|
||||
OwnableStorage.owner = address(this);
|
||||
|
||||
// Perform the migration.
|
||||
target.delegatecall(data);
|
||||
|
||||
// Set the new owner.
|
||||
OwnableStorage.owner = newOWner;
|
||||
}
|
||||
}
|
||||
|
||||
This is an example sequence of a migration (click to enlarge):
|
||||
|
||||
.. image:: ../_static/img/zero_ex_migrate.png
|
||||
:align: center
|
||||
:scale: 70%
|
||||
|
||||
Storage Buckets
|
||||
===============
|
||||
|
||||
Because feature functions get delegatecalled into, they all share the same execution context and, thus, state space. It’s critical that storage for each feature be compartmentalized from other features to avoid accidentally writing to the same slot. We solve this by strictly adhering to a storage bucket pattern for our feature contracts. This rule also extends to all inherited contracts/mixins.
|
||||
|
||||
Storage buckets are enabled by new language features in solidity 0.6, which allow us to rewrite a storage variable’s slot reference to a globally unique ID. These IDs are stored in an append-only enum defined in LibStorage, to enforce uniqueness. The true storage slot for a bucket is the feature’s storage ID multiplied by a large constant to prevent overlap between buckets.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
LibStorage {
|
||||
enum StorageId {
|
||||
MyFeature
|
||||
}
|
||||
|
||||
function getStorageSlot(StorageId id) internal pure returns (uint256) {
|
||||
return uint256(id) * 1e18;
|
||||
}
|
||||
}
|
||||
|
||||
LibMyFeatureStorage {
|
||||
// Storage layout for this feature.
|
||||
struct Storage {
|
||||
mapping(bytes32 => bytes) myData;
|
||||
}
|
||||
|
||||
// Get the storage bucket for this feature.
|
||||
function getStorage() internal view returns (Storage storage st) {
|
||||
uint256 slot = LibStorage.getStorageSlot(
|
||||
LibStorage.StorageId.MyFeature
|
||||
);
|
||||
assembly { st_slot := slot }
|
||||
}
|
||||
}
|
||||
|
||||
With the above pattern, writing to storage is simply:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
LibMyFeatureStorage.getStorage().myData[...] = ...
|
||||
|
||||
|
||||
Version Management
|
||||
==================
|
||||
|
||||
**Inspection**
|
||||
|
||||
This is a rolling release model, where every feature/function has its own version. All feature contracts (except Bootstrap because it’s ephemeral), implement the IFeature interface:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
interface IFeature {
|
||||
// The name of this feature set.
|
||||
function FEATURE_NAME() external view returns (string memory name);
|
||||
|
||||
// The version of this feature set.
|
||||
function FEATURE_VERSION() external view returns (uint256 version);
|
||||
}
|
||||
|
||||
So, to get the version of a function one could do ``IFeature(getFunctionImplementation(foo.selector)).FEATURE_VERSION``.
|
||||
|
||||
**Best Practices**
|
||||
|
||||
The registry is intentionally not prescriptive on how features should be migrated. But there are some general best practices we can follow to avoid harming users, and ourselves.
|
||||
|
||||
**Deprecation**
|
||||
|
||||
In general, unless a function has a vulnerability, we should keep it intact for the duration of the deprecation schedule. Afterwards, we can ultimately disable the function by either calling extend() with a null implementation or by calling rollback() to a null implementation.
|
||||
|
||||
**Patches**
|
||||
|
||||
These include bug-fixes, optimizations, or any other changes that preserve the intended behavior of the function. For these cases, we should upgrade the function in-place, i.e., using the same selector but changing the implementation contract, through extend().
|
||||
|
||||
**Vulnerabilities**
|
||||
|
||||
If a vulnerability is found in a live function, we should call rollback() immediately to reset it to a non-vulnerable implementation. Because rollback() is a separate function from extend(), it can be exempted from timelocks to allow a swift response.
|
||||
|
||||
**Upgrades**
|
||||
|
||||
These involve meaningful behavioral changes, such as new settlement logic, changes to the order format (or its interpretation), etc. These should always be registered under a new selector, which comes free if the arguments also change, to allow users the opportunity to opt-in to new behavior. If the upgrade is intended to replace an existing feature, the old version should follow a deprecation schedule, unless we’re confident no one is using it.
|
||||
|
||||
**Features used by Features**
|
||||
|
||||
Not all features are designed to be exclusively consumed by the public. We can have internal features by applying an onlySelf modifier to the function. We need to be mindful of another class of user: the contract itself. Avoiding missteps on this will require a combination of diligence and good regression test suites.
|
||||
|
||||
Known Risks
|
||||
===========
|
||||
|
||||
The extreme flexibility of this model means we have few built-in guardrails that more conventional architectures enjoy. To avoid pitfalls, we’ve established a few new patterns to follow during development, but the following areas will always need careful scrutiny during code reviews.
|
||||
|
||||
**Extended Attack Surface for Features**
|
||||
|
||||
Because features all run in the same execution context, they inherit potential vulnerabilities from other features. Some vulnerabilities may also arise from the interactions of separate features, which may not be obvious without examining the system as a whole. Reviewers will always need to be mindful of these scenarios and features should try to create as much isolation of responsibilities as possible.
|
||||
|
||||
**Storage Layout Risks**
|
||||
|
||||
All features registered to the proxy will run in the same storage context as the proxy itself. We employ a pattern of per-feature storage buckets (structs) with globally unique bucket slots to mitigate issues.
|
||||
|
||||
**Slot Overlap**
|
||||
|
||||
Every time we develop a new feature, an entry is appended to the ``LibStorage.StorageId`` enum, which is the bucket ID for the feature’s storage. This applies to the storage used by the proxy contract itself. When calculating the true slot for the storage bucket, this enum value is offset by ``1`` and bit shifted by ``128``:
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
function getStorageSlot(StorageId id) internal pure returns (uint256) {
|
||||
return (uint256(id) + 1) << 128;
|
||||
}
|
||||
|
||||
|
||||
Given Solidity’s `storage layout rules <https://solidity.readthedocs.io/en/v0.6.6/miscellaneous.html)>`_, subsequent storage buckets should always be 2^128 slots apart, which means buckets can have 2^128 flattened inline fields before overlapping. While it’s not impossible for buckets to overlap with this pattern, it should be extremely unlikely if we follow it closely. Maps and arrays are not stored sequentially but should also be affected by their base slot value to make collisions unlikely.
|
||||
|
||||
**Inherited Storage**
|
||||
|
||||
A more insidious way to corrupt storage buckets is to have a feature unintentionally inherit from a mixin that has plain (non-bucketed) state variables, because the mixin can potentially read/write to slots shared by other buckets through them. To avoid this:
|
||||
|
||||
1. We prefix all feature-compatible mixins with “Fixin” (“Feature” + “Mixin”) and only allow contract inheritance from these.
|
||||
|
||||
2. Storage IDs are offset by 1 before computing the slot value. This means the first real storage bucket will actually start at slot 2^128, which gives us a safety buffer for these scenarios, since it’s unlikely a mixin would unintentionally access slots beyond 2^128.
|
||||
Shared Access to Storage
|
||||
|
||||
There is nothing stopping a feature from reaching into another feature’s storage bucket and reading/modifying it. Generally this pattern is discouraged but may be necessary in some cases, or may be preferable to save gas. This can create an implicit tight coupling between features and we need to take those interactions into account when upgrading the features that own those storage buckets.
|
||||
|
||||
**Restricted Functions and Privilege Escalation**
|
||||
|
||||
We will also be registering functions that have caller restrictions. Functions designed for internal use only will have an onlySelf modifier that asserts that ``msg.sender == address(this)``. The other class of restricted functions are owner-only functions, which have an ``onlyOwner`` modifier that asserts that the ``msg.sender == LibOwnableStorage.Storage.owner``.
|
||||
|
||||
The check on owner-only functions can be easily circumvented in a feature by directly overwriting ``LibOwnableStorage.Storage.owner`` with another address. If best practices and patterns are adhered to, doing so would involve deliberate and obvious effort and should be caught in reviews.
|
||||
|
||||
**Self-Destructing Features**
|
||||
|
||||
A feature contract with self-destruct logic must safeguard this code path to only be executed after the feature is deregistered, otherwise its registered functions will fail. In most cases this would just cause the feature to temporarily go dark until we could redeploy it. But it may leave the proxy in an unusable state if this occurs in the contract of a mission-critical feature, e.g., Ownable or SimpleFunctionRegistry (neither of which can self-destruct).
|
||||
|
||||
Features should also be careful that ``selfdestruct`` is never executed in the context of the proxy to avoid destroying the proxy itself.
|
||||
|
||||
**Allowances**
|
||||
|
||||
Although the proxy will not have access to the V3 asset proxies initially, early features will require taker allowances to be accessible to the proxy somehow. Instead of having the proxy contract itself be the allowance target, we intend on using a separate “Puppet” contract, callable only by the proxy contract. This creates a layer of separation between the proxy contract and allowances, so moving user funds is a much more deliberate action. In the event of a major vulnerability, the owner can simply detach the puppet contract from the proxy. This also avoids the situation where the proxy has lingering allowances if we decide grant it asset proxy authorization.
|
||||
|
||||
**Balances**
|
||||
|
||||
Inevitably, there will be features that will cause the Exchange Proxy to hold temporary balances (e.g., payable functions). Thus, it’s a good idea that no feature should cause the Exchange Proxy to hold a permanent balance of tokens or ether, since these balances can easily get mixed up with temporary balances.
|
||||
|
||||
**Reentrancy**
|
||||
|
||||
Functions can be re-entered by default; those secured by the ``nonReentrant`` modifier cannot be re-entered.
|
||||
|
||||
**Colliding Function Selectors**
|
||||
|
||||
We manually ensure that function selectors do not collide during PR's. See the `Feature Checklist <./features.html#best-practices>`_ for a complete list of our best practices on Feature Development.
|
@@ -1,64 +0,0 @@
|
||||
###############################
|
||||
Transformer Deployer
|
||||
###############################
|
||||
|
||||
`Transformers <./transformers.html>`_ need to be permissioned because they are executed in the context of the `Flash Wallet <./flash_wallet.html>`_. This means that a malicious Transformer could grief the protocol by destroying the Flash Wallet via ``selfdestruct``, so we need some way to authenticate that the Transformer is safe to use at runtime.
|
||||
|
||||
The Transformer Deployer ``create``'s all Transformers, and its deployment nonce is used to validate a Transformer at runtime. The deployer is owned by 0x Labs, so only we are able to deploy Transformers.
|
||||
|
||||
The deployer implements two functions: ``deploy()`` and ``kill()``. The former is used to deploy new Transformers; it will emit a `Deployed <../basics/events.html#deployed>`_ event (that includes the nonce) or reverts if it fails to ``create`` the Transformer. The ``kill()`` function is used to destroy deprecated Transformers; this emits a `Killed <../basics/events.html#killed>`_ event or reverts if the Transformer's ``die()`` function reverts. Note that we cannot verify a Transformer called ``selfdestruct`` in the ``kill`` function because this information is not available until after the transaction executes.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Deploy a new contract. Only callable by an authority.
|
||||
/// Any attached ETH will also be forwarded.
|
||||
function deploy(bytes memory bytecode)
|
||||
public
|
||||
payable
|
||||
onlyAuthorized
|
||||
returns (address deployedAddress);
|
||||
|
||||
/// @dev Call `die()` on a contract. Only callable by an authority.
|
||||
/// @param target The target contract to call `die()` on.
|
||||
/// @param ethRecipient The Recipient of any ETH locked in `target`.
|
||||
function kill(IKillable target, address payable ethRecipient)
|
||||
public
|
||||
onlyAuthorized;
|
||||
|
||||
View the code for the Transformer Deployer `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/external/TransformerDeployer.sol>`__.
|
||||
|
||||
|
||||
Permissionless Transfomer Deployer
|
||||
===================================
|
||||
|
||||
A permissionless deployer has been developed and can be seen `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/external/PermissionlessTransformerDeployer.sol>`__. This serves a similar function to the current delployer, only it is capable of validating the Transformer's bytecode before deploying. It does this by tracing the bytecode in search of reachable opcodes that could post a threat to the Flash Wallet.
|
||||
|
||||
The ``isDelegateCallSafe`` function performs this check. It will return ``false`` if any of the following opcodes are reachable: ``callcode``, ``delegatecall``, ``selfdestruct``, ``create``, ``create2``, ``sload``, ``sstore``.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Checks whether a given address is safe to be called via
|
||||
/// delegatecall. A contract is considered unsafe if it includes any
|
||||
/// of the following opcodes: CALLCODE, DELEGATECALL, SELFDESTRUCT,
|
||||
/// CREATE, CREATE2, SLOAD, and STORE. This code is adapted from
|
||||
/// https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/IndestructibleRegistry.sol
|
||||
/// @param target The address to check.
|
||||
/// @return True if the contract is considered safe for delegatecall.
|
||||
function isDelegateCallSafe(address target) public view returns (bool);
|
||||
|
||||
THe ``deploy`` function is similar to the existing Transformer Deployer, only it uses a user-provided nonce to deploy the Transformer.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
/// @dev Deploy a new contract. Any attached ETH will be forwarded.
|
||||
function deploy(bytes memory bytecode, bytes32 salt)
|
||||
public
|
||||
payable
|
||||
returns (address deployedAddress);
|
||||
|
||||
|
||||
Note that there is no ``kill`` function in this deployer.
|
||||
|
||||
View the code for the Permissionless Transformer Deployer `here <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/external/PermissionlessTransformerDeployer.sol>`_.
|
||||
|
||||
There is some overhead to switching over to this deployer, as the `Flash Wallet <./flash_wallet.html>`_ would need to be redeployed and some integrators would need to update their code. Therefore, this will be put into production once there is community-demand for permissionless transformers. Reach out to us on `Discord <https://discord.com/invite/d3FTX3M>`_ if you'd like to deploy a Transformer!
|
@@ -1,53 +0,0 @@
|
||||
###############################
|
||||
Transformers
|
||||
###############################
|
||||
|
||||
Transformers extend the core protocol. They are trustless and permissioned by the `Transformer Deployer <./transformer_deployer.html>`_. A Transformer is identified by the nonce of the Transformer Deployer that corresponds to its address. These contracts are executed in the context of the `Flash Wallet <./flash_wallet.html>`_ (via ``delegatecall``).
|
||||
|
||||
Below is a catalog of Transformers.
|
||||
|
||||
.. table::
|
||||
:widths: 20 60 10 10
|
||||
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **Transformer** | **Description** | **Nonce** | **Resources** |
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| FillQuoteTransformer | Aggregates Liquidity across DEXs and Native 0x Orders. | 9 | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol>`__; `Usage <../advanced/erc20_transformations.html#liquidity-aggregation>`__ |
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| AffiliateFeesTransformer | Allows integrators to charge an affiliate fee when an order is filled by their platform. | 8 | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/AffiliateFeeTransformer.sol>`__; `Usage <../advanced/erc20_transformations.html#affiliate-fees>`__ |
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| PayTakerTransformer | Forwards funds in the Flash Wallet to the Taker. | 7 | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol>`__; `Usage <../advanced/erc20_transformations.html#pay-taker>`__ |
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| WethTransformer | Wraps ETH into WETH (and unwraps) | 6 | `Code <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/WethTransformer.sol>`__; `Usage <../advanced/erc20_transformations.html#weth-wrapping>`__ |
|
||||
+--------------------------+------------------------------------------------------------------------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
Implementing a Transformer
|
||||
==========================
|
||||
Transformers are currently used by the `TransformERC20Feature <./features.html>`_ to aggregate liquidity and perform operations on ERC20 tokens (ex, wrapping ETH). Your transformer should inherit from `Transformer Contract <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/Transformer.sol>`_ and implement the interface in `IERC20Transformer <https://github.com/0xProject/protocol/blob/development/contracts/zero-ex/contracts/src/transformers/IERC20Transformer.sol>`_.
|
||||
|
||||
.. code-block:: solidity
|
||||
|
||||
// @dev A transformation callback used in `TransformERC20.transformERC20()`.
|
||||
interface IERC20Transformer {
|
||||
|
||||
/// @dev Context information to pass into `transform()` by `TransformERC20.transformERC20()`.
|
||||
struct TransformContext {
|
||||
// The caller of `TransformERC20.transformERC20()`.
|
||||
address payable sender;
|
||||
// taker The taker address, which may be distinct from `sender` in the case
|
||||
// meta-transactions.
|
||||
address payable taker;
|
||||
// Arbitrary data to pass to the transformer.
|
||||
bytes data;
|
||||
}
|
||||
|
||||
/// @dev Called from `TransformERC20.transformERC20()`. This will be
|
||||
/// delegatecalled in the context of the FlashWallet instance being used.
|
||||
/// @param context Context information.
|
||||
/// @return success The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).
|
||||
function transform(TransformContext calldata context)
|
||||
external
|
||||
returns (bytes4 success);
|
||||
}
|
50
docs/basics/addresses.md
Normal file
50
docs/basics/addresses.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Addresses
|
||||
---
|
||||
|
||||
::: {.note}
|
||||
::: {.title}
|
||||
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
|
||||
|
||||
--------------------------------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
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 [0x407b4128e9ecad8769b2332312a9f655cb9f5f3a](https://etherscan.io/address//0x407b4128e9ecad8769b2332312a9f655cb9f5f3a)
|
||||
exchangeProxyTransformerDeployer [0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb](https://etherscan.io/address//0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb)
|
||||
--------------------------------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Transformers
|
||||
|
||||
------------------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
wethTransformer [0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7](https://etherscan.io/address//0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7)
|
||||
payTakerTransformer [0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e](https://etherscan.io/address//0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e)
|
||||
fillQuoteTransformer [0x5ce5174d7442061135ea849970ffc7763920e0fd](https://etherscan.io/address//0x5ce5174d7442061135ea849970ffc7763920e0fd)
|
||||
affiliateFeeTransformer [0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f](https://etherscan.io/address//0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f)
|
||||
------------------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# ZRX / Staking
|
||||
|
||||
-------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
-------------------- ------------------------------------------------------------------------------------------------------------------------
|
||||
devUtils [0x74134cf88b21383713e096a5ecf59e297dc7f547](https://etherscan.io/address//0x74134cf88b21383713e096a5ecf59e297dc7f547)
|
||||
etherToken [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/address//0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2)
|
||||
erc20BridgeSampler [0xd8c38704c9937ea3312de29f824b4ad3450a5e61](https://etherscan.io/address//0xd8c38704c9937ea3312de29f824b4ad3450a5e61)
|
||||
-------------------- ------------------------------------------------------------------------------------------------------------------------
|
12
docs/basics/allowances.md
Normal file
12
docs/basics/allowances.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Allowances
|
||||
---
|
||||
|
||||
Both maker and taker allowance should be be set directly on the
|
||||
[Exchange Proxy contract](./addresses.html#exchange-v4).
|
||||
|
||||
For takers, legacy allowances set on the [Allowance
|
||||
Target](./addresses.html#exchange-v4) will continue to work during this
|
||||
transition period but will suffer a gas penalty. It\'s highly encouraged
|
||||
to migrate allowances over to the Exchange Proxy as soon as possible to
|
||||
avoid interruption.
|
377
docs/basics/events.md
Normal file
377
docs/basics/events.md
Normal file
@@ -0,0 +1,377 @@
|
||||
---
|
||||
title: 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}
|
||||
::: {.title}
|
||||
Warning
|
||||
:::
|
||||
|
||||
There are pending upgrades that impact these events. Please see the
|
||||
[Releases](../additional/releases.html) page for more details.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
::: {.note}
|
||||
::: {.title}
|
||||
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](#deployed) Emitted by the [Transformer TransformerDeployer
|
||||
Deployer](../architecture/transformer_deployer.html) when a
|
||||
[Transformer](../architecture/transformers.html) is deployed.
|
||||
|
||||
[ERC20BridgeTransfer](#erc20bridgetransfer) Emitted when a trade occurs. FlashWallet
|
||||
|
||||
[Fill](#fill) Emitted by Exchange V3 when an order is filled. Exchange V3
|
||||
|
||||
[Killed](#killed) Emitted by the [Transformer TransformerDeployer
|
||||
Deployer](../architecture/transformer_deployer.html) when a
|
||||
[Transformer](../architecture/transformers.html) is killed.
|
||||
|
||||
[LimitOrderFilled](#limitorderfilled) Emitted when a [V4 Limit Order](./orders.html#limit-orders) is filled. ExchangeProxy
|
||||
|
||||
[LiquidityProviderSwap](#liquidityproviderswap) Emitted when a [PLP](../advanced/plp.html) executes a swap. ExchangeProxy
|
||||
|
||||
[OrderCancelled](#ordercancelled) Emitted when a V4 Limit or RFQ Order is cancelled. ExchangeProxy
|
||||
|
||||
[MetaTransactionExecuted](#metatransactionexecuted) Emitted when a meta-transaction is executed on the Exchange Proxy. Note ExchangeProxy
|
||||
that this differs from meta-transactions that are executed on Exchange V3.
|
||||
|
||||
[Migrated](#migrated) Emitted when [ExchangeProxy.migrate()]{.title-ref} is called. ExchangeProxy
|
||||
|
||||
[PairCancelledLimitOrders](#paircancelledlimitorders) Emitted when a Market Pair is cancelled for Limit Orders (see ExchangeProxy
|
||||
[cancelPairLimitOrders](./functions.html#cancelpairlimitorders)).
|
||||
|
||||
[PairCancelledRfqOrders](#paircancelledrfqorders) Emitted when a Market Pair is cancelled for RFQ Orders (see ExchangeProxy
|
||||
[cancelPairRfqOrders](./functions.html#cancelpairrfqorders)).
|
||||
|
||||
[ProtocolFeeUnfunded](#protocolfeeunfunded) Emitted when an order is skipped due to a lack of funds to pay the 0x FlashWallet
|
||||
Protocol fee.
|
||||
|
||||
[ProxyFunctionUpdated](#proxyfunctionupdated) Emitted when a function is upgraded via [extend()]{.title-ref} or ExchangeProxy
|
||||
[rollback()]{.title-ref}
|
||||
|
||||
[QuoteSignerUpdated](#quotesignerupdated) Emitted when [ExchangeProxy.setQuoteSigner()]{.title-ref} is called. ExchangeProxy
|
||||
|
||||
[RfqOrderFilled](#rfqorderfilled) Emitted when a [V4 RFQ Order](./orders.html#rfq-orders) is filled. ExchangeProxy
|
||||
|
||||
[RfqOrderOriginsAllowed](#rfqorderoriginsallowed) Emitted when a tx.origin is added/removed for RFQ, via ExchangeProxy
|
||||
[registerAllowedRfqOrigins](./functions.html#registerallowedrfqorigins)
|
||||
|
||||
[OrderSignerRegistered](#ordersignerregistered) Emitted when an order signer is added/removed for a maker, via ExchangeProxy
|
||||
[registerAllowedOrderSigner](./functions.html#registerallowedordersigner)
|
||||
|
||||
[TransformedERC20](#transformederc20) Emitted when an [ERC20 ExchangeProxy
|
||||
Transformation](../advanced/erc20_transformations.html) completes.
|
||||
|
||||
[TransformerDeployerUpdated](#transformerdeployerupdated) Emitted when the Transformer Deployer is upgraded. ExchangeProxy
|
||||
|
||||
[TransformerMetadata](#transformermetadata) A general, customizable event emitted that can be emitted by transformers FlashWallet
|
||||
as-needed.
|
||||
----------------------------------------------------------- --------------------------------------------------------------------------- ---------------------
|
||||
|
||||
# Deployed
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.solidity}
|
||||
event LiquidityProviderSwap(
|
||||
address inputToken,
|
||||
address outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
address provider,
|
||||
address recipient
|
||||
);
|
||||
```
|
||||
|
||||
# Migrated
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Raised when `setQuoteSigner()` is called.
|
||||
/// @param quoteSigner The new quote signer.
|
||||
event QuoteSignerUpdated(address quoteSigner);
|
||||
```
|
||||
|
||||
# RfqOrderFilled
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.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
|
||||
);
|
||||
```
|
||||
|
||||
# OrderSignerRegistered
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Emitted when new order signers are registered
|
||||
/// @param maker The maker address that is registering a designated signer.
|
||||
/// @param signer The address that will sign on behalf of maker.
|
||||
/// @param allowed Indicates whether the address should be allowed.
|
||||
event OrderSignerRegistered(
|
||||
address maker,
|
||||
address signer,
|
||||
bool allowed
|
||||
);
|
||||
```
|
||||
|
||||
# TransformedERC20
|
||||
|
||||
``` {.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
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Raised when `setTransformerDeployer()` is called.
|
||||
/// @param transformerDeployer The new deployer address.
|
||||
event TransformerDeployerUpdated(address transformerDeployer);
|
||||
```
|
||||
|
||||
# TransformerMetadata
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev A transformer that just emits an event with an arbitrary byte payload.
|
||||
event TransformerMetadata(
|
||||
bytes32 callDataHash,
|
||||
address sender,
|
||||
address taker,
|
||||
bytes data
|
||||
);
|
||||
```
|
826
docs/basics/functions.md
Normal file
826
docs/basics/functions.md
Normal file
@@ -0,0 +1,826 @@
|
||||
---
|
||||
title: 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](#filllimitorder) Fills a Limit Order up to the amount
|
||||
requested.
|
||||
|
||||
[fillOrKillLimitOrder](#fillorkilllimitorder) Fills exactly the amount requested or
|
||||
reverts.
|
||||
|
||||
[cancelLimitOrder](#cancellimitorder) Cancels an order so that it can no longer be
|
||||
filled.
|
||||
|
||||
[batchCancelLimitOrders](#batchcancellimitorders) A batch call to
|
||||
[cancelLimitOrder]{.title-ref}.
|
||||
|
||||
[cancelPairLimitOrders](#cancelpairlimitorders) Cancels Limit orders in a specific market
|
||||
pair. Ex: Cancel all Limit Orders selling
|
||||
WETH for USDC.
|
||||
|
||||
[cancelPairLimitOrdersWithSigner](#cancelpairlimitorderswithsigner) Same functionality to `cancelPairLimitOrders`
|
||||
but called by a registered order signer
|
||||
instead of the maker itself.
|
||||
|
||||
[batchCancelPairLimitOrders](#batchcancelpairlimitorders) A batch call to
|
||||
[cancelPairLimitOrders]{.title-ref}.
|
||||
|
||||
[batchCancelPairLimitOrdersWithSigner](#batchcancelpairlimitorderswithsigner) Same functionality to `cancelPairLimitOrders`
|
||||
but called by a registered order signer
|
||||
instead of the maker itself.
|
||||
|
||||
[getLimitOrderInfo](#getlimitorderinfo) Returns the state of a given order.
|
||||
|
||||
[getLimitOrderHash](#getlimitorderhash) Returns the EIP-712 hash for an order.
|
||||
|
||||
**RFQ Orders** **Overview**
|
||||
|
||||
[fillRfqOrder](#fillrfqorder) These are analogous to the above LimitOrder
|
||||
functions.
|
||||
------------------------------------------------------------------------------- ---------------------------------------------
|
||||
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [fillOrKillRfqOrder](#fillorkillrfqorder) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [cancelRfqOrder](#cancelrfqorder) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [batchCancelRfqOrders](#batchcancelrfqorders) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [cancelPairRfqOrders](#cancelpairrfqorders) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [cancelPairRfqOrdersWithSigner](#cancelpairrfqorderswithsigner) \|
|
||||
\|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [batchCancelPairRfqOrders](#batchcancelpairrfqorders) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \|
|
||||
[batchCancelPairRfqOrdersWithSigner](#batchcancelpairrfqorderswithsigner)
|
||||
\| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [getRfqOrderInfo](#getrfqorderinfo) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| \| [getRfqOrderHash](#getrfqorderhash) \| \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| [registerAllowedRfqOrigins](#registerallowedrfqorigins) \| Register
|
||||
tx.origin addresses that are allowed to fill an RFQ order. \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| [registerAllowedOrderSigner](#registerallowedordersigner) \| Register
|
||||
addresses that can sign orders on behalf of `msg.sender`. \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| [isValidOrderSigner](#isvalidordersigner) \| Returns whether a given
|
||||
address is allowed to sign orders for a given \| \| \| maker address. \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| **Protocol Fees** \| **Overview** \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| [getProtocolFeeMultiplier](#getprotocolfeemultiplier) \| Takers of
|
||||
limit orders pay a protocol fee of [Multiplier \*
|
||||
tx.gasprice]{.title-ref}. \| \| \| This returns the
|
||||
[Multiplier]{.title-ref}. \|
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\--+
|
||||
\| [transferProtocolFeesForPools](#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`:
|
||||
|
||||
``` {.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`:
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.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` or `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## batchCancelLimitOrders
|
||||
|
||||
This function cancels multiple limit orders created by the caller:
|
||||
|
||||
``` {.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` or
|
||||
`!isValidOrderSigner(maker, msg.sender)` 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.
|
||||
|
||||
``` {.solidity}
|
||||
function cancelPairLimitOrders(
|
||||
address makerToken,
|
||||
address takerToken,
|
||||
uint256 salt;
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
This function emits a
|
||||
[PairCancelledLimitOrders](../basics/events.html#paircancelledlimitorders)
|
||||
event, or reverts if the `salt` parameter is ≤ to a previous `salt`.
|
||||
|
||||
## cancelPairLimitOrdersWithSigner
|
||||
|
||||
Same functionality as `cancelPairLimitOrders` but `msg.sender` is a
|
||||
registered order signer instead of the maker itself.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Cancel all limit orders for a given maker and pair with a salt less
|
||||
/// than the value provided. The caller must be a signer registered to the maker.
|
||||
/// Subsequent calls to this function with the same maker and pair require the
|
||||
/// new salt to be >= the old salt.
|
||||
/// @param maker The maker for which to cancel.
|
||||
/// @param makerToken The maker token.
|
||||
/// @param takerToken The taker token.
|
||||
/// @param minValidSalt The new minimum valid salt.
|
||||
function cancelPairLimitOrdersWithSigner(
|
||||
address maker,
|
||||
IERC20TokenV06 makerToken,
|
||||
IERC20TokenV06 takerToken,
|
||||
uint256 minValidSalt
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
Reverts if `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## batchCancelPairLimitOrders
|
||||
|
||||
This function performs multiple `cancelPairLimitOrders()` at once. Each
|
||||
respective index across arrays is equivalent to a single call.
|
||||
|
||||
``` {.solidity}
|
||||
function batchCancelPairLimitOrders(
|
||||
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.
|
||||
|
||||
## batchCancelPairLimitOrdersWithSigner
|
||||
|
||||
Same functionality as `batchCancelPairLimitOrders` but `msg.sender` is a
|
||||
registered order signer instead of the maker itself.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Cancel all limit orders for a given maker and pairs with salts less
|
||||
/// than the values provided. The caller must be a signer registered to the maker.
|
||||
/// Subsequent calls to this function with the same maker and pair require the
|
||||
/// new salt to be >= the old salt.
|
||||
/// @param maker The maker for which to cancel.
|
||||
/// @param makerTokens The maker tokens.
|
||||
/// @param takerTokens The taker tokens.
|
||||
/// @param minValidSalts The new minimum valid salts.
|
||||
function batchCancelPairLimitOrdersWithSigner(
|
||||
address maker,
|
||||
IERC20TokenV06[] memory makerTokens,
|
||||
IERC20TokenV06[] memory takerTokens,
|
||||
uint256[] memory minValidSalts
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
Reverts if `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## 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.
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.solidity}
|
||||
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
|
||||
```
|
||||
|
||||
The hash can be manually generated using the following code:
|
||||
|
||||
``` {.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.
|
||||
keccak256('ZeroEx'),
|
||||
keccak256('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 maker,',
|
||||
'address taker,',
|
||||
'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`:
|
||||
|
||||
``` {.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](#registerallowedrfqorigins)).
|
||||
- The maker\'s signature is invalid.
|
||||
|
||||
## fillOrKillRfqOrder
|
||||
|
||||
`fillOrKillRfqOrder()` fills a single RFQ order for **exactly**
|
||||
`takerTokenFillAmount`:
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.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` or `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## batchCancelRfqOrders
|
||||
|
||||
This function cancels multiple RFQ orders created by the caller:
|
||||
|
||||
``` {.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` or
|
||||
`!isValidOrderSigner(maker, msg.sender)` for any orders 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.
|
||||
|
||||
``` {.solidity}
|
||||
function cancelPairRfqOrders(
|
||||
address makerToken,
|
||||
address takerToken,
|
||||
uint256 salt;
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
This function emits a
|
||||
[PairCancelledRfqOrders](../basics/events.html#paircancelledrfqorders)
|
||||
event, or reverts if the `salt` parameter is ≤ to a previous `salt`.
|
||||
|
||||
## cancelPairRfqOrdersWithSigner
|
||||
|
||||
Same functionality as `cancelPairRfqOrders` but `msg.sender` is a
|
||||
registered order signer instead of the maker itself.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
|
||||
/// than the value provided. The caller must be a signer registered to the maker.
|
||||
/// Subsequent calls to this function with the same maker and pair require the
|
||||
/// new salt to be >= the old salt.
|
||||
/// @param maker The maker for which to cancel.
|
||||
/// @param makerToken The maker token.
|
||||
/// @param takerToken The taker token.
|
||||
/// @param minValidSalt The new minimum valid salt.
|
||||
function cancelPairRfqOrdersWithSigner(
|
||||
address maker,
|
||||
IERC20TokenV06 makerToken,
|
||||
IERC20TokenV06 takerToken,
|
||||
uint256 minValidSalt
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
Reverts if `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## batchCancelPairRfqOrders
|
||||
|
||||
`batchCancelPairRfqOrders()` performs multiple `cancelPairRfqOrders()`
|
||||
at once. Each respective index across arrays is equivalent to a single
|
||||
call.
|
||||
|
||||
``` {.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.
|
||||
|
||||
## batchCancelPairRfqOrdersWithSigner
|
||||
|
||||
Same functionality as `batchCancelPairRfqOrders` but `msg.sender` is a
|
||||
registered order signer instead of the maker itself.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Cancel all RFQ orders for a given maker and pairs with salts less
|
||||
/// than the values provided. The caller must be a signer registered to the maker.
|
||||
/// Subsequent calls to this function with the same maker and pair require the
|
||||
/// new salt to be >= the old salt.
|
||||
/// @param maker The maker for which to cancel.
|
||||
/// @param makerTokens The maker tokens.
|
||||
/// @param takerTokens The taker tokens.
|
||||
/// @param minValidSalts The new minimum valid salts.
|
||||
function batchCancelPairRfqOrdersWithSigner(
|
||||
address maker,
|
||||
IERC20TokenV06[] memory makerTokens,
|
||||
IERC20TokenV06[] memory takerTokens,
|
||||
uint256[] memory minValidSalts
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
Reverts if `!isValidOrderSigner(maker, msg.sender)`.
|
||||
|
||||
## 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.
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.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:
|
||||
|
||||
``` {.solidity}
|
||||
bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getRfqOrderHash(order);
|
||||
```
|
||||
|
||||
The hash can be manually generated using the following code:
|
||||
|
||||
``` {.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.
|
||||
keccak256('ZeroEx'),
|
||||
keccak256('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`.
|
||||
|
||||
``` {.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.
|
||||
|
||||
## registerAllowedOrderSigner
|
||||
|
||||
Calls to fill functions require a signature provided by the maker. In
|
||||
cases where the signer can\'t be the maker itself (e.g. a contract
|
||||
wallet), the maker can delegate signing to another address.
|
||||
|
||||
To register a new delegated order signer, the maker can call
|
||||
`registerAllowedOrderSigner` with `allowed == true`.
|
||||
|
||||
To revoke permission to a signer, the maker can call
|
||||
`registerAllowedOrderSigner` with `allowed == false`.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Register a signer who can sign on behalf of msg.sender
|
||||
/// This allows one to sign on behalf of a contract that calls this function
|
||||
/// @param signer The address from which you plan to generate signatures
|
||||
/// @param allowed True to register, false to unregister.
|
||||
function registerAllowedOrderSigner(
|
||||
address signer,
|
||||
bool allowed
|
||||
)
|
||||
external;
|
||||
```
|
||||
|
||||
This function emits an
|
||||
[OrderSignerRegistered](../basics/events.html#ordersignerregistered)
|
||||
event.
|
||||
|
||||
## isValidOrderSigner
|
||||
|
||||
Returns whether the `signer` is allowed to sign orders on behalf of the
|
||||
`maker`.
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev checks if a given address is registered to sign on behalf of a maker address
|
||||
/// @param maker The maker address encoded in an order (can be a contract)
|
||||
/// @param signer The address that is providing a signature
|
||||
function isValidOrderSigner(
|
||||
address maker,
|
||||
address signer
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (bool isAllowed);
|
||||
```
|
||||
|
||||
# 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.
|
||||
|
||||
``` {.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).
|
||||
|
||||
``` {.solidity}
|
||||
/// @dev Transfers protocol fees from the `FeeCollector` pools into
|
||||
/// the staking contract.
|
||||
/// @param poolIds Staking pool IDs
|
||||
function transferProtocolFeesForPools(bytes32[] calldata poolIds)
|
||||
external;
|
||||
```
|
230
docs/basics/orders.md
Normal file
230
docs/basics/orders.md
Normal file
@@ -0,0 +1,230 @@
|
||||
---
|
||||
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](./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\]
|
||||
--------------- ----------- --------------------------------------------------------------------------
|
||||
|
||||
# How To Sign
|
||||
|
||||
Both Limit & RFQ orders must be signed by the [maker]{.title-ref} or a
|
||||
registered order signer
|
||||
([registerAllowedOrderSigner](./functions.html#registerallowedrfqorigins)).
|
||||
This signature is needed to fill an order, see [Basic
|
||||
Functionality](./functions.html).
|
||||
|
||||
The protocol accepts signatures defined by the following struct:
|
||||
|
||||
``` {.solidity}
|
||||
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](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification-of-the-eth_signtypeddata-json-rpc)
|
||||
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.
|
||||
:::
|
||||
|
||||
``` {.javascript}
|
||||
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](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.
|
||||
|
||||
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:
|
||||
|
||||
``` {.typescript}
|
||||
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,
|
||||
}
|
||||
}
|
||||
```
|
@@ -1,5 +0,0 @@
|
||||
###############################
|
||||
Governance
|
||||
###############################
|
||||
|
||||
The 0x Community uses their ZRX (and staked ZRX) tokens to govern the protocol, by voting on proposals called `ZEIPs <https://github.com/0xProject/ZEIPs>`_. Anyone can propose a change to the system by creating a ZEIP. Visit `https://0x.org/zrx/vote <https://0x.org/zrx/vote>`_ to participate!
|
@@ -1,9 +0,0 @@
|
||||
###############################
|
||||
Research
|
||||
###############################
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<embed>
|
||||
<iframe class="researchPdf" src="../_static/protocol-fees.pdf" width="100%" />
|
||||
</embed>
|
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
###############################
|
||||
Staking Reward Formula
|
||||
###############################
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<embed>
|
||||
<iframe class="researchPdf" src="../_static/adjusted-staking-percentage-formula.pdf" width="100%" />
|
||||
</embed>
|
Reference in New Issue
Block a user