diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000000..6599572186
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,23 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+
+# Build documentation with MkDocs
+#mkdocs:
+# configuration: mkdocs.yml
+
+# Optionally build your docs in additional formats such as PDF
+#formats:
+# - pdf
+
+# Optionally set the version of Python and requirements required to build your docs
+python:
+ version: 3.7
+ install:
+ - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/docs/.gitignore b/docs/.gitignore
index 06aa0e522f..d814fac828 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1 +1,2 @@
-_build*
\ No newline at end of file
+_build*
+basics/addresses.rst
diff --git a/docs/Makefile b/docs/Makefile
index c04268ff1d..54cae22adf 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -49,38 +49,48 @@ help:
clean:
rm -rf $(BUILDDIR)/*
+addresses:
+ @python scripts/generate_addresses.py > basics/addresses.rst
+
html:
+ @make addresses
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
+ @make addresses
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
+ @make addresses
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
+ @make addresses
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
+ @make addresses
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
+ @make addresses
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
+ @make addresses
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
@@ -90,6 +100,7 @@ qthelp:
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc"
devhelp:
+ @make addresses
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@@ -99,11 +110,13 @@ devhelp:
@echo "# devhelp"
epub:
+ @make addresses
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
+ @make addresses
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@@ -111,6 +124,7 @@ latex:
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
+ @make addresses
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@@ -123,16 +137,19 @@ latexpdfja:
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
+ @make addresses
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
+ @make addresses
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
+ @make addresses
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@@ -140,38 +157,45 @@ texinfo:
"(use \`make info' here to do that automatically)."
info:
+ @make addresses
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
+ @make addresses
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
+ @make addresses
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
+ @make addresses
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
+ @make addresses
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
+ @make addresses
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
+ @make addresses
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/docs/README.md b/docs/README.md
index 0aa8b4dcf5..a7536f5973 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,6 @@
### Dependencies
```bash
- pip3 install sphinx recommonmark
+ pip3 install sphinx recommonmark sphinx-rtd-theme
```
### Syntax
@@ -15,4 +15,4 @@ open _build/html/index.html
### Tips
* Generate RST tables [here](https://www.tablesgenerator.com/text_tables#).
-* Set your editor's ruler to `100` characters.
+* Set your editor's wordwrap to `98` characters.
diff --git a/docs/_drawio/RFQm.drawio b/docs/_drawio/RFQm.drawio
new file mode 100644
index 0000000000..30f30dd7a9
--- /dev/null
+++ b/docs/_drawio/RFQm.drawio
@@ -0,0 +1 @@
+7VjRbtowFP0aHls5CUnhsUC7PawaE+22VxObxJoTR45ToF8/m9hJjEM7VFBVNB5QfGzfxOecey9kEEyzzRcOi/SBIUwHPkCbQTAb+H4UBvJbAVsN+OMaSDhBNQRaYEFecA16Bq0IwqXGakgwRgUpbDBmeY5jYWGQc7a2l60YRRZQwAQ7wCKG1EV/ESTSGh2FoMW/YpKk5s4e0DMZNIs1UKYQsXUHCu4GwZQzJuqrbDPFVHFn83J/YLZ5MI5z8S8bnuaJSGPw9HP19GM2nIPYf1xeRXWUZ0grfWD9sGJrGMA5ulVEylHOcglOUpFROfLkpZy8J1SNgByVAnJhFscUliWJDayXqU31LTBymG+P4jUESWNhlmHBt3LJupXAKJB22DcYxxQK8myHh9oJSROuucOcEXljH2jT+iMdR3t2aCQ0IUpW8RjrXV3K9wINwRuBJDEJFk4gedE5dgvtFD1C3RtH3QVJcowkJh/RB985wtwVXArzDS5lHltSQyr3Kl2lSHJXMHnGXBCZKbd6IiMIqRgTjkvyApe7eMoWhTrf7sThZBDOGgeoAHjTl8Z6c5s8XW8cNrJrGB39ClyDKLqxxLjy32cWE8bz7S1stSrxWeT0hm9na8JZVbyL3gOpZ3IjsC0djPW4k5rB6DqIQPsxz91N1TE4TLTF29EkORw9wj89LpfluFCXVUZvY8G6ht6Zf85KIghTxl4yIVjW43jBCjtHWCUoyfG0aUbgNbO/aeqaOFeLrd0ju9RHknqX7dHZ2B4f1UDantDbQ7z9HqIbTreBgM/YQMJTNZD9QGduIKY+9HWQh8ffl9E6ag9feO/w3d7x8Bnq4uvdaAhsXZp8+cCS6If/S2JPJQtPVBLDmw8uie5fpjuRYo6rTKKXUhNrE196TRy9IuWeivJndY4w0hKsUyLwooCxml1zuFfuTlDZHJv7bmWLetI1Or6syWH7FqLmtn2VE9z9BQ==
\ No newline at end of file
diff --git a/docs/_drawio/architecture.drawio b/docs/_drawio/architecture.drawio
new file mode 100644
index 0000000000..eaba5ba5b4
--- /dev/null
+++ b/docs/_drawio/architecture.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/docs/_drawio/plp_sandbox.drawio b/docs/_drawio/plp_sandbox.drawio
new file mode 100644
index 0000000000..bface5dc87
--- /dev/null
+++ b/docs/_drawio/plp_sandbox.drawio
@@ -0,0 +1 @@
+3Vhbc6IwFP41PLYDhCh9rJfuPtgZZ+1028cIATIicUOs2F+/CYS7KO1qL6sP5nxJDsm5fOeIBsbr5AdDm+CeujjUTN1NNDDRTNMwLCB+JLLPEd3IEJ8RN8P0EliQV6wW5uiWuDhWWAZxSkNONnXQoVGEHV7DEGN0V1/m0dCtARvk4xawcFDYRn8TlwcZakO9xH9i4ge8uJ+aWSJn5TO6jdTzNBN4jvxm02uU61Lr4wC5dFeBwFQDY0Ypz0brZIxDady62e46ZotzMxzxPhvch8enRyMk+iy5u4X+L/95NbxSWl5QuFX2mJE/wiOE7+eMvgjXsDuM+JZhdQm+zw2XXh1L5boGRruAcLzYIEfO7kSsCCzg61BIhhh6JAzHNKQs3QtchG1hKDCKOaMrXJkZODZeemJGHQwzjpPOGxuFHUWAYrrGnO3FknzDQJlexSbIXbErHV2sCSpOvlEYUrHlF6pL+4qBMvEbzG22zN0yK47cWxnWQnJCFMfEqVtS3J3tn5TVU+FZCtcmzOVJUp2d7JXkojhI3WUoYY44xyxKEVM3Cptjt5UxDYuLFEXMx/zITcFhz1QsDw8YPscYDhEnL/VjHPKGesKcEnHAwvGFo3PHWw2HxnTLHKx2VXOmoWigNxWBuqLMDi1FaXAU135/vFiteDGuhfzAUBR7mMkhWmW/Io2iuB1NwpcztBSkXQsiFBJfOt4RfhXbwUjmGRGkeKsm1sR1pY4RwzF5RctUn4yijbxqenk40uDkWKIqxlabSyKshlN3lnRm9ZV+behDs+YX4yxhY8Ca0qubugLqeTG+iJtBy83z2VwABReLcU7HZ+VhD8rvQR5OP3IHjXgFzz7n4eeB9U5+ti/Fz/B/LodWg8wK+dPMPThDOUwIf6qMs2I4hEosa6EU8lIoWXGhnkEZD6hPIxROS3RU92b/upgVltMN18n6CT+zfjYjBTYjoG/9tGBDEWgo6qifwuVoX1mmqk53wW92erZ99FzN9ZZV653FIDvBWVl++O/R3qOH6+oPh6f6w8OZ9GUTCfZMpE9tRL9dIsHjiXGyQX7remB/QOLZrcQzZRc9TbCz5Tjrp912Rf/qvfOJam83LD0c9I7evKtuxNjlGuCbD6bGa1glR+MUM55kuZw7S74s9HZy58WYEfRkxo74+RhmHJqHiePLMmPzwBAeZzrTOrr+MkyXZ2yT6iovDO6/9wuDt5EebEZVj78uQixfymaOKV99g+lf
\ No newline at end of file
diff --git a/docs/_static/adjusted-staking-percentage-formula.pdf b/docs/_static/adjusted-staking-percentage-formula.pdf
new file mode 100644
index 0000000000..f767caf5cb
Binary files /dev/null and b/docs/_static/adjusted-staking-percentage-formula.pdf differ
diff --git a/docs/_static/img/architecture.png b/docs/_static/img/architecture.png
new file mode 100644
index 0000000000..e3f7e29432
Binary files /dev/null and b/docs/_static/img/architecture.png differ
diff --git a/docs/_static/img/bootstrap.png b/docs/_static/img/bootstrap.png
new file mode 100644
index 0000000000..7eb4222d2e
Binary files /dev/null and b/docs/_static/img/bootstrap.png differ
diff --git a/docs/_static/img/events.png b/docs/_static/img/events.png
new file mode 100644
index 0000000000..6f11e09737
Binary files /dev/null and b/docs/_static/img/events.png differ
diff --git a/docs/_static/img/fee_collectors.png b/docs/_static/img/fee_collectors.png
new file mode 100644
index 0000000000..b53505c45e
Binary files /dev/null and b/docs/_static/img/fee_collectors.png differ
diff --git a/docs/logo.svg b/docs/_static/img/logo.svg
similarity index 100%
rename from docs/logo.svg
rename to docs/_static/img/logo.svg
diff --git a/docs/_static/img/plp_sandbox.png b/docs/_static/img/plp_sandbox.png
new file mode 100644
index 0000000000..bbff0250b6
Binary files /dev/null and b/docs/_static/img/plp_sandbox.png differ
diff --git a/docs/_static/img/proxy.png b/docs/_static/img/proxy.png
new file mode 100644
index 0000000000..f26cac359c
Binary files /dev/null and b/docs/_static/img/proxy.png differ
diff --git a/docs/_static/img/rfqm.png b/docs/_static/img/rfqm.png
new file mode 100644
index 0000000000..e9faae3a32
Binary files /dev/null and b/docs/_static/img/rfqm.png differ
diff --git a/docs/_static/img/zero_ex_migrate.png b/docs/_static/img/zero_ex_migrate.png
new file mode 100644
index 0000000000..65921125cd
Binary files /dev/null and b/docs/_static/img/zero_ex_migrate.png differ
diff --git a/docs/_static/js_overrides.js b/docs/_static/js_overrides.js
new file mode 100644
index 0000000000..67a5e0a9aa
--- /dev/null
+++ b/docs/_static/js_overrides.js
@@ -0,0 +1,10 @@
+// Open external links in a new window.
+$(document).ready(function () {
+ $('a[href^="http://"], a[href^="https://"]').not('a[class*=internal]').attr('target', '_blank');
+
+ $(".researchPdf").height($( document ).height() * 0.8);
+ });
+
+$( window ).resize(function() {
+ $(".researchPdf").height($( document ).height() * 0.8);
+});
\ No newline at end of file
diff --git a/docs/_static/protocol-fees.pdf b/docs/_static/protocol-fees.pdf
new file mode 100644
index 0000000000..6883241a3d
Binary files /dev/null and b/docs/_static/protocol-fees.pdf differ
diff --git a/docs/_static/staking/Batch-Calls.png b/docs/_static/staking/Batch-Calls.png
new file mode 100644
index 0000000000..66a7a3e5ef
Binary files /dev/null and b/docs/_static/staking/Batch-Calls.png differ
diff --git a/docs/_static/staking/Batch-Calls.xml b/docs/_static/staking/Batch-Calls.xml
new file mode 100644
index 0000000000..0f38a8bb75
--- /dev/null
+++ b/docs/_static/staking/Batch-Calls.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/docs/_static/staking/CobbDouglas.png b/docs/_static/staking/CobbDouglas.png
new file mode 100644
index 0000000000..11318490af
Binary files /dev/null and b/docs/_static/staking/CobbDouglas.png differ
diff --git a/docs/_static/staking/Epochs.png b/docs/_static/staking/Epochs.png
new file mode 100644
index 0000000000..a40ac4c4ab
Binary files /dev/null and b/docs/_static/staking/Epochs.png differ
diff --git a/docs/_static/staking/Epochs.xml b/docs/_static/staking/Epochs.xml
new file mode 100644
index 0000000000..3348f90f2e
--- /dev/null
+++ b/docs/_static/staking/Epochs.xml
@@ -0,0 +1 @@
+5ZrbjtowEIafhsutkjgnLhf2pEpVV0Jqr914IFZDTB2zQJ++DnEgybDbbhXSqGYviH/b49jfeD1jMSHz9f5R0k36STDIJp7D9hNyN/E8141D/VUqh0qJIlIJK8lZJTlnYcF/gulZq1vOoDBaJSkhMsU3bTEReQ6JamlUSrFrN1uKjLWEDV0BEhYJzbD6lTOV1vNynHPFE/BVqro1a1q3NkKRUiZ2DYncT8hcCqGqp/V+Dlm5eu2FeXil9vRmEnL1Jx3UIn76cTN9nn6GL8HHeH/YLsmNX1l5odnWzNi8rDrUSwA5uy1XUpeSjBYFTyZklqp1pgVXPxaKSlW3ENpSrT3wrGzj6LK2YUplj6V+nItMyOMAhFGIl8mxlxTfoVETJjF8W+oaPFczfWAtfmbmjyDWoORBN9idqQUGRNrgVWsSMqr4S5s6Nc6zOpk7jfAsuH4Tz6kd3Td2jJt7sfMhaBspxFYmYPo1MXVMRfFvTenFXYFCpvRDY+pn6egH7/CJ4F0+kYtcizNGixSYAdzwjrGTO21Ps9zE+2tyXVNe7RQDcQtt4kac3rh1TQ3NLbKKW9wft+5/yoG5xTZx88PeuHVNDc1tahO3wO+NW9fU0NzqnMAOcGF/gUnX1ODgXJvARf1FJl1Tg4PzEDgXkVOwV92MsJnHGZzNpM9INOOrXBcTTRK0PnsBqbhOvm9NxZozVg4z26VcwWJDk3LMnaQbrUmxzdnRQcoMcyly1cgcnePnLW8px4L9m/7yWlw/PQFteFR8waM853XnabF6NxiCwOAt9d+DQYH7CMDgCxViIZhuZD4CMPhWw7cPDAq9RwAGX1sE9oFBsfUIwOB7idA+MCh2/vdg6qO+AeZ+I5L0CnBkNZ2RskG37hfZRIOywee/cwUuV9g00W3511PE3AUTXALjDwoGHzOuhWRIHQedyLiIy6Xc+Hpc8C2qjTuGTKMPIyND8HUbsZCMH42NCz7+fQu5BMH4dgw+/AMLyYRkbFxwJnNHD0WJhed6iTznEXIoeHEFVv1H0H2iQhH0BVQ9xc+6eP6tU3VBff7JGLn/BQ==
\ No newline at end of file
diff --git a/docs/_static/staking/ProtocolFee.png b/docs/_static/staking/ProtocolFee.png
new file mode 100644
index 0000000000..6a88481ab9
Binary files /dev/null and b/docs/_static/staking/ProtocolFee.png differ
diff --git a/docs/_static/staking/ProtocolFee.xml b/docs/_static/staking/ProtocolFee.xml
new file mode 100644
index 0000000000..fb501ee9c0
--- /dev/null
+++ b/docs/_static/staking/ProtocolFee.xml
@@ -0,0 +1 @@
+7Vpdd7I4EP41XtrDh1C9rB9tL953T9+257S+N3siRMiKxA2xfvz6TSBoSECpi63tbr0omYxjmOdhJjOkZQ/m6zsCFuFP7MOoZRn+umUPW5Zlml2X/eOSTSZxe1YmCAjyM5GxFzyhLRTfzKVL5MNEyDIRxTiiaFEUejiOoUcLMkAIXhXVpjjyC4IFCKAmePJApEtfkE/D/L4MYz9xD1EQUnVmDnJtIUhC4OOVJLJHLXtAMKbZ1Xw9gBH3XtExtxWzu5URGNM6X1gv6Lj7Or9dzTHdxn+/jZ1t3DYFPm8gWopbFqulm9wHMPZvuCvZyItAkiCvZfdDOo+YwGSXUxzTAY4wSdVtZ8A/TA595kphBhMa4gDHIBrtpX39FsRd8a9KAnFDdxDPISUbprDag+EI/4YSDLmMwAhQ9FYEEwhOBDtzu194wIitxDIEf7vCjCCv7RpFCwleEg+KL8muV+xYRtFQx1IMUUACSDVDzO1gI6ktuEJSvV6zYsFV61L1OyqFat6H0GcX2YrzkQTZXpTS8h0U/Z+hn8BQ27hMhubrOivjHI1xmPiQaLQjeBn7kFsyGFVWIaLwaQE8Prti6VDhIIoiiYNTh3+YPKEEz6A00x/yzwHWVnLyDRIK1wdZmc/ailvzgCSx1i5hbUdhhUxQCZP3u7zz/V1uKS63P87l15P7v9zteHRzszTe7pbjED3O2qbm8ka97QPYnXpl3na9LpxMm/FqR/VqCZG7JV7tnsurHevEdOWDJExdbRbdmrDIS3P1GMcwl90ivrIUGeY/snmVB2M+uHLy4XAtTw43u5EvrPBfgmtEX6VryQYb7U3wQW6hEsIs8RynX5ZXDjnUrplwBSPaxpVhOQVStM2uRooz5mQnX7L4eat3YlJ2DKtIbjUWVCTlvaFcEU+nCSzonJArD8LztcOI07m0MKInxCcKZigOmHDAshQBHgf4geD1RnM4u2uqRhHZeyKMyK4WIhChIOZxifmSpV+7z32IWD18IybmyPfTnXEZjEWgmwjvKi6OjkunBBe1vmoOF70aKcPlu+LhuBeGh3NqupWwODV7VvrzaE67rBrSbqqItM2iIbdmEdlULjJ1MozWXghi5maVFEeyEEgWWTtxitb8AapfS7jpn15LZH/NPIa2Wq1/YLpK7v4M6OvLj3D7+Hscvv7x+PDrV0kt8RPMSsq3JAQLfrmcRzcexXJA+wEmMHrACaII88A2wZTiOVOI+EQfeLMgDWcyCOlfSVCkWIETL2mEYgZT3iVuKj8pOHR0HMpqOvUBaw4HvXVxKBxipqd3ykQXnj1NVRXCvioYt6SioLRCyDNYBKf0CzTU3F6v/NF6bzBUDWmgNxcMy6mg71Ses2fSYJiAmAU+y2inE8YtZAM34vhMmIIb8KtD+03JRMvqS0aObnwITNAWTFIFTg/RMGTaTr/lDHXCVG54asQFlc06+Q4/RWoc2L1nEjfQkt/klMUH40opBRvhqHWl1rdFC41Ue6VtOr3Y+3ZtOvO0kH62zuj18Yj+3bKqpWHgahhYH4lBycYyjaXJfw6KjtH7ZChq7HC+Owi7ffyngVAjKJ36TrbSXxeyQTSvz/XK9XwbxHIQu+cD8fiL9U9oulgXxSO1dtTOhNTlUa9o57rm2ZLGaNR7F41EX7MOh3al50HcLxTO08PCsW7cmfHM6dM8njViwpdGXO12nhvx9569sdTMVTxLc1y/eFbnX5+9KX/B0sDWot4rc7mxdelcc9VjDqdGF1d9gfPR0UWvpF5Gz/dM8sxq/ViD+ku36TVnn69Nz4b7k8QZWPsD2fboHw==
\ No newline at end of file
diff --git a/docs/_static/staking/Read-Only Proxy.png b/docs/_static/staking/Read-Only Proxy.png
new file mode 100644
index 0000000000..d72829cd95
Binary files /dev/null and b/docs/_static/staking/Read-Only Proxy.png differ
diff --git a/docs/_static/staking/Read-Only Proxy.xml b/docs/_static/staking/Read-Only Proxy.xml
new file mode 100644
index 0000000000..ee28567e53
--- /dev/null
+++ b/docs/_static/staking/Read-Only Proxy.xml
@@ -0,0 +1 @@
+7VlLd+MmFP41OqddaI7edpa2k8ls2uZMFp2s5mAJyTSy8CCc2Pn1BYQQ6GE7fiSZabOJ+O4VhvvdF8jyZ8vNLQGrxR84gbnlOcnG8q8tz3PdccT+cWRbIaMrCWQEJVKpAe7RC5SgI9E1SmBpKFKMc4pWJhjjooAxNTBACH421VKcm7+6AhnsAPcxyLvo3yihi3pfjtMIvkCULWhbsgS1tgTKBUjwswb5N5Y/IxjT6mm5mcGcW682TPXe5wGpWhmBBT3kBRuPnNEmvX2Z/bjz/yxW38ehbV9VszyBfC13LBdLt7UJCF4XCeSTOJY/fV4gCu9XIObSZ0Y6wxZ0mbORyx5TlOcznGMi3vUTAMdpzPCSEvwINUkUj+E8ZRK5AEgo3AzuzFX2Yp4G8RJSsmUq8gW/NrF0sqjm4LmhbCyhhU5WJEEgvSRTUzd2ZA/SlP1mHc2//BO9PNxMJmvn6Xb9sEBfH233g5i1Y8MeSw+aVZnnw5g18Dp2ZQkHZoBCy4ty9vvTOWFPGX9iQZx30Q4PsEgmPFGwUZyDskTcrgkoF4Ib1+ShpIDQWr3ABayxz4jvRFDJDE623/TBAx988sJ6fL3RpddbNUrkNO4uAmFipKxB+mznk8N+U2fQdscdBsMeBmuMwBxQ9GTmwj5W5SLuMGKLVSvwgpYDBS3HKPGaxFC+paeu1kSdAG9PxCjIIN0xUa2I07SEho5wRGW9E3zT/xViPvx4MR907HpPwSMqMgbOMIsgEHOG7wjebDsWZ9um7RDWzSdjWLe1hECOsoInBWZMyPApNyJiSWUiBUuUJPxnenk0mT5HMh63iPG6xAQ9xHgX4yU6iJdflY+wzYf7znyE3dp4WK3TuBgqXfsql1EWMVtBqyzurGdV7t7fTO2te29T1Nq8j4+saa45z5VzWEk7olz1Nv5uX7mKwJIHSzEvV00DZWAHBDSBJXoBc6HAnWPFtyA2FU6t8PpVoZyDOcynIH7MRABrRS8Vf7vOD/JIKFdiqcjTXXBHJO3qq3yzrXLP4lhu0DfpWRuXXk+4bE8ts/dpDXWijzaIfqvzFXvWm2s2bDIUH6jWmuWOe7k+TOgCZ7gA+U2DTntzzGsOoe/fbgfOmdrtoJ3j2s3d27bbvV7b7QpP8MJ+nzrVpQzfbuptf2E8xvPeya2OrXjHuhUzIdhqarKgDC94oEQ3HljNeFZ/DDv++BWCxP6ryLc/xeHktAs4f38zHF2oGe5lo3s2OSU7XLB4vE0I+61T/ajdbB4cwvtywZlCuL3gNwnh0aucZv9l4SsrxMC5qe9W8D/gae2LqFE7V1zI00beG3ia2/d9oOqqyxUoDJ+Lfqz5F6Jpigtqp2CJWEHxJxZfpjyasdOQH3DXg/kT5FWgIxHas753AEEgH9YvQVHaJSQo5ZAQiHWU4kMdX4Wz2ijRXB3U7LiqV1yDZPPfWE1Wc3rBVfMcOr83W2zOE2H7k2LIrMtR8blMjWprh8LeDLnmz3zykFs0ZCzu03WVbh1ER03jNdNUpCpJipm/2wTyAivkzemKDaoDVf1qxbp6VfQHbFQlFQ67Yqh3CRwV9YsLmk7BgKtugUOyX+Cg2TFwoewZuFDrGrhE9A0crzsHDjoC0fZddRCHWFaJlFGbRBXy0FSagcaCs23wkY5Xqa2ZXZfJHNcQpclYjlB4pi2gzbkYKuJ10HRHqWf6bcrZqGKb5YoqvAeOzT/3XcpwTR3sG9mR2Y/Maw/7xMuUy5883e6FiRnj7euRJuBluP9PuxP5kUm79360WzKONfUmgv2bfwE=
\ No newline at end of file
diff --git a/docs/_static/staking/Rewards.png b/docs/_static/staking/Rewards.png
new file mode 100644
index 0000000000..12b6d938d9
Binary files /dev/null and b/docs/_static/staking/Rewards.png differ
diff --git a/docs/_static/staking/Rewards.xml b/docs/_static/staking/Rewards.xml
new file mode 100644
index 0000000000..c7baafe758
--- /dev/null
+++ b/docs/_static/staking/Rewards.xml
@@ -0,0 +1 @@
+7Vltb6M4EP410X26E2AM6cc22+2dtF1V7Um3+9EFJ1gxmDXOJtlff2MwLwayTaOkqaJGquoZ48E8zzDPxJmgWbq5kyRP7kVM+cRz4s0EfZp4nutOA/inPdvKE/ph5VhIFlcup3U8sV/UrKy9KxbTwvgqlxKCK5bbzkhkGY2U5SNSirV92Vzw2HLkZEEHjqeI8KH3PxarpH4ux2kn/qZskaj+TErqq42jSEgs1h0Xup2gmRRCVaN0M6Nco2cD83nHbLMzSTO1zwL6FUVX+I7PHje/8uUc3f54/Pqnb/j5SfjKPLLZrdrWGEAYgBuMm3XCFH3KSaRn1sA4+BKVcrBcGJIirziYsw2Fu97MGeczwYUsA6EY02nsg79QUixpZ2bqPaMggBmzGyoV3ex8TrdBD/KOipQquYVLzAIcoGqJSTnfw5W9bgkMDSdJh7raR0zKLJrILagwMLi+AmOELw5jFDg2xnXWdzB2vRGQG+fxUXYuDuWpDXIDegdkzxkBuXEeHWR/D4yz+FoXXrAykWmsY1IkGsQS2Q7Ic5GpDnLVB/yAjtx+A6fz11Vtfi/NaW1+0gg5jbXtWg9UMnhaKmvnhqkqWjjFxq7COY3dxtPGtmP0o1XPS+OBbLxIaoc1PEJa7ZOUE8V+2uHHiDR3eBAMbtzkjIdCO2nC0A5RiJWMqFnVlYt+oN4rjvtvriJyQdUgEJBPtp3Lcn1BsXvDbi/L/cCSMRhUEdukbTA9PI/3Ub02jyNOioJFdvZaWb0rld99tvjj4L86WwaC0A+0I1uORejVgNB/hSJ62SNdExlDAjr/ZHo/8HcHgOnxbS6iZEA81GtlU20XeVPVuopgXISzRabzBcjVBeNGV38GzeS1mUhZHPNd8iPFKovLjHJOIh84HJEPd1Q+TqQerjdgqWKn7MylYeeeyCVV5WBJ5R+auRxa/svlCbnYJgqdnSj0Fjr/3oujH/ZqGjqwOA4CTU8jpb53Bil1X9cTXq6W+i9J4L7pgs+spe70g9Hx9+ngAtALhPbspY/G6LA9+lx+sdX7wI362sp7AsHldK7OLre+Z58PjX6tflO5rQO/QM9D2QU59zR9prI4AT3vpB/CdQGq+6Gxw6XgTQkanuCNvyJFQnI9XKX8OlKii+UX8kz5gyiYYkJj+iyUEilcwPXEDYmWixLJTqGcl58RPpTonVeJleIsA6rrU3DHIuZ3RXhA/jFeMcfuaJuC3GEQjRDYF7rjHQ6Gr5K0C21og76e+QfqWYB6gfpn50dqaPHVGRpa9NH+7EiXQxva8KVAJ25/8PDc4aNyj1fuAVVjZxEjKefjE1VuPGxdr1OAR6dXLkUupGalPOlToqQUhPlye6MA9yvv8MfNY/VGYLa/TlfvYvsjP7r9Hw==
\ No newline at end of file
diff --git a/docs/_static/staking/StakeManagementExample2.png b/docs/_static/staking/StakeManagementExample2.png
new file mode 100644
index 0000000000..b0bee780d6
Binary files /dev/null and b/docs/_static/staking/StakeManagementExample2.png differ
diff --git a/docs/_static/staking/StakeManagementExample2.xml b/docs/_static/staking/StakeManagementExample2.xml
new file mode 100644
index 0000000000..e637714772
--- /dev/null
+++ b/docs/_static/staking/StakeManagementExample2.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/docs/_static/staking/Staking Architecture - Basic.png b/docs/_static/staking/Staking Architecture - Basic.png
new file mode 100644
index 0000000000..11c322bf61
Binary files /dev/null and b/docs/_static/staking/Staking Architecture - Basic.png differ
diff --git a/docs/_static/staking/Staking Architecture - Basic.xml b/docs/_static/staking/Staking Architecture - Basic.xml
new file mode 100644
index 0000000000..dfba79698a
--- /dev/null
+++ b/docs/_static/staking/Staking Architecture - Basic.xml
@@ -0,0 +1 @@
+7VrLcqM4FP0aL5PibXqZOK+qqVR1xT2T9OwUEI+KjFxCbsN8/UhGYJCwQzwYmKSdRdDVRUjnHF2JK2bmYpXdE7COHrEP0czQ/Gxm3swMQ9ddh/3jlrywzC29MIQk9oXT3rCM/4HCqAnrJvZh2nCkGCMar5tGDycJ9GjDBgjB26ZbgFHzqWsQQsWw9ABSrc+xT6NyXJq2r3iAcRhRuWYFSm9hSCPg423NZN7OzAXBmBZXq2wBEUevBKa47+5AbdUzAhPa5Ya3P/789vAUXmR3gbVB9yQPH4ML0covgDZixKKzNC8hIHiT+JA3os3M620UU7hcA4/XbhnpzBbRFWIlnV0GMUILjDDZ3Wv6ALqBx+wpJfgN1mocz4WvAatRh1H2CRIKs5pJDOse4hWkJGcuotZwBcRCZEbJwXZPWekS1ciyLGEEQiVh1fQeR3YhoPwArIYC623mRSBhYusT3sDmf63w7n78DpzQmr349QO7bpwGu3su1E0F9SUFb5CkM97Tu5nhINaF61fCrkJ+dQMRDAHFhz0exf2y/RPTaBoj02gpND4DhCDtQsM7wIN0XawSQZxxsqbNhO2MzIStMHGP2XASkDB8DW2ZpxSuvhor1aoxFiuOwopfxDGoUsF2MqgDQTDxr/huiZU8BNI05mu2D9JoF9H0Jl0pBYSW7glOYGm7i/lAdgGQwU3yl3rhJy9c2mXxJqtX3uRVyRet8CfBLKYvtetaG6y0b4IXyhYOMp7iDfHg+3shNpIQ0iN+88IP+o2t40H9XGiXmmE3JHShu4qE7BYJlTYCEaDxr+aetE1XohPfccwGX/XA0sxmhLclaRbQiLvqW0ipIdMxmlNBkxoqsDvSUOmIgyCFDZ/dVKjQO312zJXZ0etaPcyOtooxk9nRuq17qzgJmXHBgi8BHuf3O8FZrgDORk3lGFJHTwSROtTCBFAcJjwqMSwhs19zDGMW1a5ExSr2ff6YVhqbRPfAi6lJvJiGwovVwotxLlq+daLls9JhOROjo0xbHIs+rWttjYtTl86DeL67oOkdF7RhVitDin2WzFbX1UqfNxtynG6rVV8rkd4huVITg5hibUrQh1KC9VsJ9YYYNSCvua25Q9q9w47WSMmxi6LFfmWmJpumLjP7t8z6lJnlDiEzNbv2QZkN+jJnTEti8r5RVkZXib2r1TNJrCyfV2Jq5m/KEjMnLTFTzj9NXWKmM4TE1JSmIrGQvaesD8pCeTupDh/Ba9mCNmsVgrjL7nBuUoIxTEZRV1OKxyZe62tLt6xgPbunQnyUsrHnWZXzOm1aybNq4HcRNS3Wmr9hRtrvGeU4R8CjH53oasLs76cXZvgLbJCakvmPJyTDgGzL6ZaxD3x1Nf01StyaVgLFUfdul/ZpQcuRv6xQmzpz4CrXyvqnFE8LbpUPta7S3YnCgRT0//oIUqFh7IlnqKmtIrr9YOAknwt8V353Gx38jyV8vkjUm8uL0+lRT2F8+KinJlueb388fM4JJm8rRv8AyfhYHuKLTDD5tdU8NYel8N3buQwr7r+nLdz3nyWbt/8C
\ No newline at end of file
diff --git a/docs/_static/staking/Staking Architecture - Catastrophic Failure.png b/docs/_static/staking/Staking Architecture - Catastrophic Failure.png
new file mode 100644
index 0000000000..0a270d7854
Binary files /dev/null and b/docs/_static/staking/Staking Architecture - Catastrophic Failure.png differ
diff --git a/docs/_static/staking/Staking Architecture - Catastrophic Failure.xml b/docs/_static/staking/Staking Architecture - Catastrophic Failure.xml
new file mode 100644
index 0000000000..8f74286b35
--- /dev/null
+++ b/docs/_static/staking/Staking Architecture - Catastrophic Failure.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/docs/_static/staking/Staking Architecture - Read-Only.png b/docs/_static/staking/Staking Architecture - Read-Only.png
new file mode 100644
index 0000000000..9883737f20
Binary files /dev/null and b/docs/_static/staking/Staking Architecture - Read-Only.png differ
diff --git a/docs/_static/staking/Staking Architecture - Read-Only.xml b/docs/_static/staking/Staking Architecture - Read-Only.xml
new file mode 100644
index 0000000000..475c3469ea
--- /dev/null
+++ b/docs/_static/staking/Staking Architecture - Read-Only.xml
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/docs/_static/staking/Staking.png b/docs/_static/staking/Staking.png
new file mode 100644
index 0000000000..7e214195e2
Binary files /dev/null and b/docs/_static/staking/Staking.png differ
diff --git a/docs/_static/staking/Staking.xml b/docs/_static/staking/Staking.xml
new file mode 100644
index 0000000000..8571956fda
--- /dev/null
+++ b/docs/_static/staking/Staking.xml
@@ -0,0 +1 @@
+7Vpbc9o4FP41PML4gh3yCCRNH7qdlOy00JeOsGVbG2ExtgiQX1/JlkCW7OACSWhmyUwiHUnH8nfuh3Tc8WJzl4Fl8g8JIe44VrjpuDcdx7Ft32Z/OGVbUq76ghBnKBSb9oQH9AwF0RLUFQphXtlICcEULavEgKQpDGiFBrKMrKvbIoKrT12CGBqEhwBgk/oDhTQpqQPP2tM/QxQn8sm2JVYWQG4WhDwBIVkrJPe2444zQmg5WmzGEHPwJC7luU8Nq7uLZTClbQ5czT//5z/PbofDlfV0t5olaPLYFVyeAF6JFxaXpVuJQEZWaQg5E6vjjtYJovBhCQK+umYyZ7SELjCb2WwYIYzHBJOsOOuGAA6igNFzmpFHqKz4wQDOI7Zivoa8E8wo3Cgk8Vp3kCwgzbZsi1yVEAsd8+V8rUhMkBJFWJIGhI7EO857GNlAIPkHqPadw7DCNBxy/WSzAIM8RxymEORJAbVdhTWnIKNye0pSKGmfEL9ZIRmGX7adqpMZn/Q8Ob3ZqIs3290sFFz4k+AG0akyVniw2Z4Fn0gOjSLMySoL4GH1Y28SQ/oSoG65EYYVa23UiK7VsxyvohRde2AohVejFJKWQQwoeqq6gTpNEZe4J4i9/e4GjryyeLx3rSlbiY04pZqtzshyqsrd1xiV4L3ASG4kUZTDyp5CuXfonaDv7kdwI07/0txI34D1gYJHlMaMOCbMikHABXyfkc3WAJy9NdW9iIqecCMq1IIEMIpT7pcYlpDRRxxDxGLiUCwsUBjyx9SKsSroc7h3XS6eKZd+jVycV5OL30ouH1Uejn9h8vCODbeKLI6Nno14HoxpdsuQ9jbxaqDJ1D8yXNlVPtdWu2h1rkh01SKhjZlFLNvbwa62AHPJwaqXlDjltkhHXf9NA8nV6QbSLgVVU0kT4hdF9t6GsK16rj9VfC1ItczSzqX3ZgL2czJlhO9ghc1QdCD7AvmyLKUjtOGB433SMVcPM++djl1fhhFdiLlItdeTM5/HzOMsyIxBOqtXtiIZvBQR307GXO98zHO3ecZGMR8N86KUaki9T7SvyOM/tfZVfPgJlmUq9PJzHrszxPDedmeb6V3p3P5l4KQfC3zfujDw+/97vRpX5emx6XivZ0j8Nb1efvcrptMfX5Lnyc9ZMv06uf/2raYHzKtZVmjqcs4TsOTD1QIPA0rUSvQLmEN8T3JEEeEV6ZxQShZsA+YLIxA8xkUdqhpa8ampZinRTJasKEYpM0XZ4j9TIetqyLs1eXqNDuml0TG2Vi+IFsWLYmuE7dPaZswxia9QmNNsau3u27mzjtLNrW3tytYDhhE9qdPbtoH7RlmLZnTeseXuQUavbbtmbCyMl5GY7EAa8BGJ2C9p0+x+o2Kj9dVQLrNFlcEcPYvCl+vDkr9I8WreqOPdmBrS2Jpq4Qh09TW17WWzOblyt3rVpr1zFmVzKjy72vmzdOXrcfH+WndyIW7Cd6971W+RfL2J2TrMG6ze3FWYXWuRQDe6iu7OUej1T8PJStPhA3oaaVGX6ml6+neep/saNt3/j0K5ff+fHu7tbw==
\ No newline at end of file
diff --git a/docs/_static/staking/reward_tracking/Reward-Final.png b/docs/_static/staking/reward_tracking/Reward-Final.png
new file mode 100644
index 0000000000..18de459e7c
Binary files /dev/null and b/docs/_static/staking/reward_tracking/Reward-Final.png differ
diff --git a/docs/_static/staking/reward_tracking/RewardAfterManyEpochs-InPractice.png b/docs/_static/staking/reward_tracking/RewardAfterManyEpochs-InPractice.png
new file mode 100644
index 0000000000..461946ce88
Binary files /dev/null and b/docs/_static/staking/reward_tracking/RewardAfterManyEpochs-InPractice.png differ
diff --git a/docs/_static/staking/reward_tracking/RewardAfterManyEpochs.png b/docs/_static/staking/reward_tracking/RewardAfterManyEpochs.png
new file mode 100644
index 0000000000..b3483cdbe6
Binary files /dev/null and b/docs/_static/staking/reward_tracking/RewardAfterManyEpochs.png differ
diff --git a/docs/_static/staking/reward_tracking/RewardFromWhatWeStore-Example.png b/docs/_static/staking/reward_tracking/RewardFromWhatWeStore-Example.png
new file mode 100644
index 0000000000..529462573f
Binary files /dev/null and b/docs/_static/staking/reward_tracking/RewardFromWhatWeStore-Example.png differ
diff --git a/docs/_static/staking/reward_tracking/RewardFromWhatWeStore.png b/docs/_static/staking/reward_tracking/RewardFromWhatWeStore.png
new file mode 100644
index 0000000000..5181b47d17
Binary files /dev/null and b/docs/_static/staking/reward_tracking/RewardFromWhatWeStore.png differ
diff --git a/docs/_static/staking/reward_tracking/RewardSingleEpoch.png b/docs/_static/staking/reward_tracking/RewardSingleEpoch.png
new file mode 100644
index 0000000000..ada7b75946
Binary files /dev/null and b/docs/_static/staking/reward_tracking/RewardSingleEpoch.png differ
diff --git a/docs/_static/staking/reward_tracking/WhatWeStore.png b/docs/_static/staking/reward_tracking/WhatWeStore.png
new file mode 100644
index 0000000000..efb0a1123e
Binary files /dev/null and b/docs/_static/staking/reward_tracking/WhatWeStore.png differ
diff --git a/docs/_static/theme_overrides.css b/docs/_static/theme_overrides.css
index b48b97d863..628650e34e 100644
--- a/docs/_static/theme_overrides.css
+++ b/docs/_static/theme_overrides.css
@@ -10,4 +10,32 @@
.wy-table-responsive {
overflow: visible !important;
}
- }
\ No newline at end of file
+
+ table {
+ width: 100% !important;
+ }
+
+ td ul p {
+ font-size: 0.9rem !important;
+ }
+
+ h1 {
+ font-size: 24px !important;
+ }
+
+ h2 {
+ font-size: 20px !important;
+ }
+
+ h3 {
+ font-size: 18px !important;
+ }
+
+ .strike {
+ text-decoration: line-through;
+ }
+
+ .document a:visited {
+ color: #2980b9;
+ }
+ }
diff --git a/docs/additional/audits.rst b/docs/additional/audits.rst
index 472df02b06..c50b424f40 100644
--- a/docs/additional/audits.rst
+++ b/docs/additional/audits.rst
@@ -1,3 +1,27 @@
###############################
Audits
-###############################
\ No newline at end of file
+###############################
+
+Below are links to our third-party audit reports.
+
++------------------+---------------------------------------------------------------------------------------------------------------+
+| **Release** | **Reports** |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| Exchange V4 | We have an external audit scheduld with Consensys Diligence that will run from |
+| | November 30th - December 14th, 2020. |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| Exchange V3 | * `Trail of Bits `_ |
+| | * `Consensys Diligence (Exchange) `__ |
+| | * `Consensys Diligence (Staking) `__ |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| Exchange V2.1 | * `First `_ |
+| | * `Consensys Diligence `_ |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| MultiAssetProxy | * `Consensys Diligence `__ |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| ERC1155Proxy | * `Consensys Diligence `__ |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| StaticCallProxy | * No third-party audit. |
++------------------+---------------------------------------------------------------------------------------------------------------+
+| ERC20BridgeProxy | * No third-party audit. |
++------------------+---------------------------------------------------------------------------------------------------------------+
\ No newline at end of file
diff --git a/docs/additional/bounties.rst b/docs/additional/bounties.rst
index 256c0bdf3f..70ce320fd6 100644
--- a/docs/additional/bounties.rst
+++ b/docs/additional/bounties.rst
@@ -1,3 +1,80 @@
###############################
Bounties
-###############################
\ No newline at end of file
+###############################
+
+We run an ongoing bug bounty for the 0x Protocol smart contracts! The program is open to anyone and
+rewards up to **$100,000 for critical exploits**. The scope and disclosure instructions are below.
+
+Rewards
+-------
+The severity of reported vulnerabilities will be graded according to the `CVSS `_ (Common Vulnerability Scoring Standard).
+The following table will serve as a guideline for reward decisions:
+
++----------------------------+---------------------+
+| **Exploit Score** | **Reward** |
++----------------------------+---------------------+
+| Critical (CVSS 9.0 - 10.0) | $10,000 - $100,000 |
++----------------------------+---------------------+
+| High (CVSS 7.0 - 8.9) | $2,500 - $10,000 |
++----------------------------+---------------------+
+| Medium (CVSS 4.0 - 6.9) | $1,000 - $2,500 |
++----------------------------+---------------------+
+| Low (CVSS 0.0 - 3.9) | $0 - $1,000 |
++----------------------------+---------------------+
+
+Please note that any rewards will ultimately be awarded at the discretion of ZeroEx Intl. All rewards will be paid out in ZRX.
+
+Areas of Interest
+-----------------
+
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+| **Area** | **Examples** |
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Loss of funds | * A user loses funds in a way that they did not explicitly authorize (e.g an account is able to gain access to an ``AssetProxy`` and drain user funds). |
+| | * A user authorized a transaction or trade but spends more assets than normally expected (e.g an order is allowed to be over-filled). |
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Unintended contract state | * A user is able to update the state of a contract such that it is no longer useable (e.g permanently lock a mutex). |
+| | * Any assets get unexpectedly "stuck" in a contract with regular use of the contract's public methods. |
+| | * An action taken in the staking contracts is applied to an incorrect epoch. |
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Bypassing time locks | * The ``ZeroExGovernor`` is allowed to bypass the timelock for transactions where it is not explicitly allowed to do so. |
+| | * A user is allowed to bypass the ``ZeroExGovernor``. |
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Incorrect math | * Overflows or underflow result in unexpected behavior. |
+| | * The staking reward payouts are incorrect. |
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+Scope
+-----
+The following contracts are in scope of the bug bounty. Please note that any bugs already reported are considered out of scope. See the `Audits <./audits.html>`_ page for 3rd party security reports.
+
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| **Release** | **Contracts** | **Commit Hash** |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| Exchange V3 | * `ERC20BridgeProxy.sol `_ (`spec `__) | `fb8360edfd `__|
+| | * `Exchange.sol `__ (`spec `__) | |
+| | * `ZeroExGovernor.sol `_ (`spec `__) | |
+| | * `Staking.sol `_ (`spec `__) | |
+| | * `StakingProxy.sol `_ (`spec `__) | |
+| | * `ZrxVault.sol `_ (`spec `__) | |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| Exchange V2.1 | * `src/2.0.0/protocol `_ | `ff70c5ecfe `_ |
+| | * `src/2.0.0/utils `_ | |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| MultiAssetProxy | * `MultiAssetProxy.sol `_ | `c4d9ef9f83 `_ |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| ERC1155Proxy | * `ERC1155Proxy.sol `_ | `77484dc69e `_ |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| StaticCallProxy | * `StaticCallProxy.sol `_ | `54f4727adc `_ |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| ERC20BridgeProxy | * `ERC20BridgeProxy.sol `__ | `281658ba34 `_ |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+| ExchangeProxy | * `contracts/src `__ | `7967a8416c `_ |
++------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+
+Disclosures
+-----------
+Please e-mail all submissions to security@0x.org with the subject "BUG BOUNTY". Your submission
+should include any steps required to reproduce or exploit the vulnerability. Please allow time for
+the vulnerability to be fixed before discussing any findings publicly. After receiving a submission,
+we will contact you with expected timelines for a fix to be implemented.
\ No newline at end of file
diff --git a/docs/additional/contributing.rst b/docs/additional/contributing.rst
index f31cad546a..5226833bf7 100644
--- a/docs/additional/contributing.rst
+++ b/docs/additional/contributing.rst
@@ -1,3 +1,11 @@
###############################
Contributing
-###############################
\ No newline at end of file
+###############################
+
+We are an open source project and welcome contributions!
+
+Learn more about 0x Labs at `0x.org `_. Check out our code on `GitHub `_.
+Connect with the community on our `Forum `_ and `Reddit `_.
+Chat with our team privately on `Discord `_ or publicly on `Twitter `_.
+
+We're also hiring, see our open roles at `0x.org/jobs `_.
\ No newline at end of file
diff --git a/docs/additional/exceptional_erc20s.rst b/docs/additional/exceptional_erc20s.rst
new file mode 100644
index 0000000000..2def9d351e
--- /dev/null
+++ b/docs/additional/exceptional_erc20s.rst
@@ -0,0 +1,19 @@
+###############################
+Exceptional ERC20s
+###############################
+
+Some ERC20s have unique behavior that may require extra handling. We document these here as they are discovered.
+
+Assert vs Require
+-----------------
+These ERC20's use `assert` instead of `require`, which means that if the token reverts then (nearly) all
+of the gas from your transaction will be consumed. Specifically, you are left with 1/64 of the gas limit.
+Be mindful of this when implementing fallback logic; for example, if a call to `transferFrom` reverts then
+note you will only have 1/64 of the gas limit to handle the exception.
+
+Known tokens:
+
+- KNC
+- LINK
+- sUSD
+- USDT
diff --git a/docs/additional/releases.rst b/docs/additional/releases.rst
new file mode 100644
index 0000000000..b675ffc979
--- /dev/null
+++ b/docs/additional/releases.rst
@@ -0,0 +1,26 @@
+###############################
+Releases
+###############################
+
+.. role:: strike
+ :class: strike
+
+This page outlines upcoming releases and expected changes.
+
++-------------+----------------------+-----------------------------------------+
+| **Release** | **Est Release Date** | **Status** |
++-------------+----------------------+-----------------------------------------+
+| Tinker | TBA | In Audits |
++-------------+----------------------+-----------------------------------------+
+
+
+Tinker (Official V4 Release)
+----------------------------
+
+- Upgrade that transfer user funds to use allowances on the Proxy contract. Transfers will still fallback to the Allowance Target, but integrators will get reduced transaction costs from setting their allowance on the Proxy.. See more on the `Allowances Page <../basics/allowances.html>`_.
+- Deploy `LiquidityProviderFeature <../architecture/features.html>`_.
+- Deploy `NativeLiquidityFeature <../architecture/features.html>`_.
+- Deploy updated `FillQuoteTransformer <../architecture/transformers.html>`_, which can fill `V4 Orders <../basics/orders.html>`_. This transformer will no longer call Exchange V3.
+- Introduce `new events <../basics/events.html>`_.
+- Decommission `SignatureValidationFeature <../architecture/features.html>`_.
+- Decommission `TokenSpenderFeature <../architecture/features.html>`_.
\ No newline at end of file
diff --git a/docs/advanced/aggregation.rst b/docs/advanced/aggregation.rst
deleted file mode 100644
index 98f1abd9d9..0000000000
--- a/docs/advanced/aggregation.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Aggregation
-###############################
\ No newline at end of file
diff --git a/docs/advanced/erc20_transformations.rst b/docs/advanced/erc20_transformations.rst
index 6459556b91..8214d1a296 100644
--- a/docs/advanced/erc20_transformations.rst
+++ b/docs/advanced/erc20_transformations.rst
@@ -1,3 +1,178 @@
###############################
ERC20 Transformations
-###############################
\ No newline at end of file
+###############################
+
+
+The 0x Protocol is able to perform a variety of atomic transformations on ERC20 tokens, in addition to simply executing trades. This is made possible through composable smart contracts, called `Transformers <../architecture/transformers.html>`_. These trustless modules extend the core Exchange logic, enabling workflows like converting between ETH<>WETH or aggregating liquidity across DEX's. These operations can be combined with trade exeuction to create a seamlesss trading experience.
+
+Anyone can run transformations using the ``transformERC20`` Exchange function.
+
+.. code-block:: solidity
+
+ /// @dev Executes a series of transformations to convert an ERC20 `inputToken`
+ /// to an ERC20 `outputToken`.
+ /// @param inputToken The token being provided by the sender.
+ /// If `0xeee...`, ETH is implied and should be provided with the call.`
+ /// @param outputToken The token to be acquired by the sender.
+ /// `0xeee...` implies ETH.
+ /// @param inputTokenAmount The amount of `inputToken` to take from the sender.
+ /// If set to `uint256(-1)`, the entire spendable balance of the taker
+ /// will be solt.
+ /// @param minOutputTokenAmount The minimum amount of `outputToken` the sender
+ /// must receive for the entire transformation to succeed. If set to zero,
+ /// the minimum output token transfer will not be asserted.
+ /// @param transformations The transformations to execute on the token balance(s)
+ /// in sequence.
+ /// @return outputTokenAmount The amount of `outputToken` received by the sender.
+ function transformERC20(
+ IERC20TokenV06 inputToken,
+ IERC20TokenV06 outputToken,
+ uint256 inputTokenAmount,
+ uint256 minOutputTokenAmount,
+ Transformation[] memory transformations
+ )
+ public
+ override
+ payable
+ returns (uint256 outputTokenAmount);
+
+A Transformation is defined by a ``deploymentNonce`` (which identifies the contract that implements the transformation) and ``data`` for that contract.
+
+.. code-block:: solidity
+
+ /// @dev Defines a transformation to run in `transformERC20()`.
+ struct Transformation {
+ // The deployment nonce for the transformer.
+ // The address of the transformer contract will be derived from this
+ // value.
+ uint32 deploymentNonce;
+ // Arbitrary data to pass to the transformer.
+ bytes data;
+ }
+
+The transaction will revert if a transformation fails; the `inputTokenAmount` cannot be transferred from the sender; or the ``minOutputTokenAmount`` is not transferred to the sender. A single `TransformedERC20 <../basics/events.html#transformederc20>`_ event is be emitted upon successful execution of all transformations.
+
+Liquidity Aggregation
+---------------------
+
+Liquidity can be pulled from other Decentralized Exchanges (DEX) to supplement native liquidity (0x orders). This is currently used by 0x API to provide the aggregate the best prices across the entire DEX Ecosystem. Check out `https://matcha.xyz `_ to see this in action!
+
+Supported DEX's:
+
+* Balancer
+* Curve
+* DoDo
+* Kyber
+* MStable
+* Mooniswap
+* Oasis
+* Shell
+* Sushiswap
+* Uniswap v1/v2
+
+This transformation is implemented by the `FillQuoteTransformer <../architecture/transformers.html>`_ and has the ``deploymentNonce`` of ``5``. Abi-Encode the following struct to get the ``data``:
+
+.. warning::
+ An upgrade is pending to this transformation. This currently uses Exchange V3 Orders, but will soon be updated to use `V4 Orders <../basics/orders.html>`_. - 11/26/2020
+
+.. code-block:: solidity
+
+ /// @dev Transform data to ABI-encode and pass into `transform()`.
+ struct TransformData {
+ // Whether we are performing a market sell or buy.
+ Side side;
+ // The token being sold.
+ // This should be an actual token, not the ETH pseudo-token.
+ IERC20TokenV06 sellToken;
+ // The token being bought.
+ // This should be an actual token, not the ETH pseudo-token.
+ IERC20TokenV06 buyToken;
+ // The orders to fill.
+ IExchange.Order[] orders;
+ // Signatures for each respective order in `orders`.
+ bytes[] signatures;
+ // Maximum fill amount for each order. This may be shorter than the
+ // number of orders, where missing entries will be treated as `uint256(-1)`.
+ // For sells, this will be the maximum sell amount (taker asset).
+ // For buys, this will be the maximum buy amount (maker asset).
+ uint256[] maxOrderFillAmounts;
+ // Amount of `sellToken` to sell or `buyToken` to buy.
+ // For sells, this may be `uint256(-1)` to sell the entire balance of
+ // `sellToken`.
+ uint256 fillAmount;
+ // Who to transfer unused protocol fees to.
+ // May be a valid address or one of:
+ // `address(0)`: Stay in flash wallet.
+ // `address(1)`: Send to the taker.
+ // `address(2)`: Send to the sender (caller of `transformERC20()`).
+ address payable refundReceiver;
+ // Required taker address for RFQT orders.
+ // Null means any taker can fill it.
+ address rfqtTakerAddress;
+ }
+
+This transformation currently executes a Market Sell or Market Buy on a series of `0x V3 Orders `_. The transaction will revert if the ``fillAmount`` is not reached; an individual order can fail without the entire transaction reverting. A `ProtocolFeeUnfunded <../basics/events.html#protocolfeeunfunded>`_ event will be emitted if an order failed to fill because the Taker did not send a sufficient protocol fee.
+
+
+WETH Wrapping
+-------------
+
+This transformation is implemented by the `WethTransformer <../architecture/transformers.html>`_ and has the ``deploymentNonce`` of ``1``. Abi-Encode the following struct to get the ``data``:
+
+.. code-block:: solidity
+
+ /// @dev Transform data to ABI-encode and pass into `transform()`.
+ struct TransformData {
+ // The token to wrap/unwrap. Must be either ETH or WETH.
+ IERC20TokenV06 token;
+ // Amount of `token` to wrap or unwrap.
+ // `uint(-1)` will unwrap the entire balance.
+ uint256 amount;
+ }
+
+If the supplied token address is `WETH (etherToken) <../basics/addresses.html>`_ then the supplied WETH will be unwrapped to ``ETH``. If any other address is supplied the any ETH passed in will be wrapped into ``WETH``. No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if ``allowances <../basics/allowances.html>_`` are not set or the available balance is less than ``amount``.
+
+Affiliate Fees
+--------------
+
+This transformation is implemented by the `AffiliateFeeTransformer <../architecture/transformers.html>`_ and has the ``deploymentNonce`` of ``3``. Abi-Encode the following struct to get the ``data``:
+
+.. code-block:: solidity
+
+ /// @dev Information for a single fee.
+ struct TokenFee {
+ // The token to transfer to `recipient`.
+ IERC20TokenV06 token;
+ // Amount of each `token` to transfer to `recipient`.
+ // If `amount == uint256(-1)`, the entire balance of `token` will be
+ // transferred.
+ uint256 amount;
+ // Recipient of `token`.
+ address payable recipient;
+ }
+
+This pays the ``recipient`` in the ``amount`` of ``token`` specified. This can be used by integrators who wish to add an additional fee on top of 0x Orders. No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if `allowances <../basics/allowances.html>`_ are not set or the available balance is less than ``amount``.
+
+Pay Taker
+---------
+
+This transformation is implemented by the `PayTakerTransformer <../architecture/transformers.html>`_ and has the ``deploymentNonce`` of ``2``. Abi-Encode the following struct to get the ``data``:
+
+.. code-block:: solidity
+
+ /// @dev Transform data to ABI-encode and pass into `transform()`.
+ struct TransformData {
+ // The tokens to transfer to the taker.
+ IERC20TokenV06[] tokens;
+ // Amount of each token in `tokens` to transfer to the taker.
+ // `uint(-1)` will transfer the entire balance.
+ uint256[] amounts;
+ }
+
+This pays the ``taker`` in the ``amounts`` of each ``tokens`` specified. This is generally run at the end of all other transformations. For example, if you've swapped the taker's ETH for WETH then executed a trade through `Liquidity Aggregation`_, this transformation will can transfer the final output token back to the Taker.
+
+No events are emitted by 0x during this transformation, although token contracts may have events. This will revert if `allowances <../basics/allowances.html>`_ are not set or the available balance is less than ``amount``.
+
+Adding Custom Transformations
+-----------------------------
+Transformations are trustless, but at this time they are permissioned so only 0x Labs can deploy new Transformers. If you are interested in deploying your own transformation logic, please reach out to us on `Discord `_.
\ No newline at end of file
diff --git a/docs/advanced/mtx.rst b/docs/advanced/mtx.rst
new file mode 100644
index 0000000000..ce3be54779
--- /dev/null
+++ b/docs/advanced/mtx.rst
@@ -0,0 +1,232 @@
+###############################
+Meta-Transactions
+###############################
+
+Meta-Transactions are signed messages that instruct the 0x Protocol to run function(s) in the context of the signer. This signed mtx can then be shared off-chain, allowing anyone to execute on-chain. This is useful for integrators who would like to subsidize the Ethereum Gas Fee, or add custom smart contract logic to run atomically a fill. A signed meta-transaction can only be executed once.
+
+A common use case for this is in Request For Quote (RFQ) systems. The Maker creates an order; the Taker signs a mtx permitting 0x Protocol to fill the order on their behalf; the mtx is returned to the Maker who submits it on-chain.
+
+.. image:: ../_static/img/rfqm.png
+ :alt: Meta-Transaction Example
+ :align: center
+
+
+
+Constructing
+============
+
+To construct a Meta-Transaction, abi-encode the following struct and sign it.
+
+.. code-block:: solidity
+
+ /// @dev Describes an exchange proxy meta transaction.
+ struct MetaTransactionData {
+ // Signer of meta-transaction. On whose behalf to execute the MTX.
+ address payable signer;
+ // Required sender, or NULL for anyone.
+ address sender;
+ // Minimum gas price.
+ uint256 minGasPrice;
+ // Maximum gas price.
+ uint256 maxGasPrice;
+ // MTX is invalid after this time.
+ uint256 expirationTimeSeconds;
+ // Nonce to make this MTX unique.
+ uint256 salt;
+ // Encoded call data to a function on the exchange proxy.
+ bytes callData;
+ // Amount of ETH to attach to the call.
+ uint256 value;
+ // ERC20 fee `signer` pays `sender`.
+ IERC20TokenV06 feeToken;
+ // ERC20 fee amount.
+ uint256 feeAmount;
+ }
+
+The ``calldata`` field is specific to the function you wish to execute. At this time, the following functions are supported:
+
+- `fillLimitOrder <../basics/functions.html#filllimitorder>`_
+- `fillRfqOrder <../basics/functions.html#fillrfqorder>`_
+- `transformERC20 <../advanced/erc20_transformations.html>`_
+
+Signing
+=======
+
+Meta-Transactions use the same signing technique as 0x Orders; see the `How to Sign <../basics/orders.html#how-to-sign>`_ section of the Orders documentation. See `getMetaTransactionHash`_ for generating a unique hash for your mtx.
+
+Functionality
+=============
+
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| Function | Overview |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| `executeMetaTransaction`_ | Executes a single meta-transaction |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| `batchExecuteMetaTransactions`_ | Executes a batch of meta-transactions. |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| `getMetaTransactionExecutedBlock`_ | Returns the block that a meta-transaction was executed at. |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| `getMetaTransactionHashExecutedBlock`_ | Same as ``getMetaTransactionExecutedBlock``, only this function takes a meta-transaction hash. |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+| `getMetaTransactionHash`_ | Returns the hash of a meta-transaction. |
++----------------------------------------+------------------------------------------------------------------------------------------------+
+
+
+
+executeMetaTransaction
+----------------------
+
+A single Meta-Transaction is executed by calling ``executeMetaTransaction``. A batch of mtx's can be executed by calling ``batchExecuteMetaTransactions``.
+
+.. code-block:: solidity
+
+ /// @dev Execute a single meta-transaction.
+ /// @param mtx The meta-transaction.
+ /// @param signature The signature by `mtx.signer`.
+ /// @return returnResult The ABI-encoded result of the underlying call.
+ function executeMetaTransaction(
+ MetaTransactionData calldata mtx,
+ LibSignature.Signature calldata signature
+ )
+ external
+ payable
+ returns (bytes memory returnResult);
+
+A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted on succes. The ``returnResult`` contains the raw return data for the executed function. For example, if the function returns a ``uint256`` then the ``returnResult`` could be abi-decoded into a ``uint256``.
+
+This call will revert in the following scenarios:
+
+- The address in the ``mtx.sender`` field does not match ``msg.sender``.
+- The mtx has expired.
+- The Ethereum transaction's gas price (``tx.gasprice``) is outside of the range ``[mtx.minGasPrice..mtx.maxGasPrice]``
+- The ETH sent with the mtx is less than ``mtx.value``
+- The signature is invalid.
+- The mtx was already executed
+- The underlying function is not supported by meta-transactions (see list above).
+- The underlying function call reverts.
+
+batchExecuteMetaTransactions
+----------------------------
+
+.. code-block:: solidity
+
+ /// @dev Execute multiple meta-transactions.
+ /// @param mtxs The meta-transactions.
+ /// @param signatures The signature by each respective `mtx.signer`.
+ /// @return returnResults The ABI-encoded results of the underlying calls.
+ function batchExecuteMetaTransactions(
+ MetaTransactionData[] calldata mtxs,
+ LibSignature.Signature[] calldata signatures
+ )
+ external
+ payable
+ returns (bytes[] memory returnResults);
+
+A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted for each mtx on succes. The ``returnResult`` contains the raw return data for the executed function This call will revert if the one of the ``mtxs`` reverts.
+
+
+getMetaTransactionExecutedBlock
+-------------------------------
+
+The ``block.number`` is stored on-chain when a mtx is executed. This value can be retrieved using the following function.
+
+.. code-block:: solidity
+
+ /// @dev Get the block at which a meta-transaction has been executed.
+ /// @param mtx The meta-transaction.
+ /// @return blockNumber The block height when the meta-transactioin was executed.
+ function getMetaTransactionExecutedBlock(MetaTransactionData calldata mtx)
+ external
+ view
+ returns (uint256 blockNumber);
+
+getMetaTransactionHashExecutedBlock
+-----------------------------------
+
+This is a more gas-efficient implementation of ``getMetaTransactionExecutedBlock``.
+
+.. code-block:: solidity
+
+ /// @dev Get the block at which a meta-transaction hash has been executed.
+ /// @param mtxHash The meta-transaction hash.
+ /// @return blockNumber The block height when the meta-transactioin was executed.
+ function getMetaTransactionHashExecutedBlock(bytes32 mtxHash)
+ external
+ view
+ returns (uint256 blockNumber);
+
+
+getMetaTransactionHash
+----------------------
+
+The hash of the mtx is used to uniquely identify it inside the protocol. It is computed following the `EIP712 spec `_ standard. In solidity, the hash is computed using:
+
+.. code-block:: solidity
+
+ /// @dev Get the EIP712 hash of a meta-transaction.
+ /// @param mtx The meta-transaction.
+ /// @return mtxHash The EIP712 hash of `mtx`.
+ function getMetaTransactionHash(MetaTransactionData calldata mtx)
+ external
+ view
+ returns (bytes32 mtxHash);
+
+The simplest way to generate an order hash is by calling this function, ex:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getMetaTransactionHash(mtx);
+
+The hash can be manually generated using the following code:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = keccak256(abi.encodePacked(
+ '\x19\x01',
+ // The domain separator.
+ keccak256(abi.encode(
+ // The EIP712 domain separator type hash.
+ keccak256(abi.encodePacked(
+ 'EIP712Domain(',
+ 'string name,',
+ 'string version,',
+ 'uint256 chainId,',
+ 'address verifyingContract)'
+ )),
+ // The EIP712 domain separator values.
+ 'ZeroEx',
+ '1.0.0',
+ 1, // For mainnet
+ 0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
+ )),
+ // The struct hash.
+ keccak256(abi.encode(
+ // The EIP712 type hash.
+ keccak256(abi.encodePacked(
+ "MetaTransactionData("
+ "address signer,"
+ "address sender,"
+ "uint256 minGasPrice,"
+ "uint256 maxGasPrice,"
+ "uint256 expirationTimeSeconds,"
+ "uint256 salt,"
+ "bytes callData,"
+ "uint256 value,"
+ "address feeToken,"
+ "uint256 feeAmount"
+ ")"
+ )),
+ // The struct values.
+ mtx.signer,
+ mtx.sender,
+ mtx.minGasPrice,
+ mtx.maxGasPrice,
+ mtx.expirationTimeSeconds,
+ mtx.salt,
+ keccak256(mtx.callData),
+ mtx.value,
+ mtx.feeToken,
+ mtx.feeAmount
+ ))
+ ));
+
diff --git a/docs/advanced/plp.rst b/docs/advanced/plp.rst
new file mode 100644
index 0000000000..274aa92d1b
--- /dev/null
+++ b/docs/advanced/plp.rst
@@ -0,0 +1,101 @@
+###############################
+Pluggable Liquidity (PLP)
+###############################
+
+PLP (Pluggable Liquidity PLP) enables anyone to extend the 0x Protocol with their own on-chain liquidity provider, like an AMM (Automated Market Maker). Liquidity providers are sandboxed so their code can be totally closed-source; they are executed via the `LiquidityProviderFeature <../architecture/features.html>`_
+
+
+Implementing a Liquidity Provider
+=================================
+The only requirement is that the provider implements the interface in `ILiquidityProviderSandbox `_.
+
+.. code-block:: solidity
+
+ /// @dev Calls `sellTokenForToken` on the given `provider` contract to
+ /// trigger a trade.
+ /// @param provider The address of the on-chain liquidity provider.
+ /// @param inputToken The token being sold.
+ /// @param outputToken The token being bought.
+ /// @param recipient The recipient of the bought tokens.
+ /// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
+ /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
+ function executeSellTokenForToken(
+ address provider,
+ address inputToken,
+ address outputToken,
+ address recipient,
+ uint256 minBuyAmount,
+ bytes calldata auxiliaryData
+ )
+ external;
+
+ /// @dev Calls `sellEthForToken` on the given `provider` contract to
+ /// trigger a trade.
+ /// @param provider The address of the on-chain liquidity provider.
+ /// @param outputToken The token being bought.
+ /// @param recipient The recipient of the bought tokens.
+ /// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
+ /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
+ function executeSellEthForToken(
+ address provider,
+ address outputToken,
+ address recipient,
+ uint256 minBuyAmount,
+ bytes calldata auxiliaryData
+ )
+ external;
+
+ /// @dev Calls `sellTokenForEth` on the given `provider` contract to
+ /// trigger a trade.
+ /// @param provider The address of the on-chain liquidity provider.
+ /// @param inputToken The token being sold.
+ /// @param recipient The recipient of the bought tokens.
+ /// @param minBuyAmount The minimum acceptable amount of ETH to buy.
+ /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
+ function executeSellTokenForEth(
+ address provider,
+ address inputToken,
+ address recipient,
+ uint256 minBuyAmount,
+ bytes calldata auxiliaryData
+ )
+ external;
+
+
+Trading with a Liquidity Provider
+=================================
+
+To trade with a liquidity provider use the ``sellToLiquidityProvider`` function.
+
+.. code-block:: solidity
+
+ /// @dev Sells `sellAmount` of `inputToken` to the liquidity provider
+ /// at the given `provider` address.
+ /// @param inputToken The token being sold.
+ /// @param outputToken The token being bought.
+ /// @param provider The address of the on-chain liquidity provider
+ /// to trade with.
+ /// @param recipient The recipient of the bought tokens. If equal to
+ /// address(0), `msg.sender` is assumed to be the recipient.
+ /// @param sellAmount The amount of `inputToken` to sell.
+ /// @param minBuyAmount The minimum acceptable amount of `outputToken` to
+ /// buy. Reverts if this amount is not satisfied.
+ /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
+ /// @return boughtAmount The amount of `outputToken` bought.
+ function sellToLiquidityProvider(
+ address inputToken,
+ address outputToken,
+ address payable provider,
+ address recipient,
+ uint256 sellAmount,
+ uint256 minBuyAmount,
+ bytes calldata auxiliaryData
+ )
+ external
+ override
+ payable
+ returns (uint256 boughtAmount);
+
+This function transfers tokens from ``msg.sender`` to the liquidity provider then executes the trade through a sandboxed contract external to the Exchange Proxy. The sandbox then executes the trade through the provider. This function then transfers the output tokens to the ``recipient``.
+
+This function will emit a `LiquidityProviderSwap <../basics/events.html#liquidityproviderswap>`_ event if the trade succeeds. It will revert if the amount of ``outputToken`` returned by the Liquidity Provider is less than ``minBuyAmount``.
\ No newline at end of file
diff --git a/docs/advanced/private_liquidity_pools.rst b/docs/advanced/private_liquidity_pools.rst
deleted file mode 100644
index 1254ee4bf6..0000000000
--- a/docs/advanced/private_liquidity_pools.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Private Liquidity Poools
-###############################
\ No newline at end of file
diff --git a/docs/advanced/request_for_quote.rst b/docs/advanced/request_for_quote.rst
deleted file mode 100644
index d433caf4c5..0000000000
--- a/docs/advanced/request_for_quote.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Request for Quote
-###############################
\ No newline at end of file
diff --git a/docs/advanced/uniswap.rst b/docs/advanced/uniswap.rst
new file mode 100644
index 0000000000..6f8c82b425
--- /dev/null
+++ b/docs/advanced/uniswap.rst
@@ -0,0 +1,30 @@
+###############################
+Optimized Uniswap Router
+###############################
+
+The 0x Protocol is equipped with a highly optimized `UniswapV2 Router `_, which can reduce the transaction cost of trading with Uniswap. Call the ``sellToUniswap`` function to execute a trade on Uniswap through the 0x Protocol.
+
+.. code-block:: solidity
+
+ /// @dev Efficiently sell directly to uniswap/sushiswap.
+ /// @param tokens Sell path.
+ /// @param sellAmount of `tokens[0]` Amount to sell.
+ /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
+ /// @param isSushi Use sushiswap if true.
+ /// @return buyAmount Amount of `tokens[-1]` bought.
+ function sellToUniswap(
+ IERC20TokenV06[] calldata tokens,
+ uint256 sellAmount,
+ uint256 minBuyAmount,
+ bool isSushi
+ )
+ external
+ payable
+ returns (uint256 buyAmount);
+
+This function sells ``sellAmount`` of ``tokens[0]`` for at least ``minBuyAmount`` of ``tokens[-1]``. The ``tokens`` array defines how to route the trade between Uniswap pools. This function does not emit any events, although Uniswap pools will emit their own events. This function reverts if amount bought from Uniswap is less than ``minBuyAmount``, or if Uniswap reverts.
+
+See the official `Uniswap V2 Documentation `_ for information on events/reverts/allowances.
+
+.. note::
+ This function does not use allowances set on 0x. The ``msg.sender`` must have allowances set on Uniswap (or SushiSwap).
\ No newline at end of file
diff --git a/docs/advanced/vip_paths.rst b/docs/advanced/vip_paths.rst
deleted file mode 100644
index afdcdf5230..0000000000
--- a/docs/advanced/vip_paths.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-VIP Paths
-###############################
\ No newline at end of file
diff --git a/docs/advanced/weth_wrapping.rst b/docs/advanced/weth_wrapping.rst
deleted file mode 100644
index 867d312281..0000000000
--- a/docs/advanced/weth_wrapping.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-WETH Wrapping
-###############################
\ No newline at end of file
diff --git a/docs/architecture/features.rst b/docs/architecture/features.rst
index 943eb253a8..c8379d86bf 100644
--- a/docs/architecture/features.rst
+++ b/docs/architecture/features.rst
@@ -1,3 +1,52 @@
###############################
Features
-###############################
\ No newline at end of file
+###############################
+
+Features implement the core feature set of the 0x Protocol. They are trusted with user allowances and permissioned by the `0x Governor <./governor.html>`_. Features are run in the context of the `Proxy <../proxy.html>`_, via a ``delegatecall``.
+
+Below is a catalog of Features.
+
+.. table::
+ :widths: 20 60 20
+
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | **Feature** | **Description** | **Resources** |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | BootstrapFeature | Bootstraps the entire system. | `Code `__; `Usage <./proxy.html#bootstrapping>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | LiquidityProviderFeature | Connects the system to Pluggable Liquidity (PLP). | `Code `__; `Usage <../advanced/plp.html#trading-with-a-liquidity-provider>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | MetaTransactionsFeature | Executes Meta-Transactions. | `Code `__; `Usage <../advanced/mtx.html>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | NativeLiquidityFeature | Functions for native 0x liquidity (see `Orders <../basics/orders.html>`_). | `Code `__; `Usage <../basics/functions.html>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | OwnableFeature | An implementation of Ownable that is compatible with the delegate-call proxy pattern. | `Code `__; `Usage <./architecture/proxy.html#ownership>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | SignatureValidationFeature | *This feature is deprecated. Its code will be removed after the contract is decommissioned.* | `Code `__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | SimpleFunctionRegistry | Implements the registry of functions/features available in the system. | `Code `__; `Usage <./proxy.html#function-registry>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | TokenSpenderFeature | *This feature is deprecated. Its code will be removed after the contract is decommissioned.* | `Code `__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | TransformERC20Feature | Executes `Transformers <./transformers.html>`_ to aggregate liquidity and operate on ERC20 tokens. | `Code `__; `Usage <../advanced/erc20_transformations.html>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | UniswapFeature | A highly-optimized UniswapV2 router; used to source liquidity from Uniswap. | `Code `__; `Usage <../advanced/uniswap.html>`__ |
+ +----------------------------+----------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+Implementing a Feature
+======================
+The only requirement is that the Feature implements the interface in `IFeature `_. Review the `Proxy Section <./proxy.html>`_ for details on how to write a smart contract that is compatible with our architecture (ex, how to properly manage state).
+
+.. code-block:: solidity
+
+ /// @dev Basic interface for a feature contract.
+ interface IFeature {
+
+ // solhint-disable func-name-mixedcase
+
+ /// @dev The name of this feature set.
+ function FEATURE_NAME() external view returns (string memory name);
+
+ /// @dev The version of this feature set.
+ function FEATURE_VERSION() external view returns (uint256 version);
+ }
\ No newline at end of file
diff --git a/docs/architecture/fee_collectors.rst b/docs/architecture/fee_collectors.rst
new file mode 100644
index 0000000000..42d2ba0d75
--- /dev/null
+++ b/docs/architecture/fee_collectors.rst
@@ -0,0 +1,17 @@
+###############################
+Fee Collectors
+###############################
+
+The `Protocol Fees <../basics/protocol_fees.html>`_ are paid into special Fee Collector contracts at time-of-fill. There is one collector for each Staking Pool. The fees are paid in aggregate from the collector to the `Staking System <../tokenomics/staking.md>`_; this can happen at anytime, but is most optimal to run during finalization. This increases the cost of finalizing an epoch, but substantially reduces the transaction cost for takers executing trades.
+
+Architecture
+============
+
+1. There is one Fee Collector per staking pool. The fee collector serves as a repository for protocol fees attributed to a given pool. It automatically ``approve()s`` the staking contract so fees can be aggregated during finalization. It also contains functionality to convert ETH to WETH. Fee collectors are created using ``CREATE2``. This gives us predictable addresses.
+
+2. When a `Limit Order <../basics/orders.html#limitorders>`_ is filled, the protocol fee is paid to the Fee Collector that corresponds to ``order.pool``.
+
+3. The `transferProtocolFeesForPools() <../basics/functions.html#transferprotocolfeesforpools>` function can be called to transfer the fees for a set of pools from their respective Fee Collectors into the Staking system.
+
+.. image:: ../_static/img/fee_collectors.png
+ :align: center
diff --git a/docs/architecture/flash_wallet.rst b/docs/architecture/flash_wallet.rst
index cbe627195a..72ee8f38d7 100644
--- a/docs/architecture/flash_wallet.rst
+++ b/docs/architecture/flash_wallet.rst
@@ -1,3 +1,47 @@
###############################
Flash Wallet
-###############################
\ No newline at end of file
+###############################
+
+The Flash Wallet is a sandboxed escrow contract that holds funds for `Transformers <./transformers.html>`_ to operate on. A `Feature <./features.html>`_ contract transfers tokens to the Flash Wallet, which then delegate call's into a Transformer to run operations on the escrowed funds. Transformers are trustless and therefore only have access to the funds deposted into the Flash Wallet; they do not have access to user allowances.
+
+The wallet is currently only used by the ``TransformERC20`` feature. It is deployed using the ``createTransformWallet()`` function on the feature, which is only callable by the owner/governor. This allows us to deploy a fresh wallet in case we somehow break the old one, like if we accidentally selfdestruct it or clobber its state.
+
+.. note::
+ The wallet is currently only used for ERC20 tokens, but can be extended to work with other standards, like ERC1155 and ERC223, by implementing the required fallbacks for those standards.
+
+The Flash Wallet exposes two functions of interest: ``executeCall()`` and ``executeDelegateCall()``. The former executes a ``call`` and reverts if the callee reverts. The latter executes a ``delegatecall`` and reverts if the callee reverts.
+
+.. code-block:: solidity
+
+ /// @dev Execute an arbitrary call. Only an authority can call this.
+ /// @param target The call target.
+ /// @param callData The call data.
+ /// @param value Ether to attach to the call.
+ /// @return resultData The data returned by the call.
+ function executeCall(
+ address payable target,
+ bytes calldata callData,
+ uint256 value
+ )
+ external
+ payable
+ override
+ onlyOwner
+ returns (bytes memory resultData);
+
+ /// @dev Execute an arbitrary delegatecall, in the context of this puppet.
+ /// Only an authority can call this.
+ /// @param target The call target.
+ /// @param callData The call data.
+ /// @return resultData The data returned by the call.
+ function executeDelegateCall(
+ address payable target,
+ bytes calldata callData
+ )
+ external
+ payable
+ override
+ onlyOwner
+ returns (bytes memory resultData);
+
+View the code for the Flash Wallet `here `_.
\ No newline at end of file
diff --git a/docs/architecture/governor.rst b/docs/architecture/governor.rst
new file mode 100644
index 0000000000..fcc72743e9
--- /dev/null
+++ b/docs/architecture/governor.rst
@@ -0,0 +1,90 @@
+###############################
+Governor
+###############################
+
+.. note::
+
+ This page is tailored for Exchange V4. For information on governance over past exhcange versions, see `this specification `_.
+
+The ``ZeroExGovernor`` is a time-locked multi-signature wallet that has permission to perform administrative functions within the protocol. Functions are timelocked (see below). Many functions that can be used to mitigate damage in case of emergencies (for example, if a vulnerability is discovered that puts user funds at risk) do not have a timelock.
+
+The ``ZeroExGovernor`` is able to perform the following functions within the protocol:
+
+Managing Ownership
+==================
+
+The ``ZeroExGovernor`` can transfer ownership of any contract for which it is the ``owner`` by calling the following function:
+
+.. code-block:: solidity
+
+ /// @dev Transfers ownership to a new address.
+ /// @param newOwner Address of the new owner.
+ function transferOwnership(address newOwner)
+ public;
+
+Managing Authorizations
+=======================
+
+The ``ZeroExGovernor`` can also manage authorizations all permissioned contracts in the Exchange and Staking systems. While the ``ZeroExGovernor`` itself is currently the only authorized address in these contracts, this feature can be used to allow new contracts to perform admin functions under different conditions in the future (such as with an on-chain token vote).
+
+.. code-block:: solidity
+
+ /// @dev Authorizes an address.
+ /// @param target Address to authorize.
+ function addAuthorizedAddress(address target)
+ external;
+
+ /// @dev Removes authorizion of an address.
+ /// @param target Address to remove authorization from.
+ function removeAuthorizedAddress(address target)
+ external;
+
+ /// @dev Removes authorizion of an address.
+ /// @param target Address to remove authorization from.
+ /// @param index Index of target in authorities array.
+ function removeAuthorizedAddressAtIndex(
+ address target,
+ uint256 index
+ )
+ external;
+
+
+Administering Systems
+=======================
+
+The governor owns all permissioned, trusted contracts under the 0x Protocol. Any ``onlyOwner`` function can be executed by the governor. The governor requires 2/3 signatures and is timelocked.
+
+
+Timelocks
+============
+Function timelocks are represented in days, where one day is equivalent to 86,400 seconds.
+
+.. csv-table::
+ :header: "Contract", "Function", "Selector", "Timelock"
+
+ AllowanceTarget, ``addAuthorizedAddress``, ``42f1181e``, 1 day
+ AllowanceTarget, ``removeAuthorizedAddress``, ``70712939``, 0 days
+ AllowanceTarget, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 0 days
+ Governor, ``registerFunctionCall``, ``751ad560``, 1 day
+ ExchangeProxy, ``extend``, ``6eb224cb``, 1 day
+ ExchangeProxy, ``migrate``, ``261fe679``, 1 day
+ ExchangeProxy, ``rollback``, ``9db64a40``, 0 days
+ ExchangeProxy, ``setQuoteSigner``, ````, 1 day
+ ExchangeProxy, ``setTransformerDeployer``, ``87c96419``, 1 day
+ ExchangeProxy, ``transferOwnership``, ``f2fde38b``, 1 day
+ StakingProxy, ``addExchangeAddress``, ``8a2e271a``, 14 days
+ StakingProxy, ``removeExchangeAddress``, ``01e28d84``, 14 days
+ StakingProxy, ``attachStakingContract``, ``66615d56``, 14 days
+ StakingProxy, ``detachStakingContract``, ``37b006a6``, 14 days
+ StakingProxy, ``setParams``, ``9c3ccc82``, 7 days
+ StakingProxy, ``addAuthorizedAddress``, ``42f1181e``, 14 days
+ StakingProxy, ``removeAuthorizedAddress``, ``70712939``, 14 days
+ StakingProxy, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 14 days
+ StakingProxy, ``transferOwnership``, ``f2fde38b``, 14 days
+ ZrxVault, ``setStakingProxy``, ``6bf3f9e5``, 14 days
+ ZrxVault, ``enterCatastrophicFailure``, ``c02e5a7f``, 0 days
+ ZrxVault, ``setZrxProxy``, ``ca5b0218``, 14 days
+ ZrxVault, ``addAuthorizedAddress``, ``42f1181e``, 14 days
+ ZrxVault, ``removeAuthorizedAddress``, ``70712939``, 14 days
+ ZrxVault, ``removeAuthorizedAddressAtIndex``, ``9ad26744``, 14 days
+ ZrxVault, ``transferOwnership``, ``f2fde38b``, 14 days
\ No newline at end of file
diff --git a/docs/architecture/overview.rst b/docs/architecture/overview.rst
index 94353cd53f..29a7e8446a 100644
--- a/docs/architecture/overview.rst
+++ b/docs/architecture/overview.rst
@@ -1,3 +1,36 @@
###############################
Overview
-###############################
\ No newline at end of file
+###############################
+
+The 0x Exchange implements a delegate-call proxy pattern to create a system of composable smart contracts. This architecture enables 0x to innovate with minimal friction alongside the growing DeFi ecosystem.
+
+The diagram below illustrates our system (click to enlarge).
+
+.. image:: ../_static/img/architecture.png
+ :scale: 70%
+
+------------
+
+The table below defines our smart contract nomenclature.
+
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| **Term** | **Definition** |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Proxy <./proxy.html>`_ | The point of entry into the system. This contract delegate-calls into Features. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Features <./features.html>`_ | These contracts implement the core feature set of the 0x Protocol. They are trusted with user allowances and permissioned by the 0x Governor. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Transformers <./transformers.html>`_ | These contracts extend the core protocol. They are trustless and permissioned by the Transformer Deployer. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Flash Wallet <./flash_wallet.html>`_ | The Flash Wallet is a sandboxed escrow contract that holds funds for Transformers to operate on. For example, the ``WETHtransformer`` wraps any Ether in the Flash Wallet. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Allowance Target <../basics/allowances.html>`_ | Users set their allowances on this contract. It is scheduled to be deprecated after the official V4 release in January, 2021. After which point allowances will be set directly on the Proxy. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Governor <./governor.html>`_ | A MultiSig that governs trusted contracts in the system: Proxy, Features, Flash Wallet. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Transformer Deployer <./transformer_deployer.html>`_ | Deploys Transformers. A transformer is authenticated using a nonce of the Transformer Deployer. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `Fee Collectors <./fee_collectors.html>`_ | `Protocol fees <../basics/protocol_fees.html>`_ are paid into these contracts at time-of-fill. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| `PLP Sandbox <./plp_sandbox.html>`_ | `PLP <../advanced/plp.html>`_ liquidity providers are called from this sandbox. |
++-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
\ No newline at end of file
diff --git a/docs/architecture/plp_sandbox.rst b/docs/architecture/plp_sandbox.rst
new file mode 100644
index 0000000000..fe3da899fb
--- /dev/null
+++ b/docs/architecture/plp_sandbox.rst
@@ -0,0 +1,14 @@
+###############################
+PLP Sandbox
+###############################
+
+`PLP <../advanced/plp.html>`_ are external, closed-source contracts that provide liquidity to the 0x Protocol. We want to limit the contracts called from the context of the `Proxy <./proxy.html>` contract because this contract has access to user funds. We must mitigate the attack vector where an ERC20 Token (or some other trusted contract) is passed in place of a legitimate PLP liquidity provider. We do this by routing trades through the PLP Sandbox.
+
+The diagram below illustrates this workflow.
+
+.. image:: ../_static/img/plp_sandbox.png
+ :align: center
+
+See the `PLP Section <../advanced/plp.html>`_ for usage. View the code for the PLP Sandbox is `here `_.
+
+
diff --git a/docs/architecture/proxy.rst b/docs/architecture/proxy.rst
index 0ad5f7434b..0d9971b06e 100644
--- a/docs/architecture/proxy.rst
+++ b/docs/architecture/proxy.rst
@@ -1,3 +1,249 @@
###############################
Proxy
-###############################
\ No newline at end of file
+###############################
+
+The `ZeroEx `_ contract implements a per-function proxy pattern. Every function registered to the proxy contract can have a distinct implementation contract. Implementation contracts are called “features” and can expose multiple, related functions. Since features can be upgraded independently, there will no longer be a collective “version” of the API, defaulting to a rolling release model. The ZeroEx contract’s only responsibility is to route (delegate) calls to per-function implementation contracts through its fallback.
+
+.. image:: ../_static/img/proxy.png
+ :align: center
+ :scale: 100%
+
+View the code for the Proxy `here `_. There is also a `gas-optimized implementation `_ that may be put into production in the future (there is a lot of overhead for our integrators when redeploying this contract).
+
+Bootstrapping
+=============
+The ZeroEx contract comes pre-loaded with only one Feature: `Bootstrap `_. This exposes a ``bootstrap()`` function that can only be called by the deployer. This function does a few things:
+
+1. De-register the bootstrap() function, which prevents it being called again.
+2. Self-destruct.
+3. Delegatecall the bootstrapper target contract and call data.
+
+.. code-block:: solidity
+
+ // Execute a bootstrapper in the context of the proxy.
+ function bootstrap(address target, bytes callData) external
+
+Below is the bootstrap workflow (click to enlarge).
+
+.. image:: ../_static/img/bootstrap.png
+ :align: center
+ :scale: 70%
+
+Function Registry
+=================
+
+One of the initial features InitialMigration bootstraps into the ZeroEx contract is the function registry feature, SimpleFunctionRegistry. This feature exposes the following function registry management features: ``extend()`` and ``rollback()``.
+
+Call ``extend()`` to register a new function (selector) and implementation (address). This also maintains a history of past implementations so we can roll back to one, if needed.
+
+.. code-block:: solidity
+
+ // Register or replace a function.
+ function extend(bytes4 selector, address impl)
+ external
+ onlyOwner;
+
+Call ``rollback()`` to revert a function implementation to a prior version in its history.
+
+.. code-block:: solidity
+
+ // Roll back to a previousimplementation of a function.
+ function rollback(bytes4 selector, address targetImpl)
+ external
+ onlyOwner;
+
+Ownership
+=========
+Another Feature, ``InitialMigration``, bootstraps into the proxy is the Ownable feature. This exposes ownership management functions: ``transferOwnership()`` and ``getOwner()``. This feature also enables ubiquitous modifiers such as onlyOwner, so it is an implicit dependency of nearly every other feature.
+
+.. code-block:: solidity
+
+ // Change the owner of this contract.
+ function transferOwnership(address newOwner)
+ external
+ onlyOwner;
+
+ // Get the owner of this contract.
+ function getOwner()
+ external
+ view
+ returns (address owner_);
+
+Migrations
+==========
+Migrations are upgrade logic that run in the context of the proxy contract. To do this, the owner calls the ``migrate()`` function, provided by the ``Ownable`` Feature. This follows a similar sequence as the bootstrap process. Notably, it temporarily sets the owner of the contract to itself for the duration of the migration call, which allows the migrator to perform admin-level operations through other features, such as registering or rolling back new functions. Before exiting, the owner is set to the newOwner, which is passed in to the call.
+
+One motivation for the existence of this function, as opposed to just having the make individual admin calls, is a shortcoming of the ZeroExGoverner contract, which is designed to perform one operation at a time, with no strict ordering of those operations.
+
+This is a stripped down ``migrate()`` feature implementation:
+
+.. code-block:: solidity
+
+ contract Ownable {
+
+ // Execute a migration function in the context of the proxy contract.
+ function migrate(address target, bytes calldata data, address newOwner)
+ external
+ onlyOwner
+ {
+ // If the owner is already set to ourselves then we've reentered.
+ require(OwnableStorage.owner != address(this));
+ // Temporarily set the owner to ourselves.
+ OwnableStorage.owner = address(this);
+
+ // Perform the migration.
+ target.delegatecall(data);
+
+ // Set the new owner.
+ OwnableStorage.owner = newOWner;
+ }
+ }
+
+This is an example sequence of a migration (click to enlarge):
+
+.. image:: ../_static/img/zero_ex_migrate.png
+ :align: center
+ :scale: 70%
+
+Storage Buckets
+===============
+
+Because feature functions get delegatecalled into, they all share the same execution context and, thus, state space. It’s critical that storage for each feature be compartmentalized from other features to avoid accidentally writing to the same slot. We solve this by strictly adhering to a storage bucket pattern for our feature contracts. This rule also extends to all inherited contracts/mixins.
+
+Storage buckets are enabled by new language features in solidity 0.6, which allow us to rewrite a storage variable’s slot reference to a globally unique ID. These IDs are stored in an append-only enum defined in LibStorage, to enforce uniqueness. The true storage slot for a bucket is the feature’s storage ID multiplied by a large constant to prevent overlap between buckets.
+
+Example:
+
+.. code-block:: solidity
+
+ LibStorage {
+ enum StorageId {
+ MyFeature
+ }
+
+ function getStorageSlot(StorageId id) internal pure returns (uint256) {
+ return uint256(id) * 1e18;
+ }
+ }
+
+ LibMyFeatureStorage {
+ // Storage layout for this feature.
+ struct Storage {
+ mapping(bytes32 => bytes) myData;
+ }
+
+ // Get the storage bucket for this feature.
+ function getStorage() internal view returns (Storage storage st) {
+ uint256 slot = LibStorage.getStorageSlot(
+ LibStorage.StorageId.MyFeature
+ );
+ assembly { st_slot := slot }
+ }
+ }
+
+With the above pattern, writing to storage is simply:
+
+.. code-block:: solidity
+
+ LibMyFeatureStorage.getStorage().myData[...] = ...
+
+
+Version Management
+==================
+
+**Inspection**
+
+This is a rolling release model, where every feature/function has its own version. All feature contracts (except Bootstrap because it’s ephemeral), implement the IFeature interface:
+
+.. code-block:: solidity
+
+ interface IFeature {
+ // The name of this feature set.
+ function FEATURE_NAME() external view returns (string memory name);
+
+ // The version of this feature set.
+ function FEATURE_VERSION() external view returns (uint256 version);
+ }
+
+So, to get the version of a function one could do ``IFeature(getFunctionImplementation(foo.selector)).FEATURE_VERSION``.
+
+**Best Practices**
+
+The registry is intentionally not prescriptive on how features should be migrated. But there are some general best practices we can follow to avoid harming users, and ourselves.
+
+**Deprecation**
+
+In general, unless a function has a vulnerability, we should keep it intact for the duration of the deprecation schedule. Afterwards, we can ultimately disable the function by either calling extend() with a null implementation or by calling rollback() to a null implementation.
+
+**Patches**
+
+These include bug-fixes, optimizations, or any other changes that preserve the intended behavior of the function. For these cases, we should upgrade the function in-place, i.e., using the same selector but changing the implementation contract, through extend().
+
+**Vulnerabilities**
+
+If a vulnerability is found in a live function, we should call rollback() immediately to reset it to a non-vulnerable implementation. Because rollback() is a separate function from extend(), it can be exempted from timelocks to allow a swift response.
+
+**Upgrades**
+
+These involve meaningful behavioral changes, such as new settlement logic, changes to the order format (or its interpretation), etc. These should always be registered under a new selector, which comes free if the arguments also change, to allow users the opportunity to opt-in to new behavior. If the upgrade is intended to replace an existing feature, the old version should follow a deprecation schedule, unless we’re confident no one is using it.
+
+**Features used by Features**
+
+Not all features are designed to be exclusively consumed by the public. We can have internal features by applying an onlySelf modifier to the function. We need to be mindful of another class of user: the contract itself. Avoiding missteps on this will require a combination of diligence and good regression test suites.
+
+Known Risks
+===========
+
+The extreme flexibility of this model means we have few built-in guardrails that more conventional architectures enjoy. To avoid pitfalls, we’ve established a few new patterns to follow during development, but the following areas will always need careful scrutiny during code reviews.
+
+**Extended Attack Surface for Features**
+
+Because features all run in the same execution context, they inherit potential vulnerabilities from other features. Some vulnerabilities may also arise from the interactions of separate features, which may not be obvious without examining the system as a whole. Reviewers will always need to be mindful of these scenarios and features should try to create as much isolation of responsibilities as possible.
+
+**Storage Layout Risks**
+
+All features registered to the proxy will run in the same storage context as the proxy itself. We employ a pattern of per-feature storage buckets (structs) with globally unique bucket slots to mitigate issues.
+
+**Slot Overlap**
+
+Every time we develop a new feature, an entry is appended to the ``LibStorage.StorageId`` enum, which is the bucket ID for the feature’s storage. This applies to the storage used by the proxy contract itself. When calculating the true slot for the storage bucket, this enum value is offset by ``1`` and bit shifted by ``128``:
+
+.. code-block:: solidity
+
+ function getStorageSlot(StorageId id) internal pure returns (uint256) {
+ return (uint256(id) + 1) << 128;
+ }
+
+
+Given Solidity’s `storage layout rules `_, subsequent storage buckets should always be 2^128 slots apart, which means buckets can have 2^128 flattened inline fields before overlapping. While it’s not impossible for buckets to overlap with this pattern, it should be extremely unlikely if we follow it closely. Maps and arrays are not stored sequentially but should also be affected by their base slot value to make collisions unlikely.
+
+**Inherited Storage**
+
+A more insidious way to corrupt storage buckets is to have a feature unintentionally inherit from a mixin that has plain (non-bucketed) state variables, because the mixin can potentially read/write to slots shared by other buckets through them. To avoid this:
+
+1. We prefix all feature-compatible mixins with “Fixin” (“Feature” + “Mixin”) and only allow contract inheritance from these.
+
+2. Storage IDs are offset by 1 before computing the slot value. This means the first real storage bucket will actually start at slot 2^128, which gives us a safety buffer for these scenarios, since it’s unlikely a mixin would unintentionally access slots beyond 2^128.
+Shared Access to Storage
+
+There is nothing stopping a feature from reaching into another feature’s storage bucket and reading/modifying it. Generally this pattern is discouraged but may be necessary in some cases, or may be preferable to save gas. This can create an implicit tight coupling between features and we need to take those interactions into account when upgrading the features that own those storage buckets.
+
+**Restricted Functions and Privilege Escalation**
+
+We will also be registering functions that have caller restrictions. Functions designed for internal use only will have an onlySelf modifier that asserts that ``msg.sender == address(this)``. The other class of restricted functions are owner-only functions, which have an ``onlyOwner`` modifier that asserts that the ``msg.sender == LibOwnableStorage.Storage.owner``.
+
+The check on owner-only functions can be easily circumvented in a feature by directly overwriting ``LibOwnableStorage.Storage.owner`` with another address. If best practices and patterns are adhered to, doing so would involve deliberate and obvious effort and should be caught in reviews.
+
+**Self-Destructing Features**
+
+A feature contract with self-destruct logic must safeguard this code path to only be executed after the feature is deregistered, otherwise its registered functions will fail. In most cases this would just cause the feature to temporarily go dark until we could redeploy it. But it may leave the proxy in an unusable state if this occurs in the contract of a mission-critical feature, e.g., Ownable or SimpleFunctionRegistry (neither of which can self-destruct).
+
+Features should also be careful that ``selfdestruct`` is never executed in the context of the proxy to avoid destroying the proxy itself.
+
+**Allowances**
+
+Although the proxy will not have access to the V3 asset proxies initially, early features will require taker allowances to be accessible to the proxy somehow. Instead of having the proxy contract itself be the allowance target, we intend on using a separate “Puppet” contract, callable only by the proxy contract. This creates a layer of separation between the proxy contract and allowances, so moving user funds is a much more deliberate action. In the event of a major vulnerability, the owner can simply detach the puppet contract from the proxy. This also avoids the situation where the proxy has lingering allowances if we decide grant it asset proxy authorization.
+
+**Balances**
+
+Inevitably, there will be features that will cause the Exchange Proxy to hold temporary balances (e.g., payable functions). Thus, it’s a good idea that no feature should cause the Exchange Proxy to hold a permanent balance of tokens or ether, since these balances can easily get mixed up with temporary balances.
\ No newline at end of file
diff --git a/docs/architecture/transformer_deployer.rst b/docs/architecture/transformer_deployer.rst
new file mode 100644
index 0000000000..dc6b006b76
--- /dev/null
+++ b/docs/architecture/transformer_deployer.rst
@@ -0,0 +1,64 @@
+###############################
+Transformer Deployer
+###############################
+
+`Transformers <./transformers.html>`_ need to be permissioned because they are executed in the context of the `Flash Wallet <./flash_wallet.html>`_. This means that a malicious Transformer could grief the protocol by destroying the Flash Wallet via ``selfdestruct``, so we need some way to authenticate that the Transformer is safe to use at runtime.
+
+The Transformer Deployer ``create``'s all Transformers, and its deployment nonce is used to validate a Transformer at runtime. The deployer is owned by 0x Labs, so only we are able to deploy Transformers.
+
+The deployer implements two functions: ``deploy()`` and ``kill()``. The former is used to deploy new Transformers; it will emit a `Deployed <../basics/events.html#deployed>`_ event (that includes the nonce) or reverts if it fails to ``create`` the Transformer. The ``kill()`` function is used to destroy deprecated Transformers; this emits a `Killed <../basics/events.html#killed>`_ event or reverts if the Transformer's ``die()`` function reverts. Note that we cannot verify a Transformer called ``selfdestruct`` in the ``kill`` function because this information is not available until after the transaction executes.
+
+.. code-block:: solidity
+
+ /// @dev Deploy a new contract. Only callable by an authority.
+ /// Any attached ETH will also be forwarded.
+ function deploy(bytes memory bytecode)
+ public
+ payable
+ onlyAuthorized
+ returns (address deployedAddress);
+
+ /// @dev Call `die()` on a contract. Only callable by an authority.
+ /// @param target The target contract to call `die()` on.
+ /// @param ethRecipient The Recipient of any ETH locked in `target`.
+ function kill(IKillable target, address payable ethRecipient)
+ public
+ onlyAuthorized;
+
+View the code for the Transformer Deployer `here `_.
+
+
+Permissionless Transfomer Deployer
+===================================
+
+A permissionless deployer has been developed and can be seen `here `_. This serves a similar function to the current delployer, only it is capable of validating the Transformer's bytecode before deploying. It does this by tracing the bytecode in search of reachable opcodes that could post a threat to the Flash Wallet.
+
+The ``isDelegateCallSafe`` function performs this check. It will return ``false`` if any of the following opcodes are reachable: ``callcode``, ``delegatecall``, ``selfdestruct``, ``create``, ``create2``, ``sload``, ``sstore``.
+
+.. code-block:: solidity
+
+ /// @dev Checks whether a given address is safe to be called via
+ /// delegatecall. A contract is considered unsafe if it includes any
+ /// of the following opcodes: CALLCODE, DELEGATECALL, SELFDESTRUCT,
+ /// CREATE, CREATE2, SLOAD, and STORE. This code is adapted from
+ /// https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/IndestructibleRegistry.sol
+ /// @param target The address to check.
+ /// @return True if the contract is considered safe for delegatecall.
+ function isDelegateCallSafe(address target) public view returns (bool);
+
+THe ``deploy`` function is similar to the existing Transformer Deployer, only it uses a user-provided nonce to deploy the Transformer.
+
+.. code-block:: solidity
+
+ /// @dev Deploy a new contract. Any attached ETH will be forwarded.
+ function deploy(bytes memory bytecode, bytes32 salt)
+ public
+ payable
+ returns (address deployedAddress);
+
+
+Note that there is no ``kill`` function in this deployer.
+
+View the code for the Permissionless Transformer Deployer `here `_.
+
+There is some overhead to switching over to this deployer, as the ``Flash Wallet <./flash_wallet.html>``_ would need to be redeployed and some integrators would need to update their code. Therefore, this will be put into production once there is community-demand for permissionless transformers. Reach out to us on `Discord `_ if you'd like to deploy a Transformer!
\ No newline at end of file
diff --git a/docs/architecture/transformers.rst b/docs/architecture/transformers.rst
index 3cc92562f0..bde33e9d83 100644
--- a/docs/architecture/transformers.rst
+++ b/docs/architecture/transformers.rst
@@ -1,3 +1,52 @@
###############################
Transformers
-###############################
\ No newline at end of file
+###############################
+
+Transformers extend the core protocol. They are trustless and permissioned by the `Transformer Deployer <./transformer_deployer.html>`_. A Transformer is identified by the nonce of the Transformer Deployer that corresponds to its address. These contracts are executed in the context of the `Flash Wallet <./flash_wallet.html>`_ (via ``delegatecall``).
+
+Below is a catalog of Transformers.
+
+.. table::
+ :widths: 20 60 20
+
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | **Transformer** | **Description** | **Resources** |
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | FillQuoteTransformer | Aggregates Liquidity across DEXs and Native 0x Orders. | `Code `__; `Usage <../advanced/erc20_transformations.html#liquidity-aggregation>`__ |
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | WethTransformer | Wraps ETH into WETH (and unwraps) | `Code `__; `Usage <../advanced/erc20_transformations.html#weth-wrapping>`__ |
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | AffiliateFeesTransformer | Allows integrators to charge an affiliate fee when an order is filled by their platform. | `Code `__; `Usage <../advanced/erc20_transformations.html#affiliate-fees>`__ |
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ | PayTakerTransformer | Forwards funds in the Flash Wallet to the Taker. | `Code `__; `Usage <../advanced/erc20_transformations.html#pay-taker>`__ |
+ +--------------------------+------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+Implementing a Transformer
+==========================
+Transformers are currently used by the `TransformERC20Feature <./features.html>`_ to aggregate liquidity and perform operations on ERC20 tokens (ex, wrapping ETH). Your transformer should inherit from `Transformer Contract `_ and implement the interface in `IERC20Transformer `_.
+
+.. code-block:: solidity
+
+ // @dev A transformation callback used in `TransformERC20.transformERC20()`.
+ interface IERC20Transformer {
+
+ /// @dev Context information to pass into `transform()` by `TransformERC20.transformERC20()`.
+ struct TransformContext {
+ // The caller of `TransformERC20.transformERC20()`.
+ address payable sender;
+ // taker The taker address, which may be distinct from `sender` in the case
+ // meta-transactions.
+ address payable taker;
+ // Arbitrary data to pass to the transformer.
+ bytes data;
+ }
+
+ /// @dev Called from `TransformERC20.transformERC20()`. This will be
+ /// delegatecalled in the context of the FlashWallet instance being used.
+ /// @param context Context information.
+ /// @return success The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).
+ function transform(TransformContext calldata context)
+ external
+ returns (bytes4 success);
+ }
diff --git a/docs/basics/addresses.rst b/docs/basics/addresses.rst
new file mode 100644
index 0000000000..ba7ddd859b
--- /dev/null
+++ b/docs/basics/addresses.rst
@@ -0,0 +1,53 @@
+
+###############################
+Addresses
+###############################
+
+.. note::
+ This page is auto-generated. See the `contract-addresses `_ package for an exhaustive list of contracts across all networks.
+
+Exchange V4
+===================
+.. csv-table::
+
+ exchangeProxy, `0xdef1c0ded9bec7f1a1670819833240f027b25eff `_
+ exchangeProxyAllowanceTarget, `0xf740b67da229f2f10bcbd38a7979992fcc71b8eb `_
+ exchangeProxyFlashWallet, `0x22f9dcf4647084d6c31b2765f6910cd85c178c18 `_
+ exchangeProxyGovernor, `0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e `_
+ exchangeProxyLiquidityProviderSandbox, `0xdb971b18ea5075734cec1241732cc1b41031dfc9 `_
+ exchangeProxyTransformerDeployer, `0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb `_
+
+
+
+Transformers
+===================
+.. csv-table::
+
+ wethTransformer, `0x68c0bb685099dc7cb5c5ce2b26185945b357383e `_
+ payTakerTransformer, `0x49b9df2c58491764cf40cb052dd4243df63622c7 `_
+ fillQuoteTransformer, `0xfbfb26935f15db6a319a43db5085245a6df1e408 `_
+ affiliateFeeTransformer, `0x4581b59a05ba373b9f67676f66bdb5fcd67e7567 `_
+
+
+
+ZRX / Staking
+===================
+.. csv-table::
+
+ staking, `0x2a17c35ff147b32f13f19f2e311446eeb02503f3 `_
+ stakingProxy, `0xa26e80e7dea86279c6d778d702cc413e6cffa777 `_
+ zrxToken, `0xe41d2489571d322189246dafa5ebde1f4699f498 `_
+ zrxVault, `0xba7f8b5fb1b19c1211c5d49550fcd149177a5eaf `_
+
+
+
+Miscellaneous
+===================
+.. csv-table::
+
+ devUtils, `0x74134cf88b21383713e096a5ecf59e297dc7f547 `_
+ etherToken, `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 `_
+ erc20BridgeSampler, `0xd8c38704c9937ea3312de29f824b4ad3450a5e61 `_
+
+
+
diff --git a/docs/basics/allowances.rst b/docs/basics/allowances.rst
index 93ea7261a7..166f7768c6 100644
--- a/docs/basics/allowances.rst
+++ b/docs/basics/allowances.rst
@@ -5,8 +5,8 @@ Allowances
.. _Allowance Target Address: https://github.com/0xProject/protocol/blob/development/packages/contract-addresses/addresses.json#L40
After the official release, allowances will be set directly on the Exchange V4 Proxy contract.
-Presently, while we are in beta, allowances should be set on the `Allowance Target Address`_.
+Presently, while we are in beta, allowances should be set on the `Allowance Target <./addresses.html#exchange-v4>`_.
The motivation for eliminating the separate Allowance Target in the official release is
to reduce transaction costs. Depending on the operational overhead for our integrators,
-we may support allowances on both the Exchange V4 & the Allowance Target after the officual relase.
\ No newline at end of file
+we may support allowances on both the Exchange V4 & the Allowance Target after the official release, which is slated for January, 2021.
\ No newline at end of file
diff --git a/docs/basics/events.rst b/docs/basics/events.rst
index 129950b0cd..67464fb08e 100644
--- a/docs/basics/events.rst
+++ b/docs/basics/events.rst
@@ -1,3 +1,368 @@
###############################
Events
-###############################
\ No newline at end of file
+###############################
+
+This is a complete catalogue of 0x events emitted when interacting with the Exchange Proxy system of contracts. The diagram below
+illustrates how events are emitted when trading through the Exchange Proxy.
+
+.. warning::
+ There are pending upgrades that impact these events. Please see the `Releases <../additional/releases.html>`_ page for more details.
+
+
+.. image:: ../_static/img/events.png
+ :scale: 42%
+
+
+.. note::
+ This catalogue does not include events emitted by tokens or other exchanges, like Uniswap. It also only lists 0x V3 events
+ that are emitted during a Fill; for an extensive list of V3 events, see the `V3 Spec `_.
+
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| **Event** | **Description** | **Emitted By** |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `Deployed`_ | Emitted by the `Transformer Deployer <../architecture/transformer_deployer.html>`_ when a `Transformer <../architecture/transformers.html>`_ is deployed. | TransformerDeployer |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `ERC20BridgeTransfer`_ | Emitted when a trade occurs. | FlashWallet |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `Fill`_ | Emitted by Exchange V3 when an order is filled. | Exchange V3 |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `Killed`_ | Emitted by the `Transformer Deployer <../architecture/transformer_deployer.html>`_ when a `Transformer <../architecture/transformers.html>`_ is killed. | TransformerDeployer |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `MetaTransactionExecuted`_ | Emitted when a meta-transaction is executed on the Exchange Proxy. | ExchangeProxy |
+| | Note that this differs from meta-transactions that are executed on Exchange V3. | |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `Migrated`_ | Emitted when `ExchangeProxy.migrate()` is called. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `ProtocolFeeUnfunded`_ | Emitted when an order is skipped due to a lack of funds to pay the 0x Protocol fee. | FlashWallet |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `ProxyFunctionUpdated`_ | Emitted when a function is upgraded via `extend()` or `rollback()` | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `QuoteSignerUpdated`_ | Emitted when `ExchangeProxy.setQuoteSigner()` is called. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `TransformedERC20`_ | Emitted when an `ERC20 Transformation <../advanced/erc20_transformations.html>`_ completes. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `TransformerDeployerUpdated`_ | Emitted when the Transformer Deployer is upgraded. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `TransformerMetadata`_ | A general, customizable event emitted that can be emitted by transformers as-needed. | FlashWallet |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| **Events in upcoming releases** |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `LimitOrderFilled`_ | Emitted when a `V4 Limit Order <./orders.html#limit-orders>`_ is filled. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `RfqOrderFilled`_ | Emitted when a `V4 RFQ Order <./orders.html#rfq-orders>`_ is filled. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `OrderCancelled`_ | Emitted when a V4 Limit or RFQ Order is cancelled. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `PairCancelledLimitOrders`_ | Emitted when a Market Pair is cancelled for Limit Orders (see `cancelPairLimitOrders <./functions.html#cancelpairlimitorders>`_). | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `PairCancelledRfqOrders`_ | Emitted when a Market Pair is cancelled for RFQ Orders (see `cancelPairRfqOrders <./functions.html#cancelpairrfqorders>`_). | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `RfqOrderOriginsAllowed`_ | Emitted when a tx.origin is added/removed for RFQ, via `registerAllowedRfqOrigins <./functions.html#registerallowedrfqorigins>`_ | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+| `LiquidityProviderSwap`_ | Emitted when a `PLP <../advanced/plp.html>`_ executes a swap. | ExchangeProxy |
++-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+
+
+Deployed
+--------
+
+.. code-block:: solidity
+
+ /// @dev Emitted when a contract is deployed via `deploy()`.
+ /// @param deployedAddress The address of the deployed contract.
+ /// @param nonce The deployment nonce.
+ /// @param sender The caller of `deploy()`.
+ event Deployed(address deployedAddress, uint256 nonce, address sender);
+
+ERC20BridgeTransfer
+-------------------
+.. code-block:: solidity
+
+ /// @dev Emitted when a trade occurs.
+ /// @param inputToken The token the bridge is converting from.
+ /// @param outputToken The token the bridge is converting to.
+ /// @param inputTokenAmount Amount of input token.
+ /// @param outputTokenAmount Amount of output token.
+ /// @param from The bridge address, indicating the underlying source of the fill.
+ /// @param to The `to` address, currrently `address(this)`
+ event ERC20BridgeTransfer(
+ IERC20TokenV06 inputToken,
+ IERC20TokenV06 outputToken,
+ uint256 inputTokenAmount,
+ uint256 outputTokenAmount,
+ address from,
+ address to
+ );
+
+Fill
+----
+.. code-block:: solidity
+
+ event Fill(
+ address indexed makerAddress, // Address that created the order.
+ address indexed feeRecipientAddress, // Address that received fees.
+ bytes makerAssetData, // Encoded data specific to makerAsset.
+ bytes takerAssetData, // Encoded data specific to takerAsset.
+ bytes makerFeeAssetData, // Encoded data specific to makerFeeAsset.
+ bytes takerFeeAssetData, // Encoded data specific to takerFeeAsset.
+ bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getTypedDataHash).
+ address takerAddress, // Address that filled the order.
+ address senderAddress, // Address that called the Exchange contract (msg.sender).
+ uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker.
+ uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker.
+ uint256 makerFeePaid, // Amount of makerFeeAssetData paid to feeRecipient by maker.
+ uint256 takerFeePaid, // Amount of takerFeeAssetData paid to feeRecipient by taker.
+ uint256 protocolFeePaid // Amount of eth or weth paid to the staking contract.
+ );
+
+
+Killed
+------
+
+.. code-block:: solidity
+
+ /// @dev Emitted when a contract is killed via `kill()`.
+ /// @param target The address of the contract being killed..
+ /// @param sender The caller of `kill()`.
+ event Killed(address target, address sender);
+
+LimitOrderFilled
+----------------
+.. code-block:: solidity
+
+ /// @dev Emitted whenever a `LimitOrder` is filled.
+ /// @param orderHash The canonical hash of the order.
+ /// @param maker The maker of the order.
+ /// @param taker The taker of the order.
+ /// @param feeRecipient Fee recipient of the order.
+ /// @param takerTokenFilledAmount How much taker token was filled.
+ /// @param makerTokenFilledAmount How much maker token was filled.
+ /// @param protocolFeePaid How much protocol fee was paid.
+ /// @param pool The fee pool associated with this order.
+ event LimitOrderFilled(
+ bytes32 orderHash,
+ address maker,
+ address taker,
+ address feeRecipient,
+ address makerToken,
+ address takerToken,
+ uint128 takerTokenFilledAmount,
+ uint128 makerTokenFilledAmount,
+ uint128 takerTokenFeeFilledAmount,
+ uint256 protocolFeePaid,
+ bytes32 pool
+ );
+
+
+MetaTransactionExecuted
+-----------------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted whenever a meta-transaction is executed via
+ /// `executeMetaTransaction()` or `executeMetaTransactions()`.
+ /// @param hash The meta-transaction hash.
+ /// @param selector The selector of the function being executed.
+ /// @param signer Who to execute the meta-transaction on behalf of.
+ /// @param sender Who executed the meta-transaction.
+ event MetaTransactionExecuted(
+ bytes32 hash,
+ bytes4 indexed selector,
+ address signer,
+ address sender
+ );
+
+LiquidityProviderSwap
+---------------------
+
+.. code-block:: solidity
+
+ event LiquidityProviderSwap(
+ address inputToken,
+ address outputToken,
+ uint256 inputTokenAmount,
+ uint256 outputTokenAmount,
+ address provider,
+ address recipient
+ );
+
+Migrated
+--------
+
+.. code-block:: solidity
+
+ /// @dev Emitted when `migrate()` is called.
+ /// @param caller The caller of `migrate()`.
+ /// @param migrator The migration contract.
+ /// @param newOwner The address of the new owner.
+ event Migrated(address caller, address migrator, address newOwner);
+
+OrderCancelled
+--------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted whenever a limit or RFQ order is cancelled.
+ /// @param orderHash The canonical hash of the order.
+ /// @param maker The order maker.
+ event OrderCancelled(
+ bytes32 orderHash,
+ address maker
+ );
+
+PairCancelledLimitOrders
+------------------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted whenever limit or RFQ orders are cancelled by pair by a maker.
+ /// @param maker The maker of the order.
+ /// @param makerToken The maker token in a pair for the orders cancelled.
+ /// @param takerToken The taker token in a pair for the orders cancelled.
+ /// @param minValidSalt The new minimum valid salt an order with this pair must
+ /// have.
+ event PairCancelledLimitOrders(
+ address maker,
+ address makerToken,
+ address takerToken,
+ uint256 minValidSalt
+ );
+
+PairCancelledRfqOrders
+------------------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted whenever limit or RFQ orders are cancelled by pair by a maker.
+ /// @param maker The maker of the order.
+ /// @param makerToken The maker token in a pair for the orders cancelled.
+ /// @param takerToken The taker token in a pair for the orders cancelled.
+ /// @param minValidSalt The new minimum valid salt an order with this pair must
+ /// have.
+ event PairCancelledRfqOrders(
+ address maker,
+ address makerToken,
+ address takerToken,
+ uint256 minValidSalt
+ );
+
+ProtocolFeeUnfunded
+-------------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted when a trade is skipped due to a lack of funds
+ /// to pay the 0x Protocol fee.
+ /// @param orderHash The hash of the order that was skipped.
+ event ProtocolFeeUnfunded(bytes32 orderHash);
+
+ProxyFunctionUpdated
+--------------------
+
+.. code-block:: solidity
+
+ /// @dev A function implementation was updated via `extend()` or `rollback()`.
+ /// @param selector The function selector.
+ /// @param oldImpl The implementation contract address being replaced.
+ /// @param newImpl The replacement implementation contract address.
+ event ProxyFunctionUpdated(bytes4 indexed selector, address oldImpl, address newImpl);
+
+QuoteSignerUpdated
+------------------
+.. code-block:: solidity
+
+ /// @dev Raised when `setQuoteSigner()` is called.
+ /// @param quoteSigner The new quote signer.
+ event QuoteSignerUpdated(address quoteSigner);
+
+RfqOrderFilled
+--------------
+.. code-block:: solidity
+
+ /// @dev Emitted whenever an `RfqOrder` is filled.
+ /// @param orderHash The canonical hash of the order.
+ /// @param maker The maker of the order.
+ /// @param taker The taker of the order.
+ /// @param takerTokenFilledAmount How much taker token was filled.
+ /// @param makerTokenFilledAmount How much maker token was filled.
+ /// @param pool The fee pool associated with this order.
+ event RfqOrderFilled(
+ bytes32 orderHash,
+ address maker,
+ address taker,
+ address makerToken,
+ address takerToken,
+ uint128 takerTokenFilledAmount,
+ uint128 makerTokenFilledAmount,
+ bytes32 pool
+ );
+
+RfqOrderOriginsAllowed
+-------------------------
+
+.. code-block:: solidity
+
+ /// @dev Emitted when new addresses are allowed or disallowed to fill
+ /// orders with a given txOrigin.
+ /// @param origin The address doing the allowing.
+ /// @param addrs The address being allowed/disallowed.
+ /// @param allowed Indicates whether the address should be allowed.
+ event RfqOrderOriginsAllowed(
+ address origin,
+ address[] addrs,
+ bool allowed
+ );
+
+
+TransformedERC20
+----------------
+
+.. code-block:: solidity
+
+ /// @dev Raised upon a successful `transformERC20`.
+ /// @param taker The taker (caller) address.
+ /// @param inputToken The token being provided by the taker.
+ /// If `0xeee...`, ETH is implied and should be provided with the call.`
+ /// @param outputToken The token to be acquired by the taker.
+ /// `0xeee...` implies ETH.
+ /// @param inputTokenAmount The amount of `inputToken` to take from the taker.
+ /// @param outputTokenAmount The amount of `outputToken` received by the taker.
+ event TransformedERC20(
+ address indexed taker,
+ address inputToken,
+ address outputToken,
+ uint256 inputTokenAmount,
+ uint256 outputTokenAmount
+ );
+
+TransformerDeployerUpdated
+--------------------------
+
+.. code-block:: solidity
+
+ /// @dev Raised when `setTransformerDeployer()` is called.
+ /// @param transformerDeployer The new deployer address.
+ event TransformerDeployerUpdated(address transformerDeployer);
+
+
+TransformerMetadata
+-------------------
+
+.. code-block:: solidity
+
+ /// @dev A transformer that just emits an event with an arbitrary byte payload.
+ event TransformerMetadata(
+ bytes32 callDataHash,
+ address sender,
+ address taker,
+ bytes data
+ );
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/basics/functions.rst b/docs/basics/functions.rst
index 2141f99d9b..a3a2374603 100644
--- a/docs/basics/functions.rst
+++ b/docs/basics/functions.rst
@@ -1,3 +1,584 @@
###############################
-Functions
-###############################
\ No newline at end of file
+Basic Functionality
+###############################
+
+Below is a catalog of basic Exchange functionality. For more advanced usage, like meta-transactions and dex aggregation, see the Advanced section.
+
++---------------------------------+--------------------------------------------------------------------------+
+| **Limit Orders** | **Overview** |
++---------------------------------+--------------------------------------------------------------------------+
+| `fillLimitOrder`_ | Fills a Limit Order up to the amount requested. |
++---------------------------------+--------------------------------------------------------------------------+
+| `fillOrKillLimitOrder`_ | Fills exactly the amount requested or reverts. |
++---------------------------------+--------------------------------------------------------------------------+
+| `cancelLimitOrder`_ | Cancels an order so that it can no longer be filled. |
++---------------------------------+--------------------------------------------------------------------------+
+| `batchCancelLimitOrders`_ | A batch call to `cancelLimitOrder`. |
++---------------------------------+--------------------------------------------------------------------------+
+| `cancelPairLimitOrders`_ | Cancels Limit orders in a specific market pair. |
+| | Ex: Cancel all Limit Orders selling WETH for USDC. |
++---------------------------------+--------------------------------------------------------------------------+
+| `batchCancelLimitPairOrders`_ | A batch call to `cancelLimitPairOrders`. |
++---------------------------------+--------------------------------------------------------------------------+
+| `getLimitOrderInfo`_ | Returns the state of a given order. |
++---------------------------------+--------------------------------------------------------------------------+
+| `getLimitOrderHash`_ | Returns the EIP-712 hash for an order. |
++---------------------------------+--------------------------------------------------------------------------+
+| **RFQ Orders** | **Overview** |
++---------------------------------+--------------------------------------------------------------------------+
+| `fillRfqOrder`_ | These are analogous to the above LimitOrder functions. |
++---------------------------------+ |
+| `fillOrKillRfqOrder`_ | |
++---------------------------------+ |
+| `cancelRfqOrder`_ | |
++---------------------------------+ |
+| `batchCancelRfqOrders`_ | |
++---------------------------------+ |
+| `cancelPairRfqOrders`_ | |
++---------------------------------+ |
+| `batchCancelPairRfqOrders`_ | |
++---------------------------------+ |
+| `getRfqOrderInfo`_ | |
++---------------------------------+ |
+| `getRfqOrderHash`_ | |
++---------------------------------+--------------------------------------------------------------------------+
+| `registerAllowedRfqOrigins`_ | Register tx.origin addresses that are allowed to fill an RFQ order. |
++---------------------------------+--------------------------------------------------------------------------+
+| **Protocol Fees** | **Overview** |
++---------------------------------+--------------------------------------------------------------------------+
+| `getProtocolFeeMultiplier`_ | Takers of limit orders pay a protocol fee of `Multiplier * tx.gasprice`. |
+| | This returns the `Multiplier`. |
++---------------------------------+--------------------------------------------------------------------------+
+| `transferProtocolFeesForPools`_ | Transfers protocol fees from escrow to the 0x Staking System. |
+| | This should be called near the end of each epoch. |
++---------------------------------+--------------------------------------------------------------------------+
+
+
+Limit Orders
+============
+These are the basic functions for using a `Limit Order <../basics/orders.html#limit-orders>`_.
+
+fillLimitOrder
+--------------
+
+Limit orders can be filled with the ``fillLimitOrder()`` or ``fillOrKillLimitOrder()`` functions on the Exchange Proxy. The address calling these function will be considered the "taker" of the order.
+
+
+``fillLimitOrder()`` fills a single limit order for **up to** ``takerTokenFillAmount``:
+
+.. code-block:: solidity
+
+ function fillLimitOrder(
+ // The order
+ LimitOrder calldata order,
+ // The signature
+ Signature calldata signature,
+ // How much taker token to fill the order with
+ uint128 takerTokenFillAmount
+ )
+ external
+ payable
+ // How much maker token from the order the taker received.
+ returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
+
+
+If the trade is successful a `LimitOrderFilled <../basics/events.html#limitorderfilled>`_ will be emitted. This function reverts under any of the following conditions:
+
+- The order is fully filled: taker amount sold greater or equal to ``order.takerAmount``.
+- The order has expired.
+- The order was cancelled.
+- The market pair (Ex, ``WETH/USDT``) was cancelled (``order.salt`` is less than the value passed to ``cancelPairLimitOrders``.
+- Either the maker or taker has an insufficient allowance/balance.
+- The order's ``taker`` field is non-zero and does not match the actual taker. This is ``msg.sender``, unless used with `meta-transactions <../advanced/mtx.rst>`_ in which case it is the signer.
+- The order's ``sender`` field is non-zero and does not match ``msg.sender``.
+- The maker's signature is invalid.
+- The order's ``takerTokenFeeAmount`` is non-zero but the fee cannot be paid due to insufficient allowance/balance.
+- Not enough ETH was sent with the transaction to cover the `Protocol Fee <../basics/protocol_fees.html>`_.
+
+
+fillOrKillLimitOrder
+--------------------
+
+``fillOrKillLimitOrder()`` fills a single limit order for **exactly** ``takerTokenFillAmount``:
+
+.. code-block:: solidity
+
+ function fillOrKillLimitOrder(
+ // The order
+ LimitOrder calldata order,
+ // The signature
+ Signature calldata signature,
+ // How much taker token to fill the order with
+ uint128 takerTokenFillAmount
+ )
+ external
+ payable
+ // How much maker token from the order the taker received.
+ returns (uint128 makerTokenFillAmount);
+
+If the trade is successful a `LimitOrderFilled <../basics/events.html#limitorderfilled>`_ will be emitted. This function reverts under any of the conditions outlined above for ``fillLimitOrder``. Additionally, it will revert if the amount filled is less than ``takerTokenFillAmount``.
+
+cancelLimitOrder
+----------------
+
+This function cancels a single limit order created by the caller:
+
+.. code-block:: solidity
+
+ function cancelLimitOrder(
+ // The order
+ LimitOrder calldata order
+ )
+ external;
+
+This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
+
+batchCancelLimitOrders
+----------------------
+
+This function cancels multiple limit orders created by the caller:
+
+.. code-block:: solidity
+
+ function batchCancelLimitOrders(
+ // The orders
+ LimitOrder[] calldata orders
+ )
+ external;
+
+This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
+
+cancelPairLimitOrders
+---------------------
+
+This function cancels all limit orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
+
+.. code-block:: solidity
+
+ function cancelPairRfqOrders(
+ address makerToken,
+ address takerToken,
+ uint256 salt;
+ )
+ external;
+
+This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event, or reverts in one of the following scenarios:
+
+- ``msg.sender != order.maker``
+- The ``salt`` parameter is ≤ to a previous ``salt``.
+
+batchCancelLimitPairOrders
+--------------------------
+
+This function performs multiple ``cancelLimitPairOrders()`` at once. Each respective index across arrays is equivalent to a single call.
+
+.. code-block:: solidity
+
+ function batchCancelLimitPairOrders(
+ address[] makerTokens,
+ address[] takerTokens,
+ uint256[] salts;
+ )
+ external;
+
+This function emits a `PairCancelledLimitOrders <../basics/events.html#paircancelledlimitorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
+
+getLimitOrderInfo
+-----------------
+
+The Exchange Proxy exposes a function ``getLimitOrderInfo()`` to query information about a limit order, such as its fillable state and how much it has been filled by.
+
+.. code-block:: solidity
+
+ enum OrderStatus {
+ INVALID,
+ FILLABLE,
+ FILLED,
+ CANCELLED,
+ EXPIRED
+ }
+
+ struct OrderInfo {
+ // The order hash.
+ bytes32 orderHash;
+ // Current state of the order.
+ OrderStatus status;
+ // How much taker token has been filled in the order.
+ uint128 takerTokenFilledAmount;
+ }
+
+ function getLimitOrderInfo(
+ // The order
+ LimitOrder calldata order
+ )
+ external
+ view
+ returns (OrderInfo memory orderInfo);
+
+getLimitOrderHash
+-----------------
+
+The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec `_ standard. In solidity, the hash is computed as:
+
+
+.. code-block:: solidity
+
+ /// @dev Get the canonical hash of a limit order.
+ /// @param order The limit order.
+ /// @return orderHash The order hash.
+ function getLimitOrderHash(LibNativeOrder.LimitOrder calldata order)
+ external
+ view
+ returns (bytes32 orderHash);
+
+The simplest way to generate an order hash is by calling this function, ex:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
+
+The hash can be manually generated using the following code:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = keccak256(abi.encodePacked(
+ '\x19\x01',
+ // The domain separator.
+ keccak256(abi.encode(
+ // The EIP712 domain separator type hash.
+ keccak256(abi.encodePacked(
+ 'EIP712Domain(',
+ 'string name,',
+ 'string version,',
+ 'uint256 chainId,',
+ 'address verifyingContract)'
+ )),
+ // The EIP712 domain separator values.
+ 'ZeroEx',
+ '1.0.0',
+ 1, // For mainnet
+ 0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
+ )),
+ // The struct hash.
+ keccak256(abi.encode(
+ // The EIP712 type hash.
+ keccak256(abi.encodePacked(
+ 'LimitOrder(',
+ 'address makerToken,',
+ 'address takerToken,',
+ 'uint128 makerAmount,',
+ 'uint128 takerAmount,',
+ 'uint128 takerTokenFeeAmount,',
+ 'address taker,',
+ 'address maker,',
+ 'address sender,',
+ 'address feeRecipient,',
+ 'bytes32 pool,',
+ 'uint64 expiry,',
+ 'uint256 salt)'
+ )),
+ // The struct values.
+ order.makerToken,
+ order.takerToken,
+ order.makerAmount,
+ order.takerAmount,
+ order.takerTokenFeeAmount,
+ order.maker,
+ order.taker,
+ order.sender,
+ order.feeRecipient,
+ order.pool,
+ order.expiry,
+ order.salt
+ ))
+ ));
+
+
+RFQ Orders
+==========
+
+These are the basic functions for using an `RFQ Order <../basics/orders.html#rfq-orders>`_.
+
+fillRfqOrder
+------------
+
+RFQ orders can be filled with the ``fillRfqOrder()`` or ``fillOrKillRfqOrder()`` functions on the Exchange Proxy. The address calling this function will be considered the "taker" of the order.
+
+``fillRfqOrder()`` fills a single RFQ order for **up to** ``takerTokenFillAmount``:
+
+.. code-block:: solidity
+
+ function fillRfqOrder(
+ // The order
+ RfqOrder calldata order,
+ // The signature
+ Signature calldata signature,
+ // How much taker token to fill the order with
+ uint128 takerTokenFillAmount
+ )
+ external
+ payable
+ // How much maker token from the order the taker received.
+ returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
+
+If the trade is successful a `RfqOrderFilled <../basics/events.html#rfqorderfilled>`_ will be emitted. This function reverts under any of the following conditions:
+
+- The order is fully filled: taker amount sold greater or equal to ``order.takerAmount``.
+- The order has expired.
+- The order was cancelled.
+- The market pair (Ex, ``WETH/USDT``) was cancelled (``order.salt`` is less than the value passed to ``cancelPairLimitOrders``.
+- Either the maker or taker has an insufficient allowance/balance.
+- The order's ``taker`` field is non-zero and does not match the actual taker. This is ``msg.sender``, unless used with `meta-transactions <../advanced/mtx.rst>`_ in which case it is the signer.
+- The order's ``origin`` field is non-zero and does not match ``tx.origin`` or a valid origin (see `registerAllowedRfqOrigins <../basics/functions.html#id11>`_).
+- The maker's signature is invalid.
+
+fillOrKillRfqOrder
+------------------
+
+``fillOrKillRfqOrder()`` fills a single RFQ order for **exactly** ``takerTokenFillAmount``:
+
+.. code-block:: solidity
+
+ function fillOrKillRfqOrder(
+ // The order
+ RfqOrder calldata order,
+ // The signature
+ Signature calldata signature,
+ // How much taker token to fill the order with
+ uint128 takerTokenFillAmount
+ )
+ external
+ payable
+ // How much maker token from the order the taker received.
+ returns (uint128 makerTokenFillAmount);
+
+If the trade is successful a `RfqOrderFilled <../basics/events.html#rfqorderfilled>`_ will be emitted. This function reverts under any of the conditions outlined above for ``fillRfqOrder``. Additionally, it will revert if the amount filled is less than ``takerTokenFillAmount``.
+
+cancelRfqOrder
+--------------
+
+Similar to limit orders, RFQ orders can be cancelled on-chain through a variety of functions, which can only be called by the order's maker.
+
+``cancelRfqOrder()`` cancels a single RFQ order created by the caller:
+
+.. code-block:: solidity
+
+ function cancelRfqOrder(
+ // The order
+ RfqOrder calldata order
+ )
+ external;
+
+This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event if the cancellation is successful. The call will revert if ``msg.sender != order.maker``.
+
+batchCancelRfqOrders
+--------------------
+
+This function cancels multiple RFQ orders created by the caller:
+
+.. code-block:: solidity
+
+ function batchCancelRfqOrders(
+ // The orders
+ RfqOrder[] calldata orders
+ )
+ external;
+
+This function emits an `OrderCancelled <../basics/events.html#ordercancelled>`_ event for each order it cancels. The call will revert if ``msg.sender != order.maker`` for any of the orders.
+
+cancelPairRfqOrders
+-------------------
+
+This function cancels all RFQ orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
+
+.. code-block:: solidity
+
+ function cancelPairRfqOrders(
+ address makerToken,
+ address takerToken,
+ uint256 salt;
+ )
+ external;
+
+This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event, or reverts in one of the following scenarios:
+
+- ``msg.sender != order.maker``
+- The ``salt`` parameter is ≤ to a previous ``salt``.
+
+batchCancelPairRfqOrders
+------------------------
+
+``batchCancelPairRfqOrders()`` performs multiple ``cancelPairRfqOrders()`` at once. Each respective index across arrays is equivalent to a single call.
+
+.. code-block:: solidity
+
+ function batchCancelPairRfqOrders(
+ address[] makerTokens,
+ address[] takerTokens,
+ uint256[] salts;
+ )
+ external;
+
+This function emits a `PairCancelledRfqOrders <../basics/events.html#paircancelledrfqorders>`_ event for each market pair it cancels. It reverts if any of the individual cancellations revert.
+
+getRfqOrderInfo
+---------------
+
+The Exchange Proxy exposes a function ``getRfqOrderInfo()`` to query information about an RFQ order, such as its fillable state and how much it has been filled by.
+
+.. code-block:: solidity
+
+ enum OrderStatus {
+ INVALID,
+ FILLABLE,
+ FILLED,
+ CANCELLED,
+ EXPIRED
+ }
+
+ struct OrderInfo {
+ // The order hash.
+ bytes32 orderHash;
+ // Current state of the order.
+ OrderStatus status;
+ // How much taker token has been filled in the order.
+ uint128 takerTokenFilledAmount;
+ }
+
+ function getRfqOrderInfo(
+ // The order
+ RfqOrder calldata order
+ )
+ external
+ view
+ returns (OrderInfo memory orderInfo);
+
+getRfqOrderHash
+---------------
+
+The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec `_ standard. In solidity, the hash is computed using:
+
+.. code-block:: solidity
+
+ /// @dev Get the canonical hash of an RFQ order.
+ /// @param order The RFQ order.
+ /// @return orderHash The order hash.
+ function getRfqOrderHash(LibNativeOrder.RfqOrder calldata order)
+ external
+ view
+ returns (bytes32 orderHash);
+
+
+The simplest way to generate an order hash is by calling this function, ex:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getRfqOrderHash(order);
+
+The hash can be manually generated using the following code:
+
+.. code-block:: solidity
+
+ bytes32 orderHash = keccak256(abi.encodePacked(
+ '\x19\x01',
+ // The domain separator.
+ keccak256(abi.encode(
+ // The EIP712 domain separator type hash.
+ keccak256(abi.encodePacked(
+ 'EIP712Domain(',
+ 'string name,',
+ 'string version,',
+ 'uint256 chainId,',
+ 'address verifyingContract)'
+ )),
+ // The EIP712 domain separator values.
+ 'ZeroEx',
+ '1.0.0',
+ 1, // For mainnet
+ 0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
+ )),
+ // The struct hash.
+ keccak256(abi.encode(
+ // The EIP712 type hash.
+ keccak256(abi.encodePacked(
+ 'RfqOrder(',
+ 'address makerToken,',
+ 'address takerToken,',
+ 'uint128 makerAmount,',
+ 'uint128 takerAmount,',
+ 'address maker,'
+ 'address taker,'
+ 'address txOrigin,'
+ 'bytes32 pool,',
+ 'uint64 expiry,',
+ 'uint256 salt)'
+ )),
+ // The struct values.
+ order.makerToken,
+ order.takerToken,
+ order.makerAmount,
+ order.takerAmount,
+ order.maker,
+ order.taker,
+ order.txOrigin,
+ order.pool,
+ order.expiry,
+ order.salt
+ ))
+ ));
+
+registerAllowedRfqOrigins
+-------------------------
+
+The RFQ order includes a ``txOrigin`` field, which a maker can use to restrict which EOA's can submit the Ethereum transaction that fills their order. There are two ways a maker can use this field.
+
+1. Set to the EOA that will submit the transaction (ex, the Taker or a Meta-Transaction relayer).
+2. Set to an EOA owned by the maker, which acts as a registry key to lookup valid tx origins.
+
+Looking at the 2nd use case, a maker can register valid tx origins using this function. They would then set ``order.origin`` to be the address they used to call ``registerAllowedRfqOrigins``.
+
+.. code-block:: solidity
+
+ /// @dev Mark what tx.origin addresses are allowed to fill an order that
+ /// specifies the message sender as its txOrigin.
+ /// @param origins An array of origin addresses to update.
+ /// @param allowed True to register, false to unregister.
+ function registerAllowedRfqOrigins(address[] memory origins, bool allowed)
+ external;
+
+This function emits a `RfqOrderOriginsAllowed <../basics/events.html#rfqorderoriginsallowed>`_ event.
+
+
+Protocol Fees
+=============
+
+There is a fixed protocol fee paid by the Taker each time they fill a `Limit Order `_. Learn more in the `Protocol Fees Section <./protocol_fees.html>`_. Also check out our research in the `Tokenomics Section <../tokenomics/research.html>`_.
+
+getProtocolFeeMultiplier
+------------------------
+
+Takers of limit orders pay a protocol fee of Multiplier * tx.gasprice. This returns the Multiplier.
+
+.. code-block:: solidity
+
+ /// @dev Get the protocol fee multiplier. This should be multiplied by the
+ /// gas price to arrive at the required protocol fee to fill a native order.
+ /// @return multiplier The protocol fee multiplier.
+ function getProtocolFeeMultiplier()
+ external
+ view
+ returns (uint32 multiplier);
+
+
+transferProtocolFeesForPools
+----------------------------
+
+This function transfers protocol fees from `Fee Collectors <../architecture/fee_collectors.html>`_ to the `Staking System <../tokenomics/staking.html>`_.
+
+.. code-block:: solidity
+
+ /// @dev Transfers protocol fees from the `FeeCollector` pools into
+ /// the staking contract.
+ /// @param poolIds Staking pool IDs
+ function transferProtocolFeesForPools(bytes32[] calldata poolIds)
+ external;
\ No newline at end of file
diff --git a/docs/basics/orders.rst b/docs/basics/orders.rst
index 53434873ee..46994638c3 100644
--- a/docs/basics/orders.rst
+++ b/docs/basics/orders.rst
@@ -11,113 +11,88 @@ An order is a message passed into the 0x Protocol to facilitate an ERC20->ERC20
Limit Orders
==============
-Limit orders are the standard 0x Order, which encodes a possible trade between a maker and taker at a fixed price. These orders are typically distributed via Mesh/SRA (open orderbook) or OTC, and can be filled through the ``fillOrder()`` function on the Exchange Proxy.
-
-Structure
----------
+Limit orders are the standard 0x Order, which encodes a possible trade between a maker and taker at a fixed price. These orders are typically distributed via Mesh/SRA (open orderbook) or OTC, and can be filled through the functions on the Exchange Proxy.
The ``LimitOrder`` struct has the following fields:
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| Field | Type | Description |
-+==========================+=============+=============================================================================+
-| ``makerToken`` | ``address`` | The ERC20 token the maker is selling and the maker is selling to the taker. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``takerTokenFeeAmount`` | ``uint128`` | Amount of takerToken paid by the taker to the feeRecipient. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``maker`` | ``address`` | The address of the maker, and signer, of this order. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``sender`` | ``address`` | Allowed address to directly call ``fillLimitOrder()`` (``msg.sender``). |
-| | | This is distinct from ``taker`` in meta-transactions. |
-| | | Set to zero to allow any caller. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``feeRecipient`` | ``address`` | Recipient of maker token or taker token fees (if non-zero). |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``pool`` | ``bytes32`` | The staking pool to attribute the 0x protocol fee from this order. |
-| | | Set to zero to attribute to the default pool, not owned by anyone. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
-| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order's hash. |
-+--------------------------+-------------+-----------------------------------------------------------------------------+
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| Field | Type | Description |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``makerToken`` | ``address`` | The ERC20 token the maker is selling and the maker is selling to the taker. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``takerTokenFeeAmount`` | ``uint128`` | Amount of takerToken paid by the taker to the feeRecipient. [optional; default 0] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``maker`` | ``address`` | The address of the maker, and signer, of this order. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. [optional; default 0] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``sender`` | ``address`` | Allowed address to call ``fillLimitOrder()`` (``msg.sender``). |
+| | | This is the same as ``taker``, expect when using meta-transactions. |
+| | | Set to zero to allow any caller. [optional; default 0] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``feeRecipient`` | ``address`` | Recipient of maker token or taker token fees (if non-zero). [optional; default 0] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``pool`` | ``bytes32`` | The staking pool to attribute the 0x protocol fee from this order. |
+| | | Set to zero to attribute to the default pool, not owned by anyone. [optional; default 0] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
+| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order hash. [required] |
++-------------------------+-------------+------------------------------------------------------------------------------------------+
-Hashing limit orders
---------------------
+RFQ Orders
+==========
-The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec `_ standard. In solidity, the hash is computed as:
+RFQ orders are a stripped down version of standard limit orders, supporting fewer fields and a leaner settlement process.
+These orders are fielded just-in-time, directly from market makers, during the construction of a swap quote on 0x API,
+and can be filled through the ``fillRfqOrder()`` function on the Exchange Proxy.
-.. code-block:: solidity
+Some notable differences from regular limit orders are:
- bytes32 orderHash = keccak256(abi.encodePacked(
- '\x19\x01',
- // The domain separator.
- keccak256(abi.encode(
- // The EIP712 domain separator type hash.
- keccak256(abi.encodePacked(
- 'EIP712Domain(',
- 'string name,',
- 'string version,',
- 'uint256 chainId,',
- 'address verifyingContract)'
- )),
- // The EIP712 domain separator values.
- 'ZeroEx',
- '1.0.0',
- 1, // For mainnet
- 0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
- )),
- // The struct hash.
- keccak256(abi.encode(
- // The EIP712 type hash.
- keccak256(abi.encodePacked(
- 'LimitOrder(',
- 'address makerToken,',
- 'address takerToken,',
- 'uint128 makerAmount,',
- 'uint128 takerAmount,',
- 'uint128 takerTokenFeeAmount,',
- 'address taker,',
- 'address maker,',
- 'address sender,',
- 'address feeRecipient,',
- 'bytes32 pool,',
- 'uint64 expiry,',
- 'uint256 salt)'
- )),
- // The struct values.
- order.makerToken,
- order.takerToken,
- order.makerAmount,
- order.takerAmount,
- order.takerTokenFeeAmount,
- order.maker,
- order.taker,
- order.sender,
- order.feeRecipient,
- order.pool,
- order.expiry,
- order.salt
- ))
- ));
+* There is no ``sender`` field.
+* There is no taker fee.
+* Must restrict ``transaction.origin`` via the `order.txOrigin` field.
+* There is currently no protocol fee paid when filling an RFQ order.
-Alternatively, the Exchange Proxy contract can be used to retrieve the hash given an order.
+The ``RFQOrder`` struct has the following fields:
-.. code-block:: solidity
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| Field | Type | Description |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``makerToken`` | ``address`` | The ERC20 token the maker is selling and the maker is selling to the taker. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``maker`` | ``address`` | The address of the maker, and signer, of this order. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. [optional; default 0] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``txOrigin`` | ``address`` | The allowed address of the EOA that submitted the Ethereum transaction. **This must be set**. |
+| | | Multiple addresses are supported via `registerAllowedRfqOrigins <./functions.html#registerallowedrfqorigins>`_. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``pool`` | ``bytes32`` | The staking pool to attribute the 0x protocol fee from this order. |
+| | | Set to zero to attribute to the default pool, not owned by anyone. [optional; default 0] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
+| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order hash. [required] |
++-----------------+-------------+----------------------------------------------------------------------------------------------------------------------------+
- bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
-Signing limit orders
---------------------
+How To Sign
+==============
-Limit orders must be signed by the maker of the order. This signature must be passed into the fill function by the taker in order to fill the order.
+Both Limit & RFQ orders must be signed by the `maker`. This signature is needed to fill an order, see `Basic Functionality <./functions.rst>`_.
The protocol accepts signatures defined by the following struct:
@@ -137,10 +112,13 @@ There are two types of signatures supported: ``EIP712`` and ``EthSign``.
In both cases, the ``@0x/protocol-utils`` package simplifies generating these signatures.
+.. note::
+ The Protocol Utils package is still under development. This message will be removed once the package is published. - 11/24/2020.
+
.. code-block:: javascript
const utils = require('@0x/protocol-utils');
- const order = new utils.LimitOrder({
+ const order = new utils.LimitOrder({ // or utils.RfqOrder
makerToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
... // Other fields
@@ -156,369 +134,7 @@ In both cases, the ``@0x/protocol-utils`` package simplifies generating these si
makerAddress,
);
-Filling limit orders
---------------------
-Limit orders can be filled with the ``fillLimitOrder()`` or ``fillOrKillLimitOrder()`` functions on the Exchange Proxy. The address calling these function will be considered the "taker" of the order.
-
-
-``fillLimitOrder()`` fills a single limit order for **up to** ``takerTokenFillAmount``:
-
-.. code-block:: solidity
-
- function fillLimitOrder(
- // The order
- LimitOrder calldata order,
- // The signature
- Signature calldata signature,
- // How much taker token to fill the order with
- uint128 takerTokenFillAmount
- )
- external
- payable
- // How much maker token from the order the taker received.
- returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
-
-``fillOrKillLimitOrder()`` fills a single limit order for **exactly** ``takerTokenFillAmount``:
-
-.. code-block:: solidity
-
- function fillOrKillLimitOrder(
- // The order
- LimitOrder calldata order,
- // The signature
- Signature calldata signature,
- // How much taker token to fill the order with
- uint128 takerTokenFillAmount
- )
- external
- payable
- // How much maker token from the order the taker received.
- returns (uint128 makerTokenFillAmount);
-
-Cancelling a limit order
-------------------------
-
-Because there is no way to un-sign an order that has been distributed, limit orders must be cancelled on-chain through one of several functions. They can only be called by the order's maker.
-
-``cancelLimitOrder()`` cancels a single limit order created by the caller:
-
-.. code-block:: solidity
-
- function cancelLimitOrder(
- // The order
- LimitOrder calldata order
- )
- external;
-
-``batchCancelLimitOrders()`` cancels multiple limit orders created by the caller:
-
-.. code-block:: solidity
-
- function batchCancelLimitOrders(
- // The orders
- LimitOrder[] calldata orders
- )
- external;
-
-``cancelLimitPairOrders()`` will cancel all limit orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
-
-.. code-block:: solidity
-
- function cancelLimitPairLimitOrders(
- address makerToken,
- address takerToken,
- uint256 salt;
- )
- external;
-
-``batchCancelLimitPairOrders()`` performs multiple ``cancelLimitPairOrders()`` at once. Each respective index across arrays is equivalent to a single call.
-
-.. code-block:: solidity
-
- function batchCancelLimitPairOrders(
- address[] makerTokens,
- address[] takerTokens,
- uint256[] salts;
- )
- external;
-
-Getting the status of a limit order
------------------------------------
-
-The Exchange Proxy exposes a function ``getLimitOrderInfo()`` to query information about a limit order, such as its fillable state and how much it has been filled by.
-
-.. code-block:: solidity
-
- enum OrderStatus {
- INVALID,
- FILLABLE,
- FILLED,
- CANCELLED,
- EXPIRED
- }
-
- struct OrderInfo {
- // The order hash.
- bytes32 orderHash;
- // Current state of the order.
- OrderStatus status;
- // How much taker token has been filled in the order.
- uint128 takerTokenFilledAmount;
- }
-
- function getLimitOrderInfo(
- // The order
- LimitOrder calldata order
- )
- external
- view
- returns (OrderInfo memory orderInfo);
-
-RFQ Orders
-==========
-
-RFQ orders are a stripped down version of standard limit orders, supporting fewer fields and a leaner settlement process. These orders are fielded just-in-time, directly from market makers, during the construction of a swap quote on 0x API, and can be filled through the ``fillRfqOrder()`` function on the Exchange Proxy.
-
-Some notable differences from regular limit orders are:
-
-* The only fill restrictions that can be placed on an RFQ order is on the ``tx.origin`` and ``taker`` of the transaction.
-* There are no taker token fees.
-
-Structure
-----------
-
-The ``RFQOrder`` struct has the following fields:
-
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| Field | Type | Description |
-+=================+=============+=============================================================================+
-| ``makerToken`` | ``address`` | The ERC20 token the maker is selling and the maker is selling to the taker. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``takerToken`` | ``address`` | The ERC20 token the taker is selling and the taker is selling to the maker. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``makerAmount`` | ``uint128`` | The amount of makerToken being sold by the maker. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``takerAmount`` | ``uint128`` | The amount of takerToken being sold by the taker. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``maker`` | ``address`` | The address of the maker, and signer, of this order. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``taker`` | ``address`` | Allowed taker address. Set to zero to allow any taker. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``txOrigin`` | ``address`` | The allowed address of the EOA that submitted the Ethereum transaction. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``pool`` | ``bytes32`` | The staking pool to attribute the 0x protocol fee from this order. |
-| | | Set to zero to attribute to the default pool, not owned by anyone. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``expiry`` | ``uint64`` | The Unix timestamp in seconds when this order expires. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-| ``salt`` | ``uint256`` | Arbitrary number to enforce uniqueness of the order's hash. |
-+-----------------+-------------+-----------------------------------------------------------------------------+
-
-Hashing RFQ orders
-------------------
-
-The hash of the order is used to uniquely identify an order inside the protocol. It is computed following the `EIP712 spec `_ standard. In solidity, the hash is computed as:
-
-.. code-block:: solidity
-
- bytes32 orderHash = keccak256(abi.encodePacked(
- '\x19\x01',
- // The domain separator.
- keccak256(abi.encode(
- // The EIP712 domain separator type hash.
- keccak256(abi.encodePacked(
- 'EIP712Domain(',
- 'string name,',
- 'string version,',
- 'uint256 chainId,',
- 'address verifyingContract)'
- )),
- // The EIP712 domain separator values.
- 'ZeroEx',
- '1.0.0',
- 1, // For mainnet
- 0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
- )),
- // The struct hash.
- keccak256(abi.encode(
- // The EIP712 type hash.
- keccak256(abi.encodePacked(
- 'RfqOrder(',
- 'address makerToken,',
- 'address takerToken,',
- 'uint128 makerAmount,',
- 'uint128 takerAmount,',
- 'address maker,'
- 'address taker,'
- 'address txOrigin,'
- 'bytes32 pool,',
- 'uint64 expiry,',
- 'uint256 salt)'
- )),
- // The struct values.
- order.makerToken,
- order.takerToken,
- order.makerAmount,
- order.takerAmount,
- order.maker,
- order.taker,
- order.txOrigin,
- order.pool,
- order.expiry,
- order.salt
- ))
- ));
-
-Alternatively, the Exchange Proxy contract can be used to retrieve the hash given an order.
-
-.. code-block:: solidity
-
- bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getLimitOrderHash(order);
-
-Signing RFQ orders
-------------------
-
-RFQ orders must be signed by the maker of the order. This signature must be passed into the fill function by the taker in order to fill the order.
-
-The protocol accepts signatures defined by the following struct:
-
-.. code-block:: solidity
-
- struct {
- uint8 v; // Signature data.
- bytes32 r; // Signature data.
- bytes32 s; // Signature data.
- }
-
-The ``@0x/protocol-utils`` node package simplifies the process of creating a valid signature object.
-
-.. code-block:: javascript
-
- const utils = require('@0x/protocol-utils');
- const order = new utils.RfqOrder({
- makerToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
- takerToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
- ... // Other fields
- });
- // Generate an EthSign signature
- const signature = await order.ethSignHashWithProviderAsync(
- web3.currentProvider,
- makerAddress,
- );
-
-Filling RFQ Orders
-------------------
-
-RFQ orders can be filled with the ``fillRfqOrder()`` or ``fillOrKillRfqOrder()`` functions on the Exchange Proxy. The address calling this function will be considered the "taker" of the order.
-
-``fillRfqOrder()`` fills a single RFQ order for **up to** ``takerTokenFillAmount``:
-
-.. code-block:: solidity
-
- function fillRfqOrder(
- // The order
- RfqOrder calldata order,
- // The signature
- Signature calldata signature,
- // How much taker token to fill the order with
- uint128 takerTokenFillAmount
- )
- external
- // How much maker token from the order the taker received.
- returns (uint128 takerTokenFillAmount, uint128 makerTokenFillAmount);
-
-``fillOrKillRfqOrder()`` fills a single RFQ order for **exactly** ``takerTokenFillAmount``:
-
-.. code-block:: solidity
-
- function fillOrKillRfqOrder(
- // The order
- RfqOrder calldata order,
- // The signature
- Signature calldata signature,
- // How much taker token to fill the order with
- uint128 takerTokenFillAmount
- )
- external
- // How much maker token from the order the taker received.
- returns (uint128 makerTokenFillAmount);
-
-Cancelling an RFQ order
------------------------
-
-Similar to limit orders, RFQ orders can be cancelled on-chain through a variety of functions, which can only be called by the order's maker.
-
-``cancelRfqOrder()`` cancels a single RFQ order created by the caller:
-
-.. code-block:: solidity
-
- function cancelRfqOrder(
- // The order
- RfqOrder calldata order
- )
- external;
-
-``batchCancelRfqOrders()`` cancels multiple RFQ orders created by the caller:
-
-.. code-block:: solidity
-
- function batchCancelRfqOrders(
- // The orders
- RfqOrder[] calldata orders
- )
- external;
-
-``cancelPairRfqOrders()`` will cancel all RFQ orders created by the caller with with a maker and taker token pair and a ``salt`` field < the ``salt`` provided. Subsequent calls to this function with the same tokens must provide a ``salt`` >= the last call to succeed.
-
-.. code-block:: solidity
-
- function cancelPairRfqOrders(
- address makerToken,
- address takerToken,
- uint256 salt;
- )
- external;
-
-``batchCancelPairRfqOrders()`` performs multiple ``cancelPairRfqOrders()`` at once. Each respective index across arrays is equivalent to a single call.
-
-.. code-block:: solidity
-
- function batchCancelPairRfqOrders(
- address[] makerTokens,
- address[] takerTokens,
- uint256[] salts;
- )
- external;
-
-Getting the status of an RFQ order
-----------------------------------
-
-The Exchange Proxy exposes a function ``getRfqOrderInfo()`` to query information about an RFQ order, such as its fillable state and how much it has been filled by.
-
-.. code-block:: solidity
-
- enum OrderStatus {
- INVALID,
- FILLABLE,
- FILLED,
- CANCELLED,
- EXPIRED
- }
-
- struct OrderInfo {
- // The order hash.
- bytes32 orderHash;
- // Current state of the order.
- OrderStatus status;
- // How much taker token has been filled in the order.
- uint128 takerTokenFilledAmount;
- }
-
- function getRfqOrderInfo(
- // The order
- RfqOrder calldata order
- )
- external
- view
- returns (OrderInfo memory orderInfo);
+The Orderbook
+=======================
+Orders are shared through a decentralized and permissionless network, called `0x Mesh `_. The simplest way to post and discover orders is through `0x API `_. See `this guide `_ tailored for Market Makers.
\ No newline at end of file
diff --git a/docs/basics/protocol_fees.rst b/docs/basics/protocol_fees.rst
new file mode 100644
index 0000000000..749191818e
--- /dev/null
+++ b/docs/basics/protocol_fees.rst
@@ -0,0 +1,18 @@
+###############################
+Protocol Fees
+###############################
+
+An ETH protocol fee is paid by the Taker each time a `Limit Order <./orders.html#limit-orders>`_ is `filled <./functions.html>`_.
+The fee is proportional to the gas cost of filling an order and scales linearly with gas price. The cost is currently ``70k * tx.gasprice``.
+Every 10 days, these fees are aggregated and distributed to the makers as a liquidity reward: the reward is proportional to the maker's collected fees and staked ZRX relative to other makers.
+To learn more about protocol fees and liquidity incentives, see the `Official Spec `_.
+
+.. note::
+
+ `RFQ Orders <./orders.html#rfq-orders>`_ are introduced in Exchange V4, and there is currently no protocol fee for filling this type of order.
+ The existing fee mechanics work well for limit orders, where arb bots pay to compete for liquidity; however, it does not translate well to RFQ where makers are matched with a specific taker.
+ We are researching fee models that could be used for RFQ and will keep the community up-to-date on our `Forum `_.
+
+.. warning::
+
+ In Exchange V3, protocol fees could be paid in ETH or WETH. As of V4, they can only be paid in ETH.
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index 3c5c1c6bd3..050bc27755 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,6 +14,7 @@
import sys
import os
+import sphinx_rtd_theme
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -28,7 +29,11 @@ import os
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['recommonmark']
+extensions = [
+ 'recommonmark',
+ 'sphinx_rtd_theme',
+ 'sphinx_markdown_tables',
+]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -55,9 +60,9 @@ copyright = u'2016, ZeroEx Inc'
# built documents.
#
# The short X.Y version.
-version = '1.0'
+version = '4.0'
# The full version, including alpha/beta/rc tags.
-release = '1.0'
+release = '4.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -71,7 +76,7 @@ release = '1.0'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ['_build', 'README.md', 'requirements.txt']
# The reST default role (used for this markup: `text`) to use for all
# documents.
@@ -102,7 +107,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'default'
+html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -139,6 +144,10 @@ html_context = {
],
}
+html_js_files = [
+ 'js_overrides.js',
+]
+
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
diff --git a/docs/contributing.rst b/docs/contributing.rst
deleted file mode 100644
index e582053ea0..0000000000
--- a/docs/contributing.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../CONTRIBUTING.rst
diff --git a/docs/dummy.rst b/docs/dummy.rst
deleted file mode 100644
index 78c815da4c..0000000000
--- a/docs/dummy.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Dummy
-###############################
\ No newline at end of file
diff --git a/docs/history.rst b/docs/history.rst
deleted file mode 100644
index 250649964b..0000000000
--- a/docs/history.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../HISTORY.rst
diff --git a/docs/index.rst b/docs/index.rst
index ea7a0903c6..f155f53a11 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,17 +1,17 @@
0x Protocol
===========
-.. image:: logo.svg
- :width: 120px
+0x is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets.
+Learn more about 0x Labs at `0x.org `_. Check out our code on `GitHub `_.
+Connect with the community on our `Forum `_ and `Reddit `_.
+Chat with our team privately on `Discord `_ or publicly on `Twitter `_.
+
+
+.. image:: ./_static/img/logo.svg
+ :width: 20%
:alt: 0x Protocol logo
:align: center
-
-Contents
-========
-
-:ref:`Keyword Index `, :ref:`Search Page `
-
.. toctree::
:maxdepth: 2
:caption: Basics
@@ -20,16 +20,17 @@ Contents
basics/functions.rst
basics/events.rst
basics/allowances.rst
+ basics/protocol_fees.rst
+ basics/addresses.rst
.. toctree::
:maxdepth: 2
:caption: Advanced
+ advanced/mtx.rst
advanced/erc20_transformations.rst
- advanced/aggregation.rst
- advanced/weth_wrapping.rst
- advanced/private_liquidity_pools.rst
- advanced/request_for_quote.rst
+ advanced/plp.rst
+ advanced/uniswap.rst
.. toctree::
:maxdepth: 2
@@ -38,17 +39,22 @@ Contents
architecture/overview.rst
architecture/proxy.rst
architecture/features.rst
- architecture/flash_wallet.rst
architecture/transformers.rst
+ architecture/flash_wallet.rst
+ architecture/governor.rst
+ architecture/transformer_deployer.rst
+ architecture/fee_collectors.rst
+ architecture/plp_sandbox.rst
+
.. toctree::
:maxdepth: 2
:caption: ZRX Tokenomics
- tokenomics/protocol_fees.rst
- tokenomics/staking.rst
+ tokenomics/research.rst
+ tokenomics/staking.md
+ tokenomics/staking_reward_formula.rst
tokenomics/governance.rst
- tokenomics/voting.rst
.. toctree::
:maxdepth: 2
@@ -57,12 +63,16 @@ Contents
additional/audits.rst
additional/bounties.rst
additional/contributing.rst
+ additional/exceptional_erc20s.rst
+ additional/releases.rst
+.. toctree::
+ :maxdepth: 1
+ :caption: Connect
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
+ 0x Labs
+ GitHub
+ Forum
+ Reddit
+ Discord
+ Twitter
\ No newline at end of file
diff --git a/docs/installation.rst b/docs/installation.rst
deleted file mode 100644
index 9667188bd8..0000000000
--- a/docs/installation.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-============
-Installation
-============
-
-Install the package with pip::
-
- $ pip install read-the-docs-template
diff --git a/docs/readme.rst b/docs/readme.rst
deleted file mode 100644
index 72a3355815..0000000000
--- a/docs/readme.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../README.rst
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000000..8fd28e4779
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,2 @@
+six
+sphinx-markdown-tables
\ No newline at end of file
diff --git a/docs/scripts/generate_addresses.py b/docs/scripts/generate_addresses.py
new file mode 100644
index 0000000000..a3889e9dbf
--- /dev/null
+++ b/docs/scripts/generate_addresses.py
@@ -0,0 +1,84 @@
+import json
+
+####
+#### Run from `root/docs` directory. Generates `root/docs/basics/addresses.rst`
+####
+
+
+sections = [
+
+ # Exchange V4
+ {
+ "name": "Exchange V4",
+ "contracts": [
+ 'exchangeProxy',
+ 'exchangeProxyAllowanceTarget',
+ 'exchangeProxyFlashWallet',
+ 'exchangeProxyGovernor',
+ 'exchangeProxyLiquidityProviderSandbox',
+ 'exchangeProxyTransformerDeployer'
+ ]
+ },
+
+ # Exchange V4 transformers
+ {
+ "name": "Transformers",
+ "contracts": [
+ "transformers"
+ ]
+ },
+
+ # ZRX / Staking
+ {
+ "name": "ZRX / Staking",
+ "contracts": [
+ 'staking',
+ 'stakingProxy',
+ 'zrxToken',
+ 'zrxVault'
+ ]
+ },
+
+ # Miscellaneous
+ {
+ "name": "Miscellaneous",
+ "contracts": [
+ 'devUtils',
+ 'etherToken',
+ 'erc20BridgeSampler'
+ ]
+ }
+]
+
+def printRow(contract, address):
+ etherscanLink = "%s/%s"%("https://etherscan.io/address/", address)
+ print(" %s, `%s <%s>`_"%(contract, address, etherscanLink))
+
+def printTable(contracts, addresses):
+ print(".. csv-table::\n")
+ for contract in contracts:
+ if isinstance(addresses[contract], unicode):
+ printRow(contract, addresses[contract])
+ else:
+ for contract,address in addresses[contract].items():
+ printRow(contract, address)
+
+
+print(
+'''
+###############################
+Addresses
+###############################
+
+.. note::
+ This page is auto-generated. See the `contract-addresses `_ package for an exhaustive list of contracts across all networks.
+'''
+)
+
+with open('../packages/contract-addresses/addresses.json') as f:
+ addresses = json.load(f)
+ for section in sections:
+ print("%s\n==================="%(section["name"]))
+ printTable(section["contracts"], addresses["1"])
+ print("\n\n")
+
diff --git a/docs/tokenomics/governance.rst b/docs/tokenomics/governance.rst
index 8616542eeb..0ac6c79fbc 100644
--- a/docs/tokenomics/governance.rst
+++ b/docs/tokenomics/governance.rst
@@ -1,3 +1,5 @@
###############################
Governance
-###############################
\ No newline at end of file
+###############################
+
+The 0x Community uses their ZRX (and staked ZRX) tokens to govern the protocol, by voting on proposals called `ZEIPs `_. Anyone can propose a change to the system by creating a ZEIP. Visit `https://0x.org/zrx/vote `_ to participate!
\ No newline at end of file
diff --git a/docs/tokenomics/protocol_fees.rst b/docs/tokenomics/protocol_fees.rst
deleted file mode 100644
index 9c9a8d9deb..0000000000
--- a/docs/tokenomics/protocol_fees.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Protocol Fees
-###############################
\ No newline at end of file
diff --git a/docs/tokenomics/research.rst b/docs/tokenomics/research.rst
new file mode 100644
index 0000000000..db11b2a9f7
--- /dev/null
+++ b/docs/tokenomics/research.rst
@@ -0,0 +1,9 @@
+###############################
+Research
+###############################
+
+.. raw:: html
+
+
\ No newline at end of file
diff --git a/docs/tokenomics/staking.md b/docs/tokenomics/staking.md
new file mode 100644
index 0000000000..477aaf5cd1
--- /dev/null
+++ b/docs/tokenomics/staking.md
@@ -0,0 +1,1484 @@
+# Staking
+
+## Table of Contents
+
+1. [Overview](#overview)
+ 1. [Motivation](#motivation)
+ 1. [Utility of Stake](#utility-of-stake)
+ 1. [Staking Pools](#staking-pools)
+1. [Architecture](#architecture)
+ 1. [Normal Mode](#normal-mode)
+ 1. [Catastrophic Failure Mode](#catastrophic-failure-mode)
+1. [Contract Migrations](#contract-migrations)
+ 1. [Deploying the system](#deploying-the-system)
+ 1. [Upgrading `StakingProxy`](#upgrading-stakingproxy)
+ 1. [Upgrading `Staking` contract](#upgrading-staking-contract)
+ 1. [Upgrading `ZrxVault`](#upgrading-zrxvault)
+ 1. [Handling upgrades to the ERC20Proxy](#handling-upgrades-to-the-erc20proxy)
+ 1. [Setting Parameters](#setting-parameters)
+ 1. [Managing Exchange Addresses](#managing-exchange-addresses)
+1. [Epochs & Scheduling](#epochs--scheduling)
+ 1. [Ending One Epoch, and Starting a New One](#ending-one-epoch-and-starting-a-new-one)
+ 1. [Logic of `endEpoch`](#logic-of-endepoch)
+ 1. [Errors by `endEpoch`](#errors-by-endepoch)
+1. [Staking](#staking)
+ 1. [Logic of `stake`](#logic-of-stake)
+ 1. [Errors by `stake`](#errors-by-stake)
+ 1. [Logic of `unstake`](#logic-of-unstake)
+ 1. [Errors by `unstake`](#errors-by-unstake)
+ 1. [Staking Pools](#staking-pools)
+ 1. [Stake Status](#stake-status)
+ 1. [Logic of `moveStake`](#logic-of-movestake)
+ 1. [Errors by `moveStake`](#errors-by-movestake)
+ 1. [Querying Stake](#querying-stake)
+1. [Liquidity Incentives](#liquidity-incentives)
+ 1. [Market Making](#market-making)
+ 1. [Logic of `createStakingPool`](#logic-of-createstakingpool)
+ 1. [Errors by `createStakingPool`](#errors-by-createstakingpool)
+ 1. [Logic of `decreaseStakingPoolOperatorShare`](#logic-of-decreasestakingpooloperatorshare)
+ 1. [Errors by `decreaseStakingPoolOperatorShare`](#errors-by-decreasestakingpooloperatorshare)
+ 1. [Logic of `joinStakingPoolAsMaker`](#logic-of-joinstakingpoolasmaker)
+ 1. [Errors by `joinStakingPoolAsMaker`](#errors-by-joinstakingpoolasmaker)
+ 1. [Paying Liquidity Rewards (Finalization)](#paying-liquidity-rewards-finalization)
+ 1. [Logic of `finalizePool`](#logic-of-finalizepool)
+ 1. [Precision of Rewards Computation](#precision-of-rewards-computation)
+ 1. [Errors by `finalizePool`](#errors-by-finalizepool)
+ 1. [Logic of `withdrawDelegatorRewards`](#logic-of-withdrawdelegatorrewards)
+ 1. [Errors by `withdrawDelegatorRewards`](#errors-by-withdrawdelegatorrewards)
+1. [Batch Calls](#batch-calls)
+ 1. [Logic of `batchExecute`](#logic-of-batchexecute)
+ 1. [Errors by `batchExecute`](#errors-by-batchexecute)
+1. [Paying the Protocol Fee](#paying-the-protocol-fee)
+ 1. [Logic of `payProtocolFee`](#logic-of-payprotocolfee)
+ 1. [Errors by `payProtocolFee`](#errors-by-payprotocolfee)
+1. [Interfaces](#interfaces)
+ 1. [Staking Logic Contract](#staking-logic-contract)
+ 1. [`Staking` Contract State](#staking-contract-state)
+ 1. [`StakingProxy` Contract](#staking-proxy-contract)
+ 1. [`ZrxVault`](#zrx-vault)
+ 1. [Structs](#structs)
+1. [Events](#events)
+ 1. [Staking Logic Contract](#staking-logic-contract)
+ 1. [`StakingProxy` Contract](#staking-proxy-contract)
+ 1. [`ZrxVault`](#zrx-vault)
+1. [Algorithms, Data Structures & Design Patterns](#algorithms-data-structures--design-patterns)
+ 1. [Securing the Proxy Pattern](#securing-the-proxy-pattern)
+ 1. [Tracking for Reward Balances for Pool Members](#tracking-for-reward-balances-for-pool-members)
+ 1. [Computing Rewards in Practice](#computing-rewards-in-practice)
+ 1. [Handling Epochs With No Rewards](#handling-epochs-with-no-rewards)
+ 1. [Stake Management](#stake-management)
+
+## 1 Overview
+
+This spec outlines the architecture, implementation and usage of 0x stake-based liquidity incentives.
+
+### Motivation
+
+Staking aligns all market participants with the long-term mission and objectives of 0x. Specifically, it incentivizes ownership of the protocol among market makers through liquidity rewards. Rewards are generated by a protocol fee that is denominated in WETH and proportional to the gas cost of filling an order. The fee scales linearly with gas price to redirect proceeds from arbitrage-driven gas auctions back to market makers.
+
+### Utility of Stake
+
+Token holders stake their ZRX to unlock utility within the 0x ecosystem. This includes earning liquidity rewards through market making on the 0x protocol and participating in governance over the protocol.
+
+A market maker provides liquidity by creating 0x orders that are filled by takers through the [`Exchange`](../v3/v3-specifications.md#exchange) contract. The `Exchange` charges a fee to the taker on each fill and forwards it to the [`Staking`](#staking) contract. The fee is attributed to the maker so long as they have created a staking pool that holds at least 100 ZRX. After every 10 day epoch, the fees are aggregated and distributed to the makers as a liquidity reward: the reward is proportional to the maker's collected fees and stake relative to other makers.
+
+Governance over the protocol is conducted by voting on [ZEIPs (ZeroEx Improvement Proposals)](https://github.com/0xProject/ZEIPs). A ZEIP generally corresponds to a modification or upgrade to the 0x protocol. The ecosystem votes on the proposal, collectively deciding whether the feature will be included in a future version of the protocol. One Staked ZRX equals one vote.
+
+### Staking Pools
+
+Staking pools are created to leverage the weight of other stakers. A market maker, for example, can increase their liquidity reward without exposing themselves to the price fluctuations of the ZRX token. Market makers, in turn, incentivize delegators to contribute their ZRX by paying them a portion of the liquidity reward.
+
+Staking pools can also be used to increase voting power. Delegators share a portion of their vote with the pool (50% of their vote goes to the pool operator and 50% is retained by the delegator), amplifying the pool's impact in governance over 0x. This allows stakers to form cliques within the greater governance system.
+
+## Architecture
+
+The system of staking contracts is composed of three contracts.
+
+| Contract | Description |
+|---------------- |----------------------------------------------------------------- |
+| `Staking` | An upgradeable/stateless contract that implements staking logic |
+| `StakingProxy` | Stores staking state and delegates to the `Staking` contract |
+| `ZrxVault` | Securely holds staked ZRX Tokens |
+
+### Normal Mode
+
+The diagram below shows how the staking contracts connect to each other and the broader 0x ecosystem.
+
+
+
+### Catastrophic Failure Mode
+
+In this worst-case scenario, state has been irreparably corrupted and the staking contracts must be redeployed. Users would withdraw their ZRX and re-stake under the new system.
+
+1. The 0x `Exchange` contract stops charging protocol fees.
+2. The `ZrxVault` is detached from the staking contract.
+3. Users withdraw their funds from the `ZrxVault` directly.
+
+
+
+## Contract Migrations
+
+This section outlines steps for managing the system of smart contracts. Operations are atomically executed as a group. Contracts are owned by the [`ZeroExGovernor`](../architecture/governor.html).
+
+### Deploying the system
+
+1. Deploy `ZrxVault`.
+2. Deploy `Staking` contract (address of `ZrxVault` is hardcoded in this contract).
+3. Deploy `StakingProxy`.
+4. Attach `Staking` contract to `StakingProxy`.
+
+### Upgrading `StakingProxy`
+
+1. Deploy new `StakingProxy`.
+2. Set `StakingProxy` in `ZrxVault`.
+3. Set `StakingProxy` in 0x Exchanges.
+
+### Upgrading `Staking` contract
+
+1. Deploy new `Staking` contract.
+2. Attach `Staking` contract to `StakingProxy`.
+
+### Upgrading `ZrxVault`
+
+The `ZrxVault` address is hardcoded in the `Staking` contract and should not be upgraded. If it does need to be changed, then set the current `ZrxVault` into Catastrophic Failure mode (allowing users to withdraw their ZRX) and redeploy the entire system.
+
+### Handling upgrades to the ERC20Proxy
+
+The `ZrxVault` shares the `Exchange` contract's `ERC20Proxy`. It is possible this contract could get re-deployed for reasons outside of staking.
+
+1. Update the ERC20 Asset Proxy in the `ZrxVault`.
+2. Update the ZRX Asset Data (if necessary) in the `ZrxVault`.
+
+### Setting Parameters
+
+Configurable parameters can be set or queried using the functions below.
+
+```solidity
+/// @dev Set all configurable parameters at once.
+/// @param _epochDurationInSeconds Minimum seconds between epochs.
+/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
+/// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
+/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
+/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
+function setParams(
+ uint256 _epochDurationInSeconds,
+ uint32 _rewardDelegatedStakeWeight,
+ uint256 _minimumPoolStake,
+ uint32 _cobbDouglasAlphaNumerator,
+ uint32 _cobbDouglasAlphaDenominator
+)
+ external
+ onlyAuthorized;
+
+/// @dev Retrieves all configurable parameter values.
+/// @return _epochDurationInSeconds Minimum seconds between epochs.
+/// @return _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
+/// @return _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
+/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
+/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
+function getParams()
+ external
+ view
+ returns (
+ uint256 _epochDurationInSeconds,
+ uint32 _rewardDelegatedStakeWeight,
+ uint256 _minimumPoolStake,
+ uint32 _cobbDouglasAlphaNumerator,
+ uint32 _cobbDouglasAlphaDenominator
+ );
+```
+
+Please refer to [ZEIP-61](https://github.com/0xProject/ZEIPs/issues/61) for a description of each parameter and justification for their starting values.
+
+### Managing Exchange Addresses
+
+Exchanges that generate protocol fees must be registered in the staking contract by an authorized address. The interface is described below.
+
+```solidity
+/// @dev Adds a new exchange address
+/// @param addr Address of exchange contract to add
+function addExchangeAddress(address addr)
+ external
+ onlyAuthorized;
+
+/// @dev Removes an existing exchange address
+/// @param addr Address of exchange contract to remove
+function removeExchangeAddress(address addr)
+ external
+ onlyAuthorized;
+
+/// @dev Returns true iff the input address is a valid exchange.
+function validExchanges(address addr)
+ public
+ returns (bool isValid);
+```
+
+## Epochs & Scheduling
+
+All processes in the system are segmented into contiguous time intervals, called epochs. Epochs have a fixed minimum period (10 days at time of writing), which is configurable via [MixinParams](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/sys/MixinParams.sol). Epochs serve as the basis for all other timeframes within the system, which provides a more stable and consistent scheduling metric than blocks or block timestamps.
+
+
+
+### Ending One Epoch, and Starting a New One
+
+A new epoch automatically begins when the current epoch ends. Anyone can end an epoch by calling the staking contract after the minimum epoch period has elapsed.
+
+```solidity
+/// @dev Begins a new epoch, preparing the prior one for finalization.
+/// Throws if not enough time has passed between epochs or if the
+/// previous epoch was not fully finalized.
+/// @return numPoolsToFinalize The number of unfinalized pools.
+function endEpoch()
+ external
+ returns (uint256 numPoolsToFinalize)
+```
+
+The return value describes the number of pools to finalize; this concept is described in [Section 6.2](#62-paying-liquidity-rewards-finalization).
+
+#### Logic of `endEpoch`
+
+When this function is called:
+
+1. Assert the previous epoch (`currentEpoch-1`) is finalized: all rewards have been paid to pools.
+2. Wrap any ETH into WETH (protocol fees can be paid in ETH or WETH, but rewards are always paid in WETH).
+3. Store statistics on the epoch, including the total WETH in the contract - this value is the total reward available to pools.
+4. Emit [EpochEnded](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L60) event.
+5. Assert that enough time has elapsed to increment the epoch.
+6. Increase the `currentEpoch` by 1.
+7. If no pools earned rewards this epoch then the epoch is implicitly finalized; emit the [EpochFinalized](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L72) Event.
+
+#### Errors by `endEpoch`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
+| [PreviousEpochNotFinalizedError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L294) | The previous epoch is not finalized: at least one pool has not been paid its reward. |
+| [BlockTimestampTooLowError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L173) | Not enough time has elapsed to end the epoch. |
+
+## Staking
+
+ZRX is staked by depositing tokens into the `Staking` contract. The diagram below illustrates this workflow.
+
+
+
+ZRX can simlarly be unstaked by withdrawing tokens from the Staking contract. There are time-restrictions on unstaking, which are discussed later in this section.
+
+Below is the interface for staking and unstaking.
+
+```solidity
+/// @dev Stake ZRX tokens. Tokens are deposited into the `ZrxVault`.
+/// Unstake to retrieve the ZRX.
+/// @param amount of ZRX to stake.
+function stake(uint256 amount)
+ external;
+
+/// @dev Unstake. Tokens are withdrawn from the `ZrxVault` and returned to
+/// the staker. Stake must be in the 'undelegated' status in both the
+/// current and next epoch in order to be unstaked.
+/// @param amount of ZRX to unstake.
+function unstake(uint256 amount)
+ external;
+```
+
+#### Logic of `stake`
+
+1. Deposit ZRX tokens into `ZrxVault`.
+2. `ZrxVault` emits the [Deposit](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IZrxVault.sol#L34) event.
+3. Increase the sender's stake balance.
+4. Emit the [Stake](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L9) event.
+
+#### Errors by `stake`
+
+| Error | Condition |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
+| [StandardError("TRANSFER_FAILED")](https://github.com/0xProject/0x-monorepo/blob/development/contracts/asset-proxy/contracts/src/ERC20Proxy.sol#L162) | Failed to deposit tokens into the `ZrxVault`; likely the user had an insufficient ZRX balance. |
+
+#### Logic of `unstake`
+
+1. Compute amount of staked ZRX that can be unstaked: this is the `min` of the user's undelegated stake in the current and next epoch.
+2. Assert the amount to unstake is less or equal to the amount computed in (1).
+3. Decrease the user's stake in the current and next epoch.
+4. Transfer ZRX tokens from the `ZrxVault` to the user.
+5. The `ZrxVault` emits the [Withdraw](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IZrxVault.sol#L42) event.
+6. Emit the [Unstake](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L17) event.
+
+#### Errors by `unstake`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
+| [InsufficientBalanceError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L143) | Staked ZRX balance too low. |
+| [StandardError("TRANSFER_FAILED")](https://github.com/0xProject/0x-monorepo/blob/development/contracts/asset-proxy/contracts/src/ERC20Proxy.sol#L162) | Failed to withdraw tokens from the `ZrxVault` |
+
+### Staking Pools
+
+Staking pools can be created to leverage the weight of other stakers. A pool has a single operator and any number of members, who delegate their ZRX to the pool. Any staker can create a pool, although at present it is only beneficial for market makers to create staking pools. This is discussed more in [Section 6](#6-liquidity-incentives), along with details on creating a staking pool.
+
+| Term | Definition |
+| ------------- | ------------------------------------------------------------------------------------------ |
+| Pool Id | A unique id generated by this contract and assigned to a pool when it is created. |
+| Pool Operator | The creator and operator of the pool. |
+| Pool Members | Stakers who delegate their ZRX to the pool in exchange for a portion of liquidity rewards. |
+| Market Makers | Makers on the 0x protocol whose orders generate liquidity rewards for the pool. |
+
+It is presently intended for the pool operator to be sole the market maker of the pool. This is incentivized by making it more profitable for a maker to create their own pool over joining an existing one: the operator's stake is weighted greater than stake delegated by members when computing liquidity rewards.
+
+### Stake Status
+
+Each staked ZRX has an associated status that reflects its utility within the 0x Ecosystem.
+
+| Status | Definition |
+| ----------- | ------------------------------------------------------------------------------------------- |
+| Undelegated | Can be used to participate in governance. This is the default status. |
+| Delegated | ZRX is delegated to a pool; can be used in governance and contributes to liquidity rewards. |
+
+There is a single function for moving stake between statuses:
+
+```solidity
+/// @dev Statuses that stake can exist in.
+/// Any stake can be (re)delegated effective at the next epoch
+/// Undelegated stake can be withdrawn if it is available in both the current and next epoch
+enum StakeStatus {
+ UNDELEGATED,
+ DELEGATED
+}
+
+/// @dev Info used to describe a status.
+/// @param status of the stake.
+/// @param poolId Unique Id of pool. This is set when status=DELEGATED.
+struct StakeInfo {
+ StakeStatus status;
+ bytes32 poolId;
+}
+
+/// @dev Moves stake between statuses: 'undelegated' or 'delegated'.
+/// Delegated stake can also be moved between pools.
+/// This change comes into effect next epoch.
+/// @param from status to move stake out of.
+/// @param to status to move stake into.
+/// @param amount of stake to move.
+function moveStake(
+ IStructs.StakeInfo calldata from,
+ IStructs.StakeInfo calldata to,
+ uint256 amount
+)
+ external;
+```
+
+Note that when stake is moved its new status comes into effect on the _next epoch_. Stake's status remains unchanged over the duration of an epoch. See [section 11.4](#114-stake-management) for informaton on the implementation of stake accounting.
+
+#### Logic of `moveStake`
+
+1. No-op if amount to move is zero or moving both from and to the `undelegated` state.
+2. If moving from `delegated` state then `undelegate` the stake.
+ 1. Sanity check the pool we're undelegating from exists.
+ 1. Withdraw any rewards owed to the delegator by this pool (see [Section 6.2.3](#623-logic-of-withdrawDelegatorRewards)).
+ 1. Decrease how much stake the staker has delegated to the input pool.
+ 1. Decrease how much stake has been delegated to pool.
+ 1. Decrease balance of global delegated stake (aggregated across all stakers).
+3. If moving to `delegated` state then `delegate` the stake.
+ 1. Sanity check the pool we're delegating to exists.
+ 1. Withdraw any rewards owed to the delegator by this pool (see [Section 6.2.3](#623-logic-of-withdrawDelegatorRewards)).
+ 1. Increase how much stake the staker has delegated to the input pool.
+ 1. Increase how much stake has been delegated to pool.
+ 1. Increase balance of global delegated stake (aggregated across all stakers).
+4. Execute move.
+5. Emit the [MoveStake](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L25) event.
+
+#### Errors by `moveStake`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| [InsufficientBalanceError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L143) | Staked ZRX balance too low. |
+| [PoolExistenceError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L234) | Tried to un/delegate when pool does not exist. |
+| [PoolNotFinalizedError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L309) | The pool being un/delegated is not finalized: it is still owed rewards from the previous epoch. Fix this by calling `finalizePool`. |
+
+### Querying Stake
+
+The interface below describes how to query balances in the `Staking` contract.
+
+```solidity
+/// @dev Encapsulates a balance for the current and next epochs.
+/// Note that these balances may be stale if the current epoch
+/// is greater than `currentEpoch`.
+/// @param currentEpoch the current epoch
+/// @param currentEpochBalance balance in the current epoch.
+/// @param nextEpochBalance balance in `currentEpoch+1`.
+struct StoredBalance {
+ uint64 currentEpoch;
+ uint96 currentEpochBalance;
+ uint96 nextEpochBalance;
+}
+
+/// @dev Gets global stake for a given status.
+/// @param stakeStatus UNDELEGATED or DELEGATED
+/// @return Global stake for given status.
+function getGlobalStakeByStatus(IStructs.StakeStatus stakeStatus)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Gets an owner's stake balances by status.
+/// @param staker Owner of stake.
+/// @param stakeStatus UNDELEGATED or DELEGATED
+/// @return Owner's stake balances for given status.
+function getOwnerStakeByStatus(
+ address staker,
+ IStructs.StakeStatus stakeStatus
+)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Returns the total stake for a given staker.
+/// @param staker of stake.
+/// @return Total ZRX staked by `staker`.
+function getTotalStake(address staker)
+ public
+ view
+ returns (uint256);
+
+/// @dev Returns the stake delegated to a specific staking pool, by a given staker.
+/// @param staker of stake.
+/// @param poolId Unique Id of pool.
+/// @return Stake delegated to pool by staker.
+function getStakeDelegatedToPoolByOwner(address staker, bytes32 poolId)
+ public
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Returns the total stake delegated to a specific staking pool,
+/// across all members.
+/// @param poolId Unique Id of pool.
+/// @return Total stake delegated to pool.
+function getTotalStakeDelegatedToPool(bytes32 poolId)
+ public
+ view
+ returns (IStructs.StoredBalance memory balance);
+```
+
+## Liquidity Incentives
+
+Liquidity incentives are used to align market participants with long-term objectives of the 0x protocol. Fees are charged by the 0x protocol and paid to market makers as a reward for their trade volume and amount of ZRX staked.
+
+
+
+The protocol fee is paid in either WETH or ETH. If ETH is not included in the transaction (by setting `msg.value`) then the fee will be taken in WETH from the taker, as illustrated in the diagram above.
+
+Note also that the WETH allowances are set in the `StakingProxy` opposed to the standard ERC20 Asset Proxy, used by the exchange. There are two reasons for this. Firstly, this separation means that users must explicitly opt-in to fees (no hidden fees). Secondly, the `Staking` contract only needs access to WETH, whereas the ERC20 Proxy would provide access to _all_ tokens that a user has given allowance for; since the `Staking` contract is upgradable, this separation reduces the attack surface.
+
+### Market Making
+
+We want to align market makers with the long-term objectives of the 0x protocol; however, the immobility of staked ZRX exposes makers to potential short-term volatility in the crypto markets. This risk is mitigated through staking pools.
+
+A maker creates a pool, which can be delegated to by any other staker. When computing a maker's reward, we account for all the stake in their pool. We favor ZRX staked directly by the maker by assigning a lower weight (90%) to ZRX delegated by other stakers.
+
+Market makers incentivize delegators to join their pool by setting aside a fixed percentage of their reward for the members of their pool. A member receives an amount of this percentage that is proportional to how much stake they have delegated to the pool.
+
+
+
+The interface below describes how to create a pool, add market making addresses, and set the percentage of rewards for pool members.
+
+Note that a single staker can operate several pools, but a market making address can only belong to one pool.
+Note also that the operator's reward share can only be decreased: so the change can only ever benefit pool members.
+
+```solidity
+/// @dev Holds the metadata for a staking pool.
+/// @param operator of the pool.
+/// @param operatorShare Fraction of the total balance owned by the operator, in ppm.
+struct Pool {
+ address operator;
+ uint32 operatorShare;
+}
+
+//// @dev Create a new staking pool. The sender will be the operator of this pool.
+/// Note that an operator must be payable.
+/// @param operatorShare Portion of rewards owned by the operator, in ppm.
+/// @param addOperatorAsMaker Adds operator to the created pool as a maker for convenience iff true.
+/// @return poolId The unique pool id generated for this pool.
+function createStakingPool(uint32 operatorShare, bool addOperatorAsMaker)
+ external
+ returns (bytes32 poolId);
+
+/// @dev Decreases the operator share for the given pool (i.e. increases pool rewards for members).
+/// @param poolId Unique Id of pool.
+/// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator.
+function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare)
+ external
+ onlyStakingPoolOperator(poolId);
+
+/// @dev Allows caller to join a staking pool as a maker.
+/// @param poolId Unique id of pool.
+function joinStakingPoolAsMaker(bytes32 poolId)
+ public;
+
+/// @dev Returns a staking pool
+/// @param poolId Unique id of pool.
+function getStakingPool(bytes32 poolId)
+ public
+ view
+ returns (IStructs.Pool memory);
+```
+
+#### Logic of `createStakingPool`
+
+1. Generate unique Pool Id.
+2. Assert the operator's share of pool rewards is valid.
+3. Store the newly created pool's information in state. This includes the operator's address and their share of future liquidity rewards.
+4. Emit [StakingPoolCreated](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L108) event.
+5. If requested, add the operator as a market maker for the pool: fees generated by their orders will go to the pool. (See [Section 6.1.5](#615-logic-of-joinstakingpoolasmaker))
+
+#### Errors by `createStakingPool`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
+| [OperatorShareError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L217) | Operator's share is not a valid percentage (between [0..100]) |
+
+#### Logic of `decreaseStakingPoolOperatorShare`
+
+1. Assert sender is pool operator.
+2. Assert new operator share is valid: must be a valid percentage that's less or equal to current value.
+3. Set new operator share in state.
+4. Emit [OperatorShareDecreased](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L126).
+
+#### Errors by `decreaseStakingPoolOperatorShare`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
+| [OnlyCallableByPoolOperatorError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#158) | Sender must be pool operator. |
+| [OperatorShareError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L217) | Operator's share is not a valid percentage (between [0..100]) |
+
+#### Logic of `joinStakingPoolAsMaker`
+
+1. Set the staking pool for the maker (sender). Note that a market maker can only be associated with a single pool.
+2. Emit [MakerStakingPoolSet](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#117) Event.
+
+#### Errors by `joinStakingPoolAsMaker`
+
+No errors are triggered by this function.
+
+### Paying Liquidity Rewards (Finalization)
+
+The Cobb-Douglas function is used to compute how much of the aggregate fees should be rewarded to each market maker.
+
+
+
+| Term | Definition |
+| ---- | ---------------------------------------------------------------------------- |
+| _r_ | Reward for a specific market maker. |
+| _R_ | Total reward to be split between all market makers. |
+| _f_ | Total fees earned by the market maker this epoch. |
+| _F_ | Total fees earned across all (staked) market maker pools this epoch. |
+| _d_ | Total weighted ZRX staked by the market maker's pool this epoch. |
+| _D_ | Total weighted ZRX staked across all (active) market maker pools this epoch. |
+| _α_ | A constant in the range [0..1] that determines the weight of fees vs stake. |
+
+At the end of an epoch, each pool that traded can retrieve their liquidity reward. This is done by calling the finalize function. Dust pools (that have less than 100 ZRX staked) are not elegible for rewards.
+
+```solidity
+/// @dev Instantly finalizes a single pool that earned rewards in the previous
+/// epoch, crediting it rewards for members and withdrawing operator's
+/// rewards as WETH. This can be called by internal functions that need
+/// to finalize a pool immediately. Does nothing if the pool is already
+/// finalized or did not earn rewards in the previous epoch.
+/// @param poolId The pool ID to finalize.
+function finalizePool(bytes32 poolId)
+ external;
+```
+
+Each pool has until the end of the epoch to finalize their pool for the previous epoch. During finalization the market maker will be paid their % of the reward in WETH. Pool members are paid when they modify how much stake they've delegated to the pool (or undelegate). Alternatively, members can retrieve their reward in WETH by calling the withdraw function.
+
+```solidity
+/// @dev Withdraws the caller's WETH rewards that have accumulated
+/// until the last epoch.
+/// @param poolId Unique id of pool.
+function withdrawDelegatorRewards(bytes32 poolId) external;
+```
+
+Both operators and delegators can compute their unpaid balance in a pool using the functions below.
+
+```solidity
+/// @dev Computes the reward balance in ETH of the operator of a pool.
+/// @param poolId Unique id of pool.
+/// @return totalReward Balance in ETH.
+function computeRewardBalanceOfOperator(bytes32 poolId)
+ external
+ view
+ returns (uint256 reward);
+
+/// @dev Computes the reward balance in ETH of a specific member of a pool.
+/// @param poolId Unique id of pool.
+/// @param member The member of the pool.
+/// @return totalReward Balance in ETH.
+function computeRewardBalanceOfDelegator(bytes32 poolId, address member)
+ external
+ view
+ returns (uint256 reward);
+```
+
+#### Logic of `finalizePool`
+
+Finalizing pays any unsettled liquidity rewards from the previous epoch to the pool.
+
+1. Load the aggregated stats for the previous epoch.
+2. If the epoch is finalized then return (NOP).
+3. Load the pool's stats for the previous epoch.
+4. If the pool is already finalized then return (NOP).
+5. Delete the pool's stats from state.
+6. Use in-memory aggregated/pool stats to compute the unsettled rewards owed to the pool.
+7. Of the unsettled rewards, compute how much is owed to the operator and collectively how much to the pool members.
+8. Pay reward in WETH to the operator.
+9. Store the reward held collectively by the pool members in state. This is used later for each member to compute their individual portion.
+10. Emit [RewardsPaid](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L83) Event.
+11. Update aggregated stats in state to reflect that this pool's rewards have been settled.
+12. If all pool's are settled then the previous epoch is finalized. Emit the [EpochFinalized](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L72) Event.
+
+#### Precision of Rewards Computation
+
+The [solidity](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibCobbDouglas.sol) implementation of the Cobb-Douglas function ultimately relies on [Taylor series approximations](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibFixedMath.sol) using fixed-point, signed-integer math. These approximations have an expected minimum precision of `12` digits.
+
+This can result in very small errors in reward computation, in either direction. In order to guard against the sum of total rewards exceeding the total rewards available, the computed reward for a pool is always [clipped](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/sys/MixinFinalizer.sol#L247) to the total (unfinalized) rewards remaining.
+
+#### Errors by `finalizePool`
+
+The errors in finalize pool are all math errors related to reward computation. If any of these are triggered then it indicates= an internal logic error.
+
+| Error | Condition |
+| --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
+| [SignedValueError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol#51) | An error in signed computation. |
+| [UnsignedValueError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol#L66) | An error in unsigned computation. |
+| [BinOpError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol#L81) | An overflow or underflow error when performing unsigned arithmetic. |
+
+#### Logic of `withdrawDelegatorRewards`
+
+1. Assert the pool's rewards have been settled in the current epoch via `finalizePool`.
+2. Compute the portion of the pool's reward owed to the delegator.
+3. If the amount owed is non-zero then transfer it in WETH to the delegator.
+4. Update reward tracking metrics to reflect that a delegator interacted with the pool. See [Section 10.3](#103-tracking-for-reward-balances-for-pool-members) for more information on reward tracking.
+
+#### Errors by `withdrawDelegatorRewards`
+
+| Error | Condition |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
+| [PoolNotFinalizedError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L309) | The pool is not finalized: it is still owed rewards from the previous epoch. Fix this by calling `finalizePool`. |
+| [BinOpError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol#L81) | An overflow or underflow error when performing unsigned arithmetic. |
+
+## Batch Calls
+
+The staking contract supports arbitrary batch function calls to the staking logic contract, allowing for several operations in a single transaction. For example, finalizing several pools in one transaction.
+
+
+
+```solidity
+/// @dev Batch executes a series of calls to the staking contract.
+/// @param data An array of data that encodes a sequence of functions to
+/// call in the staking contracts.
+function batchExecute(bytes[] calldata data)
+ external
+ returns (bytes[] memory batchReturnData);
+```
+
+#### Logic of `batchExecute`
+
+1. Assert there is a `Staking` contract connected to the proxy.
+2. Execute each call to the `Staking` contract, constructing an array of return data.
+3. Revert if a single call fails.
+
+#### Errors by `batchExecute`
+
+| Error | Condition |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
+| [ProxyDestinationCannotBeNilError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L286) | The `StakingProxy` has not been correctly configured. |
+
+Note: any error generated in the Staking Logic contract will be propagated back to the client.
+
+## Paying the Protocol Fee
+
+Protocol fees are paid to the Staking contract by the Exchange contract. The Staking logic is unopinionated about the amount paid: it is the responsibility of the exchange to compute this value. The fee can be paid in either ETH or WETH and are paid out as rewards to staking pools during finalization.
+
+```solidity
+/// @dev Pays a protocol fee in ETH or WETH.
+/// Only a known 0x exchange can call this method. See
+/// (MixinExchangeManager).
+/// @param makerAddress The address of the order's maker.
+/// @param payerAddress The address of the protocol fee payer.
+/// @param protocolFeeAmount The protocol fee amount. This is either passed as ETH or transferred as WETH.
+function payProtocolFee(
+ address makerAddress,
+ address payerAddress,
+ uint256 protocolFeeAmount
+)
+ external
+ payable
+ onlyExchange;
+```
+
+#### Logic of `payProtocolFee`
+
+1. Assert that either (i) the value passed into the Staking contract matches the fee, or (ii) the amount passed in is zero.
+2. If the amount of ETH passed in is zero, then transfer the fee as WETH. Note that users must have WETH allowance set on the `StakingProxy` to facilitate this transfer.
+3. Lookup the staking pool the maker has associated with. If no pool, then return.
+4. Check if the pool holds the minimum required stake (see [Section 3.6](#36-setting-params)).
+5. If this is the first fee earned by the pool in this epoch, then:
+ i. Record that they earned fees this epoch (and hence must be paid rewards in the next epoch, via finalization).
+ ii. Emit the [StakingPoolEarnedRewardsInEpoch](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol#L49) Event.
+6. Record the fee and attribute it to the pool.
+
+#### Errors by `payProtocolFee`
+
+| Error | Condition |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
+| [InvalidProtocolFeePaymentError](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol#L249) | The protocol fee paid by the Exchange as ETH was non-zero and did not match the expected protocol fee amount. |
+| [StandardError("")](https://github.com/0xProject/0x-monorepo/blob/development/contracts/erc20/contracts/src/WETH9.sol#L65) | The payer had an insufficient WETH balance. |
+
+## Interfaces
+
+### Staking Logic Contract
+
+This interface is defined in [IStaking](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStaking.sol).
+
+```solidity
+/// @dev Adds a new exchange address
+/// @param addr Address of exchange contract to add
+function addExchangeAddress(address addr)
+ external;
+
+/// @dev Computes the reward balance in ETH of a specific member of a pool.
+/// @param poolId Unique id of pool.
+/// @param member The member of the pool.
+/// @return totalReward Balance in ETH.
+function computeRewardBalanceOfDelegator(bytes32 poolId, address member)
+ external
+ view
+ returns (uint256 reward);
+
+/// @dev Computes the reward balance in ETH of the operator of a pool.
+/// @param poolId Unique id of pool.
+/// @return totalReward Balance in ETH.
+function computeRewardBalanceOfOperator(bytes32 poolId)
+ external
+ view
+ returns (uint256 reward);
+
+/// @dev Create a new staking pool. The sender will be the operator of this pool.
+/// Note that an operator must be payable.
+/// @param operatorShare Portion of rewards owned by the operator, in ppm.
+/// @param addOperatorAsMaker Adds operator to the created pool as a maker for convenience iff true.
+/// @return poolId The unique pool id generated for this pool.
+function createStakingPool(uint32 operatorShare, bool addOperatorAsMaker)
+ external
+ returns (bytes32 poolId);
+
+function currentEpochStartTimeInSeconds()
+ external
+ view
+ returns (uint256);
+
+/// @dev Decreases the operator share for the given pool (i.e. increases pool rewards for members).
+/// @param poolId Unique Id of pool.
+/// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator.
+function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare)
+ external;
+
+/// @dev Begins a new epoch, preparing the prior one for finalization.
+/// Throws if not enough time has passed between epochs or if the
+/// previous epoch was not fully finalized.
+/// @return numPoolsToFinalize The number of unfinalized pools.
+function endEpoch()
+ external
+ returns (uint256);
+
+/// @dev Instantly finalizes a single pool that earned rewards in the previous
+/// epoch, crediting it rewards for members and withdrawing operator's
+/// rewards as WETH. This can be called by internal functions that need
+/// to finalize a pool immediately. Does nothing if the pool is already
+/// finalized or did not earn rewards in the previous epoch.
+/// @param poolId The pool ID to finalize.
+function finalizePool(bytes32 poolId)
+ external;
+
+/// @dev Returns the earliest end time in seconds of this epoch.
+/// The next epoch can begin once this time is reached.
+/// Epoch period = [startTimeInSeconds..endTimeInSeconds)
+/// @return Time in seconds.
+function getCurrentEpochEarliestEndTimeInSeconds()
+ external
+ view
+ returns (uint256);
+
+/// @dev Gets global stake for a given status.
+/// @param stakeStatus UNDELEGATED or DELEGATED
+/// @return Global stake for given status.
+function getGlobalStakeByStatus(IStructs.StakeStatus stakeStatus)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Gets an owner's stake balances by status.
+/// @param staker Owner of stake.
+/// @param stakeStatus UNDELEGATED or DELEGATED
+/// @return Owner's stake balances for given status.
+function getOwnerStakeByStatus(
+ address staker,
+ IStructs.StakeStatus stakeStatus
+)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Retrieves all configurable parameter values.
+/// @return _epochDurationInSeconds Minimum seconds between epochs.
+/// @return _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
+/// @return _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
+/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
+/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
+function getParams()
+ external
+ view
+ returns (
+ uint256 _epochDurationInSeconds,
+ uint32 _rewardDelegatedStakeWeight,
+ uint256 _minimumPoolStake,
+ uint32 _cobbDouglasAlphaNumerator,
+ uint32 _cobbDouglasAlphaDenominator
+ );
+
+/// @param staker of stake.
+/// @param poolId Unique Id of pool.
+/// @return Stake delegated to pool by staker.
+function getStakeDelegatedToPoolByOwner(address staker, bytes32 poolId)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev Returns a staking pool
+/// @param poolId Unique id of pool.
+function getStakingPool(bytes32 poolId)
+ external
+ view
+ returns (IStructs.Pool memory);
+
+/// @dev Get stats on a staking pool in this epoch.
+/// @param poolId Pool Id to query.
+/// @return PoolStats struct for pool id.
+function getStakingPoolStatsThisEpoch(bytes32 poolId)
+ external
+ view
+ returns (IStructs.PoolStats memory);
+
+/// @dev Returns the total stake delegated to a specific staking pool,
+/// across all members.
+/// @param poolId Unique Id of pool.
+/// @return Total stake delegated to pool.
+function getTotalStakeDelegatedToPool(bytes32 poolId)
+ external
+ view
+ returns (IStructs.StoredBalance memory balance);
+
+/// @dev An overridable way to access the deployed WETH contract.
+/// Must be view to allow overrides to access state.
+/// @return wethContract The WETH contract instance.
+function getWethContract()
+ external
+ view
+ returns (IEtherToken wethContract);
+
+/// @dev An overridable way to access the deployed zrxVault.
+/// Must be view to allow overrides to access state.
+/// @return zrxVault The zrxVault contract.
+function getZrxVault()
+ external
+ view
+ returns (IZrxVault zrxVault);
+
+/// @dev Initialize storage owned by this contract.
+/// This function should not be called directly.
+/// The StakingProxy contract will call it in `attachStakingContract()`.
+function init()
+ external;
+
+/// @dev Allows caller to join a staking pool as a maker.
+/// @param poolId Unique id of pool.
+function joinStakingPoolAsMaker(bytes32 poolId)
+ external;
+
+/// @dev Moves stake between statuses: 'undelegated' or 'delegated'.
+/// Delegated stake can also be moved between pools.
+/// This change comes into effect next epoch.
+/// @param from status to move stake out of.
+/// @param to status to move stake into.
+/// @param amount of stake to move.
+function moveStake(
+ IStructs.StakeInfo calldata from,
+ IStructs.StakeInfo calldata to,
+ uint256 amount
+)
+ external;
+
+/// @dev Pays a protocol fee in ETH.
+/// @param makerAddress The address of the order's maker.
+/// @param payerAddress The address that is responsible for paying the protocol fee.
+/// @param protocolFeeAmount The amount of protocol fees that should be paid.
+function payProtocolFee(
+ address makerAddress,
+ address payerAddress,
+ uint256 protocolFeeAmount
+)
+ external
+ payable;
+
+/// @dev Removes an existing exchange address
+/// @param addr Address of exchange contract to remove
+function removeExchangeAddress(address addr)
+ external;
+
+/// @dev Set all configurable parameters at once.
+/// @param _epochDurationInSeconds Minimum seconds between epochs.
+/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
+/// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
+/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
+/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
+function setParams(
+ uint256 _epochDurationInSeconds,
+ uint32 _rewardDelegatedStakeWeight,
+ uint256 _minimumPoolStake,
+ uint32 _cobbDouglasAlphaNumerator,
+ uint32 _cobbDouglasAlphaDenominator
+)
+ external;
+
+/// @dev Stake ZRX tokens. Tokens are deposited into the `ZrxVault`.
+/// Unstake to retrieve the ZRX. Stake is in the 'Active' status.
+/// @param amount of ZRX to stake.
+function stake(uint256 amount)
+ external;
+
+/// @dev Unstake. Tokens are withdrawn from the `ZrxVault` and returned to
+/// the staker. Stake must be in the 'undelegated' status in both the
+/// current and next epoch in order to be unstaked.
+/// @param amount of ZRX to unstake.
+function unstake(uint256 amount)
+ external;
+
+/// @dev Withdraws the caller's WETH rewards that have accumulated
+/// until the last epoch.
+/// @param poolId Unique id of pool.
+function withdrawDelegatorRewards(bytes32 poolId)
+ external;
+```
+
+### `Staking` contract State
+
+This interface is defined in [IStorage](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStorage.sol).
+
+```solidity
+function stakingContract()
+ external
+ view
+ returns (address);
+
+function lastPoolId()
+ external
+ view
+ returns (bytes32);
+
+function numMakersByPoolId(bytes32 poolId)
+ external
+ view
+ returns (uint256);
+
+function currentEpoch()
+ external
+ view
+ returns (uint256);
+
+function currentEpochStartTimeInSeconds()
+ external
+ view
+ returns (uint256);
+
+function protocolFeesThisEpochByPool(bytes32 poolId)
+ external
+ view
+ returns (uint256);
+
+function validExchanges(address exchangeAddress)
+ external
+ view
+ returns (bool);
+
+function epochDurationInSeconds()
+ external
+ view
+ returns (uint256);
+
+function rewardDelegatedStakeWeight()
+ external
+ view
+ returns(uint32);
+
+function minimumPoolStake()
+ external
+ view
+ returns (uint256);
+
+function cobbDouglasAlphaNumerator()
+ external
+ view
+ returns (uint32);
+
+function cobbDouglasAlphaDenominator()
+ external
+ view
+ returns (uint32);
+```
+
+### `StakingProxy` Contract
+
+This interface is defined in [IStakingProxy](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingProxy.sol).
+
+```solidity
+/// @dev Attach a staking contract; future calls will be delegated to the staking contract.
+/// Note that this is callable only by an authorized address.
+/// @param _stakingContract Address of staking contract.
+function attachStakingContract(address _stakingContract)
+ external;
+
+/// @dev Detach the current staking contract.
+/// Note that this is callable only by an authorized address.
+function detachStakingContract()
+ external;
+
+/// @dev Asserts that an epoch is between 5 and 30 days long.
+// Asserts that 0 < cobb douglas alpha value <= 1.
+// Asserts that a stake weight is <= 100%.
+// Asserts that pools allow >= 1 maker.
+// Asserts that all addresses are initialized.
+function assertValidStorageParams()
+ external
+ view;
+```
+
+### `ZrxVault`
+
+This interface is defined in [IZrxVault](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IZrxVault.sol).
+
+```solidity
+/// @dev Sets the address of the StakingProxy contract.
+/// Note that only the contract staker can call this function.
+/// @param _stakingProxyAddress Address of Staking proxy contract.
+function setStakingProxy(address _stakingProxyAddress)
+ external;
+
+/// @dev Vault enters into Catastrophic Failure Mode.
+/// *** WARNING - ONCE IN CATOSTROPHIC FAILURE MODE, YOU CAN NEVER GO BACK! ***
+/// Note that only the contract staker can call this function.
+function enterCatastrophicFailure()
+ external;
+
+/// @dev Sets the Zrx proxy.
+/// Note that only the contract staker can call this.
+/// Note that this can only be called when *not* in Catastrophic Failure mode.
+/// @param zrxProxyAddress Address of the 0x Zrx Proxy.
+function setZrxProxy(address zrxProxyAddress)
+ external;
+
+/// @dev Deposit an `amount` of Zrx Tokens from `staker` into the vault.
+/// Note that only the Staking contract can call this.
+/// Note that this can only be called when *not* in Catastrophic Failure mode.
+/// @param staker of Zrx Tokens.
+/// @param amount of Zrx Tokens to deposit.
+function depositFrom(address staker, uint256 amount)
+ external;
+
+/// @dev Withdraw an `amount` of Zrx Tokens to `staker` from the vault.
+/// Note that only the Staking contract can call this.
+/// Note that this can only be called when *not* in Catastrophic Failure mode.
+/// @param staker of Zrx Tokens.
+/// @param amount of Zrx Tokens to withdraw.
+function withdrawFrom(address staker, uint256 amount)
+ external;
+
+/// @dev Withdraw ALL Zrx Tokens to `staker` from the vault.
+/// Note that this can only be called when *in* Catastrophic Failure mode.
+/// @param staker of Zrx Tokens.
+function withdrawAllFrom(address staker)
+ external
+ returns (uint256);
+
+/// @dev Returns the balance in Zrx Tokens of the `staker`
+/// @return Balance in Zrx.
+function balanceOf(address staker)
+ external
+ view
+ returns (uint256);
+
+/// @dev Returns the entire balance of Zrx tokens in the vault.
+function balanceOfZrxVault()
+ external
+ view
+ returns (uint256);
+```
+
+### Structs
+
+This interface is defined in [IStructs](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStructs.sol).
+
+```solidity
+/// @dev Stats for a pool that earned rewards.
+/// @param feesCollected Fees collected in ETH by this pool.
+/// @param weightedStake Amount of weighted stake in the pool.
+/// @param membersStake Amount of non-operator stake in the pool.
+struct PoolStats {
+ uint256 feesCollected;
+ uint256 weightedStake;
+ uint256 membersStake;
+}
+
+/// @dev Holds stats aggregated across a set of pools.
+/// @param rewardsAvailable Rewards (ETH) available to the epoch
+/// being finalized (the previous epoch). This is simply the balance
+/// of the contract at the end of the epoch.
+/// @param numPoolsToFinalize The number of pools that have yet to be finalized through `finalizePools()`.
+/// @param totalFeesCollected The total fees collected for the epoch being finalized.
+/// @param totalWeightedStake The total fees collected for the epoch being finalized.
+/// @param totalRewardsFinalized Amount of rewards that have been paid during finalization.
+struct AggregatedStats {
+ uint256 rewardsAvailable;
+ uint256 numPoolsToFinalize;
+ uint256 totalFeesCollected;
+ uint256 totalWeightedStake;
+ uint256 totalRewardsFinalized;
+}
+
+/// @dev Encapsulates a balance for the current and next epochs.
+/// Note that these balances may be stale if the current epoch
+/// is greater than `currentEpoch`.
+/// @param currentEpoch the current epoch
+/// @param currentEpochBalance balance in the current epoch.
+/// @param nextEpochBalance balance in `currentEpoch+1`.
+struct StoredBalance {
+ uint64 currentEpoch;
+ uint96 currentEpochBalance;
+ uint96 nextEpochBalance;
+}
+
+/// @dev Statuses that stake can exist in.
+/// Any stake can be (re)delegated effective at the next epoch
+/// Undelegated stake can be withdrawn if it is available in both the current and next epoch
+enum StakeStatus {
+ UNDELEGATED,
+ DELEGATED
+}
+
+/// @dev Info used to describe a status.
+/// @param status of the stake.
+/// @param poolId Unique Id of pool. This is set when status=DELEGATED.
+struct StakeInfo {
+ StakeStatus status;
+ bytes32 poolId;
+}
+
+/// @dev Struct to represent a fraction.
+/// @param numerator of fraction.
+/// @param denominator of fraction.
+struct Fraction {
+ uint256 numerator;
+ uint256 denominator;
+}
+
+/// @dev Holds the metadata for a staking pool.
+/// @param operator of the pool.
+/// @param operatorShare Fraction of the total balance owned by the operator, in ppm.
+struct Pool {
+ address operator;
+ uint32 operatorShare;
+}
+```
+
+## Events
+
+### Staking Logic Contract
+
+These events are defined in [IStakingEvents](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingEvents.sol).
+
+```solidity
+/// @dev Emitted by MixinStake when ZRX is staked.
+/// @param staker of ZRX.
+/// @param amount of ZRX staked.
+event Stake(
+ address indexed staker,
+ uint256 amount
+);
+
+/// @dev Emitted by MixinStake when ZRX is unstaked.
+/// @param staker of ZRX.
+/// @param amount of ZRX unstaked.
+event Unstake(
+ address indexed staker,
+ uint256 amount
+);
+
+/// @dev Emitted by MixinStake when ZRX is unstaked.
+/// @param staker of ZRX.
+/// @param amount of ZRX unstaked.
+event MoveStake(
+ address indexed staker,
+ uint256 amount,
+ uint8 fromStatus,
+ bytes32 indexed fromPool,
+ uint8 toStatus,
+ bytes32 indexed toPool
+);
+
+/// @dev Emitted by MixinExchangeManager when an exchange is added.
+/// @param exchangeAddress Address of new exchange.
+event ExchangeAdded(
+ address exchangeAddress
+);
+
+/// @dev Emitted by MixinExchangeManager when an exchange is removed.
+/// @param exchangeAddress Address of removed exchange.
+event ExchangeRemoved(
+ address exchangeAddress
+);
+
+/// @dev Emitted by MixinExchangeFees when a pool starts earning rewards in an epoch.
+/// @param epoch The epoch in which the pool earned rewards.
+/// @param poolId The ID of the pool.
+event StakingPoolEarnedRewardsInEpoch(
+ uint256 indexed epoch,
+ bytes32 indexed poolId
+);
+
+/// @dev Emitted by MixinFinalizer when an epoch has ended.
+/// @param epoch The epoch that ended.
+/// @param numPoolsToFinalize Number of pools that earned rewards during `epoch` and must be finalized.
+/// @param rewardsAvailable Rewards available to all pools that earned rewards during `epoch`.
+/// @param totalWeightedStake Total weighted stake across all pools that earned rewards during `epoch`.
+/// @param totalFeesCollected Total fees collected across all pools that earned rewards during `epoch`.
+event EpochEnded(
+ uint256 indexed epoch,
+ uint256 numPoolsToFinalize,
+ uint256 rewardsAvailable,
+ uint256 totalFeesCollected,
+ uint256 totalWeightedStake
+);
+
+/// @dev Emitted by MixinFinalizer when an epoch is fully finalized.
+/// @param epoch The epoch being finalized.
+/// @param rewardsPaid Total amount of rewards paid out.
+/// @param rewardsRemaining Rewards left over.
+event EpochFinalized(
+ uint256 indexed epoch,
+ uint256 rewardsPaid,
+ uint256 rewardsRemaining
+);
+
+/// @dev Emitted by MixinFinalizer when rewards are paid out to a pool.
+/// @param epoch The epoch when the rewards were paid out.
+/// @param poolId The pool's ID.
+/// @param operatorReward Amount of reward paid to pool operator.
+/// @param membersReward Amount of reward paid to pool members.
+event RewardsPaid(
+ uint256 indexed epoch,
+ bytes32 indexed poolId,
+ uint256 operatorReward,
+ uint256 membersReward
+);
+
+/// @dev Emitted whenever staking parameters are changed via the `setParams()` function.
+/// @param epochDurationInSeconds Minimum seconds between epochs.
+/// @param rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
+/// @param minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
+/// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
+/// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
+event ParamsSet(
+ uint256 epochDurationInSeconds,
+ uint32 rewardDelegatedStakeWeight,
+ uint256 minimumPoolStake,
+ uint256 cobbDouglasAlphaNumerator,
+ uint256 cobbDouglasAlphaDenominator
+);
+
+/// @dev Emitted by MixinStakingPool when a new pool is created.
+/// @param poolId Unique id generated for pool.
+/// @param operator The operator (creator) of pool.
+/// @param operatorShare The share of rewards given to the operator, in ppm.
+event StakingPoolCreated(
+ bytes32 poolId,
+ address operator,
+ uint32 operatorShare
+);
+
+/// @dev Emitted by MixinStakingPool when a maker sets their pool.
+/// @param makerAddress Adress of maker added to pool.
+/// @param poolId Unique id of pool.
+event MakerStakingPoolSet(
+ address indexed makerAddress,
+ bytes32 indexed poolId
+);
+
+/// @dev Emitted when a staking pool's operator share is decreased.
+/// @param poolId Unique Id of pool.
+/// @param oldOperatorShare Previous share of rewards owned by operator.
+/// @param newOperatorShare Newly decreased share of rewards owned by operator.
+event OperatorShareDecreased(
+ bytes32 indexed poolId,
+ uint32 oldOperatorShare,
+ uint32 newOperatorShare
+);
+```
+
+### `StakingProxy` Contract
+
+These events are defined in [IStakingProxy](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStakingProxy.sol).
+
+```solidity
+/// @dev Emitted by StakingProxy when a staking contract is attached.
+/// @param newStakingContractAddress Address of newly attached staking contract.
+event StakingContractAttachedToProxy(
+ address newStakingContractAddress
+);
+
+/// @dev Emitted by StakingProxy when a staking contract is detached.
+event StakingContractDetachedFromProxy();
+```
+
+### `ZrxVault`
+
+These events are defined in [IZrxVault](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IZrxVault.sol).
+
+```solidity
+/// @dev Emmitted whenever a StakingProxy is set in a vault.
+event StakingProxySet(address stakingProxyAddress);
+
+/// @dev Emitted when the Staking contract is put into Catastrophic Failure Mode
+/// @param sender Address of sender (`msg.sender`)
+event InCatastrophicFailureMode(address sender);
+
+/// @dev Emitted when Zrx Tokens are deposited into the vault.
+/// @param staker of Zrx Tokens.
+/// @param amount of Zrx Tokens deposited.
+event Deposit(
+ address indexed staker,
+ uint256 amount
+);
+
+/// @dev Emitted when Zrx Tokens are withdrawn from the vault.
+/// @param staker of Zrx Tokens.
+/// @param amount of Zrx Tokens withdrawn.
+event Withdraw(
+ address indexed staker,
+ uint256 amount
+);
+
+/// @dev Emitted whenever the ZRX AssetProxy is set.
+event ZrxProxySet(address zrxProxyAddress);
+```
+
+## Algorithms, Data Structures & Design Patterns
+
+This section dives deeper into the mechanics of the smart contracts.
+
+### Securing the Proxy Pattern
+
+The proxy pattern splits the state and logic into different contracts, allowing the logic contract to be upgraded. This is achieved using a `delegatecall` from the state contract into the logic contract.
+
+One of the dangers in this pattern is that the storage slot or offset could change in a future version of Solidity. This could happen for any number of reasons; the most likely of which is that the order of state variables changes between two versions of the logic contract. An error like this would certainly be catastrophic, as the state variables in the logic contract would point to _different_ variables in the state contract.
+
+One way to mitigate this danger is to store the state variables in a single immutable contract, which is inherited by both the state and logic contract. This will work, but it does not future-proof against external changes that may result from changes to Solidity or the EVM.
+
+The best way we found to mitigate this danger is with runtime sanity checks. We hardcode the expected slot and offset of each state variable and assert the value every time the logic contract is updated. This is handled in the `Staking` contract constructor [here](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/Staking.sol).
+
+### Tracking for Reward Balances for Pool Members
+
+This section describes the workflow for tracking and computing the portion of a pool's reward that belongs to a given member. The general equations for this are shown below.
+
+A pool with _D_ delegated stake that earned _R_ rewards for its pool members in a given epoch, the reward (_r_) for a member that delegated _d_ stake is computed by:
+
+
+
+The member's reward after n epochs (given member does not change their stake) is then given by:
+
+
+
+When a member modifies their stake in the pool, the [StoredBalance struct](https://github.com/0xProject/0x-monorepo/blob/development/contracts/staking/contracts/src/interfaces/IStructs.sol) gives us:
+
+1. How many epochs since they last modified their stake (`n`)
+2. How much stake they had contributed during those epochs (`d`)
+
+In addition to these values, we also need sum of ratios `R_k / D_k`, for each epoch `k` that the member was delegated. This ratio is available during the pool's finalization of epoch `k`. We are able to store this information concisely using a cumulative sum of these reward ratios, as follows:
+
+We store the following ratio for each epoch that a reward is earned for the pool:
+
+
+
+We compute a member's reward using the following equation:
+
+
+
+Example:
+
+
+
+With the cumulative reward along with the stored balance of a member, we are able to compute their reward in the pool at any time.
+
+This information is stored on-chain as follows:
+
+```solidity
+// mapping from Owner to Pool Id to Amount Delegated
+mapping (address => mapping (bytes32 => StoredBalance)) internal _delegatedStakeToPoolByOwner;
+
+// mapping from Pool Id to Amount Delegated
+mapping (bytes32 => StoredBalance) internal _delegatedStakeByPoolId;
+
+// mapping from Pool Id to Epoch to Reward Ratio
+mapping (bytes32 => mapping (uint256 => Fraction)) internal _cumulativeRewardsByPool;
+```
+
+#### Computing Rewards in Practice
+
+In the equations above, a staker earned rewards from epochs `[0..n]`. This means that the staker modified between epochs `n` and stopped earning rewards in epoch `n+1`. So at the time of the call, we don't have access to the reward for epoch `n`.
+
+In practice, this equation becomes:
+
+
+
+The final equation for computing a member's reward during epoch `n` becomes:
+
+
+
+#### Handling Epochs With No Rewards
+
+To compute a member's reward using this algorithm, we need to know the cumulative rewards at the entry and exit epoch of the member. But, what happens if no reward was recorded during one of these epochs?
+
+In this case, there will be `nil` entry in `cumulativeRewardsByPool`. However, this isn't a problem. If a reward is earned in epoch _n_ but not epoch _n + 1_ then the cumulative rewards will not have changed. So in epoch _n + 1_ we can simply use the entry for epoch _n_.
+
+We keep track of the last epoch that the `cumulativeRewardsByPool` was updated in using the following state variable:
+
+```solidity
+// mapping from Pool Id to Epoch
+mapping (bytes32 => uint256) internal cumulativeRewardsByPoolLastStored;
+```
+
+### Stake Management
+
+Below are the design objectives of stake management:
+
+1. Depositing ZRX mints stake that is is undelegated by default.
+2. Withdrawing ZRX is done by unstaking; any undelegated stake can be unstaked.
+3. Delegating, un-delegating and re-delegating stake comes into effect next epoch.
+4. Users can freely adjust the distribution of their stake for the next epoch.
+
+There are two statuses that stake can exist in: Undelegated or Delegated. Each has three fields:
+
+1. How much stake is currently in this state (`currentEpochBalance` in the code; `cur` in the diagram below)
+2. How much stake is in this state next epoch (`nextEpochBalance` in the code; `next` in the diagram below)
+3. The last time this state was stored (`currentEpoch` in the code)
+
+These fields combined allow us to compute the correct values at any given epoch without user intervention.
+
+The amount that can be unstaked is equal to `min(undelegated.cur, undelegated.next)`.
+
+The figure below illustrates how these fields are updated to track a user's stake.
+
+
\ No newline at end of file
diff --git a/docs/tokenomics/staking.rst b/docs/tokenomics/staking.rst
deleted file mode 100644
index a401b33ba9..0000000000
--- a/docs/tokenomics/staking.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Staking
-###############################
\ No newline at end of file
diff --git a/docs/tokenomics/staking_reward_formula.rst b/docs/tokenomics/staking_reward_formula.rst
new file mode 100644
index 0000000000..4d8bebcef3
--- /dev/null
+++ b/docs/tokenomics/staking_reward_formula.rst
@@ -0,0 +1,9 @@
+###############################
+Staking Reward Formula
+###############################
+
+.. raw:: html
+
+
\ No newline at end of file
diff --git a/docs/tokenomics/voting.rst b/docs/tokenomics/voting.rst
deleted file mode 100644
index a3c24b2ba6..0000000000
--- a/docs/tokenomics/voting.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-###############################
-Voting
-###############################
\ No newline at end of file
diff --git a/docs/usage.rst b/docs/usage.rst
deleted file mode 100644
index fb9b1ec7e9..0000000000
--- a/docs/usage.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-========
-Usage
-========
-
-To use this template, simply update it::
-
- import read-the-docs-template