├── ISSUE_TEMPLATE.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── ZEIP-X.md ├── ZEIPs ├── ZEIP-1.md ├── ZEIP-15.md ├── ZEIP-17.md ├── ZEIP-18.md ├── ZEIP-19.md ├── ZEIP-2.md ├── ZEIP-20.md ├── ZEIP-28.md ├── ZEIP-31.md ├── ZEIP-32.md ├── ZEIP-33.md ├── ZEIP-34.md ├── ZEIP-35.md ├── ZEIP-36.md ├── ZEIP-37.md ├── ZEIP-40.md ├── ZEIP-41.md ├── ZEIP-42.md ├── ZEIP-47.md ├── ZEIP-50.md ├── ZEIP-59.md ├── ZEIP-61.md └── ZEIP-7.md └── zeip96_images ├── ABDK_0x_MetaTransaction_v_1_0.pdf ├── metaTxn_current.png ├── metaTxn_proposed.png ├── multihopAudit (1).svg └── multihopAudit.svg /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Summary ( 2-5 Sentences ) 2 | "If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the issue. 3 | 4 | ## Type: 5 | Select on of the following [CORE | NON-CORE | PARAMETERS | OPERATIONS] 6 | 7 | ## Motivation 8 | The motivation is critical to change the 0x protocol. It should clearly explain why the existing protocol specification is inadequate with respect to the issue raised. It is acceptable to state an issue without offering suggestions if the issue is cleary defined. 9 | 10 | ## Specification 11 | The technical specification should describe the syntax and semantics of the issue. Be it an improvement in computational efficiency or security, try to provide concrete evidence and easily testable cases. If a suggestion is proposed, provide sufficient details so that an implementation would be possible (Proof of Concepts are acceptable). 12 | 13 | ## Rationale (if a suggestion is proposed) 14 | The rationale should flesh out the specification by describing what motivated the design and why particular design decisions were made. 15 | 16 | ## Implementation 17 | 18 | This section must be updated before any Core/Non-Core ZEIP is brought to an executive vote, with a summary of the latest implementation, and by tagging the Issue to the relevant PRs. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. 19 | 20 | ## Designated team: UFG 21 | 22 | This field can be left as UFG (up for grabs) in its initial discussion phase. In order for the ZEIP to be brought to vote (poll and/or executive vote), it needs to have a designated team who have agreed to work on the implementation. 23 | 24 | 25 | ## Sponsor (for CORE type only): UFG 26 | 27 | This is relevant only for ZEIPs of type CORE. This field can be left as UFG (up for grabs) in its initial discussion phase. In order for the ZEIP to be brought to vote (poll and/or executive vote), it needs to have a designated team who have agreed to schedule and sponsor the audit. 28 | 29 | ## Notes 30 | Any notes like links or references that help supporting the present claims. 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Preamble 6 | 7 | ZEIP: 8 | Title: 9 | Author: 10 | Type: 11 | Category (*only required for Standard Track): 12 | Status: Draft 13 | Created: 14 | Requires (*optional): 15 | Replaces (*optional): 16 | 17 | ## Simple Summary 18 | 19 | 20 | 21 | 22 | ## Abstract 23 | 24 | 25 | 26 | ## Motivation 27 | 28 | 29 | 30 | ## Specification 31 | 32 | 33 | 34 | ## Rationale 35 | 36 | 37 | 38 | ## Test Cases 39 | 40 | 41 | 42 | ## Implementation 43 | 44 | 45 | 46 | ## Copyright 47 | 48 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ZEIPs 4 | 5 | 0x Improvement Proposals (ZEIPs) describe standards and protocol specifications for the 0x protocol. 6 | 7 | ## Accepted ZEIPs 8 | 9 | | Title | Number | Version Included | 10 | | --------------------------------------------------------------------------------------------------------------------------- | ------ | ---------------- | 11 | | [Initial Staking Parameters](https://github.com/0xProject/ZEIPs/issues/61) | 61 | 3.0 | 12 | | [Mixed assets in "market" operations](https://github.com/0xProject/ZEIPs/issues/59) | 59 | 3.0 | 13 | | [marketBuy/SellOrdersFillOrKill](https://github.com/0xProject/ZEIPs/issues/50) | 50 | 3.0 | 14 | | [ERC20BridgeProxy](https://github.com/0xProject/ZEIPs/issues/47) | 47 | 3.0 | 15 | | [Protocol Fees](https://github.com/0xProject/ZEIPs/issues/42) | 42 | 3.0 | 16 | | [Batch Order Matching](https://github.com/0xProject/ZEIPs/issues/41) | 41 | 3.0 | 17 | | [New Order Matching Strategy](https://github.com/0xProject/ZEIPs/issues/40) | 40 | 3.0 | 18 | | [Allow 0x transactions to be cancelled (or expired)](https://github.com/0xProject/ZEIPs/issues/37) | 37 | 3.0 | 19 | | [Allow batch 0x transaction execution](https://github.com/0xProject/ZEIPs/issues/36) | 36 | 3.0 | 20 | | [Permissive Order Cancellations](https://github.com/0xProject/ZEIPs/issues/35) | 35 | 3.0 | 21 | | [0x transaction developer experience improvements](https://github.com/0xProject/ZEIPs/issues/34) | 34 | 3.0 | 22 | | [New/Consolidated Signature Type(s) and Behavior](https://github.com/0xProject/ZEIPs/issues/33) | 33 | 3.0 | 23 | | [Rich Reverts](https://github.com/0xProject/ZEIPs/issues/32) | 32 | 3.0 | 24 | | [Stake-based Liquidity Incentives](https://github.com/0xProject/ZEIPs/issues/31) | 31 | 3.0 | 25 | | [Arbitrary fee tokens](https://github.com/0xProject/ZEIPs/issues/28) | 28 | 3.0 | 26 | | [Allow for mass order cancellations based on `salt` value](https://github.com/0xProject/ZEIPs/issues/20) | 20 | 2.0 | 27 | | [Replace `isTransferable` with `fillOrder` variant that uses `delegatecall`](https://github.com/0xProject/ZEIPs/issues/19) | 19 | 2.0 | 28 | | [Allow `taker` to be different from `sender` with optional `taker` signature](https://github.com/0xProject/ZEIPs/issues/18) | 18 | 2.0 | 29 | | [Use order schema hash in signature verification for EIP712 compatibility](https://github.com/0xProject/ZEIPs/issues/17) | 17 | 2.0 | 30 | | [Do not double check signatures of previously filled/cancelled orders](https://github.com/0xProject/ZEIPs/issues/15) | 15 | 2.0 | 31 | | [On-chain order generation by smart contracts](https://github.com/0xProject/ZEIPs/issues/7) | 7 | 2.0 | 32 | | [Atomic order matching](https://github.com/0xProject/ZEIPs/issues/2) | 2 | 2.0 | 33 | | [Off-chain order generation by smart contracts](https://github.com/0xProject/ZEIPs/issues/1) | 1 | 2.0 | 34 | -------------------------------------------------------------------------------- /ZEIP-X.md: -------------------------------------------------------------------------------- 1 | This is the suggested template for new ZEIPs. 2 | 3 | Note that an ZEIP number will be assigned by an editor. When opening a pull request to submit your ZEIP, please use an abbreviated title in the filename, `ZEIP-draft_title_abbrev.md`. 4 | 5 | ## Preamble 6 | 7 | ZEIP: 8 | Title: 9 | Author: 10 | Type: 11 | Category (*only required for Standard Track): 12 | Status: Draft 13 | Created: 14 | Requires (*optional): 15 | Replaces (*optional): 16 | 17 | ## Simple Summary (2 Sentences) 18 | 19 | "If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the ZEIP. 20 | 21 | ## Abstract 22 | 23 | A short (~200 word) description of the technical issue being addressed. 24 | 25 | ## Motivation 26 | 27 | The motivation is critical for ZEIPs that want to change the 0x protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the ZEIP solves. ZEIP submissions without sufficient motivation may be rejected outright. 28 | 29 | ## Specification 30 | 31 | The technical specification should describe the syntax and semantics of any new feature and the problems it sovles. The specification should be detailed enough to allow implementation. 32 | 33 | ## Rationale 34 | 35 | The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion. 36 | 37 | ## Test Cases 38 | 39 | Test cases for an implementation are mandatory for ZEIPs that are affecting consensus changes. Other ZEIPs can choose to include links to test cases if applicable. 40 | 41 | ## Implementation 42 | 43 | The implementations must be completed before any ZEIP is given status "Final", but it need not be completed before the ZEIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. 44 | 45 | ## Copyright 46 | 47 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 48 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-1.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 1 4 | Title: Off-chain order generation by smart contracts 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2017-04-25 10 | 11 | ## Simple Summary 12 | 13 | Allow smart contracts to generate orders to be used in 0x protocol. 14 | 15 | ## Abstract 16 | 17 | In the current version of 0x protocol, Ethereum accounts can both generate and fill orders. Smart contracts are not capable of generating 0x orders as they do not possess a private key with which to produce an ECDSA signature; however, smart contracts _are_ capable of filling 0x orders that are passed to them as args. This limitation prevents Ethereum smart contracts that hold a balance of ERC20 tokens from generating liquidity via 0x protocol. 18 | 19 | ## Motivation 20 | 21 | Melonport is a platform for creating and operating investment funds. Limited partners (LPs) invest their 22 | Ethereum-based assets with a fund manager (GP) who may then invest LP funds in a set of ERC20 tokens. To prevent the GP from simply stealing LP funds, they are stored within an Ethereum smart contract that places a set of constraints on how the GP moves the assets. As a result, the GP is unable to generate an order to trade LP funds via 0x protocol but they are capable of filling 0x orders generated by others. 23 | 24 | ## Specification 25 | 26 | Allow the owner of a smart contract to generate 0x orders on behalf of the smart contract. 27 | 28 | ![zerc1 diagram](https://cloud.githubusercontent.com/assets/2459070/25763798/ab3e725e-3199-11e7-8a83-b69056192955.png) 29 | 30 | **Draft pseudo-code, going to provide more detail later.** 31 | 32 | ## Rationale 33 | 34 | ## Test Cases 35 | 36 | ## Implementation 37 | 38 | ## Copyright 39 | 40 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 41 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-15.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 15 4 | Title: Do not double check signatures of previously filled/cancelled orders 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2017-12-15 10 | 11 | ## Simple Summary 12 | 13 | Improve gas effeciency by only validating signatures once. 14 | 15 | ## Abstract 16 | 17 | Currently, if you fill (or partially fill) an order that was already filled or cancelled, the Exchange contract will re-evaluate the signature of the order. This ZEIP would remove the need to verify the signature of an already partially filled or cancelled order. 18 | 19 | ## Motivation 20 | 21 | Gas savings for orders that have previously been partially filled. 22 | 23 | ## Specification 24 | 25 | An order that has already been partially filled or cancelled always implies that the order has been approved by the maker. Skipping signature verification would save at least 3000 gas with no additional downside. 26 | 27 | ``` 28 | if (filled[orderHash] == 0 && cancelled[orderHash] == 0) { 29 | require(isValidSignature(...); 30 | } 31 | ``` 32 | 33 | ## Rationale 34 | 35 | ## Test Cases 36 | 37 | ## Implementation 38 | 39 | ## Copyright 40 | 41 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 42 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-17.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 17 4 | Title: Use order schema hash in signature verification for EIP712 compatibility 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2017-12-20 10 | Requires: EIP712 11 | 12 | ## Simple Summary 13 | 14 | Allow the signer to see 0x order data when signing in supported wallets. 15 | 16 | ## Abstract 17 | 18 | [EIP712](https://github.com/ethereum/EIPs/pull/712) describes a standard for human-readable typed data signing. This would allow the signer of a 0x order to see the exact parameters that they are signing with tools such as Metamask. In order to be compatible with this EIP, we must update how signatures are validated in the `Exchange` contract. 19 | 20 | ## Motivation 21 | 22 | Currently, it is very difficult for a user of 0x to verify that the order that they are signing is exactly what they intended to sign. This adds an extra level of trust between users and relayers, potentially opening users up to scams. Open source [tools](https://github.com/ethfinex/0x-order-verify) exist for verifying orders, but they require users to take extra steps, are more difficult to understand, and are unlikely to gain the same level of traction as functionality that is built into the user's wallet. 23 | 24 | ## Specification 25 | 26 | Currently, signatures are verified with: 27 | 28 | ``` 29 | return signer == ecrecover( 30 | keccak256("\x19Ethereum Signed Message:\n32", hash), 31 | v, 32 | r, 33 | s 34 | ); 35 | ``` 36 | 37 | Instead, we first calculate the hash of the order's schema: 38 | 39 | ``` 40 | bytes32 public constant orderSchemaHash = keccak256( 41 | "address exchangeContractAddress", 42 | "address makerAddress", 43 | "address takerAddress", 44 | "address makerTokenAddress", 45 | "address takerTokenAddress", 46 | "address feeRecipientAddress", 47 | "uint256 makerTokenAmount", 48 | "uint256 takerTokenAmount", 49 | "uint256 makerFeeAmount", 50 | "uint256 takerFeeAmount", 51 | "uint256 expirationTimestamp", 52 | "uint256 salt" 53 | ); 54 | ``` 55 | 56 | We then can verify signatures with: 57 | 58 | ``` 59 | return signer == ecrecover( 60 | keccak256(orderSchemaHash, orderHash), 61 | v, 62 | r, 63 | s 64 | ); 65 | ``` 66 | 67 | ## Rationale 68 | 69 | ## Test Cases 70 | 71 | ## Implementation 72 | 73 | ## Copyright 74 | 75 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 76 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-18.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 18 4 | Title: Allow `taker` to be different from `sender` with optional `taker` signature 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2018-01-18 10 | 11 | ## Simple Summary 12 | 13 | Allow fills and other 0x operations to be submitted by a third party (e.g Relayers or contracts). 14 | 15 | ## Abstract 16 | 17 | In the current implementation of the Exchange contract, the taker of an order is always msg.sender. By optionally allowing the signature of the taker to be passed into fillOrder, we can decouple these two addresses and allow for much greater flexibility. 18 | 19 | ## Motivation 20 | 21 | This change would allow for much easier implementations of `Exchange` wrapper contracts. Wrapper contracts are currently impractical because they are required to hold the taker's tokens that will be exchanged. Some basic use cases for wrapper contracts include: 22 | 23 | - creating orders that can only be filled by addresses in a whitelist 24 | - creating orders that can only be filled with a signature from another party 25 | - creating custom functions for conditionally filling multiple orders (similar to `batchFillOrders` or `fillOrdersUpTo`) 26 | 27 | In addition, this change greatly simplifies logic for relayers using the [matching strategy](https://0xproject.com/wiki#Matching). There is now a clear distinction between the `maker` and `taker` of an order in this model, simplifying logic for calculating fees. Tokens will also be swapped directly from the `maker` to `taker`, which results in fewer intermediate state changes and lower gas costs. 28 | 29 | ## Specification 30 | 31 | For the purposes of this proposal it makes sense to rename the `taker` parameter in the message format to `sender`, since the two are no longer necessarily the same (note: a case can be made for including both `taker` and `sender` parameters in the order message format). 32 | 33 | Psuedocode for `fillOrder`: 34 | 35 | ``` 36 | struct Order { 37 | address maker; 38 | address sender; 39 | address makerToken; 40 | address takerToken; 41 | address feeRecipient; 42 | uint256 makerTokenAmount; 43 | uint256 takerTokenAmount; 44 | uint256 makerFee; 45 | uint256 takerFee; 46 | uint256 expirationTimestampInSec; 47 | uint8 v; 48 | bytes32 r; 49 | bytes32 s; 50 | } 51 | 52 | struct Fill { 53 | uint256 takerTokenFillAmount; 54 | uint256 salt; 55 | uint8 v; 56 | bytes32 r; 57 | bytes32 s; 58 | } 59 | 60 | mapping (bytes32 => uint256) filled; 61 | 62 | function fillOrder(Order memory order, Fill memory fill) 63 | public 64 | returns (uint256 takerTokenFilledAmount) 65 | { 66 | require(order.sender == msg.sender || order.sender == address(0)); 67 | 68 | address taker; 69 | bytes32 fillHash; 70 | bytes32 orderHash = getOrderHash(order); 71 | 72 | if (fill.r == bytes32(0)) { 73 | taker = msg.sender; 74 | } else { 75 | fillHash = keccak256(orderHash, fill.takerTokenFillAmount, fill.salt); 76 | bytes32 msgHash = keccak256("\x19Ethereum Signed Message:\n32", fillHash); 77 | taker = ecrecover(msgHash, fill.v, fill.r, fill.s); 78 | } 79 | 80 | ... // remaining fill logic 81 | 82 | if (fillHash != bytes32(0)) { 83 | filled[fillHash] = takerTokenFilledAmount; // the filled mapping must be updated an extra time to prevent replay attacks 84 | } 85 | } 86 | 87 | function getOrderHash(Order memory order) 88 | internal 89 | returns (bytes32 orderHash) 90 | { 91 | orderHash = keccak256(...) // calculate order's hash 92 | } 93 | ``` 94 | 95 | ## Rationale 96 | 97 | ## Test Cases 98 | 99 | ## Implementation 100 | 101 | ## Copyright 102 | 103 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 104 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-19.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 19 4 | Title: Replace `isTransferable` with `fillOrder` variant that uses `delegatecall` 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2018-01-01 10 | 11 | ## Simple Summary 12 | 13 | Replace the transfer validity check `isTransferable` with a more succint implementation using `delegatecall`. `isTransferable` has caused issues in the past and is expensive. 14 | 15 | ## Abstract 16 | 17 | The `Exchange` contract's `fillOrder` function currently takes an argument `shouldThrowOnInsufficientBalanceOrAllowance`. If set to `false`, balances and allowances of the `makerToken`, `takerToken`, and ZRX will be checked before attempting any token transfers. If any balances or allowances are insufficient, `fillOrder` will fail gracefully be returning 0 and logging an error. This is intended to be used with any functions that fill multiple orders in a single transaction. If a single fill fails, we do not necessarily want the entire transaction to `throw` or `revert`. 18 | 19 | This proposal would remove the `shouldThrowOnInsufficientBalanceOrAllowance` argument and add a function that replicates this functionality by calling the `fillOrder` function with `delegatecall`. In this case, balances and allowances are not checked before attempting a token transfer. However, using `delegatecall` ensures that the the subcall returns false on a failed transfer, rather than reverting the entire transaction. 20 | 21 | ## Motivation 22 | 23 | The implementation of `isTransferable` contains many edge cases, is bug prone, and is a constant point of confusion in the `Exchange` contract. With the addition of the `REVERT` opcode in the Byzantium hard fork, it no longer results in gas savings compared to the transaction reverting. In addition, it is extremely expensive to use (making 8 external calls and copying an extra 384 bytes to memory), and using `delegatecall` is significantly cheaper most of the time (making 1 extra external call and copying 480 extra bytes to memory). 24 | 25 | ## Specification 26 | 27 | ``` 28 | bytes4 constant public FILL_ORDER_OR_THROW_SELECTOR = bytes4(sha3("fillOrderOrThrow(address[5],uint256[6],uint256,uint8,bytes32,bytes32)")); 29 | 30 | function fillOrderOrThrow( 31 | address[5] orderAddresses, 32 | uint256[6] orderValues, 33 | uint256 fillTakerTokenAmount, 34 | uint8 v, 35 | bytes32 r, 36 | bytes32 s) 37 | public 38 | returns (uint256 takerTokenFilledAmount) 39 | { 40 | ... // all fill logic, always reverts on a failed transfer 41 | } 42 | 43 | function fillOrderOrReturn( 44 | address[5] orderAddresses, 45 | uint256[6] orderValues, 46 | uint256 fillTakerTokenAmount, 47 | uint8 v, 48 | bytes32 r, 49 | bytes32 s) 50 | public 51 | public 52 | returns (bool success) // if we want to return the amount filled instead, we have to calculate the orderHash and then check the filled mapping before/after delegatecall 53 | { 54 | return address(this).delegatecall( 55 | FILL_ORDER_OR_THROW_SELECTOR, 56 | orderAddresses, 57 | orderValues, 58 | fillTakerTokenAmount, 59 | v, 60 | r, 61 | s 62 | ); 63 | } 64 | ``` 65 | 66 | ## Rationale 67 | 68 | ## Test Cases 69 | 70 | ## Implementation 71 | 72 | ## Copyright 73 | 74 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 75 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-2.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 2 4 | Title: Atomic Order Matching 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2017-07-07 10 | 11 | ## Simple Summary 12 | 13 | Allow a pair of opposing orders to be matched without upfront capital. 14 | 15 | ## Abstract 16 | 17 | ## Motivation 18 | 19 | Currently, order matching of limit orders is supported through use of `batchFillOrders` and `batchFillOrKillOrders`. While the net result of filling a pair of opposing orders with these functions is the same as an atomic match, a taker is still required to have sufficient funds to fill the first order in order to complete the transaction. This adds an unnecessary cost of capital and is especially problematic when matching very large orders. A taker without the necessary funds to fill the initial order would be required to break down the match into smaller batches, which is also an inefficient use of gas. 20 | 21 | ## Specification 22 | 23 | Add a `matchOrders` function that will atomically fill valid crossing orders without requiring capital upfront. This will lower the barriers to entry of running a centralized matching engine and of arbitraging across exchanges. The requirements of this function would be: 24 | 25 | - Takes 2 orders as input parameters 26 | - `orderA.makerToken` == `orderB.takerToken` 27 | - `orderA.takerToken` == `orderB.makerToken` 28 | - `msg.sender` is a valid taker for both orders 29 | - Prices of both orders cross each other 30 | - Makers of both orders receive amounts specified by orders 31 | - `msg.sender` keeps the difference 32 | 33 | ## Rationale 34 | 35 | ## Test Cases 36 | 37 | ## Implementation 38 | 39 | ## Copyright 40 | 41 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 42 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-20.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 20 4 | Title: Allow for mass order cancellations based on `salt` value 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2018-01-13 10 | 11 | ## Simple Summary 12 | 13 | Allow traders to very cheaply cancel multiple orders in a single transaction with a single state update. 14 | 15 | ## Abstract 16 | 17 | By using an incrementing number as a salt value, all previous orders which contain smaller salt numbers can be cancelled. This allows Market Makers to effeciently bulk cancel any number of orders with one state update. 18 | 19 | ## Motivation 20 | 21 | Currently, each individual order must be cancelled separately, which can be very expensive if required for a large amount of orders. This can prevent market makers from creating multiple orders for fear of large and sudden market moves. 22 | 23 | In addition, if a trader forgets or loses their old orders, it is currently not possible to cancel them. This is potentially dangerous, since there is always a chance that other parties are still storing the orders. 24 | 25 | ## Specification 26 | 27 | Traders SHOULD treat the `salt` order field as a timestamp with arbitrary precision. Then we can add the following functionality: 28 | 29 | ``` 30 | mapping (address => uint256) cancelledBefore; // mapping of maker => timestamp 31 | 32 | function cancelOrdersBefore(uint256 timestamp) 33 | external 34 | { 35 | require(cancelledBefore[msg.sender] < timestamp); // removing this check allows makers to "pause" orders, but adds complexity 36 | cancelledBefore[msg.sender] = timestamp; 37 | } 38 | 39 | function fillOrder(...) 40 | public 41 | returns (uint256) 42 | { 43 | require(order.salt > cancelledBefore[order.maker]); 44 | // remaining fill logic 45 | } 46 | ``` 47 | 48 | Note that while it is in the best interest of makers to treat an order's `salt` as a timestamp, there is no way to enforce this and it should therefore NOT be relied upon for any other functionality (doing so would create incentives for makers to provide inaccurate timestamps). 49 | 50 | It would also be useful to allow makers to cancel orders of specific token pairs, but this may add too much extra complexity. 51 | 52 | ## Rationale 53 | 54 | ## Test Cases 55 | 56 | ## Implementation 57 | 58 | ## Copyright 59 | 60 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 61 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-28.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 28 4 | Title: Arbitrary Fee Tokens 5 | Author: @PhABC, 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-03-8 10 | 11 | Discussion: #28 12 | 13 | ## Simple Summary 14 | 15 | Allow taker and maker fees to be paid in any asset, not only ZRX. 16 | 17 | ## Abstract 18 | 19 | Add two new asset data fields to the order schema so maker and taker fees can be paid in arbitrary assets. 20 | 21 | ## Motivation 22 | 23 | Currently, most relayers take their fee via a spread instead of accepting fees paid in ZRX. The main reasons for this are better UX, lower cost and because relayers and users do not want to transact using ZRX. This ZEIP proposes to allow maker and taker fees to be paid in any asset, not only ZRX. 24 | 25 | This also allows all relayers, not just matching relayers to take percentage fees. 26 | 27 | ## Specification 28 | 29 | Add two new fields to the order schema: 30 | 31 | - `makerFeeAssetData`: The fee asset to be paid by the maker on fill. 32 | - `takerFeeAssetData`: The fee asset to be paid by the taker on fill. 33 | 34 | In `_settleOrder()` and `_settleMatchedOrders()`, transfer maker and taker fees to the fee recipients _after_ transfering maker and taker assets (in case the main assets would help cover the fees). 35 | 36 | ## Copyright 37 | 38 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 39 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-31.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 31 5 | Title: Stake-based Liquidity Incentives 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #31 14 | 15 | ## Summary 16 | 17 | ZEIP-31 introduces a stake-based liquidity incentive to the 0x protocol. This proposal outlines the design principles and constraints of the incentive mechanism, along with guidelines for its implementation. See the official [0x Staking Specification](https://github.com/0xProject/0x-protocol-specification/blob/3.0/staking/staking-specification.md) for a comprehensive explanation of architecture, implementation and usage. 18 | 19 | ## 1 Overview 20 | 21 | ### 1.1 Motivation 22 | 23 | 1. Encourage ownership over the protocol among market makers 24 | 2. Reward market makers that stake ZRX tokens 25 | 3. Align all market participants with the long-term mission and objectives of 0x 26 | 4. Redirect proceeds from arbitrage-driven gas auctions back to market makers 27 | 28 | ### 1.2 Principles 29 | 30 | 1. Incentivize liquidity providers to invest in the long-term success of the protocol 31 | 2. Create a level playing field across all types of assets and classes of market makers 32 | 3. Minimize overhead and cost, both in terms of gas and effort to participate 33 | 34 | ### 1.3 Specification 35 | 36 | 1. Participate in governance and liquidity incentives by staking ZRX (section 2.1) 37 | 2. Delegate stake to market makers (section 2.2) 38 | 3. Funding self-sustaining development with protocol fees (section 2.3) 39 | 4. Earn liquidity rewards on trading (section 2.4) 40 | 5. Vote on 0x protocol proposals (section 2.5) 41 | 6. Scheduling process for claiming rewards (section 2.6) 42 | 7. Setting up liquidity rewards for market makers (section 2.7) 43 | 44 | ## 2 Specification 45 | 46 | ### 2.1 Staking ZRX 47 | 48 | #### 2.1.1 Utility 49 | 50 | - Vote on proposals and the allocation of community funds 51 | - Market makers earn liquidity rewards proportional to their trade volume and amount of stake 52 | - Anyone can delegate stake to a market maker to earn a portion of their liquidity reward 53 | 54 | #### 2.1.2 Depositing Stake 55 | 56 | - Anyone can stake by depositing ZRX into the 0x staking contract 57 | - Stake can be deposited at any time 58 | - ZRX remains staked until withdrawn by the staker 59 | 60 | #### 2.1.3 Withdrawing Stake 61 | 62 | - Stake can be withdrawn at any time so long as it is not delegated (section 2.2) 63 | - A timelock on withdrawals may be introduced in the future to handle edge cases in on-chain governance 64 | 65 | ### 2.2 Delegating Stake 66 | 67 | #### 2.2.1 Overview 68 | 69 | - Market makers can contribute stake on their own behalf 70 | - Third parties can delegate stake to market makers 71 | - Delegated stake has the same utility as regular stake 72 | - Stake contributed by market makers receives additional weight when computing rewards 73 | - A delegator transfers a portion of his voting rights to the market maker (section 2.5) 74 | 75 | #### 2.2.2 Incentives 76 | 77 | - Market makers can incentivize delegation by sharing a fixed percentage of their liquidity reward with their delegators 78 | - Via delegation market makers can obtain liquidity rewards and voting power without locking up capital in ZRX 79 | 80 | #### 2.2.3 Weight of Stake 81 | 82 | - Regular stake is always weighted more heavily than delegated stake 83 | - Market makers obtain rewards more cost effectively when staking their own ZRX 84 | 85 | #### 2.2.4 Delegating Stake 86 | 87 | - ZRX must be staked before it can be delegated 88 | - Anyone can delegate their stake to a market maker at anytime 89 | - Delegating stake comes into affect on the next epoch 90 | - Stake remains delegated until withdrawn by the delegator 91 | - The portion of a market maker's liquidity reward reserved for delegators is held in a reward pool 92 | - Each delegator owns a percentage of the reward pool that is proportional to their stake in the pool 93 | 94 | #### 2.2.5 Undelegating Stake 95 | 96 | - Stake can be undelegated at any time via a smart contract call; however, stake will remain delegated until the epoch ends 97 | - The delegator continues to earn rewards through to the end of the epoch 98 | 99 | ### 2.3 Fees 100 | 101 | #### 2.3.1 Charging Fees 102 | 103 | - Each fill on the 0x Exchange contract incurs a static fee 104 | - The fee scales linearly with the gas price of the transaction 105 | - The fee is denominated in ETH (or WETH) 106 | - The fee is paid in ETH if msg.value is set, otherwise it is taken in WETH 107 | - The fee is paid by whoever submits the transaction 108 | - This is the taker in an open orderbook relayer model 109 | - This is the relayer in a matching / closed orderbook model 110 | - This is an arbitrary third-party when using contract-fillable liquidity (meta-transactions) 111 | 112 | #### 2.3.2 Motivation for Fee Mechanics 113 | 114 | - Making the fee proportional to the transaction gas price protects market makers from arbitrage-drive gas auctions 115 | - A portion of fees currently paid to miners are recycled back into the 0x ecosystem 116 | 117 | #### 2.3.3 Accumulating Fees 118 | 119 | - The 0x Exchange contract deposits fees into the staking contract 120 | - The fee is associated with the originating market maker and acts as a measure of their trade volume 121 | - At the end of each epoch the accumulated fees are distributed as liquidity rewards 122 | 123 | ### 2.4 Liquidity Rewards 124 | 125 | #### 2.4.1 Earning Liquidity Rewards 126 | 127 | - Liquidity rewards are generated by protocol fees 128 | - Liquidity rewards are paid out at the end of each epoch 129 | - Liquidity rewards are divided between market makers, delegators, and the 0x Ecosystem Fund 130 | 131 | #### 2.4.2 Liquidity Rewards for Market Makers 132 | 133 | - A market maker's liquidity reward is a function of: 134 | - The total fees collected across all market makers 135 | - The amount of stake held by the market maker 136 | - The amount of stake delegated to the market maker 137 | - The fees attributed to the market maker 138 | - A variable subsidy that we add or remove to influence liquidity provision 139 | - 1 Staked ZRX = 1 Reward Credit 140 | - 1 Delegated ZRX = 0.9 Reward Credits 141 | 142 | #### 2.4.3 Liquidity Rewards for Delegators 143 | 144 | - Delegators receive a portion of the reward for each market maker they have delegated to 145 | - This portion is set once by the market maker when creating the delegation pool 146 | - Each delegator earns a reward proportional to the amount they delegated 147 | 148 | #### 2.4.4 Liquidity Rewards for the Ecosystem Fund 149 | 150 | - The 0x Ecosystem Fund is a pool of ETH collectively managed by ZRX holders 151 | - A small fixed percentage of the total fees collected are allocated to the fund 152 | - Until the 0x Ecosystem Fund has been created all fees will be paid to market makers and their delegators 153 | 154 | ### 2.5 Governance 155 | 156 | #### 2.5.1 Voting on Proposals 157 | 158 | - Anyone can vote on a proposal using their stake, the stake they delegate, or using stake delegated to them 159 | - 1 Staked ZRX = 1 Vote 160 | - 1 Delegated ZRX = 0.5 Votes for the delegator and 0.5 Votes for the delegate 161 | 162 | ### 2.6 Epochs 163 | 164 | #### 2.6.1 Scheduling 165 | 166 | - All processes are segmented into time intervals called epochs 167 | - Fees accumulate over an epoch and are paid out at the end of the epoch 168 | - Time-locks for withdrawing stake (and exiting reward pools) are measured in epochs 169 | - All epochs last a fixed minimum time 170 | - ~The duration of an epoch is to be determined, but will likely be 2-4 weeks~ 171 | - The duration of an epoch is 10 days 172 | 173 | #### 2.6.2 Epoch Finalization 174 | 175 | - Epoch T must be finalized before Epoch T+1 can start 176 | - Anyone can finalize an epoch by calling a function in the staking contract that: 177 | - Computes liquidity reward allocations across market makers 178 | - Pays market makers and escrows the portion allocated to their delegators (section 2.2) 179 | - Pays a portion of the liquidity rewards to the 0x Ecosystem Fund 180 | - Increments the epoch 181 | - Stake and delegated stake automatically carry over to the next epoch 182 | 183 | ### 2.7 Setting Up Liquidity Rewards for Market Makers 184 | 185 | #### 2.7.1 Registering as a Market Maker 186 | 187 | - A market maker first creates a staking pool 188 | - The maker then registers their trading addresses with the pool (each address must call into the staking contract) 189 | - Each time a 0x order is filled, the maker address is used to lookup a staking pool 190 | - If the pool has a non-negligible amount of ZRX staked then the fee is attributed to the pool 191 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-32.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 32 4 | Title: Rich Reverts 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-04-19 10 | 11 | ## Simple Summary 12 | 13 | Instead of throwing opaque string reverts, 3.0 contracts will instead throw custom, ABI-encoded "rich" revert types augmented with much more useful parameters. 14 | 15 | ## Motivation 16 | 17 | Reverting with expressive error data will enable developers to create more robust applications built on top of the 0x protocol. 18 | 19 | Additionally, this is a critical step towards our goal of becoming a language-agnostic protocol, wherein applications can rely more on the contracts themselves and less on off-chain tooling to validate and debug interactions. 20 | 21 | ## Specification 22 | 23 | #### Encoding 24 | 25 | Standard string reverts (à la Soldity's `require()` and `revert()` builtins) are ABI-encoded as a function call with signature `Error(string)`. 26 | 27 | For example, a `revert("foobar")` would encode as: 28 | 29 | ```yaml 30 | # 4-byte function selector (keccak of "Error(string)") 31 | 08c379a0 32 | # Offset to the error string calldata. 33 | 0000000000000000000000000000000000000000000000000000000000000020 34 | # -> Error string data 35 | # Length of string (6) 36 | 0000000000000000000000000000000000000000000000000000000000000006 37 | # String bytes 38 | 0000000000000000000000000000000000000000000000000000666f6f626172 39 | ``` 40 | 41 | Our rich reverts follow the same encoding rules but with varying function signatures. 42 | 43 | For example, the rich revert `SignatureError` has the signature: 44 | 45 | ```solidity 46 | SignatureError(uint8 errorCode, bytes32 hash, address signer, bytes signature) 47 | ``` 48 | 49 | If we construct it with the following values: 50 | 51 | ```solidity 52 | SignatureError( 53 | // errorCode 54 | 3, 55 | // signature hash 56 | 0xa3dcd8f6179b531a8c33b675b700708090d4e94d6f6f4cd9e652239a6225db45, 57 | // signer 58 | 0x828f817d6612f7b477d66591ff96a9e064bcc98a, 59 | // signature 60 | 0x010aeaf352d05c6dcf64882760014703432133689f4507cd91e81aaa3b289223 61 | 507bc8cf2629ff3ea8a468013a49b32227900be174575ce135ed2560c236dba6 62 | 8802 63 | ) 64 | ``` 65 | 66 | The resulting encoding will be: 67 | 68 | ```yaml 69 | # 4-byte function selector (keccak of "SignatureError(uint8,bytes32,address,bytes)") 70 | 7e5a2318 71 | # errorCode, padded to 32-bytes 72 | 0000000000000000000000000000000000000000000000000000000000000003 73 | # Signature hash 74 | a3dcd8f6179b531a8c33b675b700708090d4e94d6f6f4cd9e652239a6225db45 75 | # Offset to signature bytes data 76 | 0000000000000000000000000000000000000000000000000000000000000060 77 | # -> Signature bytes data 78 | # Length of bytes (66) 79 | 0000000000000000000000000000000000000000000000000000000000000042 80 | # bytes data 81 | 010aeaf352d05c6dcf64882760014703432133689f4507cd91e81aaa3b289223 82 | 507bc8cf2629ff3ea8a468013a49b32227900be174575ce135ed2560c236dba6 83 | 8802 84 | ``` 85 | 86 | #### Decoding 87 | 88 | Nodes will only return revert data for `eth_call` operations, though it is possible (but not foolproof) to replay a failed transaction using `eth_call` and a block number. 89 | 90 | Furthermore, with geth there is an [issue](https://github.com/ethereum/go-ethereum/issues/19027) where the JSON-RPC response for a successful `eth_call` is indistinguishable from a revert. For this reason, (at minimum) we need to check the leading 4 bytes of the return data against a mapping of known error selectors to detect that a revert actually occurred. This is a little inelegant, but with roughly 4 billion combinations of leading 4 bytes, combined with more rigorous conformance checks, false positives should be extremely rare. 91 | 92 | Once the exact error type is detected, ABI decoding tools can be used to extract individual parameter values. 93 | 94 | For environments where ABI decoding tools are not exposed/available, we will also be deploying a helper contract that decomposes encoded error bytes into its constituent fields. 95 | 96 | ## Copyright 97 | 98 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 99 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-33.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 33 4 | Title: New/Consolidated Signature Type(s) and Behavior 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-04-19 10 | 11 | Discussion: #33 12 | 13 | ## Simple Summary 14 | 15 | Introduce new signature types for orders and and change validation behavior. 16 | 17 | ## Abstract 18 | 19 | Add more robust order and transaction signature validation with the following callback signature types, which accept an entire `Order` or `ZeroExTransaction` object: 20 | 21 | - `Validator` (\*_replaces existing behavior_) 22 | - `EIP1271Wallet` 23 | 24 | Also, _all_ signature types (including these) will be checked on every fill. This is in contrast to the behavior in `2.0` where we only validate the signature on the first fill. 25 | 26 | ## Motivation 27 | 28 | In `2.0`, we have `Validator` and `Wallet` signature types, which can only validate against a hash, which means the order/transaction must be somehow registered with the validator contract prior to execution to determine meaningful context. It would be more useful if the validator contract was provided with the complete order/transaction data so they can implement more nuanced and dynamic filtering criteria. 29 | 30 | Recent improvements to solidity and `ABIEncoderV2` have made this approach relatively simple to execute. 31 | 32 | ## Specification 33 | 34 | ### Restrictions 35 | 36 | - Validator contracts will be called via `staticcall()`. If the contract attempts to update state during call, the validation will fail. 37 | - Validator contracts using the `Validator` signature type must be registered in advance via `setSignatureValidatorApproval()` (unchanged from `2.0`). This only has to be done once per validator-signer pair. 38 | 39 | ### Signature Encoding 40 | 41 | The `Validator` signature type is tightly packed with the ordered fields: 42 | 43 | ```solidity 44 | // Arbitrary data passed to validator as `signature`. 0 or more bytes. 45 | bytes signatureData 46 | // Address of the validator contract. 20 bytes. 47 | address validatorAddress 48 | // Signature type. Always `0x05`. 1 byte. 49 | uint8 signatureType 50 | ``` 51 | 52 | The `EIP1271Wallet` signature type is tightly packed with the following ordered fields. Note that the address of the validator contract is implied as the order maker or transaction signer. 53 | 54 | ```solidity 55 | // Arbitrary signature data passed to validator as `signature`. 0 or more bytes. 56 | bytes signatureData 57 | // Signature type. Always `0x07`. 1 byte. 58 | uint8 signatureType 59 | ``` 60 | 61 | ### Implementation 62 | 63 | Contracts validating the `Validator` and `EIP1271` signature types follow the EIP-1271 pattern and must expose the following callback: 64 | 65 | ```solidity 66 | function isValidSignature( 67 | // ABI-encoded data associated with the signature. 68 | bytes calldata data, 69 | // arbitrary signature bytes passed in top-level call. 70 | bytes calldata signature 71 | ) 72 | external 73 | view 74 | // Should return 0x20c13b0b if the signature is valid. 75 | returns (bytes4 magicValue); 76 | ``` 77 | 78 | #### EIP-1271 `data` Encoding 79 | 80 | There are two ways the `data` parameter for `EIP1271Wallet` and `Validator` signatures can be encoded, depending on what type of data is signed: 81 | 82 | - For Orders: `abi.encodeWithSelector(bytes4(0x3efe50c8), Order order, bytes32 orderHash)` 83 | - For ZeroExTransactions: `abi.encodeWithSelector(bytes4(0xde047db4), ZeroExTransaction transaction, bytes32 transactionHash)` 84 | 85 | #### Example 86 | 87 | Here is a complete (if trivial) implementation that validates an Order signature: 88 | 89 | ```solidity 90 | pragma solidity ^0.5.9; 91 | pragma experimental ABIEncoderV2; 92 | 93 | import "@0x/contracts-utils/LibBytes.sol"; 94 | 95 | contract MyOrderValidator { 96 | 97 | using LibBytes for bytes; 98 | 99 | // 0x order structure 100 | struct Order { 101 | address makerAddress; 102 | address takerAddress; 103 | address feeRecipientAddress; 104 | address senderAddress; 105 | uint256 makerAssetAmount; 106 | uint256 takerAssetAmount; 107 | uint256 makerFee; 108 | uint256 takerFee; 109 | uint256 expirationTimeSeconds; 110 | uint256 salt; 111 | bytes makerAssetData; 112 | bytes takerAssetData; 113 | bytes makerFeeAssetData; 114 | bytes takerFeeAssetData; 115 | } 116 | 117 | /// @dev Validate an order signature. 118 | /// @param data The ABI-encoded order and hash. 119 | /// @param signature Signature data for the order. 120 | /// @return magicValue 0x20c13b0b if the signature is valid. 121 | function isValidSignature( 122 | bytes calldata data, 123 | bytes calldata signature 124 | ) 125 | external 126 | view 127 | returns (bytes4 magicValue) 128 | { 129 | // Decode the order and hash. 130 | (Order memory order, bytes32 orderHash) = abi.decode(data.slice(4), (Order, bytes32)); 131 | // Validate the order 132 | // ... 133 | magicValue = 0x20c13b0b; // Success 134 | } 135 | } 136 | ``` 137 | 138 | ## Copyright 139 | 140 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 141 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-34.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 34 5 | Title: 0x transaction developer experience improvements 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #34 14 | 15 | ## Summary 16 | 17 | This is a catch-all for smaller developer experience improvements to [0x transactions](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#transactions). Improvements include: 18 | 19 | - Logging an event upon successful transaction execution 20 | - Refactoring `executeTransaction` to take a `ZeroExTransaction` struct as an input 21 | - Adding a `bytes` return value to `executeTransaction` that is equal to the return data of the underlying function call 22 | 23 | ## Motivation 24 | 25 | All of these features should make it easier to work with 0x transactions, both off-chain and at the smart contract level. 26 | 27 | ## Specification 28 | 29 | ### TransactionExecuted event 30 | 31 | Upon successful execution, `executeTransaction` will log a `TransactionExecution` event. 32 | 33 | ``` 34 | // TransactionExecution event is emitted when a ZeroExTransaction is executed. 35 | event TransactionExecution( 36 | bytes32 indexed transactionHash 37 | ); 38 | ``` 39 | 40 | ### New executeTransaction function signature 41 | 42 | The inputs and outputs of `executeTransaction` will be modified as follows: 43 | 44 | ``` 45 | struct ZeroExTransaction { 46 | uint256 salt; // Arbitrary number to ensure uniqueness of transaction hash. 47 | uint256 expirationTimeSeconds; // Timestamp in seconds at which transaction expires. 48 | uint256 gasPrice; // gasPrice that transaction is required to be executed with. 49 | address signerAddress; // Address of transaction signer. 50 | bytes data; // AbiV2 encoded calldata. 51 | } 52 | 53 | /// @dev Executes an Exchange method call in the context of signer. 54 | /// @param transaction 0x transaction containing salt, signerAddress, and data. 55 | /// @param signature Proof that transaction has been signed by signer. 56 | /// @return ABI encoded return data of the underlying Exchange function call. 57 | function executeTransaction( 58 | LibZeroExTransaction.ZeroExTransaction memory transaction, 59 | bytes memory signature 60 | ) 61 | public 62 | payable 63 | returns (bytes memory); 64 | ``` 65 | 66 | ## Copyright 67 | 68 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 69 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-35.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 35 5 | Title: Permissive Order Cancellations 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #35 14 | 15 | ## Summary 16 | 17 | The current `batchCancelOrders` function is difficult to use because the caller runs the risk of the entire transaction reverting if only a single cancellation fails. This is difficult to prevent because a cancellation may fail for non-deterministic reasons (such as the order being expired). This can be improved by doing a no-op instead of reverting for noncritical errors. 18 | 19 | The proposed change would alter the logic of `cancelOrder` and `batchCancelOrders`, but would not affect the interface. 20 | 21 | ## Motivation 22 | 23 | This will improve the reliability of cancelling batches of specific orders. 24 | 25 | ## Specification 26 | 27 | The table below compares how failure scenarios are handled when cancelling an order. 28 | 29 | | Scenario | Current Action | Proposed Action | 30 | | ----------------------- | -------------- | --------------- | 31 | | Reentrancy | Revert | Revert | 32 | | Sender Not Authorized | Revert | Revert | 33 | | Order Expired | Revert | No-op | 34 | | Order Already Cancelled | Revert | No-op | 35 | | Order Already Filled | Revert | No-op | 36 | | Order Invalid | Revert | No-op | 37 | 38 | ## Copyright 39 | 40 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 41 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-36.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 36 5 | Title: Allow batch 0x transaction execution 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #36 14 | 15 | ## Summary 16 | 17 | The Exchange contract currently only allows for a single 0x transaction to be executed atomically. This proposal would add the ability to atomically execute a batch of transactions by calling a single function. 18 | 19 | ## Motivation 20 | 21 | There are niche use cases for composing custom a custom series of Exchange function calls. One example: 22 | 23 | 1. A maker places a buy order on market A 24 | 2. A sell order appears on market B that would satisfy the maker's buy order 25 | 3. The maker would like to atomically fill the sell order and cancel the buy order, rather than executing the transactions asynchronously and risking that only one of the transactions is successful. 26 | 27 | ## Specification 28 | 29 | A naive solution is extremely simple to implement and adds no additional attack surface: 30 | 31 | ``` 32 | /// @dev Executes a batch of Exchange method calls in the context of signer(s). 33 | /// @param transactions Array of 0x transactions containing salt, signerAddress, and data. 34 | /// @param signatures Array of proofs that transactions have been signed by signer(s). 35 | /// @return Array containing ABI encoded return data for each of the underlying Exchange function calls. 36 | function batchExecuteTransactions( 37 | ZeroExTransaction[] memory transactions, 38 | bytes[] memory signatures 39 | ) 40 | public 41 | returns (bytes[] memory) 42 | { 43 | uint256 length = transactions.length; 44 | bytes[] memory returnData = new bytes[](length); 45 | for (uint256 i = 0; i != length; i++) { 46 | returnData[i] = _executeTransaction(transactions[i], signatures[i]); 47 | } 48 | return returnData; 49 | } 50 | ``` 51 | 52 | It would be useful if the return data of each transaction could be passed into and processed by the next transaction, but this would be extremely complex to implement (and is potentially infeasible). 53 | 54 | ## Copyright 55 | 56 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 57 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-37.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 37 5 | Title: Allow 0x transactions to be cancelled (or expired) 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #37 14 | 15 | ## Summary 16 | 17 | A signed 0x transaction is currently valid until executed. There is no explicit way to cancel or invalidate a transaction. This ZEIP will discuss 3 different mechanisms accomplishing this. 18 | 19 | ## Motivation 20 | 21 | There are pros and cons to allowing 0x transactions to be cancelled. The initial decision to not allow cancels in 2.0 was actually intentional. 22 | 23 | ### Argument against cancellation 24 | 25 | In many cases, a 0x transaction will be submitted by a user that is not actually the transaction signer (such as a relayer). Allowing the transaction signer to cancel adds an additional griefing vector, where the signer can cancel and force the submitter to waste gas. 26 | 27 | ### Argument for cancellation 28 | 29 | If a taker signs a fill transaction that can only be executed by a different address (i.e when `order.senderAddress` is not the taker), that address can withhold the transaction and submit it at a later time. If the market price has moved during this time, a taker may end up filling an order at an undesirable price. 30 | 31 | ## Specification 32 | 33 | There are at least 3 viable options for allowing 0x transaction cancellations: a `cancelTransaction` function; a monotonically increasing `nonce`; or an `expirationTimeSeconds` field. The three options are described in detail below. _For V3 of the Exchange, we have gone with Option #3: adding an `expirationTimeSeconds` field to transactions_. 34 | 35 | ### 1 `cancelTransaction` function 36 | 37 | The logic for this would be very similar to `cancelOrder`. Pseudocode: 38 | 39 | ``` 40 | function cancelTransaction(ZeroExTransaction memory transaction) 41 | public 42 | { 43 | address signerAddress = getCurrentContextAddress(); 44 | require( 45 | transaction.signerAddress == signerAddress, 46 | "INVALID_SIGNER" 47 | ); 48 | bytes32 transactionHash = getTransactionHash(transaction); 49 | transactions[transactionHash] = true; 50 | } 51 | ``` 52 | 53 | ### 2 Force salt to be strictly incrementing by 1 54 | 55 | A transaction's `salt` field would serve the same functionality as an Ethereum transaction's `nonce` field (and could also be renamed to reflect this). Valid transactions must have a `nonce` equal to the most recently submitted transaction's `nonce` + 1. Multiple transactions with the same `nonce` cannot be submitted, so a "cancellation" would merely be submitting a transaction with the same nonce as the transaction that is intended to be cancelled. 56 | 57 | ### 3 Add an `expirationTimeSeconds` field 58 | 59 | Transactions mined in a block with timestamp at or after the `expirationTimeSeconds` field would be invalid. This is my personal favorite approach, as it seems to minimize griefing vectors while also limiting the potential damage of a withholding attack (most transactions would likely be very short lived). 60 | 61 | ## Copyright 62 | 63 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 64 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-40.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 40 5 | Title: New Order Matching Strategy 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #40 14 | 15 | ## Summary 16 | 17 | We propose an additional order matching function that maximally fills both orders (referred to as the left and right order). The matcher would receive profit denominated in either the left maker asset, the right maker asset, or a combination of both. This proposal allows matching relayers to execute trades without upfront capital, and does not modify the current [matchOrders](https://github.com/0xProject/0x-monorepo/blob/development/contracts/exchange/contracts/src/MixinMatchOrders.sol#L46) interface or implementation. 18 | 19 | ## Motivation 20 | 21 | The current implementation of matchOrders maximally fills the left order, returning a profit to the matcher that is taken from the left maker. The proposed implementation maximally fills both orders, returning a profit to the matcher that is taken from the left or right maker (or both). The former implementation is beneficial for arbitrage and the latter for matching relayers. 22 | 23 | Note that the proposed functionality can also be achieved by calling `matchOrders` and subsequently `fillOrder` on the right order. This strategy has been implemented in the [Order Matcher](https://github.com/0xProject/0x-monorepo/tree/development/contracts/extensions/contracts/src/OrderMatcher) extension contract. 24 | 25 | ## Specification 26 | 27 | ### Comparison of Matching Strategies 28 | 29 | The figure below compares how profit is generated by the current and proposed matching strategies, along with the respective formulas for computing the flow of value between makers and the matcher. 30 | 31 | ![Comparison of Matching Strategies](https://user-images.githubusercontent.com/4369805/67817738-dbf19c80-fa6b-11e9-845e-ee7e8fd96b22.png) 32 | 33 | ### A Note on Rounding 34 | 35 | In the formulas above, we round up or down to ensure that a maker's exchange rate does not exceed the price specified by their order. We favor the maker (opposed to the taker / matcher) when the exchange rate is rounded. 36 | 37 | ### Interface 38 | 39 | ``` 40 | /// @dev Match two complementary orders that have a profitable spread. 41 | /// Each order is maximally filled at their respective price point, and 42 | /// the matcher receives a profit denominated in either the left maker asset, 43 | /// right maker asset, or a combination of both. 44 | /// @param leftOrder First order to match. 45 | /// @param rightOrder Second order to match. 46 | /// @param leftSignature Proof that order was created by the left maker. 47 | /// @param rightSignature Proof that order was created by the right maker. 48 | /// @return matchedFillResults Amounts filled by maker and taker of matched orders. 49 | function matchOrdersWithMaximalFill( 50 | LibOrder.Order memory leftOrder, 51 | LibOrder.Order memory rightOrder, 52 | bytes memory leftSignature, 53 | bytes memory rightSignature 54 | ) 55 | public 56 | nonReentrant 57 | returns (LibFillResults.MatchedFillResults memory matchedFillResults); 58 | ``` 59 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-41.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 41 5 | Title: Batch Order Matching 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #41 14 | 15 | ## Summary 16 | 17 | We propose a new feature set that allows multiple orders to be matched with one or more complementary orders. This would extend the exchange contract with batch functions for each matching strategy (see [ZEIP 40](https://github.com/0xProject/ZEIPs/issues/40)). 18 | 19 | ## Motivation 20 | 21 | This enables more efficient order matching when orders are not maximally filled with a single call to `matchOrders` or `matchOrdersWithMaximalFill`. One use case is market fills on matching relayers, where a single taker order is matched against one or more maker orders: 22 | 23 | 1. A taker wants to fill one or more maker orders 24 | 2. They submit to the relayer a single complementary taker order 25 | 3. The relayer calls the exchange contract with the respective maker orders and complementary taker order 26 | 27 | ## Specification 28 | 29 | ### Interface 30 | 31 | Below are the interfaces for the proposed batch matching functions. 32 | 33 | ``` 34 | /// @dev Match complementary orders that have a profitable spread. 35 | /// Each order is filled at their respective price point, and 36 | /// the matcher receives a profit denominated in the left maker asset. 37 | /// @param leftOrders Set of orders with the same maker / taker asset. 38 | /// @param rightOrders Set of orders to match against `leftOrders` 39 | /// @param leftSignatures Proof that left orders were created by the left makers. 40 | /// @param rightSignatures Proof that right orders were created by the right makers. 41 | /// @return batchMatchedFillResults Amounts filled and profit generated. 42 | function batchMatchOrders( 43 | LibOrder.Order[] memory leftOrders, 44 | LibOrder.Order[] memory rightOrders, 45 | bytes[] memory leftSignatures, 46 | bytes[] memory rightSignatures 47 | ) 48 | public 49 | nonReentrant 50 | returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults); 51 | 52 | /// @dev Match complementary orders that have a profitable spread. 53 | /// Each order is maximally filled at their respective price point, and 54 | /// the matcher receives a profit denominated in either the left maker asset, 55 | /// right maker asset, or a combination of both. 56 | /// @param leftOrders Set of orders with the same maker / taker asset. 57 | /// @param rightOrders Set of orders to match against `leftOrders` 58 | /// @param leftSignatures Proof that left orders were created by the left makers. 59 | /// @param rightSignatures Proof that right orders were created by the right makers. 60 | /// @return batchMatchedFillResults Amounts filled and profit generated. 61 | function batchMatchOrdersWithMaximalFill( 62 | LibOrder.Order[] memory leftOrders, 63 | LibOrder.Order[] memory rightOrders, 64 | bytes[] memory leftSignatures, 65 | bytes[] memory rightSignatures 66 | ) 67 | public 68 | nonReentrant 69 | returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults); 70 | ``` 71 | 72 | ### Fill Results 73 | 74 | The [LibFillResults](https://github.com/0xProject/0x-monorepo/blob/development/contracts/exchange-libs/contracts/src/LibFillResults.sol) contract would be extended to include a results struct for batch matching. One FillResult is created for each order that is filled. The total profit denominated in the left and right maker assets is also included. 75 | 76 | ``` 77 | contract LibFillResults { 78 | ... 79 | struct BatchMatchedFillResults { 80 | FillResults[] left; // Fill results for left orders 81 | FillResults[] right; // Fill results for right orders 82 | uint256 profitInLeftMakerAsset; // Profit taken from left makers 83 | uint256 profitInRightMakerAsset; // Profit taken from right makers 84 | } 85 | } 86 | ``` 87 | 88 | ### Implementation 89 | 90 | The pseudocode below describes the implementation of each batch fill function. 91 | 92 | ``` 93 | // sanity checks 94 | require(leftOrders.length > 0) 95 | require(leftOrders.length == leftSignatures.length) 96 | require(rightOrders.length > 0) 97 | require(rightOrders.length == rightSignatures.length) 98 | 99 | // init 100 | leftIdx = 0 101 | rightIdx = 0 102 | leftOrder = leftOrders[0] 103 | rightOrder = rightOrders[0] 104 | leftSignature = leftSignatures[0] 105 | rightSignature = rightSignatures[0] 106 | 107 | // batch match 108 | batchMatchResults = {} 109 | while True: 110 | // perform match 111 | matchResult = match(leftOrder, rightOrder, leftSignature, rightSignature) 112 | batchMatchResults.left.append(matchResult.left) 113 | batchMatchResults.right.append(matchResult.right) 114 | batchMatchResults.profitInLeftMakerAsset += matchResult.profitInLeftMakerAsset 115 | batchMatchResults.profitInRightMakerAsset += matchResult.profitInRightMakerAsset 116 | 117 | // iterate left 118 | if isFilled(leftOrder): 119 | leftIdx += 1 120 | if leftIdx == leftOrders.length: 121 | // all left orders have been matched 122 | break 123 | leftOrder = leftOrders[leftIdx] 124 | leftSignature = leftSignatures[leftIdx] 125 | 126 | // iterate right 127 | if isFilled(rightOrder): 128 | rightIdx += 1 129 | if rightIdx == rightOrders.length: 130 | // all right orders have been matched 131 | break 132 | rightOrder = rightOrders[rightIdx] 133 | rightSignature = rightSignatures[rightIdx] 134 | 135 | return batchMatchResults 136 | ``` 137 | 138 | ## Notes 139 | 140 | - Redundant asset data can be optimized out by the [0x ABI Encoder](https://github.com/0xProject/0x-monorepo/tree/development/packages/utils/src/abi_encoder) 141 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-42.md: -------------------------------------------------------------------------------- 1 | # ZEIP-42 2 | 3 | ## Summary 4 | 5 | The stake-based liquidity incentives proposed in ZEIP 31 (https://github.com/0xProject/ZEIPs/issues/31) specify a protocol fee for each fill executed on the Exchange contract. This proposal defines the fees for each function in the Exchange. 6 | 7 | Discussion: [ZEIP-42 Discussion](https://github.com/0xProject/ZEIPs/issues/42). 8 | 9 | ## Fees 10 | 11 | ### Exchange Fees 12 | 13 | Each fill on the Exchange contract will incur a static fee that scales linearly with the gas price of the transaction. A multiplier, the protocolFeeMultiplier will be set in the Exchange contract. This multiplier will be multiplied by a transaction’s gas price to calculate the protocol fee that should be paid. 14 | 15 | A protocol fee will be paid for each order that is “filled” (even if this is only a partial fill). As an example, a successful call to matchOrders will pay twice as many protocol fees as a successful call to fillOrder because two orders will be filled in the order matching operation. This behavior also applies to batch functions. 16 | 17 | The initial proposed value for the protocolFeeMultiplier is 150k, roughly the cost of filling an ERC20 order through the exchange. While this value is not expected to change, it is upgradeable and can be updated after a time-lock has elapsed. 18 | 19 | | Exchange Function | Fee | 20 | | ------------------------------- | ---------------------------------------------------- | 21 | | batchCancelOrders | N/A | 22 | | batchFillOrKillOrders | multiplier x x tx.gasPrice | 23 | | batchFillOrders | multiplier x x tx.gasPrice | 24 | | batchFillOrdersNoThrow | multiplier x x tx.gasPrice | 25 | | batchMatchOrders | multiplier x x tx.gasPrice | 26 | | batchMatchOrdersWithMaximalFill | multiplier x x tx.gasPrice | 27 | | cancelOrder | N/A | 28 | | cancelOrdersUpTo | N/A | 29 | | fillOrKillOrder | multiplier x tx.gasPrice | 30 | | fillOrder | multiplier x tx.gasPrice | 31 | | fillOrderNoThrow | multiplier x tx.gasPrice | 32 | | marketBuyOrders | multiplier x x tx.gasPrice | 33 | | marketBuyOrdersNoThrow | multiplier x x tx.gasPrice | 34 | | marketSellOrders | multiplier x x tx.gasPrice | 35 | | marketSellOrdersNoThrow | multiplier x x tx.gasPrice | 36 | | matchOrders | multiplier x 2 x tx.gasPrice | 37 | | matchOrdersWithMaximalFill | multiplier x 2 x tx.gasPrice | 38 | 39 | ### Fee Assets 40 | 41 | The only assets that will be used to pay protocol fees will be ether and ether that has been wrapped by the canonical weth contract (https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code). The inclusion of WETH as a protocol fee asset improves the user and developer experience of using protocol fees in many cases, especially when a contract is interacting with the protocol. 42 | 43 | If enough ether is sent to the Exchange contract to pay the protocol fee, the ether will be used to pay the fee. In case there is not enough ether to pay the protocol fee, the staking contract can transfer WETH from the address that called the Exchange contract to pay the protocol fee. If WETH is taken to pay the protocol fee, any ether that was sent to the Exchange contract will be completely refunded. 44 | 45 | To use WETH to pay protocol fees, one must first set an allowance for the Staking contract address. Otherwise, ether can be used to pay the fee. 46 | 47 | ### Meta-transactions 48 | 49 | The execute and batchExecute functions are also required to pay protocol fees when calling any functions that require protocol fees. If enough ether is sent to the Exchange contract by the sender of the meta-transaction to pay the protocol fee, this ether will actually be used to pay the fee (and the sender will not be refunded by the creator of the meta-transaction). Otherwise, WETH will be taken from the signerAddress of the meta-transaction. 50 | 51 | The decision to forego refunding the signerAddress was influenced by the fact that some senders of meta-transactions may intentionally subsidize the protocol fee that must be paid. This mechanism allows fees to be paid by either the sender or the signerAddress. 52 | 53 | Charging the signerAddress WETH for protocol fees opened up an attack vector that would allow the sender of meta-transactions to grief the signerAddress out of WETH by submitting transactions with arbitrarily high gas prices. To mitigate this attack, a gasPrice field has been added to the ZeroExTransaction struct. execute and batchExecute will now verify that tx.gasPrice == transaction.gasPrice. 54 | 55 | ### Exception For Order Matching 56 | 57 | In the original ZEIP, there was discussion around making an exception for one of the protocol fees in matchOrders for addresses that the exchange contract could identify as a matching relayer. After further discussion, we decided not to include this exception in an effort to reduce the complexity of V1 of the staking contracts. 58 | 59 | ## Notes 60 | 61 | - A fee is only incurred by successful transactions 62 | - In batch/market functions, each maker is credited with a portion of fee that is proportional to the number of their orders that were filled 63 | - Any ETH sent to the Exchange contract in excess of the protocol fee is refunded to the sender 64 | - If too little ETH is sent to the Exchange contract, WETH will be used to pay the protocol fee. 65 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-47.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 47 4 | Title: ERC20BridgeProxy 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-07-01 10 | 11 | Discussion: #47 12 | 13 | ## Simple Summary 14 | 15 | A pluggable asset proxy for transferring ERC20 maker assets to a taker. 16 | 17 | ## Abstract 18 | 19 | Introduce a new asset proxy that allows for a custom contract to be called that transfers ERC20 maker tokens to the taker. The asset proxy simply calls this contract and asserts that the taker's balance has increased by the required `amount`. 20 | 21 | ## Motivation 22 | 23 | Liquidity is a primary concern for the 0x ecosystem. One potentially impactful way to supplement liquidity is to source liquidity from other on-chain exchanges and networks. By introducing a new asset proxy that is able to exchange taker tokens for maker tokens in an arbitrary manner, we can tap into these other liquidity sources. 24 | 25 | ## Specification 26 | 27 | A custom "bridge" contract is specified in the asset data for this asset proxy. This bridge contract is called, converting ERC20 taker tokens into maker tokens. The asset proxy then confirms that the taker's balance has increased by the `amount` required. 28 | 29 | ### Asset data 30 | 31 | ```solidity 32 | abi.encodeWithSelector( 33 | ERC20BridgeProxy(0).PROXY_ID, 34 | // Maker token address 35 | address tokenAddress 36 | // Address of the bridge contract 37 | address bridgeAddress, 38 | // Arbitrary data to pass to the bridge contract 39 | bytes bridgeData 40 | ); 41 | ``` 42 | 43 | The `bridgeContract` does the heavy lifting of actually swapping tokens and implements the `IERC20Bridge` interface: 44 | 45 | ### IERC20Bridge interface 46 | 47 | ```solidity 48 | interface IERC20Bridge { 49 | bytes4 constant public BRIDGE_SUCCESS = 0xb5d40d78; 50 | 51 | function bridgeTransferFrom( 52 | bytes assetData, 53 | address tokenAddress, 54 | address from, 55 | address to, 56 | uint256 amount 57 | ) 58 | external 59 | returns (bytes4 success); 60 | } 61 | ``` 62 | 63 | ## Flow 64 | 65 | 1. Order is created with `makerAddress` as the `IERC20Bridge` contract, with a `Wallet` signature type. 66 | 2. Taker calls `fillOrder()` on this order. 67 | 1. taker tokens are transferred from taker to maker (`IERC20Bridge`). 68 | 2. `ERC20BridgeProxy.transferFrom()` is invoked to transfer `amount` of maker tokens to the taker. 69 | 1. `ERC20BridgeProxy` uses `IERC20(makerToken).balanceOf()` to get the maker token balance of the taker. 70 | 2. `ERC20BridgeProxy` calls `bridgeContract.bridgeTransferFrom()`. 71 | 1. `IERC20Bridge` interacts with on-chain liquidity sources to swap taker tokens for maker tokens and sending them to the taker. 72 | 3. If `bridgeContract.bridgeTransferFrom()` does not return the magic value `0xb5d40d78`, revert. 73 | 4. If the maker token balance of the taker has not increased by at least `amount`, revert. 74 | 3. Taker now has maker tokens! 75 | 76 | ## Pros and Cons 77 | 78 | ### PROS 79 | 80 | - It’s much easier to roll out support for more liquidity sources using this pattern. 81 | - Anyone can create a buyer contract for use with this asset proxy. 82 | - Buyer contracts have extreme flexibility with what they can do. We might see some really novel use cases. 83 | - Neither the asset proxy nor buyer contracts are granted allowances in this pattern, so they can’t spend funds they don’t have. 84 | 85 | ## Implementation 86 | 87 | The `ERC20BridgeProxy` would look like: 88 | 89 | ```solidity 90 | contract ERC20BridgeProxy { 91 | bytes4 constant public BRIDGE_SUCCESS = 0xb5d40d78; 92 | 93 | function transferFrom( 94 | bytes assetData, 95 | address from, 96 | address to, 97 | uint256 amount 98 | ) 99 | external 100 | { 101 | ( 102 | address tokenAddress, 103 | address bridgeAddress, 104 | bytes bridgeData 105 | ) = abi.decode( 106 | assetData.sliceDestructive(4), 107 | (address, address, bytes) 108 | ); 109 | uint256 balanceBefore = balanceOf(tokenAddress, to); 110 | bytes4 result = IERC20Bridge(bridgeAddress) 111 | .bridgeTransferFrom(bridgeData, tokenAddress, from, to, amount); 112 | require(result == BRIDGE_SUCCESS, "BRIDGE_FAILED"); 113 | uint256 balanceAfter = balanceOf(tokenAddress, to); 114 | require(balanceBefore.safeAdd(amount) >= balanceAfter, "BRIDGE_UNDERPAY"); 115 | } 116 | } 117 | ``` 118 | 119 | A `bridgeContract` for Eth2Dai would look like: 120 | 121 | ```solidity 122 | contract Eth2DaiBridge is 123 | ERC20Bridge 124 | { 125 | address constant public ETH2DAI_ADDRESS = 0x39755357759ce0d7f32dc8dc45414cca409ae24e; 126 | address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; 127 | address constant public DAI_ADDRESS = 0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359; 128 | 129 | constructor() public { 130 | // Grant the Eth2Dai contract unlimited WETH and DAI allowance. 131 | IERC20Token(WETH_ADDRESS).approve(ETH2DAI_ADDRESS, uint256(-1)); 132 | IERC20Token(DAI_ADDRESS).approve(ETH2DAI_ADDRESS, uint256(-1)); 133 | } 134 | 135 | function bridgeTransferFrom( 136 | bytes bridgeData, 137 | address toTokenAddress, 138 | address from, 139 | address to, 140 | uint256 amount 141 | ) 142 | external 143 | returns (bytes4 success) 144 | { 145 | // The "from" token is the opposite of the "to" token. 146 | IERC20Token fromToken = IERC20Token(WETH_ADDRESS); 147 | IERC20Token toToken = IERC20Token(DAI_ADDRESS); 148 | // Swap them if necessary. 149 | if (toTokenAddress == address(fromToken)) { 150 | (fromToken, toToken) = (toToken, fromToken); 151 | } else { 152 | require( 153 | toTokenAddress == address(toToken), 154 | "INVALID_ETH2DAI_TOKEN" 155 | ); 156 | } 157 | // Try to sell all of this contract's `fromToken` balance. 158 | uint256 boughtAmount = IEth2Dai(ETH2DAI_ADDRESS).sellAllAmount( 159 | address(fromToken), 160 | fromToken.balanceOf(address(this)), 161 | address(toToken), 162 | amount 163 | ); 164 | // Transfer the converted `toToken`s. 165 | toToken.transfer(to, boughtAmount); 166 | return BRIDGE_SUCCESS; 167 | } 168 | 169 | // `SignatureType.Wallet` callback, so that this bridge can be the maker 170 | // and sign for itself in orders. Always succeeds. 171 | function isValidSignature( 172 | bytes32 orderHash, 173 | bytes calldata signature 174 | ) 175 | external 176 | view 177 | returns (bytes4 magicValue) 178 | { 179 | return LEGACY_WALLET_MAGIC_VALUE; 180 | } 181 | } 182 | ``` 183 | 184 | ## Copyright 185 | 186 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 187 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-50.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 50 4 | Title: marketBuy/SellOrdersFillOrKill 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-08-14 10 | 11 | ## Summary 12 | 13 | Remove the old `marketBuyOrders()` and `marketSellOrders()` Exchange functions in `3.0` in favor of just `marketBuyOrdersNoThrow()` and `marketSellOrdersNoThrow()`. Add `marketBuyOrdersFillOrKill()` and `marketSellOrdersFillOrKill()` which wrap these functions. 14 | 15 | ## Motivation 16 | 17 | Our reasoning for this decision was that the typical user performing a market buy or sell would likely not care if any individual order in the operation fails. 18 | 19 | One feature of `marketBuy/SellOrdersNoThrow()` is that it will not fail even if it buys or sells _less_ than the amount of taker or maker asset requested. Thus, it’s useful when you’re simply trying to purchase or liquidate as much of an asset as possible. However, there are cases when more deterministic behavior is desirable, i.e., where it must fill _no less_ than the amount requested or revert. This is the motivation for introducing `marketSellOrdersFillOrKill()` and `marketBuyOrdersFillOrKill()`. 20 | 21 | ## Specification 22 | 23 | The behavior of these new functions would be nearly identical to `marketBuyOrdersNoThrow()` and `marketSellOrdersNoThrow()` but with a final check that the combined fill results indicate that the correct amount of assets were sold or bought: 24 | 25 | - In the case of `marketBuyOrdersNoThrow()`: 26 | - `fillResults.makerAssetFilledAmount >= makerAssetFillAmount` 27 | - In the case of `marketSellOrdersNoThrow()`: 28 | - `fillResults.takerAssetFilledAmount >= takerAssetFillAmount` 29 | 30 | ## Implementation 31 | 32 | The pseudocode for `marketSellOrdersFillOrKill()` would look like: 33 | 34 | ```python 35 | def marketSellOrdersFillOrKill(orders, taker_asset_to_sell, signatures): 36 | # Leaving out checks that orders are homogenous for simplicity. 37 | fill_results = FillResults() 38 | for order, signature in orders, signatures: 39 | fill_results += fillOrderNoThrow( 40 | order, 41 | taker_asset_to_sell - fill_results.taker_asset_filled, 42 | signature 43 | ) 44 | # Stop if we've met our target 45 | if fill_results.taker_asset_filled >= taker_asset_to_sell: 46 | break 47 | # Revert if we did not spend all of taker_asset_fill_amount 48 | if fill_results.taker_asset_filled < taker_asset_to_sell: 49 | revert() 50 | return fill_results 51 | ``` 52 | 53 | The pseudocode for `marketBuyOrdersFillOrKill()` would look like: 54 | 55 | ```python 56 | def marketBuyOrdersFillOrKill(orders, maker_asset_to_buy, signatures): 57 | # Leaving out checks that orders are homogenous for simplicity. 58 | fill_results = FillResults() 59 | for order, signature in orders, signatures: 60 | fill_results += fillOrderNoThrow( 61 | order, 62 | # Calculate the amount of taker asset to sell given the 63 | # amount of remaining maker asset we need. 64 | (maker_asset_to_buy - fill_results.maker_asset_filled) 65 | * order.taker_asset_amount / order.maker_asset_amount, 66 | signature 67 | ) 68 | # Stop if we've met our target 69 | if fill_results.maker_asset_filled >= maker_asset_to_buy: 70 | break 71 | # Revert if we did not spend all of taker_asset_fill_amount 72 | if fill_results.maker_asset_filled < maker_asset_to_buy: 73 | revert() 74 | return fill_results 75 | ``` 76 | 77 | ## Notes/Challenges 78 | 79 | - If you preferred the original versions because they asserted that all orders were valid, you can still detect invalid orders (as an EOA) by examining the `Fill` event logs. If an order hash does not appear in the logs, it was either unfillable or you hit your target without needing to fill that order. 80 | 81 | ## Copyright 82 | 83 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 84 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-59.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 59 4 | Title: Mixed assets in "market" operations 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category: Core 8 | Status: Final 9 | Created: 2019-10-23 10 | 11 | Discussion: #59 12 | 13 | ## Summary 14 | 15 | Remove the restriction of all orders sharing the same maker or taker asset data in `marketBuy...()` and `marketSell...()` functions. 16 | 17 | ## Motivation 18 | 19 | The V3 world is evolving into one where the same asset can be represented by different asset data encodings. A good example would be with the new Bridge (#47) proxies, which can exchange any ERC20 token but can also carry arbitrary payloads in its asset data. 20 | 21 | ## Specification 22 | 23 | In V2, we copied the `makerAssetData` (in the case of a `marketBuy...()`) or the `takerAssetData` (in the case of `marketSell...()`) to each subsequent order passed into the market functions. This essentially enforced homogenous asset types across all orders. 24 | 25 | Going forward, we will simply no longer perform this copy, and fill orders as usual, continuing 26 | to track and assert the maker/taker asset amounts bought/sold. 27 | 28 | ## Rationale 29 | 30 | Because we no longer enforce homogenous asset types, this places more burden on the taker/interface to ensure that orders are, indeed, compatible or desirable. 31 | 32 | ## Copyright 33 | 34 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 35 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-61.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ``` 4 | ZEIP: 61 5 | Title: Initial Staking Parameters 6 | Author: 0x Core Team 7 | Type: Standard Track 8 | Category: Core 9 | Status: Final 10 | Created: 2019-10-29 11 | ``` 12 | 13 | Discussion: #61 14 | 15 | ## Summary 16 | 17 | This proposal outlines the initial parameters for stake-based liquidity incentives. Parameters are upgradeable via a vote by the ZRX token holders. See [ZEIP 31](https://github.com/0xProject/ZEIPs/issues/31) for the original stake-based liquidity incentives proposal, and the [0x Staking Specification](https://github.com/0xProject/0x-protocol-specification/blob/3.0/staking/staking-specification.md) for the most up-to-date information on architecture, implementation and usage. 18 | 19 | ## Specification 20 | 21 | | Parameter | Value | 22 | | ----------------------- | ------- | 23 | | α (alpha) | 2/3 | 24 | | Epoch Length | 10 days | 25 | | Minimum Stake | 100 ZRX | 26 | | Delegated Stake Weight | 90% | 27 | | Protocol Fee Multiplier | 150,000 | 28 | 29 | ## Rationale 30 | 31 | **α (alpha)** 32 | This is a term in the [Cobb-Douglas formula](https://github.com/0xProject/0x-protocol-specification/blob/3.0/staking/staking-specification.md#62-paying-liquidity-rewards-finalization) that dictates the weight of fees versus stake when computing liquidity rewards. By choosing a weighting of 2/3 we are giving a greater weight to fees over stake. 33 | 34 | **Epoch Length** 35 | All processes in the system are segmented into contiguous time intervals, called epochs. Protocol fees accumulate throughout an epoch and are distributed when the epoch ends. Stake remains delegated (or undelegated) for the duration of an epoch. 36 | 37 | This parameter is the minimum number of seconds between epochs. Short epochs are open to abuse (like griefing) and long epochs aren’t great for UX. 38 | 39 | **Minimum Stake** 40 | This is the minimum amount of stake required for a pool to collect rewards. It should be low enough to mitigate griefing through dust pools, but not so high that it creates a significant barrier to entry. 41 | 42 | **Delegated Stake Weight** 43 | We incentivize makers to stake their own ZRX by lowering the weight of ZRX delegated to their pool. This mitigates monopolization of staking pools, as it is always more profitable for a maker to create their own pool than delegate to a centralized pool. 44 | 45 | **Protocol Fee Multiplier** 46 | The protocol fee per-fill is this parameter times the transaction gas price. The value chosen is roughly equal to the average gas cost of filling an order on 0x. 47 | 48 | ## Copyright 49 | 50 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 51 | -------------------------------------------------------------------------------- /ZEIPs/ZEIP-7.md: -------------------------------------------------------------------------------- 1 | ## Preamble 2 | 3 | ZEIP: 7 4 | Title: On-chain order generation by smart contracts 5 | Author: 0x Core Team 6 | Type: Standard Track 7 | Category (*only required for Standard Track): Core 8 | Status: Final 9 | Created: 2017-09-16 10 | 11 | ## Simple Summary 12 | 13 | Allow contracts to create orders without the use of signatures. 14 | 15 | ## Abstract 16 | 17 | Contracts cannot currently generate orders. With ZEIP-1 contracts are able to generate orders by implementing an `isValidSignature` function. This ZEIP will allow contracts to generate orders on demand and dynamically. This allows a contract to create an order in the transaction lifecycle. 18 | 19 | ## Motivation 20 | 21 | Currently, there is no way for smart contracts to generate orders (see issue #1 ). 22 | 23 | ## Specification 24 | 25 | The following additions can be added to the Exchange contract: 26 | 27 | ``` 28 | mapping(bytes32 => bool) public isOrderApproved; 29 | 30 | function approveOrder( 31 | address[5] orderAddresses, 32 | uint[6] orderValues) 33 | public 34 | returns (bool) 35 | { 36 | require(orderAddresses[0] == msg.sender); 37 | bytes32 orderHash = getOrderHash(orderAddresses, orderValues); 38 | isOrderApproved[orderHash] = true; 39 | return true; 40 | } 41 | ``` 42 | 43 | Then, when verifying an order signature, we check: 44 | 45 | ``` 46 | require(isValidSignature(...) || isOrderApproved[order.orderHash]); 47 | ``` 48 | 49 | ## Rationale 50 | 51 | This allows any contract to approve an order on-chain in place of a signature. 52 | 53 | ## Test Cases 54 | 55 | ## Implementation 56 | 57 | ## Copyright 58 | 59 | Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). 60 | -------------------------------------------------------------------------------- /zeip96_images/ABDK_0x_MetaTransaction_v_1_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/ZEIPs/1dd589b544739c904f998cc1b33e83acfd5d65da/zeip96_images/ABDK_0x_MetaTransaction_v_1_0.pdf -------------------------------------------------------------------------------- /zeip96_images/metaTxn_current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/ZEIPs/1dd589b544739c904f998cc1b33e83acfd5d65da/zeip96_images/metaTxn_current.png -------------------------------------------------------------------------------- /zeip96_images/metaTxn_proposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/ZEIPs/1dd589b544739c904f998cc1b33e83acfd5d65da/zeip96_images/metaTxn_proposed.png -------------------------------------------------------------------------------- /zeip96_images/multihopAudit.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------