Compare commits

...

916 Commits

Author SHA1 Message Date
Fabio Berger
490aafba4e Publish
- 0x.js@6.0.7
 - @0x/abi-gen@2.0.10
 - @0x/abi-gen-templates@2.1.0
 - @0x/abi-gen-wrappers@4.3.0
 - @0x/assert@2.0.10
 - @0x/asset-buyer@6.1.1
 - @0x/base-contract@5.1.0
 - @0x/connect@5.0.6
 - @0x/contract-artifacts@1.5.1
 - @0x/contract-wrappers@9.1.0
 - @0x/contracts-gen@1.0.9
 - @0x/dev-tools-pages@0.0.26
 - @0x/dev-utils@2.2.2
 - @0x/fill-scenarios@3.0.6
 - @0x/instant@1.0.21
 - @0x/json-schemas@3.0.10
 - @0x/metacoin@0.0.48
 - @0x/migrations@4.1.2
 - @0x/monorepo-scripts@1.0.31
 - @0x/order-utils@8.0.0
 - @0x/order-watcher@4.0.7
 - @0x/pipeline@1.0.18
 - @0x/react-docs@2.0.11
 - @0x/react-shared@2.0.11
 - @0x/sol-compiler@3.1.7
 - @0x/sol-coverage@3.0.4
 - @0x/sol-doc@2.0.11
 - @0x/sol-profiler@3.1.6
 - @0x/sol-trace@2.0.12
 - @0x/sol-tracing-utils@6.0.11
 - @0x/sra-spec@2.0.10
 - @0x/subproviders@4.0.6
 - @0x/testnet-faucets@1.0.77
 - @0x/utils@4.3.3
 - @0x/web3-wrapper@6.0.6
 - @0x/website@0.0.80
 - @0x/contracts-asset-proxy@2.1.2
 - @0x/contracts-coordinator@2.0.1
 - @0x/contracts-erc1155@1.1.2
 - @0x/contracts-erc20@2.2.1
 - @0x/contracts-erc721@2.1.2
 - @0x/contracts-exchange@2.1.2
 - @0x/contracts-exchange-forwarder@3.0.0
 - @0x/contracts-exchange-libs@2.1.2
 - @0x/contracts-extensions@3.1.2
 - @0x/contracts-multisig@3.1.2
 - @0x/contracts-test-utils@3.1.3
 - @0x/contracts-utils@3.1.2
2019-05-10 14:12:32 -03:00
Fabio Berger
3cd31d49bb Updated CHANGELOGS 2019-05-10 14:12:19 -03:00
Fabio Berger
6dd78b8d35 Update exchange forwarder package version 2019-05-10 13:46:30 -03:00
Jacob Evans
bd51c34098 Merge pull request #1809 from 0xProject/order-watcher-weth-events
OrderWatcher Deposit/Withdraw events
2019-05-10 18:32:31 +02:00
Jacob Evans
0e758fadee Merge changelog entries 2019-05-10 17:53:09 +02:00
Jacob Evans
a67659ff8e Update changelog 2019-05-10 16:37:09 +02:00
Jacob Evans
d1203f90da Revert "Mutate ERC20 ABI to handle WETH Deposit and Withdrawl"
This reverts commit c5f6ebee18.
2019-05-10 16:32:17 +02:00
Jacob Evans
c5f6ebee18 Mutate ERC20 ABI to handle WETH Deposit and Withdrawl 2019-05-10 16:09:09 +02:00
Xianny
41cc5234c4 Add coordinator wrapper (#1792)
* wip first pass at coordinator wrapper

* implement cancels, helper methods, and more unit tests

* pin typeorm version in pipeline

* prettier

* add export to 0x.js

* generate ZeroEx transaction using EIP712

* update Coordinator artifact

* change OrderError -> TypedDataError
2019-05-09 15:48:41 -07:00
Amir Bandeali
c2d3e5f052 Merge pull request #1804 from yxliang01/patch-1
fix.docs(README.md): wrong package name
2019-05-09 10:06:48 -07:00
Jacob Evans
f944b95e32 Added CHANGELOG 2019-05-09 17:26:57 +02:00
Jacob Evans
0a5b919cd9 Add fix for failing test 2019-05-09 16:46:56 +02:00
Jacob Evans
b5f85c11fe Re-enable orderwatcher tests. Add test for WETH withdraw 2019-05-09 16:46:08 +02:00
Greg Hysz
5d44b5e913 Merge pull request #1808 from 0xProject/fix/abiEncoder/typo1
Fixed typo in ABI Encoder error message
2019-05-08 13:27:53 -07:00
Greg Hysen
dd1961d86c updated changelog 2019-05-08 11:22:06 -07:00
Greg Hysen
f3539bf448 fixed typo 2019-05-08 11:22:03 -07:00
David Sun
d831e559f0 Merge pull request #1805 from 0xProject/feature/website/remove-meta-description
Removed default descriptions for website SEO performance
2019-05-07 13:06:15 -07:00
David Sun
cc079660f3 Merge pull request #1800 from 0xProject/feature/website/add-patryk
Added Patryk to the team page
2019-05-07 13:05:58 -07:00
Greg Hysz
4460dac697 Merge pull request #1806 from 0xProject/fix/abiEncoder/multibyteStrings
Support for ABI Encoding multibyte strings (Fixes Issue #1723)
2019-05-07 13:01:53 -07:00
Greg Hysen
31190f921c fixed linter errors 2019-05-07 12:34:05 -07:00
Greg Hysen
22515d8dce updated changelog 2019-05-07 11:59:27 -07:00
Greg Hysen
a099d970a4 Fixes Issue #1723: ABI-Encoded strings can have incorrect length header (multibyte characters) 2019-05-07 11:52:14 -07:00
David Sun
95bb2c5504 removed actual meta tags for description 2019-05-06 16:07:01 -07:00
David Sun
0b1262cc4d removed default description 2019-05-06 15:59:55 -07:00
Xiao Liang
f9244f6f7e fix.docs(README.md): wrong package name 2019-05-07 04:14:19 +08:00
Chris Kalani
cfa1bf36de Fixing Greg's placement in the grid 2019-05-02 14:43:22 -07:00
Chris Kalani
c362b33b5a Added Patryk to the team page 2019-05-02 14:33:36 -07:00
F. Eugene Aumson
222a151eff bump versions, after recent publications (#1646)
* bump versions, after recent publications

* Changelog updates and version bumps

* Correct broken URL's in setup.py's

* Correct SRA Client description (append "Client")

* Add convenience script for uninstalling all pkgs

* Add documentation link to SRA Client README.md
2019-04-30 15:56:40 -04:00
Lawrence Forman
d6115cff25 Merge pull request #1797 from 0xProject/feature/abi-gen-templates/awaitTransactionSuccess
Add awaitTransactionSuccessAsync() to generated contract functions.
2019-04-30 14:13:13 -04:00
Lawrence Forman
6459522617 Merge pull request #1799 from 0xProject/fix/contracts/temporarily-disable-useDockerisedSolc
Disable `useDockerisedSolc` for all contracts `compiler.json`s until latest solc docker images are published
2019-04-30 14:12:31 -04:00
Lawrence Forman
16e1f0eea1 Disable useDockerisedSolc for all contracts compiler.jsons until 0.5.8 docker image is released. 2019-04-30 11:01:31 -04:00
F. Eugene Aumson
0564ac1530 Python doc polish (#1757)
* Exercise doctests as a test not as a linter

* Add a contract artifact doctest, and exercise it

* Clean up linter issues

* Change asset data decoding output type

Previously, it was a TypedDict, but that was causing problems.  Sphinx
seems to be broken, such that none of the fields of the class were being
rendered into the doc.

Thinking on it further, I decided that a NamedTuple makes more sense
here anyways, since tuples are immutable and this output value isn't
something someone should ever build or modify.  And, NamedTuple is
getting its fields properly rendered by Sphinx.

* Add type annotations to JSON schemas docs

* Add doc publish metadata file for middlewares pkg

* Improve documentation

Note that none of the changes to .py files impact functionality in any
way, because the changes are restricted to "docstrings", which to the
Python interpreter are simply no-op statements.

However, one caveat to that is that much of these docstring changes DO
affect the functionality of automated test runs, because all of the code
examples (blocks beginning with `>>> `) are "doctests", which are
exercised via the test framework.

The index.rst files are the top-level templates for generating the
documentation, and the "automodule"/"autoclass"/etc statements pull in
the docstrings from the source code.

* correct package name in doc URL

* Move sra_client module into zero_ex namespace

* Add functions to encode asset data to bytes

* Fix: SRA client was deserializing orders weirdly

The generated code was transforming the order structure, from the camel
case field name format in the spec, into the snake case field name
format expected by Python convention.  With this problem in place, the
only way to take an order from a relayer and send it to a contract (for
fill, cancel, etc) was to manually transform the field names, one by
one, into a new structure.

* Fix problem with Web3/JSON order conversion utils

* doctest: maker, trade ZRX for WETH, not vice versa

* Remove redundant test

* Construct order in native Python, not JSON

Then convert it to JSON before sending it to the relayer.

* doctest: simplify asset units

* Add doctests for filling and cancelling

* Minor doctetst copy edits; whitespace

* Rename function, and add optional parameter

* Tweak docstrings on JSON conversion functions.

* Demo asset data decoding to view asset pairs

* Demo selecting an order from the order book

And have taker take it.

* Rename variable

* Abstract ganache from examples

Doing that exposed excessive use of the verbose
NETWORK_TO_ADDRESSES[NetworkId.Ganache] construct, so simplified that,
which ripped into eliminating other temporary variables that had been
used to hold specific contract addresses.

Also cleaned up some misplaced import statements.

* Add missing SRA client doc publication metadata

* Ran prettier on new SRA client doc pub metadata

* Remove local env customizations in doc metadata

* Eliminate temporary variable

* Rename variable

* Show `pip install` in every package's doc

* Doc NetorkID & pagination params as int, not float

* Clean up unmatched parenthesis in docs
2019-04-30 07:44:51 -04:00
Amir Bandeali
b896f82282 Merge pull request #1798 from 0xProject/feat/clean-contracts
Add clean:contracts command to top level package.json
2019-04-29 16:07:45 -07:00
Amir Bandeali
d737d419d9 Add clean:contracts command to top level package.json 2019-04-29 16:06:00 -07:00
F. Eugene Aumson
0de2b6983b Add LibAssetData to contracts/asset-proxy (#1779)
* Stop restarting node unnecesssarily during test

* Add new, empty LibAssetData

* Support encoding & decoding of ERC20 asset data

* Support encoding & decoding of ERC721 asset data

* Support encoding & decoding of ERC1155 asset data

* Support encoding & decoding of multi-asset data

* Support querying ERC20 balance from asset data

* Support querying ERC721 balance from asset data

* Support querying ERC1155 balance from asset data

* Support querying balance from multi-asset data

* Support querying ERC20 allowance from asset data

* Support querying ERC721 allowance from asset data

* Support querying ERC1155 allowance from asset data

* In tests, wait for allowance set before checking

* Introduce temporary variable `assetDataBody`

* Handle edge case in multi-asset balance query

* Support multi-asset allowance query by asset data

* Move variable declaration up for readability.

* Make all solhint-disable's cite specific rules

And move the directives to the ends of lines whenever possible

* Rename query tests to include " by asset data"

* Extract test helper method

* Extract another test helper method

* Support batch queries of allowances & balances

* In LibAssetData.sol, use IERC1155, not ...Mintable

* Rename balance*() return vars: amount -> balance

* Fix bug in ERC721 balance query

Was using method balanceOf(), but needed to be using ownerOf().

getERC721TokenOwner() method lifted from
@0x/extensions/contracts/src/OrderValidator/OrderValidator.sol

* Reuse new en/decoders; avoid abi.decode().

* Start lowest allowance/balance from 0, not MAX_INT

* Properly implement ERC1155 balance querying

* Split lines for readability

* Also check isApprovedForAll in 721 allowance query

* Add neglected division of allowances by amounts

* Rename methods: balanceOf -> getBalance

* Rename methods: allowance -> getAllowance

* Add methods: getBalanceAndAllowance() & batch...()

* Rename return vars: amount -> allowance

* Add devdoc comments

* Rename batchGet* methods to getBatch*

* Remove refactoring relic

* Add revert messages to all require() calls

* Reduce gas usage for ERC1155 asset data decoding

* Don't use dockerized solc for ERC20 contracts

Because they demand solc version 0.4.26, and it seems as though the tag
for that version has been deleted from dockerhub.

Without this, @0x/contracts-erc20 was failing to build.

* Rename batch functions to use plurals

* Skip dockerized solc for contracts needing 0.4.26

I seems as though the tag for that version has been deleted from
dockerhub.

Without this, these contracts were failing to build.

* Make revert reasons follow snake case convention
2019-04-29 15:46:26 -04:00
Lawrence Forman
25628c34ee Add PR numbers to CHANGELOGs 2019-04-28 22:25:12 -04:00
Lawrence Forman
54fdccd397 Ran prettier. 2019-04-28 22:25:12 -04:00
Lawrence Forman
27af4a988d In @0x/abi-gen-wrappers: Regenerate contract wrappers. 2019-04-28 22:25:12 -04:00
Lawrence Forman
fddad131a2 In @0x/base-contract: Expose txHashPromise in PromiseWithTransactionHash.
In `@0x/abi-gen-templates`: Update `awaitTransactionSuccessAsync()` partial to expose `txHashPromise`.
2019-04-28 22:25:12 -04:00
Lawrence Forman
4d493eeebd In @0x/contracts-asset-proxy: Update tests to use contract-built-in awaitTransactionSuccessAsync(). 2019-04-28 22:25:12 -04:00
Lawrence Forman
14c1495a1a In @0x/abi-gen-templates: Make txData parameter optional in awaitTransactionSuccessAsync().
In `@0x/base-contract`: Make `PromiseWithTransactionHash` class compatible with ES5 transpiler.
In `@0x/abi-gen-wrappers`: Regenerate contract wrappers.
2019-04-28 22:25:12 -04:00
Lawrence Forman
49c029ddb3 In @0x/abi-gen-templates: Add txData parameter to awaitTransactionSuccessAsync.
In `@0x/abi-gen-templates`: Regenerate wrappers.
2019-04-28 22:25:12 -04:00
Lawrence Forman
ddbe142c4c In @0x/abi-gen-wrappers: Regenerate contract wrappers. 2019-04-28 22:25:12 -04:00
Lawrence Forman
4710b40e45 In @0x/abi-gen-templates: Add timeoutMs parameter to awaitTransactionSuccessAsync 2019-04-28 22:25:12 -04:00
Lawrence Forman
be0b296769 Fix more linter errors. 2019-04-28 22:25:12 -04:00
Lawrence Forman
0a0ee67740 Fix linter errors. 2019-04-28 22:25:12 -04:00
Lawrence Forman
943d648225 In @0x/abi-gen-wrappers: Regenerate wrappers. 2019-04-28 22:25:12 -04:00
Lawrence Forman
6d835f5cc1 In @0x/abi-gen-templates: Add awaitTransactionSuccessAsync() to transaction template. 2019-04-28 22:25:12 -04:00
Lawrence Forman
a59cd67acf In @0x/base-contract: expose a PromiseWithTransactionHash type. 2019-04-28 22:25:12 -04:00
Lawrence Forman
bbc06be091 Update contracts/exchange-forwarder to 0.5.5 (#1796)
* Cherry-pick updated `@0x/contracts-exchange-forwarder` from `3.0` branch.

* Add PR numbers to changelogs
2019-04-28 22:21:13 -04:00
David Sun
d303e9f347 Merge pull request #1795 from 0xProject/feature/website/new-sitemap.txt
Added new sitemap.txt
2019-04-26 20:03:59 -04:00
David Sun
85ee923d89 added new sitemap.txt 2019-04-26 20:01:55 -04:00
David Sun
fe6ba20ff5 Merge pull request #1788 from 0xProject/feature/website/seo+polish
Updated meta data for website
2019-04-26 16:24:31 -04:00
Fabio B
18acf50b12 Merge pull request #1789 from 0xProject/fix/order-watcher-race-condition
Fix OrderWatcher race-condition bug
2019-04-24 16:09:58 -05:00
Fabio B
509fabb61c Merge pull request #1733 from PaulRBerg/fix/monorepo-scripts/broken-yarn-command
Fix yarn command in monorepo-scripts
2019-04-23 18:19:33 -05:00
Fabio Berger
cc3378b4cd Add CHANGELOG entry 2019-04-23 18:07:12 -05:00
Fabio Berger
8d3ccf333d Fix race-condition bug 2019-04-23 18:05:33 -05:00
David Sun
520919b165 prettier+lint 2019-04-23 18:41:54 -04:00
Francesco Agosti
600b86dd31 Merge pull request #1787 from 0xProject/feature/instant/utility-methods
Export utility methods and data from instant
2019-04-23 13:21:27 -07:00
fragosti
9c3fdd2584 Export utility methods and data from instant 2019-04-23 13:03:31 -07:00
David Sun
73974cd90f added large card variant 2019-04-23 11:12:36 -04:00
David Sun
8a60b3b402 switched metadata for explore page 2019-04-23 11:05:14 -04:00
Francesco Agosti
59ed5ae6b7 Merge pull request #1785 from 0xProject/feature/instant/erc721-screen-support
Add overflow scroll to instant overlay & fix display bug
2019-04-22 20:39:15 -05:00
fragosti
c687385974 Fix token amount bug 2019-04-22 18:21:32 -07:00
fragosti
2f72e15ea7 Add overflow scroll to instant overlay 2019-04-22 18:07:20 -07:00
Brandon Millman
7ea99baeb2 Merge pull request #1781 from 0xProject/feature/website/add-rui-mason
Added Rui and Mason to the team page
2019-04-22 14:21:11 -07:00
Francesco Agosti
14f3d20772 Merge pull request #1768 from 0xProject/feature/instant/erc-721-support
Super MVP ERC 721 in Instant
2019-04-19 18:21:07 -05:00
fragosti
72f51df25f Change 0x site URL 2019-04-19 17:59:37 -05:00
fragosti
a94b58e304 Remove lodash is undefined 2019-04-19 17:57:06 -05:00
fragosti
d327fabf9c Remove empty switch statement in instant 2019-04-19 17:21:06 -05:00
fragosti
9e02888c74 Apply prettier 2019-04-19 17:05:09 -05:00
fragosti
98c9a847f3 Improve index.html 2019-04-19 16:58:42 -05:00
fragosti
a159f4c9d6 Make ERC721 image fitting more flexible 2019-04-19 16:49:37 -05:00
fragosti
b197731ed2 Add back mysterious change because of merge 2019-04-19 12:34:17 -05:00
fragosti
028f54fdf0 Fix linting errors 2019-04-19 12:28:28 -05:00
fragosti
de62a0f8ed Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/instant/erc-721-support 2019-04-19 11:31:52 -05:00
Chris Kalani
a0fcc50a5f Added Rui and Mason to the team page 2019-04-18 11:58:31 -07:00
Brandon Millman
4f186e843c Merge pull request #1777 from 0xProject/feature/website/add-paul-vienhage
Added Paul to team page, updated 2 photos, cleaned up titles
2019-04-15 09:13:52 -07:00
Chris Kalani
df64c20587 Added Paul to team page, updated 2 photos, cleaned up titles 2019-04-12 16:00:24 -07:00
Jacob Evans
c78a602990 Publish
- 0x.js@6.0.6
 - @0x/abi-gen@2.0.9
 - @0x/abi-gen-templates@2.0.2
 - @0x/abi-gen-wrappers@4.2.0
 - @0x/assert@2.0.9
 - @0x/asset-buyer@6.1.0
 - @0x/base-contract@5.0.5
 - @0x/connect@5.0.5
 - @0x/contract-addresses@2.3.1
 - @0x/contract-artifacts@1.5.0
 - @0x/contract-wrappers@9.0.0
 - @0x/contracts-gen@1.0.8
 - @0x/dev-tools-pages@0.0.25
 - @0x/dev-utils@2.2.1
 - ethereum-types@2.1.2
 - @0x/fill-scenarios@3.0.5
 - @0x/instant@1.0.20
 - @0x/json-schemas@3.0.9
 - @0x/metacoin@0.0.47
 - @0x/migrations@4.1.1
 - @0x/monorepo-scripts@1.0.30
 - @0x/order-utils@7.2.0
 - @0x/order-watcher@4.0.6
 - @0x/pipeline@1.0.17
 - @0x/react-docs@2.0.10
 - @0x/react-shared@2.0.10
 - @0x/sol-compiler@3.1.6
 - @0x/sol-coverage@3.0.3
 - @0x/sol-doc@2.0.10
 - @0x/sol-profiler@3.1.5
 - @0x/sol-resolver@2.0.7
 - @0x/sol-trace@2.0.11
 - @0x/sol-tracing-utils@6.0.10
 - @0x/sra-spec@2.0.9
 - @0x/subproviders@4.0.5
 - @0x/testnet-faucets@1.0.76
 - @0x/tslint-config@3.0.1
 - @0x/types@2.2.2
 - @0x/typescript-typings@4.2.2
 - @0x/utils@4.3.1
 - @0x/web3-wrapper@6.0.5
 - @0x/website@0.0.79
 - @0x/contracts-asset-proxy@2.1.1
 - @0x/contracts-coordinator@2.0.0
 - @0x/contracts-erc1155@1.1.1
 - @0x/contracts-erc20@2.2.0
 - @0x/contracts-erc721@2.1.1
 - @0x/contracts-exchange@2.1.1
 - @0x/contracts-exchange-forwarder@2.1.1
 - @0x/contracts-exchange-libs@2.1.1
 - @0x/contracts-extensions@3.1.1
 - @0x/contracts-multisig@3.1.1
 - @0x/contracts-test-utils@3.1.2
 - @0x/contracts-utils@3.1.1
2019-04-11 17:00:06 +01:00
Jacob Evans
0acec57ba9 Updated CHANGELOGS 2019-04-11 16:59:38 +01:00
Xianny
7423028fea Replace lodash with built-ins where possible to reduce bundle size (#1766)
* add tslint rule to disallow lodash.isUndefined

* add tslint rule to disallow lodash.isNull

* apply fixes
2019-04-10 09:36:32 -07:00
David Sun
49d951b7be Merge pull request #1772 from 0xProject/bug/website-photos
Fix bug with photo name url
2019-04-09 23:44:55 -07:00
David Sun
a554c9518d changed photo name url 2019-04-09 23:43:23 -07:00
David Sun
f3c7ba445e Merge pull request #1771 from 0xProject/feature/website/new-team-photos
Website new team photos
2019-04-09 23:30:51 -07:00
David Sun
3abff41385 commiting photos 2019-04-09 23:08:29 -07:00
Ryan Chow
6c36832f0e Stop using deprecated web3.py interface (#1759)
* Refactor contract function call to support web3.py v5.0.0. (backwards compatible with v4)
2019-04-09 09:33:36 -04:00
fragosti
310c18707b Improve index.html 2019-04-05 16:57:13 -07:00
fragosti
422a4a5578 Add image component 2019-04-05 16:44:17 -07:00
fragosti
a995b2e1ae UI presenting NFT a bit more nicely 2019-04-05 16:25:53 -07:00
fragosti
90ad681a9e Extreme MVP of buying a ERC721 works 2019-04-05 15:55:10 -07:00
David Sun
2ff5c39712 Merge pull request #1767 from dave4506/fix/website/bug-sort-menu
Fix for menu z-index for explore
2019-04-05 15:03:13 -07:00
David Sun
ded849fd6d fix for menu z-index 2019-04-05 15:01:07 -07:00
David Sun
02f7064953 Merge pull request #1763 from dave4506/fix/website/flash-css-error
Fix Explore Issues with flash of css + other minor bugs
2019-04-05 14:57:19 -04:00
David Sun
1ddadfce1e added animation to tiles 2019-04-05 11:26:14 -07:00
David Sun
7720e5007c added animations to explore 2019-04-05 11:17:56 -07:00
David Sun
ccfd021796 switched header 'href' to 'to' 2019-04-05 11:17:56 -07:00
F. Eugene Aumson
fdcad84cee Delete merge conflict artifact (#1758) 2019-04-04 18:08:13 -04:00
Alex Browne
ad3e3b8421 Merge pull request #1755 from 0xProject/fix/circleci-yarn-permission-denied
Fix yarn permission denied errors in CircleCI
2019-04-04 13:21:36 -07:00
Jacob Evans
f67b4f8902 Merge pull request #1747 from 0xProject/feature/cut-the-package-fat
Cut the package fat! Part 1: Unwanted files
2019-04-04 14:26:23 +01:00
Jacob Evans
3c0d7319ba Update artifacts and remove top level artifacts 2019-04-04 12:30:41 +01:00
Jacob Evans
7f0aab6ec6 Remove unused deps 2019-04-04 12:30:41 +01:00
Jacob Evans
669578a926 Add contract-artifacts to circleci 2019-04-04 12:30:41 +01:00
Jacob Evans
fa1db64a8e Add a test to keep artifact sizes down 2019-04-04 12:30:41 +01:00
Jacob Evans
7cf60fa927 Remove sourcecode and opcodes from artifacts 2019-04-04 12:30:41 +01:00
Jacob Evans
75a0d3e494 Update all .npmignores 2019-04-04 12:30:41 +01:00
Jacob Evans
a98218ae22 Whitelist npmignore 2019-04-04 12:30:40 +01:00
Jacob Evans
10952e9dc4 Cut the package fat 2019-04-04 12:30:33 +01:00
Alex Browne
b36e23471b Fix yarn permission denied errors in CircleCI 2019-04-03 17:19:58 -07:00
Alex Browne
f45bf1c95b Merge pull request #1754 from 0xProject/fix/skip-geth-tests-ci
Disable Geth tests in CircleCI
2019-04-03 17:06:09 -07:00
Alex Browne
d4db2587aa Disable Geth tests in CircleCI 2019-04-03 16:38:58 -07:00
F. Eugene Aumson
62e6336a7d Fix race condition in CI runs of Python SRA client tests (#1751)
* In CI, don't start Launch Kit til Ganache is ready

* Re-enable Python SRA client tests

* For local testing, await service readiness
2019-04-03 18:22:26 -04:00
F. Eugene Aumson
2d8acd4711 Disable Python SRA tests against Launch Kit (#1750)
These tests have worked multiple times in Circle CI, but now they're not, and it seems to be misbehaving intermittently, so just disabling them for now.
2019-04-02 13:24:27 -04:00
Brandon Millman
d7d95be042 Merge pull request #1745 from 0xProject/fix/website/fix-codesandbox
Fix code sandbox link and 0x.js dep in website
2019-04-01 10:21:17 -07:00
David Sun
e3c97f0681 Merge pull request #1748 from dave4506/fix/website/pixure+bugs
Switched Pixura link
2019-04-01 08:59:20 -04:00
David Sun
1a4fa015b9 switched back to roboto 2019-04-01 08:54:02 -04:00
David Sun
63dacfaac5 switched pixura link 2019-04-01 08:48:46 -04:00
Brandon Millman
f7263ac2c6 Fix 0x.js dep 2019-03-29 16:54:41 -07:00
Brandon Millman
c7d7e1f0e3 Fix codesandbox link 2019-03-29 16:53:13 -07:00
Daniel Pyrathon
9c54b615f5 Merge pull request #1744 from 0xProject/feature/website/moar-Explore-updates
updates explore page
2019-03-29 16:28:02 -07:00
F. Eugene Aumson
69fe1aa981 Remove doctest skip for get_order method (#1743)
* Remove doctest skip for get_order method

* Set ganache env for Launch Kit in Circle CI

* Unpin Launch Kit version used in CI
2019-03-29 18:54:46 -04:00
rsingireddy
bfb3d19e3b fixes by way of yarn prettier 2019-03-29 15:45:49 -07:00
rsingireddy
0b4e62a63e updates explore page 2019-03-29 15:26:44 -07:00
David Sun
5cdbc03e71 Merge pull request #1676 from dave4506/website/feature/explore-page
Explore page
2019-03-28 21:10:57 -04:00
David Sun
16cd6dd25d removed .DS_Store 2019-03-28 20:54:00 -04:00
David Sun
fc71e7f99f updated to svg assets + new description 2019-03-28 20:51:56 -04:00
David Sun
e740380731 added changes for PR 2019-03-28 17:33:26 -04:00
Jacob Evans
f9921d2c91 Merge pull request #1714 from 0xProject/feature/order-utils/one-sided-transfer-validation
Simulate Maker transfer in order validation
2019-03-28 15:10:00 +01:00
Jacob Evans
d8bfc92cc5 Update documentation and changelog 2019-03-28 14:49:22 +01:00
Jacob Evans
1f2214f891 Major bump as this change could break existing orderbooks 2019-03-28 14:19:33 +01:00
Jacob Evans
50835e317f Update CHANGELOG 2019-03-28 14:00:40 +01:00
Jacob Evans
6c8d4dcc1e Allow simulation taker address to be specified 2019-03-28 14:00:40 +01:00
Jacob Evans
85a7efbd61 Change to accept maker amount 2019-03-28 14:00:40 +01:00
Jacob Evans
6b5ef10467 Remove unused imports 2019-03-28 14:00:39 +01:00
Jacob Evans
0bf46bfcb5 Re-use order relevant state 2019-03-28 14:00:39 +01:00
Jacob Evans
8b8dc7ac78 Update jsdoc 2019-03-28 14:00:39 +01:00
Fabio B
a017122c44 Update packages/contract-wrappers/src/types.ts
Co-Authored-By: dekz <dekz@dekz.net>
2019-03-28 14:00:39 +01:00
Fabio B
86a9a892d2 Update packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts
Co-Authored-By: dekz <dekz@dekz.net>
2019-03-28 14:00:39 +01:00
Fabio B
f31a141d78 Update packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts
Co-Authored-By: dekz <dekz@dekz.net>
2019-03-28 14:00:39 +01:00
Jacob Evans
fa67997424 Move order_utils from asset-buyer to order-utils package 2019-03-28 14:00:39 +01:00
Jacob Evans
a5f06c577d Remove unused pause 2019-03-28 14:00:38 +01:00
Jacob Evans
e575672877 Update CHANGELOGs 2019-03-28 14:00:38 +01:00
Jacob Evans
a34d5b29e8 Return eventually rejectedWith 2019-03-28 14:00:38 +01:00
Jacob Evans
91ec65da1b Await in tests to prevent clash in before blocks 2019-03-28 14:00:38 +01:00
Jacob Evans
ee8d40a66e Add IAssetProxy to python 2019-03-28 14:00:38 +01:00
Jacob Evans
38ac2e80ed Remove unused code 2019-03-28 14:00:38 +01:00
Jacob Evans
8b70762e34 Add a Test for an Untransferrable ERC20 token 2019-03-28 14:00:37 +01:00
Jacob Evans
18c613a611 Update comments 2019-03-28 14:00:37 +01:00
Jacob Evans
957f8c56a1 validateRemainingOrderAmountIsFillable 2019-03-28 14:00:37 +01:00
Jacob Evans
b16446877e only 2019-03-28 14:00:37 +01:00
Jacob Evans
9164d58dc7 Simulate maker transfer in order validation 2019-03-28 14:00:27 +01:00
Francesco Agosti
0beb2f9d3c Merge pull request #1740 from 0xProject/feature/website/add-Lawrence-change-Mel-role-change-Alex-Browne-role
adds lawrence forman to the website. changes mel role and alex browne…
2019-03-27 11:58:34 -07:00
Brandon Millman
ccdd66052a Merge pull request #1737 from 0xProject/feature/instant/update-infura
[instant] Add infura project id via env variables when bundling instant
2019-03-26 19:04:57 -07:00
Brandon Millman
518fd814b6 Merge branch 'development' into feature/website/add-Lawrence-change-Mel-role-change-Alex-Browne-role 2019-03-26 17:23:58 -07:00
rsingireddy
f49bb78dba adds lawrennce picture 2019-03-26 17:13:56 -07:00
rsingireddy
a54aa77d28 adds lawrence forman to the website. changes mel role and alex browne role 2019-03-26 16:51:07 -07:00
Brandon Millman
f85e443c9c Add instant.0x.org to host domains 2019-03-26 16:33:16 -07:00
Alex Browne
399e004e7f Merge pull request #1738 from 0xProject/fix/test-python-ci-failure-launch-kit-needs-pinning
Pin Launch Kit version in test-python CI task
2019-03-26 16:26:07 -07:00
Michael Huang
3099ba71eb New demos for Python packages (#1734)
End-to-end demos of constructing and signing an order and submitting it to a Relayer.  Docs are generated from the code, and include usage examples that are verified through automated testing.
2019-03-26 19:07:04 -04:00
F. Eugene Aumson
951fcf384c pin launch kit version in test-python ci task 2019-03-26 18:00:16 -04:00
Brandon Millman
c750368a3e Add infura project id via env variables when bundling instant 2019-03-26 14:17:57 -07:00
David Sun
3149d86855 lint + prettier 2019-03-26 16:55:10 -04:00
David Sun
3aaf21e34e removed banner and lint + prettier 2019-03-26 16:20:03 -04:00
David Sun
519c375a42 added responsive features 2019-03-26 16:20:03 -04:00
David Sun
3ed2c732bd added announcement banner 2019-03-26 16:20:02 -04:00
David Sun
0aa5550d0f Rearchitected Explore Page + added new features 2019-03-26 16:20:02 -04:00
David Sun
1bc8dd83d3 added settings dropdown 2019-03-26 16:20:02 -04:00
David Sun
c642cd6fed changed to popular 2019-03-26 16:20:01 -04:00
David Sun
f72918362d created most of the page's functionality 2019-03-26 16:20:01 -04:00
Leonid Logvinov
28c4ca73ab Merge pull request #1728 from ochikov/patch-6
Update constants.ts
2019-03-26 14:46:15 +01:00
Michael Huang
a256494ec8 Python contract wrappers (#1721) 2019-03-25 19:25:41 -04:00
Paul Berg
5fd359a64f Fix yarn command 2019-03-25 19:32:07 +00:00
Michael Huang
e043735362 Fix regex validation on numeric inputs (#1731)
* Fix regex validation on numeric inputs
2019-03-25 15:18:58 -04:00
Amir Bandeali
7010b1adb9 Merge pull request #1729 from 0xProject/feat/coordinator/functionVisibility
Modify function visibilities in Coordinator contract
2019-03-25 11:51:23 -07:00
Amir Bandeali
17ff262729 Update CHANGELOG 2019-03-25 10:11:37 -07:00
Amir Bandeali
1c18838cd8 Fix typos and add tests for decodeOrdersFromFillData 2019-03-25 10:11:37 -07:00
Amir Bandeali
55b87ae78d Make decodeOrdersFromFillData oublic and assertValidTransactionOrdersApproval internal 2019-03-25 10:11:37 -07:00
Amir Bandeali
e446e902f3 Remove TestMixins contract 2019-03-25 10:11:37 -07:00
Amir Bandeali
095b52e0b2 Make hashing methods public 2019-03-25 10:11:37 -07:00
Michael Huang
4f25ff6a50 local_message_signer middleware for web3.py (#1713) 2019-03-25 11:25:41 -04:00
ochikov
6242e0aeec Update constants.ts 2019-03-25 00:21:07 +02:00
Francesco Agosti
fde9fc9dd4 Merge pull request #1722 from 0xProject/fix/instant-polling
Unmount Instant when closing
2019-03-22 17:03:16 -07:00
fragosti
c481e42673 Reset yarn.lock 2019-03-22 16:21:02 -07:00
fragosti
5e228d7232 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into fix/instant-polling 2019-03-22 15:03:15 -07:00
fragosti
6b8e40fdc9 Make unrender idempotent 2019-03-22 15:02:12 -07:00
Alex Svanevik
bca44bf9e3 Merge pull request #1684 from 0xProject/pull-github-data
Pull Github data
2019-03-22 18:33:40 +08:00
askeluv
08e49dcf2e Throttling to respect rate limits 2019-03-22 18:15:49 +08:00
Fabio Berger
0f45409b4d Publish
- 0x.js@6.0.5
 - @0x/abi-gen@2.0.8
 - @0x/abi-gen-wrappers@4.1.0
 - @0x/assert@2.0.8
 - @0x/asset-buyer@6.0.5
 - @0x/base-contract@5.0.4
 - @0x/connect@5.0.4
 - @0x/contract-addresses@2.3.0
 - @0x/contract-artifacts@1.4.0
 - @0x/contract-wrappers@8.0.5
 - @0x/contracts-gen@1.0.7
 - @0x/dev-tools-pages@0.0.24
 - @0x/dev-utils@2.2.0
 - @0x/fill-scenarios@3.0.4
 - @0x/instant@1.0.19
 - @0x/json-schemas@3.0.8
 - @0x/metacoin@0.0.46
 - @0x/migrations@4.1.0
 - @0x/monorepo-scripts@1.0.29
 - @0x/order-utils@7.1.1
 - @0x/order-watcher@4.0.5
 - @0x/pipeline@1.0.16
 - @0x/react-docs@2.0.9
 - @0x/react-shared@2.0.9
 - @0x/sol-compiler@3.1.5
 - @0x/sol-coverage@3.0.2
 - @0x/sol-doc@2.0.9
 - @0x/sol-profiler@3.1.4
 - @0x/sol-resolver@2.0.6
 - @0x/sol-trace@2.0.10
 - @0x/sol-tracing-utils@6.0.9
 - @0x/sra-spec@2.0.8
 - @0x/subproviders@4.0.4
 - @0x/testnet-faucets@1.0.75
 - @0x/types@2.2.1
 - @0x/typescript-typings@4.2.1
 - @0x/utils@4.3.0
 - @0x/web3-wrapper@6.0.4
 - @0x/website@0.0.78
 - @0x/contracts-asset-proxy@2.1.0
 - @0x/contracts-coordinator@1.1.0
 - @0x/contracts-erc1155@1.1.0
 - @0x/contracts-erc20@2.1.0
 - @0x/contracts-erc721@2.1.0
 - @0x/contracts-exchange@2.1.0
 - @0x/contracts-exchange-forwarder@2.1.0
 - @0x/contracts-exchange-libs@2.1.0
 - @0x/contracts-extensions@3.1.0
 - @0x/contracts-multisig@3.1.0
 - @0x/contracts-test-utils@3.1.1
 - @0x/contracts-utils@3.1.0
2019-03-21 17:07:20 +01:00
Fabio Berger
5469d3ec13 Updated CHANGELOGS 2019-03-21 17:07:04 +01:00
Fabio B
d12f8410b9 Merge pull request #1689 from 0xProject/addCoordinatorSupport
Add Coordinator contracts support in dev tools
2019-03-21 16:04:19 +01:00
Fabio Berger
704c52d229 Move @0x/contracts-test-utils dependency from devDep to deps to fix publish test 2019-03-21 15:33:47 +01:00
Fabio Berger
7dcdda14f5 modify types 2019-03-21 15:13:39 +01:00
Fabio Berger
0f59256ca7 merge development 2019-03-21 15:04:52 +01:00
Fabio Berger
ddee04e98c Try import instead of const 2019-03-21 14:46:47 +01:00
Steve Klebanoff
50f5002b71 Unmount component when closing 2019-03-21 14:43:31 +01:00
Fabio Berger
e866add4b0 Add artifacts to python packages 2019-03-21 14:33:54 +01:00
Fabio Berger
39b93b88c5 Fix prettier 2019-03-21 14:32:21 +01:00
Fabio Berger
deb7e95567 Revert change 2019-03-21 14:29:26 +01:00
Jacob Evans
91500501ce Merge pull request #1695 from 0xProject/feature/reduce-excess-block-polling
Reduce excess block polling when using Web3ProviderEngine
2019-03-21 13:37:07 +01:00
Jacob Evans
6a1caeb9a1 Update CHANGELOGs 2019-03-21 12:33:09 +01:00
Jacob Evans
cee7803c37 Remove IAssetProxy 2019-03-21 12:02:38 +01:00
Jacob Evans
4e8d0ac7cb Add IAssetProxy to python 2019-03-21 11:52:43 +01:00
Jacob Evans
47bbcb9935 Add HACK explanation 2019-03-21 11:52:43 +01:00
Jacob Evans
c0288c5f26 Fix changelog, remove migrate_testnet 2019-03-21 11:52:28 +01:00
Jacob Evans
18c2013625 Update contract CHANGELOGs 2019-03-21 11:51:53 +01:00
Jacob Evans
548089888d Remove excess web3providernegine polling from contracts 2019-03-21 11:50:19 +01:00
Jacob Evans
180c65cfeb Change all packages to use web3providerengine without excess polling 2019-03-21 11:50:19 +01:00
Jacob Evans
6a28e41bc8 Remove unnecessary type assertion 2019-03-21 11:50:19 +01:00
Jacob Evans
f9ef942a98 Use providerUtils.startProviderEngine to minimize the HACK 2019-03-21 11:50:18 +01:00
Jacob Evans
8272c7a74e Reduce excess block polling when using Web3ProviderEngine 2019-03-21 11:49:26 +01:00
Amir Bandeali
4e745489db Merge pull request #1720 from 0xProject/fix/remove-tec
Remove TEC package artifacts
2019-03-20 14:01:39 -07:00
Amir Bandeali
fc2625a0c0 Remove TEC package artifacts 2019-03-20 13:28:37 -07:00
Amir Bandeali
d0e43ebaf1 Merge pull request #1712 from merklejerk/fix/feature/contracts/LibAddressArray-tests
Fix LibAddressArray.indexOf() and add LibAddressArray tests.
2019-03-20 11:38:08 -07:00
Fabio Berger
879805e316 merge development 2019-03-20 17:07:02 +01:00
Fabio Berger
6845d2e0ef Add coordinator artifacts to python package 2019-03-20 16:56:08 +01:00
Fabio Berger
542d1c1c41 In-line the declaration 2019-03-20 16:27:13 +01:00
Greg Hysen
31568e7abb Merge pull request #1716 from 0xProject/contracts-asset-proxy/updateProxyId
ERC1155 ProxyId - ERC1155Token -> ERC1155Assets
2019-03-20 08:12:58 -07:00
Lawrence
4b2488b124 Ran prettier. 2019-03-20 10:58:25 -04:00
Leonid Logvinov
d4c37ecfa3 Publish
- 0x.js@6.0.4
 - @0x/abi-gen@2.0.7
 - @0x/abi-gen-wrappers@4.0.3
 - @0x/assert@2.0.7
 - @0x/asset-buyer@6.0.4
 - @0x/base-contract@5.0.3
 - @0x/connect@5.0.3
 - @0x/contract-addresses@2.2.3
 - @0x/contract-wrappers@8.0.4
 - @0x/contracts-gen@1.0.6
 - @0x/dev-tools-pages@0.0.23
 - @0x/dev-utils@2.1.4
 - ethereum-types@2.1.1
 - @0x/fill-scenarios@3.0.3
 - @0x/instant@1.0.18
 - @0x/json-schemas@3.0.7
 - @0x/metacoin@0.0.45
 - @0x/migrations@4.0.4
 - @0x/monorepo-scripts@1.0.28
 - @0x/order-utils@7.1.0
 - @0x/order-watcher@4.0.4
 - @0x/pipeline@1.0.15
 - @0x/react-docs@2.0.8
 - @0x/react-shared@2.0.8
 - @0x/sol-compiler@3.1.4
 - @0x/sol-coverage@3.0.1
 - @0x/sol-doc@2.0.8
 - @0x/sol-profiler@3.1.3
 - @0x/sol-resolver@2.0.5
 - @0x/sol-trace@2.0.9
 - @0x/sol-tracing-utils@6.0.8
 - @0x/sra-spec@2.0.7
 - @0x/subproviders@4.0.3
 - @0x/testnet-faucets@1.0.74
 - @0x/types@2.2.0
 - @0x/typescript-typings@4.2.0
 - @0x/utils@4.2.3
 - @0x/web3-wrapper@6.0.3
 - @0x/website@0.0.77
 - @0x/contracts-asset-proxy@2.0.0
 - @0x/contracts-coordinator@1.0.0
 - @0x/contracts-erc1155@1.0.1
 - @0x/contracts-erc20@2.0.0
 - @0x/contracts-erc721@2.0.0
 - @0x/contracts-exchange@2.0.0
 - @0x/contracts-exchange-forwarder@2.0.0
 - @0x/contracts-exchange-libs@2.0.0
 - @0x/contracts-extensions@3.0.0
 - @0x/contracts-multisig@3.0.0
 - @0x/contracts-test-utils@3.1.0
 - @0x/contracts-utils@3.0.0
2019-03-20 15:26:54 +01:00
Leonid Logvinov
3f9fd7c060 Updated CHANGELOGS 2019-03-20 15:26:43 +01:00
Lawrence
6ed1412bdd Remove unnecessary copy operation in TestLibAddressArray.testAppendRealloc().
Test explicitly for newly allocated address in LibAddressArray "append" tests.
2019-03-20 10:19:46 -04:00
Lawrence
78b9a45158 Add PR#s to changelogs. 2019-03-20 10:19:46 -04:00
Lawrence
b8925baa88 Add unit tests for contracts/utils/LibAddressArray.
Fix `LibAddressArray.indexOf` returning wrong index.
2019-03-20 10:19:46 -04:00
Lawrence
87fd3f2a82 Add RevertReason.InvalidFreeMemoryPtr to packages/types. 2019-03-20 10:19:46 -04:00
Leonid Logvinov
0490ef5900 Merge pull request #1719 from 0xProject/feature/update-soliidty-parser-antlr
Update solidity-parser-antlr
2019-03-20 15:15:11 +01:00
Fabio Berger
8af164dbd2 Attempt to fix type issue 2019-03-20 15:05:21 +01:00
Fabio Berger
c994afbf3c Fix Pylint 2019-03-20 15:02:49 +01:00
Leonid Logvinov
fa36c91bd6 Remove legacy entries from AST Visitor 2019-03-20 14:50:26 +01:00
Fabio Berger
843caf86fb merge development 2019-03-20 14:32:26 +01:00
Leonid Logvinov
5b8f294aaf Update solidity-parser-antlr 2019-03-20 14:31:51 +01:00
Fabio Berger
44eef5b0e0 Fix comment 2019-03-20 14:31:10 +01:00
Fabio B
aad75840d4 Merge pull request #1718 from 0xProject/orderWatcher/fixRaceCondition
Fix race-condition in Order-watcher
2019-03-20 14:19:39 +01:00
Fabio Berger
31faef7030 Add changelog entry 2019-03-20 14:19:25 +01:00
Fabio Berger
941877a05a Fix linter 2019-03-20 13:48:59 +01:00
Fabio B
4fd4c1e8e1 Merge pull request #1717 from ochikov/fix-documentation
Fix documentation typos
2019-03-20 13:47:29 +01:00
Fabio Berger
7cd27cd9c8 Make sure we reset blockchain state 2019-03-20 13:31:55 +01:00
Fabio Berger
54dbef2b4f Add semaphore around event callbacks that all modify shared state 2019-03-20 13:31:35 +01:00
Ognyan Chikov
05424c9f33 Fix documentation typos 2019-03-20 11:37:38 +02:00
askeluv
346c6fc590 Deal with failing Github API for issues 2019-03-20 12:41:56 +08:00
Greg Hysen
7ed3afe9f0 Updated function signature for ERC1155 ProxyId - ERC1155Token -> ERC1155Assets 2019-03-19 15:35:08 -07:00
Greg Hysen
d29ed6cd49 Merge pull request #1715 from 0xProject/update/contract-wrappers/dutchAuctionMainnetAddress
Added Dutch Auction mainnet address to contract-addresses package
2019-03-19 15:18:34 -07:00
Greg Hysen
8c3abf3473 Updated changelog 2019-03-19 15:03:43 -07:00
Greg Hysen
384114d3c7 Added Dutch Auction address on mainnet to contract-addresses package 2019-03-19 15:01:24 -07:00
Greg Hysen
e8be5a0a8f Merge pull request #1673 from 0xProject/feature/contracts/erc1155ProxyIntegrationTests-2
Exchange & Proxy Integration Tests - ERC1155
2019-03-19 11:00:56 -07:00
Greg Hysen
98c6fa10e6 Added 1explicit ERC1555Poxy testsfor cwhen receiver allback data is NULLL (0x) 2019-03-19 09:37:16 -07:00
Greg Hysen
30d0bdec07 Updated changelog and yarn.lock 2019-03-19 09:37:16 -07:00
Greg Hysen
7024f29865 updated changelogs 2019-03-19 09:36:12 -07:00
Greg Hysen
29ebed9514 Added ERC1155 artifacts to log decoder for exchange wrapper 2019-03-19 09:36:11 -07:00
Greg Hysen
c0260bc44a rebased against development 2019-03-19 09:36:11 -07:00
Greg Hysen
6992bff0e0 Ran prettier & linter 2019-03-19 09:36:11 -07:00
Greg Hysen
6957e6e8f7 ERC1155 integration tests with MultiAssetProxy 2019-03-19 09:36:11 -07:00
Greg Hysen
31dbca7efc More integration tests for ERC1155 <> Multi Asset Proxy encoding / decoding 2019-03-19 09:36:11 -07:00
Greg Hysen
82b6dad1ba Exchange Integration Tests 2019-03-19 09:36:11 -07:00
Greg Hysen
5063c17e6b ERC1155 Asset Data tests + types 2019-03-19 09:36:11 -07:00
Amir Bandeali
3fff3d9c60 Merge pull request #1707 from 0xProject/fix/update-ganache
Change `evmVersion` to `constantinople` for contract compilation
2019-03-19 08:23:12 -07:00
Fabio Berger
2fbe0aed32 Fix Python tests 2019-03-19 14:53:43 +01:00
Alex Svanevik
3bdc1802cb Merge branch 'development' into pull-github-data 2019-03-19 14:31:31 +08:00
Francesco Agosti
2675833b0d Merge pull request #1709 from 0xProject/feature/website/add-Daniel
adds daniel pyrahon to website
2019-03-18 14:53:49 -07:00
fragosti
939a5b477a Run linter 2019-03-18 14:51:51 -07:00
Rahul Singireddy
dc57e7a5b3 adds daniel pyrahon to website 2019-03-18 14:19:27 -07:00
Amir Bandeali
a401b8f475 Fix web3wrapper node version test 2019-03-18 13:07:34 -07:00
Amir Bandeali
b008fabdac Change petersburg to constantinople 2019-03-18 13:07:34 -07:00
Amir Bandeali
caf286b8cb Update CHANGELOGs 2019-03-18 13:07:34 -07:00
Amir Bandeali
aea278c022 Update evmVersion to petersburg 2019-03-18 13:07:34 -07:00
Amir Bandeali
4e20fe1602 Update ganache-core to 2.5.3 2019-03-18 13:07:34 -07:00
Fabio Berger
849ca58228 Fix PR number 2019-03-18 20:40:29 +01:00
Fabio Berger
9991fca2e5 Add changelog entry for contract-addressesa 2019-03-18 20:39:02 +01:00
Fabio Berger
9c7bdcfeef Add testnet and mainnet coordinator and coordinatorRegistry addresses 2019-03-18 20:37:01 +01:00
Fabio Berger
b5463d522b Add PR numbers 2019-03-18 17:30:10 +01:00
Fabio Berger
af0d830103 Update coordinator wrapper 2019-03-18 17:20:58 +01:00
Fabio Berger
d4187dffa3 Add createCoordinatorApprovalTypedData method to order-utils and use in Coordinator tests 2019-03-18 17:20:51 +01:00
Fabio Berger
a7f06f2be5 Update coordinator abi-gen-wrapper 2019-03-18 16:44:11 +01:00
Fabio Berger
7ff7d1a185 Merge branch 'development' into addCoordinatorSupport
* development:
  Fix order-watcher version
2019-03-18 12:00:18 +01:00
Fabio Berger
d3ab612a89 Fix order-watcher version 2019-03-18 11:59:56 +01:00
Fabio Berger
e3bc80e027 Merge branch 'development' into addCoordinatorSupport
* development: (93 commits)
  Linting
  Copied MixinAssetProxyDispatcher from exchange
  Added deployed contract packages to readme (and link to top-level readme)
  Bumped version of ERC1155Proxy to 0.5.5 + merged ERC20Proxy/ERC721Proxy/MultiAssetProxy dependencies into base contract files
  Make credits program participants 1 row
  Correct comment in `hashEIP712Message()` in `LibEIP712Domai.sol`. Merge janky changelog notes in `types` package. Correct changelog note in `coordinator` changelog.
  Add PR numbers to changelogs.
  additional zero outcome tests
  renamed perUnitValue to valueMultiplier
  added test for amount=0
  Adjusted changelog version since nothing has been published during this PR
  Added calldatacopy comment
  Do not revert if value or amount are zero. Only if amount is non-zero and there is an overflow.
  updated comment for calldatacopy
  yarn.lock for erc1155 proxy
  added exports for 1155 proxy
  Renamed tokenIds -> ids, tokenValues -> values, callbackData -> data to be consistent with the ERC1155 reference implementation.
  Rebased against development
  Ran prettier
  Updated changelogs and documentation for erc1155 proxy
  ...
2019-03-18 11:20:22 +01:00
Alex Svanevik
a8720806f1 Merge pull request #1702 from 0xProject/fix/pipeline/replace-edps-endpoint
Changed EDPS endpoint to a 0x AWS one
2019-03-18 18:09:31 +08:00
askeluv
5aac4c2e5d Linting 2019-03-18 17:36:19 +08:00
Amir Bandeali
6fa645aab9 Merge pull request #1705 from merklejerk/feature/contracts/coordinator-tx-eip712-mixed-domains
Separate domains for Coordinator transactions and approvals
2019-03-16 16:21:01 -07:00
Greg Hysen
842ea4645b Merge pull request #1701 from 0xProject/feature/contracts/erc1155ProxySolidity055
Upgrade asset-proxy package to solidity 0.5.5
2019-03-15 21:32:57 -07:00
Greg Hysen
e1cfbcd4f6 Copied MixinAssetProxyDispatcher from exchange 2019-03-15 21:16:21 -07:00
Greg Hysen
6f17ff55fa Added deployed contract packages to readme (and link to top-level readme) 2019-03-15 21:16:18 -07:00
Greg Hysen
d88af4dfa6 Bumped version of ERC1155Proxy to 0.5.5 + merged ERC20Proxy/ERC721Proxy/MultiAssetProxy dependencies into base contract files 2019-03-15 19:02:24 -07:00
fragosti
bb0ba21e92 Merge https://github.com/0xProject/0x-monorepo into development 2019-03-15 16:48:41 -07:00
fragosti
f0753c8e58 Make credits program participants 1 row 2019-03-15 16:48:18 -07:00
Lawrence Forman
4c55004b08 Correct comment in hashEIP712Message() in LibEIP712Domai.sol.
Merge janky changelog notes in `types` package.
Correct changelog note in `coordinator` changelog.
2019-03-15 19:23:56 -04:00
Lawrence Forman
ae24119c09 Merge branch 'development' into feature/contracts/coordinator-tx-eip712-mixed-domains 2019-03-15 19:10:44 -04:00
Lawrence Forman
b8753d8f20 Add PR numbers to changelogs. 2019-03-15 18:29:26 -04:00
Greg Hysen
bab368b956 Merge pull request #1661 from 0xProject/feature/contracts/erc1155Proxy-4
ERC1155 Asset Proxy
2019-03-15 15:25:55 -07:00
Greg Hysen
22bc1fb21e additional zero outcome tests 2019-03-15 15:05:52 -07:00
Greg Hysen
63ba764de8 renamed perUnitValue to valueMultiplier 2019-03-15 15:05:52 -07:00
Greg Hysen
6a7530d741 added test for amount=0 2019-03-15 15:05:52 -07:00
Greg Hysen
eb9bf7c4f9 Adjusted changelog version since nothing has been published during this PR 2019-03-15 15:05:52 -07:00
Greg Hysen
b6571d0ca3 Added calldatacopy comment 2019-03-15 15:05:52 -07:00
Greg Hysen
9207d1c680 Do not revert if value or amount are zero. Only if amount is non-zero and there is an overflow. 2019-03-15 15:05:52 -07:00
Greg Hysen
f783c9bb25 updated comment for calldatacopy 2019-03-15 15:05:52 -07:00
Greg Hysen
df5786deda yarn.lock for erc1155 proxy 2019-03-15 15:05:51 -07:00
Greg Hysen
de971e6c46 added exports for 1155 proxy 2019-03-15 15:05:02 -07:00
Greg Hysen
2a6ed0c96e Renamed tokenIds -> ids, tokenValues -> values, callbackData -> data to be consistent with the ERC1155 reference implementation. 2019-03-15 15:05:02 -07:00
Greg Hysen
9ec380777a Rebased against development 2019-03-15 15:05:02 -07:00
Greg Hysen
8916d0d367 Ran prettier 2019-03-15 15:05:02 -07:00
Greg Hysen
1e5648111e Updated changelogs and documentation for erc1155 proxy 2019-03-15 15:05:02 -07:00
Greg Hysen
ae51cfe8b9 Added method descriptions to erc1155 proxy wrapper 2019-03-15 15:05:02 -07:00
Greg Hysen
05ef250ab4 Ran prettier & linter 2019-03-15 15:05:02 -07:00
Greg Hysen
38e4871f32 Moved transferFrom with/without logs into ERC1155 Proxy Wrapper 2019-03-15 15:05:02 -07:00
Greg Hysen
a86ba7af2e moved transferFrom into ERC1155 Proxy Wrapper 2019-03-15 15:05:02 -07:00
Greg Hysen
5704afc54c ERC1155 Asset Data tests + types 2019-03-15 15:05:02 -07:00
Greg Hysen
55c4fc9aca Ran prettier / linter 2019-03-15 15:05:02 -07:00
Greg Hysen
888c17353b Renamed erc1155token to erc1155Contract in proxy tests 2019-03-15 15:05:02 -07:00
Greg Hysen
054c0e91a3 removed erc1155 proxy tests from general proxy test file 2019-03-15 15:05:02 -07:00
Greg Hysen
4dfb610eba updated erc1155 proxy tests and moved to their own test file 2019-03-15 15:05:02 -07:00
Greg Hysen
008eb8dd8b cleaning up erc1155 proxy tests 2019-03-15 15:05:02 -07:00
Greg Hysen
2882c4bb89 test with several tokens erc1155 proxy 2019-03-15 15:05:02 -07:00
Greg Hysen
4473851f5b Remaining tests for erc1155 proxy 2019-03-15 15:05:02 -07:00
Greg Hysen
15d9e2d3d5 Split ERC1155 Asset Proxy from ERC1155 POC implementation - squashed 2019-03-15 15:05:02 -07:00
Greg Hysen
d5d9df383e Added remaining erc1155 revert reasons to types package 2019-03-15 15:05:02 -07:00
Greg Hysen
243a04b756 tests for allowance approvals on erc1155 2019-03-15 15:05:02 -07:00
Greg Hysen
b77dcbd39b bumped revision verson for types package 2019-03-15 15:05:02 -07:00
Lawrence Forman
ad5d4bdfc5 Unexport constants from order-utils.
Directly grab the EIP712 constants from the `order-utils` package in `/contracts/coordinator/test/util/hash_utils`.
Update changelogs.
2019-03-15 18:01:43 -04:00
Lawrence Forman
54c17b0068 Ran prettier & linter.
Updated CHANGELOGs.
2019-03-15 17:32:36 -04:00
Lawrence Forman
616907eff8 Update coordinator tests to comply with mixed EIP712 domains. 2019-03-15 16:52:18 -04:00
Lawrence Forman
afaabb3673 Move Coordinator EIP712 constants from contracts/test-utils to packages/order-utils.
Export `constants` from `packages/types`.
Add `SignatureInvalid` to `RevertReason` in `packages/types`.
2019-03-15 16:52:18 -04:00
Lawrence Forman
1c1f625352 Add SignatureType.Invalid to Coordinator.
`LibEIP712Domain.sol` can now produce hashes for both Coordinator and Exchange data through `hashEIP712CoordinatorMessage()` and `hashEIP712ExchangeMessage()`.
Coordinator now only uses its own domain for approval hashes, and the Exchange's domain for transaction hashes.
2019-03-15 16:52:18 -04:00
fragosti
d3f45d2148 Remove facebook from credits page 2019-03-15 11:30:36 -07:00
Xianny
7326dbd108 add greenhouse (#1690) 2019-03-15 10:37:52 -07:00
F. Eugene Aumson
4bf311a282 Enable cryptokitties data from nonfungible.com (#1680)
* enable cryptokitties

    Recall that nonfungible.com sent us an initial data dump so that we
    wouldn't have to pull everything from the API. And recall that we're
    storing that initial dump on S3. Finally, recall that the cryptokitties
    data was particularly voluminous (~1GB), which doesn't easily transfer to
    and from S3.

    These changes provide a CLI script to partition that data (or any such data
    from nonfungible.com) into a set of smaller files; and a scraping script
    that seamlessly recombines those partitions for loading into the database.

* add chainbreakers, chibifighters & mlbcryptobaseball
2019-03-15 10:50:59 -04:00
F. Eugene Aumson
7f5a3f12ca Relay failures through command line interface (#1700)
* Relay failures through command line interface
2019-03-15 10:38:21 -04:00
askeluv
6a9b71466d Changed endpoint to an AWS one + added increased timeout 2019-03-15 15:52:32 +08:00
Amir Bandeali
70e550a25f Merge pull request #1698 from ochikov/patch-3
Update constants.ts
2019-03-14 20:25:54 -07:00
ochikov
1328882ab6 Update constants.ts 2019-03-14 18:12:50 +02:00
Jacob Evans
b378a0608d Merge pull request #1692 from 0xProject/fix/order-watcher/1550
Fix error where object could be undefined given an approval event
2019-03-14 11:30:54 +01:00
Jacob Evans
e28c6d6f9c Add a regression test for #1550 2019-03-14 10:45:20 +01:00
Jacob Evans
f57f29e426 Update changelog 2019-03-14 10:12:13 +01:00
Jacob Evans
f2857452e3 Fix error were object could be undefined given an approval event 2019-03-14 10:12:03 +01:00
Amir Bandeali
af04c294b9 Merge pull request #1693 from 0xProject/fix/contracts/unpinVersions
Unpin Solidity versions for contracts that are not deployed
2019-03-13 22:34:31 -07:00
Amir Bandeali
65c8630534 Unpin Solidity versions for contracts that are not deployed 2019-03-13 16:53:22 -07:00
askeluv
095882d016 Added Github issue entity 2019-03-13 16:30:10 +08:00
askeluv
1693506f80 name -> full_name + fixed error message for missing access token 2019-03-13 11:47:42 +08:00
Greg Hysen
667c22169f Merge pull request #1657 from 0xProject/feature/contracts/erc1155MinimalImplementation
erc1155 minimal implementation
2019-03-12 12:51:43 -07:00
Greg Hysen
c53edf6bd9 0.5.3 -> 0.5.5 in erc1155 contracts 2019-03-12 11:39:00 -07:00
Greg Hysen
b601220845 Updated package.json dependencies 2019-03-12 11:09:39 -07:00
Greg Hysen
e77a608f45 Got build working on erc1155 2019-03-11 19:07:58 -07:00
Amir Bandeali
2822e77716 Merge pull request #1682 from 0xProject/feat/contracts/solidity0.5.5
Upgrade contracts to Solidity 0.5.5
2019-03-11 17:06:28 -07:00
Greg Hysen
98227928af Added Address.sol for isContract checks to contracts-utils package 2019-03-11 16:12:31 -07:00
Greg Hysen
430afbdc80 Replaced SafeMath in ERC1155 package with the version in contracts-utils 2019-03-11 16:06:18 -07:00
Greg Hysen
dfdb48ce7d Updated README and circleci for erc1155 package 2019-03-11 15:00:41 -07:00
Greg Hysen
257d1b2b52 Set evm version to byzantium to avoid using unsupported opcodes in solidity 0.5.5 2019-03-11 15:00:41 -07:00
Greg Hysen
07200437b6 style improvements for erc1155 basic implementation 2019-03-11 15:00:41 -07:00
Greg Hysen
ebfa00d555 Added remaining erc1155 revert reasons to types package 2019-03-11 15:00:41 -07:00
Greg Hysen
421f555d57 Ran prettier 2019-03-11 14:59:58 -07:00
Greg Hysen
4b60d941cc erc1155 wrapper improvements - handle minting for mutliple addresses at once + more revert reasons 2019-03-11 14:59:58 -07:00
Greg Hysen
60d24ada62 tests for allowance approvals on erc1155 2019-03-11 14:59:58 -07:00
Greg Hysen
a1c121e2fe ignore erc1155 artifacts and wrappers for prettier 2019-03-11 14:59:58 -07:00
Greg Hysen
b3775a3ca5 more style cleanup of erc1155 basic implementation 2019-03-11 14:59:58 -07:00
Greg Hysen
5d36c97a46 Added license to utils 2019-03-11 14:59:58 -07:00
Greg Hysen
4bdd412c15 added pr to changelogs 2019-03-11 14:59:58 -07:00
Greg Hysen
46e3bcd6b9 cleaned up reference implementation revert reasons 2019-03-11 14:59:58 -07:00
Greg Hysen
68a85ddf90 removed unnecessary solhintignore 2019-03-11 14:59:58 -07:00
Greg Hysen
6eba9273cb bumped revision verson for types package 2019-03-11 14:59:58 -07:00
Greg Hysen
9de151cc14 ran prettier 2019-03-11 14:55:45 -07:00
Greg Hysen
b8c9a5dd1f renamed contracts::lib -> contracts::utils 2019-03-11 14:55:45 -07:00
Greg Hysen
4dfb3507c4 updated compiler.json 2019-03-11 14:55:45 -07:00
Greg Hysen
0cac2d407b Cleanup 2019-03-11 14:55:45 -07:00
Greg Hysen
b3106cd932 Removed DummyERC1155Token 2019-03-11 14:55:45 -07:00
Greg Hysen
c4a467fa96 Ran lint-contracts 2019-03-11 14:55:45 -07:00
Greg Hysen
cf7afbe7f6 ran linter 2019-03-11 14:55:45 -07:00
Greg Hysen
a8d58aeac4 ran prettier 2019-03-11 14:55:45 -07:00
Greg Hysen
28209e9413 cleaning 2019-03-11 14:55:45 -07:00
Greg Hysen
68ed56f2d9 some cleanup 2019-03-11 14:55:45 -07:00
Greg Hysen
0c03747807 Basic ERC1155 wrapper 2019-03-11 14:55:45 -07:00
Greg Hysen
dfe7ecbb5b Added erc1155 package to top-level package.json 2019-03-11 14:55:45 -07:00
Greg Hysen
3039d8edfa Ran prettier 2019-03-11 14:55:45 -07:00
Greg Hysen
7c850cc082 Basic ERC1155 Implementation. Derived from reference implementation, with bug fixes. 2019-03-11 14:55:45 -07:00
Alex Browne
0e07ee3d81 Merge pull request #1683 from 0xProject/feature/pipeline-entities-documentation
Add documentation for some pipeline entities
2019-03-11 11:55:43 -07:00
Amir Bandeali
14b820f2c1 Merge pull request #1685 from merklejerk/fix/order-watcher/websocket-1.0.25
Upgrade to websocket@^1.0.26 to fix broken tests
2019-03-11 11:08:28 -07:00
Fabio Berger
9366fa3b45 Add CHANGELOG entries 2019-03-11 15:29:26 +01:00
Fabio Berger
d356e9e65f Add deploying Coordinator contracts to migration script 2019-03-11 14:38:51 +01:00
Fabio Berger
230ebffd0e Generate Coordinator contract wrappers and add to abi-gen-wrappers package 2019-03-11 14:38:35 +01:00
Fabio Berger
5eedc1edca Add Coordinator contracts to contract-artifacts package 2019-03-11 14:38:00 +01:00
Fabio Berger
fa6db9411b Remove unused file 2019-03-11 13:07:38 +01:00
askeluv
b88e42a52d Prettier 2019-03-11 14:33:17 +08:00
askeluv
8d1b27d130 Added entity tests 2019-03-11 14:31:51 +08:00
askeluv
1148d37102 Added comparison details to forks vs main branch 2019-03-11 14:10:08 +08:00
askeluv
88704ce417 Prettier 2019-03-08 20:07:26 +08:00
askeluv
9f69d2cb76 Third entity: Github fork 2019-03-08 20:04:03 +08:00
Lawrence
644f54bfba Update connect package as well because it was also asking for websocket@^1.0.25. 2019-03-08 02:20:23 -08:00
Lawrence
755c4da8cc Add PR 2019-03-08 01:39:45 -08:00
Lawrence
483c77fba8 Remove websocket@1.0.25 entry from yarn.lock so yarn installs websocket@^1.0.26.
Update order-watcher's websocket dependency from ^1.0.25 (broken on some node architectures) to ^1.0.26.
2019-03-08 01:26:28 -08:00
askeluv
55fd71c5e1 Second entity: Github pull request 2019-03-08 14:37:36 +08:00
askeluv
1991bd437f First entity: Github repo 2019-03-08 12:32:21 +08:00
Amir Bandeali
22af796302 Cleanup 2019-03-07 19:36:26 -08:00
Alex Browne
a70931ffbf Add documentation for some pipeline entities. 2019-03-07 18:28:57 -08:00
Amir Bandeali
2f7dd177c1 Update CHANGELOGs 2019-03-07 15:17:56 -08:00
Amir Bandeali
d35a053efd Update remaining contract Solidity versions to 0.5.5 2019-03-07 15:17:51 -08:00
Amir Bandeali
87cc1f9415 Update TEC solidity versions 2019-03-07 14:57:13 -08:00
Amir Bandeali
e7bb524362 Update dependencies and update solc types 2019-03-07 14:57:13 -08:00
Amir Bandeali
9e03e1c742 Merge pull request #1668 from 0xProject/feat/contracts/tec-txorigin-check
Add tx.origin to TEC approvals
2019-03-07 14:55:32 -08:00
Greg Hysen
6fbfcef1fa Merge pull request #1681 from 0xProject/update/codeowners
Updated codeowners
2019-03-07 14:29:57 -08:00
Amir Bandeali
9471510086 Optimize LibAddressArray and update CHANGELOG 2019-03-07 14:29:06 -08:00
Greg Hysen
56320468fd Updated codeowners 2019-03-07 14:16:08 -08:00
Amir Bandeali
53a70bbffb Change InvalidSender err to invalidOrigin 2019-03-07 13:58:50 -08:00
David Sun
4f2e547bd6 Merge pull request #1679 from dave4506/feature/website/add-ethFinex
Add svg file for ethfinex to website
2019-03-07 12:39:52 -08:00
David Sun
af82fa7b62 fixed row issues 2019-03-07 12:35:52 -08:00
Greg Hysen
6bd1a5ab80 Merge pull request #1675 from 0xProject/feature/contracts/TECRegistry-2
Coordinator Registry
2019-03-07 11:49:49 -08:00
Greg Hysen
93568f6fd0 Coordinator Registry + tests 2019-03-07 11:32:18 -08:00
David Sun
1a3bf81c19 linted + prettier 2019-03-07 11:21:30 -08:00
David Sun
2eeabe3998 add svg file for ethfinex 2019-03-07 11:08:25 -08:00
Amir Bandeali
b1d86a7a2d Update yarn.lock 2019-03-07 11:06:17 -08:00
Amir Bandeali
6cfc9ba47b Use != instead of < in loops 2019-03-07 10:56:12 -08:00
Amir Bandeali
350474540b Optimize for loops in LibAddressArray 2019-03-07 10:56:12 -08:00
Amir Bandeali
1136e58de7 Add txOrigin to approvals 2019-03-07 10:56:12 -08:00
Amir Bandeali
558ce4713c Optimize approval hashing 2019-03-07 10:34:10 -08:00
Amir Bandeali
69c6f50dfb Optimize transaction hashing 2019-03-07 10:30:17 -08:00
Greg Hysen
babe01321c Merge pull request #1677 from 0xProject/update/contracts/tecToCoordinator
Rename TEC to Coordinator in contracts
2019-03-07 10:28:47 -08:00
Greg Hysen
ff61dc4391 Updated coordinator name in package.json 2019-03-07 10:13:44 -08:00
Greg Hysen
4da6ede9d0 More tec -> coordinator changes 2019-03-07 10:11:15 -08:00
Greg Hysen
0b1bab873e Updated contracts-tec to contracts-coordinator in package.json 2019-03-07 09:47:59 -08:00
Greg Hysen
6c60341ce8 Changed coordinator domain name to "0x Protocol Coordinator" 2019-03-07 09:28:29 -08:00
Greg Hysen
e1c1878130 Ran linter 2019-03-07 09:11:26 -08:00
Greg Hysen
fea5a39740 Ran prettier 2019-03-07 08:57:30 -08:00
Greg Hysen
9f2221a885 Updated gitignore 2019-03-07 08:37:41 -08:00
Greg Hysen
977cd2505e updated constants for TEC to Coordinator rename 2019-03-07 08:34:11 -08:00
Greg Hysen
e3f85a7c0f Updated README for coordinator package 2019-03-07 08:34:11 -08:00
Greg Hysen
d81339722e Updated CHANGELOG for coordinator package 2019-03-07 08:34:11 -08:00
Greg Hysen
f5c09e02de Remaining TEC -> Coordinator renaming 2019-03-07 08:33:22 -08:00
Greg Hysen
5e102526ec Renamed tec package to coordinator package 2019-03-07 08:33:22 -08:00
Greg Hysen
3c2efd4b67 Rename TEC to Coordinator in contracts 2019-03-07 08:33:22 -08:00
Greg Hysen
7bb93a7c32 Merge pull request #1678 from 0xProject/fix/contracts/solidityUpgradeFix
Fix contracts after Solidity 0.5.5 update
2019-03-07 08:13:01 -08:00
Greg Hysen
ac8f4ae2f9 updated changelogs of contracts packages 2019-03-06 15:45:18 -08:00
Greg Hysen
1ff49188b1 Set evm version to byzantium to avoid using unsupported opcodes in solidity 0.5.5 2019-03-06 15:10:11 -08:00
David Sun
2c329023c2 Merge pull request #1666 from dave4506/feature/website/update-states
Updated stats on website
2019-03-03 18:49:24 -08:00
David Sun
4457a300bf updated 2019-03-03 18:48:37 -08:00
Leonid Logvinov
397496aff0 Publish
- 0x.js@6.0.3
 - @0x/abi-gen@2.0.6
 - @0x/abi-gen-wrappers@4.0.2
 - @0x/assert@2.0.6
 - @0x/asset-buyer@6.0.3
 - @0x/base-contract@5.0.2
 - @0x/connect@5.0.2
 - @0x/contract-wrappers@8.0.3
 - @0x/contracts-gen@1.0.5
 - @0x/dev-tools-pages@0.0.22
 - @0x/dev-utils@2.1.3
 - @0x/fill-scenarios@3.0.2
 - @0x/instant@1.0.17
 - @0x/json-schemas@3.0.6
 - @0x/metacoin@0.0.44
 - @0x/migrations@4.0.3
 - @0x/monorepo-scripts@1.0.27
 - @0x/order-utils@7.0.2
 - @0x/order-watcher@4.0.3
 - @0x/pipeline@1.0.14
 - @0x/react-docs@2.0.7
 - @0x/react-shared@2.0.7
 - @0x/sol-compiler@3.1.3
 - @0x/sol-coverage@3.0.0
 - @0x/sol-doc@2.0.7
 - @0x/sol-profiler@3.1.2
 - @0x/sol-trace@2.0.8
 - @0x/sol-tracing-utils@6.0.7
 - @0x/sra-spec@2.0.6
 - @0x/subproviders@4.0.2
 - @0x/testnet-faucets@1.0.73
 - @0x/utils@4.2.2
 - @0x/web3-wrapper@6.0.2
 - @0x/website@0.0.76
 - @0x/contracts-asset-proxy@1.0.9
 - @0x/contracts-erc20@1.0.9
 - @0x/contracts-erc721@1.0.9
 - @0x/contracts-exchange@1.0.9
 - @0x/contracts-exchange-forwarder@1.0.9
 - @0x/contracts-exchange-libs@1.1.3
 - @0x/contracts-extensions@2.0.8
 - @0x/contracts-multisig@2.0.8
 - @0x/contracts-tec@0.0.4
 - @0x/contracts-test-utils@3.0.8
 - @0x/contracts-utils@2.0.8
2019-03-01 14:34:26 -08:00
Leonid Logvinov
7458fe0d81 Updated CHANGELOGS 2019-03-01 14:34:15 -08:00
Leonid Logvinov
453c81f634 Merge pull request #1663 from 0xProject/fix/sol-profiler
Sol profiler improvements and bug fixes
2019-03-01 14:19:41 -08:00
Leonid Logvinov
eebce4b54d Fix linter errors 2019-03-01 13:59:56 -08:00
Fabio B
f7976e18f1 Update packages/sol-profiler/src/profiler_subprovider.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-03-01 13:46:47 -08:00
Fabio B
d951fe9988 Update packages/sol-tracing-utils/CHANGELOG.json
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-03-01 13:46:42 -08:00
Fabio B
fd4da78075 Update packages/sol-profiler/src/profiler_subprovider.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-03-01 13:46:35 -08:00
Fabio B
a025ae3f54 Update packages/sol-profiler/src/profiler_subprovider.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-03-01 13:46:27 -08:00
Jacob Evans
a75ba0d903 Merge pull request #1662 from 0xProject/bug/move-contracts-test-utils
Move contracts-test-utils to dev dependencies
2019-03-01 10:35:59 -05:00
Alex Svanevik
99318ae2ba Merge pull request #1658 from 0xProject/fix/pipeline/edps-rate-limiting
Added bottleneck for EDPS to deal with rate-limiting
2019-03-01 18:11:18 +08:00
Leonid Logvinov
8369bcb605 Fix linter issues 2019-02-28 22:37:32 -08:00
askeluv
338cc69034 Removed logging 2019-03-01 14:33:19 +08:00
Leonid Logvinov
4526c52fe8 Add PR numbers 2019-02-28 20:23:24 -08:00
Leonid Logvinov
81f9bda502 Add CHANGELOG entries 2019-02-28 20:19:47 -08:00
Leonid Logvinov
46bc5463ca Change the way we access the stack in traces 2019-02-28 20:19:05 -08:00
Leonid Logvinov
bb346537ba Make sol-profiler faster 2019-02-28 20:18:44 -08:00
F. Eugene Aumson
3b5f0d5c30 Adapt to Bloxy API change (#1659)
* Adapt to Bloxy API change

We were using the `days` parameter, but that's no longer available in
the API, so our fetching of previous days (before "today") was broken.

This change gets rid of the concept of "days", and uses the API's new
`from_date` and `till_date` parameters to fetch previous days' trades.

The change to the query in `getLastSeenTimestampAsync()` was necessary
because it was returning a string (despite the `as Array<{ tx_timestamp:
number }>` cast), which was later causing problems trying to pass that
value into `new Date()`.  It worked before because we were doing some
math operations on it (multiplying it by some numbers), so coercion was
saving us.  With the change from a raw query to a `typeorm` call, the
`numberToBigIntTransformer` specified in the `DexTrade` entity is now
doing the proper type conversion for us.

The new `MAX_DAYS` constant in `pull_competing_dex_trades.ts` is
necessary in order to avoid trying to pull data all the way back to 1969
:D, which induces the API to return an HTTP 503.

* Increase trades per query to match current API doc

This is needed in order to be able to pull more than a handful of days
of data at a time (at least, with the script the way its currently
written).
2019-02-28 20:28:00 -05:00
Leonid Logvinov
808ce969d9 Fix a bug with OpCode gas costs being incorrect or NaN 2019-02-28 16:53:59 -08:00
Leonid Logvinov
16f8339f3c Add HEX_BASE to constants 2019-02-28 16:52:18 -08:00
Leonid Logvinov
25d68c3904 Add opCodeToGasCost and opCodeToParamToStackOffset to constants 2019-02-28 16:51:29 -08:00
Leonid Logvinov
77ad8e1a80 Fix a bug when TruffleArtifactAdapter wasn't correctly parsing solc config in the pre 5.0 version of trufle 2019-02-28 16:46:08 -08:00
Jacob Evans
9e8c18075a Move fill-scenarios to devDependecies 2019-02-28 17:48:40 -05:00
Jacob Evans
4278cdfd29 Add CHANGELOG 2019-02-28 17:32:08 -05:00
Jacob Evans
142c2bd0f0 Move contracts-test-utils to dev dependencies 2019-02-28 16:50:23 -05:00
Jacob Evans
13ee8686bb Merge pull request #1660 from 0xProject/bug/log-utils-process
Check for process in browser environments
2019-02-28 16:45:54 -05:00
Jacob Evans
5c06df2635 Update changelog PR 2019-02-28 15:43:07 -05:00
Jacob Evans
d69bf76341 Update CHANGELOG 2019-02-28 15:28:09 -05:00
Jacob Evans
d0d1b295b4 Check for process in browser environments 2019-02-28 15:26:07 -05:00
askeluv
e450191548 Added bottleneck to deal with rate-limiting 2019-02-28 13:08:09 +08:00
Francesco Agosti
3aee83f3d8 Merge pull request #1633 from 0xProject/feature/pipeline/concepts-schema-and-radar-depth-table
[pipeline] Add concepts schema and radar orderbook USD price concept
2019-02-27 20:40:00 -08:00
fragosti
3610a2bc8d Run linter 2019-02-27 20:23:10 -08:00
fragosti
ab559d4620 Include new test path in package.json 2019-02-27 20:11:48 -08:00
fragosti
15d308d4c5 Remove isCli method 2019-02-27 19:34:35 -08:00
Alex Svanevik
e7ea66afb5 Merge pull request #1629 from 0xProject/etherscan-exchange-transactions
Pull exchange contract transactions from Etherscan
2019-02-28 08:30:05 +08:00
David Sun
d9a1d8bde6 Merge pull request #1655 from 0xProject/feature/extensions-page-freds-jank-pr-mirror
Feature/extensions page freds jank pr mirror
2019-02-27 16:38:41 -05:00
Leonid Logvinov
9ac4486403 Merge pull request #1656 from 0xProject/fix/1635
Allow project specific coverage ignore paths by specifying `config.ignoreFilesGlobs`
2019-02-27 13:35:11 -08:00
David Sun
428afabaa3 disabling lint for prettier 2019-02-27 16:21:00 -05:00
Leonid Logvinov
9162189fa6 Add PR numbers 2019-02-27 13:09:30 -08:00
Leonid Logvinov
154ca9b760 Merge branch 'development' into fix/1635 2019-02-27 13:09:04 -08:00
Leonid Logvinov
9fcead3973 Fix the docs 2019-02-27 13:07:03 -08:00
Leonid Logvinov
2fd9d0359c Ignore node_modules, test and interfaces coverage in contracts 2019-02-27 13:06:54 -08:00
Leonid Logvinov
4cf9e030a2 Add ignoreFilesGlobs config option to sol-coverage 2019-02-27 13:06:30 -08:00
David Sun
5570d14179 fixed build issues 2019-02-27 16:05:48 -05:00
David Sun
fd3c546994 changed links 2019-02-27 15:54:09 -05:00
Leonid Logvinov
e81ae05df9 Publish
- 0x.js@6.0.2
 - @0x/asset-buyer@6.0.2
 - @0x/contract-wrappers@8.0.2
 - @0x/instant@1.0.16
 - @0x/metacoin@0.0.43
 - @0x/migrations@4.0.2
 - @0x/order-watcher@4.0.2
 - @0x/pipeline@1.0.13
 - @0x/sol-compiler@3.1.2
 - @0x/sol-coverage@2.0.6
 - @0x/sol-doc@2.0.6
 - @0x/sol-profiler@3.1.1
 - @0x/sol-trace@2.0.7
 - @0x/sol-tracing-utils@6.0.6
 - @0x/testnet-faucets@1.0.72
 - @0x/website@0.0.75
 - @0x/contracts-asset-proxy@1.0.8
 - @0x/contracts-erc20@1.0.8
 - @0x/contracts-erc721@1.0.8
 - @0x/contracts-exchange@1.0.8
 - @0x/contracts-exchange-forwarder@1.0.8
 - @0x/contracts-exchange-libs@1.1.2
 - @0x/contracts-extensions@2.0.7
 - @0x/contracts-multisig@2.0.7
 - @0x/contracts-tec@0.0.3
 - @0x/contracts-test-utils@3.0.7
 - @0x/contracts-utils@2.0.7
2019-02-27 12:45:19 -08:00
Leonid Logvinov
cb394f3a1c Updated CHANGELOGS 2019-02-27 12:45:09 -08:00
David Sun
03ed057ff6 fixed linting + prettier issues 2019-02-27 15:34:24 -05:00
Leonid Logvinov
807290ff38 Merge pull request #1654 from 0xProject/fix/truffle-config-parsing
Fix a bug when TruffleArtifactAdapter was incorrectly parsing the truffle config of the newest version
2019-02-27 12:29:05 -08:00
Leonid Logvinov
40a4b4fa7a Add an explanatory comment 2019-02-27 12:28:41 -08:00
Leonid Logvinov
b7d2ad3651 Merge pull request #1653 from 0xProject/fix/remove-redundant-log
Remove redundant logging from sol-compiler
2019-02-27 12:26:45 -08:00
David Sun
faac286f70 fixed links 2019-02-27 15:21:07 -05:00
David Sun
c6c7f6f907 added title for extensions 2019-02-27 15:01:59 -05:00
fragosti
ccd0da58cb fix build errors 2019-02-27 11:34:04 -08:00
Francesco Agosti
500e5f1b5d Merge pull request #1630 from bakkenbaeck/website-updates
[WIP] Extensions page and tweaks to website
2019-02-27 11:09:57 -08:00
Fred Carlsen
ebb6177271 Update link to whitelist filter 2019-02-27 10:49:41 +01:00
Fred Carlsen
951c256980 Remove redundant fragment 2019-02-27 10:47:59 +01:00
Fred Carlsen
a134ef03dd Update illustrations and copy 2019-02-27 10:45:39 +01:00
Leonid Logvinov
f21a9d16d0 Fix a bug when TruffleArtifactAdapter was incorrectly parsing the truffle config of the newest version 2019-02-26 16:16:44 -08:00
fragosti
42c3bb00ec move to using require.main === module 2019-02-26 16:05:20 -08:00
Leonid Logvinov
0d0fcfe49a Remove redundant logging from sol-compiler 2019-02-26 15:03:06 -08:00
Leonid Logvinov
3f0db92be6 Fix prettier 2019-02-26 14:50:34 -08:00
Leonid Logvinov
ec24c79da1 Publish
- 0x.js@6.0.1
 - @0x/abi-gen@2.0.5
 - @0x/abi-gen-wrappers@4.0.1
 - @0x/assert@2.0.5
 - @0x/asset-buyer@6.0.1
 - @0x/base-contract@5.0.1
 - @0x/connect@5.0.1
 - @0x/contract-wrappers@8.0.1
 - @0x/contracts-gen@1.0.4
 - @0x/dev-tools-pages@0.0.21
 - @0x/dev-utils@2.1.2
 - @0x/fill-scenarios@3.0.1
 - @0x/instant@1.0.15
 - @0x/json-schemas@3.0.5
 - @0x/metacoin@0.0.42
 - @0x/migrations@4.0.1
 - @0x/monorepo-scripts@1.0.26
 - @0x/order-utils@7.0.1
 - @0x/order-watcher@4.0.1
 - @0x/pipeline@1.0.12
 - @0x/react-docs@2.0.6
 - @0x/react-shared@2.0.6
 - @0x/sol-compiler@3.1.1
 - @0x/sol-coverage@2.0.5
 - @0x/sol-doc@2.0.5
 - @0x/sol-profiler@3.1.0
 - @0x/sol-resolver@2.0.4
 - @0x/sol-trace@2.0.6
 - @0x/sol-tracing-utils@6.0.5
 - @0x/sra-spec@2.0.5
 - @0x/subproviders@4.0.1
 - @0x/testnet-faucets@1.0.71
 - @0x/types@2.1.1
 - @0x/utils@4.2.1
 - @0x/web3-wrapper@6.0.1
 - @0x/website@0.0.74
 - @0x/contracts-asset-proxy@1.0.7
 - @0x/contracts-erc20@1.0.7
 - @0x/contracts-erc721@1.0.7
 - @0x/contracts-exchange@1.0.7
 - @0x/contracts-exchange-forwarder@1.0.7
 - @0x/contracts-exchange-libs@1.1.1
 - @0x/contracts-extensions@2.0.6
 - @0x/contracts-multisig@2.0.6
 - @0x/contracts-tec@0.0.2
 - @0x/contracts-test-utils@3.0.6
 - @0x/contracts-utils@2.0.6
2019-02-26 14:45:52 -08:00
Leonid Logvinov
f5fffbea04 Updated CHANGELOGS 2019-02-26 14:45:42 -08:00
Amir Bandeali
fb0a2ef248 Merge pull request #1545 from 0xProject/feat/contracts/tec
TEC MVP
2019-02-26 14:24:30 -08:00
Leonid Logvinov
240f482e8e Merge pull request #1652 from 0xProject/fix/sol-compiler-settings
Fix a bug when combining sol-compiler settings from different sources
2019-02-26 14:15:37 -08:00
Leonid Logvinov
885031d3ce Add PR number 2019-02-26 14:15:23 -08:00
fragosti
eb212de70e run linter and add doc string 2019-02-26 14:05:18 -08:00
Amir Bandeali
68323d6def Fix geth tests 2019-02-26 14:00:21 -08:00
Leonid Logvinov
7c492071f1 Merge pull request #1647 from 0xProject/feature/sol-profiler-ganache
Sol-profiler ganache
2019-02-26 13:53:55 -08:00
fragosti
8fbdef2a1d Make job look at last timestamp, fix tests 2019-02-26 13:52:18 -08:00
Leonid Logvinov
8f64784781 Fix a bug when combining sol-compiler settings from different sources 2019-02-26 13:50:45 -08:00
David Sun
1bd6095c60 Merge pull request #1651 from dave4506/fix/website/add-temporary-seo
Added temporary metadata
2019-02-26 16:38:59 -05:00
David Sun
e133a5f0f3 added temporary metadata 2019-02-26 16:38:09 -05:00
Amir Bandeali
b47886416e Unpin deps when unnecessary 2019-02-26 13:29:18 -08:00
Amir Bandeali
c522d611d1 Fix typos 2019-02-26 13:29:18 -08:00
Amir Bandeali
f6d9b6b7aa Remove unused deps 2019-02-26 13:29:18 -08:00
Amir Bandeali
1de6bca12d Add TEC integration tests 2019-02-26 13:29:18 -08:00
Amir Bandeali
2de9b862d8 Add more verification test cases 2019-02-26 13:29:18 -08:00
Amir Bandeali
3c649df3df simplify approval verification logic 2019-02-26 13:29:18 -08:00
Amir Bandeali
9bf38d9e4d Add 'contains' function to LibAddressArray 2019-02-26 13:29:18 -08:00
Amir Bandeali
dee40f038d Add more approval verification tests 2019-02-26 13:29:18 -08:00
Amir Bandeali
d0aa907418 Add TEC revert reasons 2019-02-26 13:29:18 -08:00
Amir Bandeali
8dbdffc9b4 Fix abi decoding of 0x transaction data 2019-02-26 13:29:17 -08:00
Amir Bandeali
f409780455 Add ApprovalFactory class 2019-02-26 13:29:17 -08:00
Amir Bandeali
bebcd99b3b Add signature validator tests 2019-02-26 13:29:17 -08:00
Amir Bandeali
99aeaddf42 Make internal functions public 2019-02-26 13:29:17 -08:00
Amir Bandeali
793398216f Update deps versions 2019-02-26 13:29:17 -08:00
Amir Bandeali
b353ed3157 Update deps versions 2019-02-26 13:29:17 -08:00
Amir Bandeali
8637212a17 temp 2019-02-26 13:29:17 -08:00
Amir Bandeali
c42ce38e1c Bump dep versions 2019-02-26 13:29:17 -08:00
Amir Bandeali
76d228a603 Bump solidity version 2019-02-26 13:29:17 -08:00
Amir Bandeali
5cb52faa10 Do not verify orders with a null senderAddress 2019-02-26 13:29:17 -08:00
Amir Bandeali
e67e822845 Add tests for hashing libs 2019-02-26 13:29:17 -08:00
Amir Bandeali
a52686ca3b Fix README typos 2019-02-26 13:29:17 -08:00
Amir Bandeali
7a1e6cccfd Add public wrappers for libs 2019-02-26 13:29:17 -08:00
Amir Bandeali
1166b6c2fb Do not check approvals for orders where sender == feeRecipient 2019-02-26 13:29:17 -08:00
Amir Bandeali
7a6693694c Update README 2019-02-26 13:29:17 -08:00
Amir Bandeali
6ed423d1af Make all cancels permissionless 2019-02-26 13:29:17 -08:00
Amir Bandeali
8b69444602 Add tec package to relevant files 2019-02-26 13:29:17 -08:00
Amir Bandeali
7de5e8d9c8 Update READMEs 2019-02-26 13:29:17 -08:00
Amir Bandeali
844e3d1934 Implement TEC MVP 2019-02-26 13:29:17 -08:00
Amir Bandeali
9eafbbc0ae Update solidity versions of relevant contracts 2019-02-26 13:29:17 -08:00
Amir Bandeali
74677e3d54 Rename getTransactionHex to getTransactionHashHex for clarity 2019-02-26 13:29:17 -08:00
Amir Bandeali
57f4638742 Update CHANGELOGs 2019-02-26 13:29:17 -08:00
Amir Bandeali
c7a32f2d56 Update dep versions 2019-02-26 13:29:17 -08:00
Leonid Logvinov
d2dc64aa2d Rename idx to index 2019-02-26 13:25:26 -08:00
Fabio B
edb2a34c51 Update packages/sol-tracing-utils/src/utils.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-26 13:13:56 -08:00
Leonid Logvinov
dbd9b1c5c4 Add CHANGELOG entry 2019-02-26 11:00:37 -08:00
Leonid Logvinov
c3b758845d Refactor structLogs normalization to handle ganache 2019-02-26 10:55:58 -08:00
Leonid Logvinov
4d770549fc Fix stack content reporting in custom JS tracer 2019-02-26 10:55:40 -08:00
Leonid Logvinov
a67674bae1 Fix memory cost computing 2019-02-26 10:54:54 -08:00
Leonid Logvinov
462a61da73 Move structLogs normalization right after we fetch the trace 2019-02-26 10:54:00 -08:00
Leonid Logvinov
ae8a7f6320 Remove ganache profiling warning 2019-02-26 10:50:14 -08:00
Leonid Logvinov
a23c6a0996 Fix linter issues 2019-02-26 10:03:42 -08:00
Fred Carlsen
e6594cecce Fix jumping part of animated hero logo 2019-02-26 12:41:09 +01:00
askeluv
85ed5d27f5 Bumped up timeout to 4 mins 2019-02-26 19:37:59 +08:00
askeluv
6ac9e11245 Linting 2019-02-26 11:46:21 +08:00
askeluv
9fbd809344 Improved testing - added fixtures 2019-02-26 11:42:53 +08:00
David Sun
63a098d757 Merge pull request #1643 from dave4506/feature/remove-website-vote
Removed announcement
2019-02-25 20:23:18 -05:00
David Sun
b68d9ed672 removed announcement 2019-02-25 20:21:49 -05:00
Leonid Logvinov
5934eb0559 Publish
- 0x.js@6.0.0
 - @0x/abi-gen@2.0.4
 - @0x/abi-gen-templates@2.0.1
 - @0x/abi-gen-wrappers@4.0.0
 - @0x/assert@2.0.4
 - @0x/asset-buyer@6.0.0
 - @0x/base-contract@5.0.0
 - @0x/connect@5.0.0
 - @0x/contract-addresses@2.2.2
 - @0x/contract-wrappers@8.0.0
 - @0x/contracts-gen@1.0.3
 - @0x/dev-tools-pages@0.0.20
 - @0x/dev-utils@2.1.1
 - ethereum-types@2.1.0
 - @0x/fill-scenarios@3.0.0
 - @0x/instant@1.0.14
 - @0x/json-schemas@3.0.4
 - @0x/metacoin@0.0.41
 - @0x/migrations@4.0.0
 - @0x/monorepo-scripts@1.0.25
 - @0x/order-utils@7.0.0
 - @0x/order-watcher@4.0.0
 - @0x/pipeline@1.0.11
 - @0x/react-docs@2.0.5
 - @0x/react-shared@2.0.5
 - @0x/sol-compiler@3.1.0
 - @0x/sol-coverage@2.0.4
 - @0x/sol-doc@2.0.4
 - @0x/sol-profiler@3.0.0
 - @0x/sol-resolver@2.0.3
 - @0x/sol-trace@2.0.5
 - @0x/sol-tracing-utils@6.0.4
 - @0x/sra-spec@2.0.4
 - @0x/subproviders@4.0.0
 - @0x/testnet-faucets@1.0.70
 - @0x/types@2.1.0
 - @0x/typescript-typings@4.1.0
 - @0x/utils@4.2.0
 - @0x/web3-wrapper@6.0.0
 - @0x/website@0.0.73
 - @0x/contracts-asset-proxy@1.0.6
 - @0x/contracts-erc20@1.0.6
 - @0x/contracts-erc721@1.0.6
 - @0x/contracts-exchange@1.0.6
 - @0x/contracts-exchange-forwarder@1.0.6
 - @0x/contracts-exchange-libs@1.1.0
 - @0x/contracts-extensions@2.0.5
 - @0x/contracts-multisig@2.0.5
 - @0x/contracts-test-utils@3.0.5
 - @0x/contracts-utils@2.0.5
2019-02-25 13:35:29 -08:00
Leonid Logvinov
b998d719a6 Updated CHANGELOGS 2019-02-25 13:35:17 -08:00
Leonid Logvinov
33832244cf Merge pull request #1638 from 0xProject/feature/sol-profiler-improvements
Sol profiler improvements
2019-02-25 13:19:51 -08:00
Fabio B
df8ea3b65c Merge pull request #1641 from 0xProject/fixAddresses
Fix OrderValidator and Forwarder addresses in Python package
2019-02-25 15:57:21 -05:00
Leonid Logvinov
7067d4a499 Fix prettier 2019-02-25 12:53:42 -08:00
Leonid Logvinov
3e764eafd9 Use contracts-test-utils in metacoin 2019-02-25 12:52:21 -08:00
Leonid Logvinov
4169a41eda Rename traceInfo.data to traceInfo.dataIfExists 2019-02-25 12:40:10 -08:00
Leonid Logvinov
379eab19ad FIx CHANGELOGs 2019-02-25 12:35:57 -08:00
Fabio B
6cba1f3b61 Update packages/sol-profiler/CHANGELOG.json
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-25 12:34:18 -08:00
Fabio B
5dad2404d3 Update packages/ethereum-types/src/index.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-25 12:33:58 -08:00
Fabio B
a1b20eea2c Update packages/ethereum-types/src/index.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-25 12:33:50 -08:00
Fabio Berger
af075e7b8b Fix OrderValidator and Forwarder addresses in Python package 2019-02-25 15:05:18 -05:00
Amir Bandeali
ef0a699919 Merge pull request #1604 from 0xProject/feat/exchange-libs/solc5.0
Update exchange-libs and utils Solidity versions + bugfix
2019-02-25 10:29:52 -08:00
Amir Bandeali
8279ef0e05 Add more slice tests 2019-02-25 10:12:59 -08:00
Amir Bandeali
c1cee8e951 Run lerna link before building 2019-02-25 09:59:25 -08:00
Amir Bandeali
4c17373311 Update dep versions 2019-02-25 09:59:25 -08:00
Amir Bandeali
c20972de3f Update CHANGELOGs 2019-02-25 09:59:25 -08:00
Amir Bandeali
64401f1031 Fix bug in slice functions that disallow slicing the last byte of a byte array 2019-02-25 09:59:25 -08:00
Amir Bandeali
1f895d0f27 Make constants internal 2019-02-25 09:59:25 -08:00
Amir Bandeali
5aa8ea10c3 Upgrade solc version to 0.5.3 for exchange-libs and utils 2019-02-25 09:59:25 -08:00
Fred Carlsen
cf65d4a909 Prettier fixes 2019-02-25 15:32:57 +01:00
Fred Carlsen
079f627b34 Fix linting issues 2019-02-25 15:29:24 +01:00
Fred Carlsen
f6c6cbc343 Constrain icon size to container 2019-02-25 15:22:48 +01:00
Fred Carlsen
c6cdea77b6 Fix website errors related to props/children 2019-02-25 15:22:35 +01:00
Jacob Evans
b1fd3429ae Merge pull request #1639 from 0xProject/vote/zeip-23-pst-end-date
Change vote end date to end on PST 25/02/2019
2019-02-24 12:29:07 -08:00
Jacob Evans
dc161ef08d Change vote end date to end on PST 25/02/2019 2019-02-24 12:01:45 -08:00
Leonid Logvinov
9502e789b3 Move constants up 2019-02-22 19:47:29 -08:00
Leonid Logvinov
a71aed0233 Run prettier 2019-02-22 18:16:38 -08:00
Leonid Logvinov
eda8dc278b Remove excesive exports 2019-02-22 18:01:19 -08:00
Leonid Logvinov
23a7ffb167 Fix linter 2019-02-22 17:35:14 -08:00
Leonid Logvinov
ab11aaa694 Export ContractAbi from sol-tracing-utils 2019-02-22 16:58:57 -08:00
Leonid Logvinov
83b5a2709d Remove commented code 2019-02-22 16:57:50 -08:00
Leonid Logvinov
f67f94fd6b Rename logHeader to header 2019-02-22 16:28:04 -08:00
Leonid Logvinov
4e8ae037bb Add PR numbers 2019-02-22 16:23:04 -08:00
Leonid Logvinov
04d8f46ff3 Major sol-profiler overhaul 2019-02-22 16:16:03 -08:00
fragosti
3191de68b8 Fix typo in query 2019-02-22 16:13:48 -08:00
Leonid Logvinov
047de370d6 Add logUtils.table and logUtils.header 2019-02-22 16:12:34 -08:00
Leonid Logvinov
e21dc5f026 Add all existing opcodes to OpCode 2019-02-22 16:06:55 -08:00
fragosti
f3da56773e Run prettier 2019-02-22 12:02:58 -08:00
fragosti
5197758579 Add missing file 2019-02-22 10:36:30 -08:00
Fred Carlsen
d48af7c4c2 Add icons 2019-02-22 13:42:17 +01:00
Fred Carlsen
bbafe0fc46 Add link to extensions in footer 2019-02-22 13:27:18 +01:00
Fred Carlsen
9a91f917e0 Tweak cards + add links 2019-02-22 13:03:30 +01:00
Fred Carlsen
1f681f02ae More cleanup 2019-02-22 11:23:55 +01:00
Fred Carlsen
778a86e7eb Fix linting issues 2019-02-22 11:18:04 +01:00
Fabio B
78da033441 Merge pull request #1627 from 0xProject/supportEIP1193Providers
Support EIP1193 provider interface
2019-02-21 20:26:25 -08:00
askeluv
6eb923d22f Throw error when API key is missing + use response in parser test 2019-02-22 11:21:33 +08:00
fragosti
e602afcd5f add documentation 2019-02-21 18:24:11 -08:00
askeluv
bf1115d417 Backfills automatically + prettier 2019-02-22 09:45:25 +08:00
Fabio Berger
b51038b9e7 Merge branch 'development' into supportEIP1193Providers
* development:
  Demonstrate calling contracts with tuple arrays (#1615)
  removed default meta tags in public/index.html
  fixed linting issue
  updated documentTitle component
  added metadata for pages (incomplete)
  fixed title comment-out
  removed react-document-title in favor of using react-helmet for consistency and bug fix
2019-02-21 16:45:00 -08:00
Fabio Berger
44e0b58c66 Fix migration exported types 2019-02-21 16:44:38 -08:00
Fabio Berger
3f7d5274a2 Fix version 2019-02-21 16:29:50 -08:00
Fabio Berger
c8f5f6045e Fix CI failures 2019-02-21 16:27:38 -08:00
F. Eugene Aumson
6bcc2064a2 Demonstrate calling contracts with tuple arrays (#1615) 2019-02-21 16:24:54 -08:00
Fabio Berger
3f9872d8b3 Remove getZeroExProvider method since it can be confusing 2019-02-21 16:07:23 -08:00
Fabio Berger
5814cd5fae Export supportedProvider in interface since this package is also used by external devs 2019-02-21 16:04:11 -08:00
Fabio Berger
44f8c7c548 Add TODO about consolidating type checks 2019-02-21 16:03:51 -08:00
Fabio Berger
c2549308fe Remove superfluous standardization 2019-02-21 16:00:44 -08:00
Fabio Berger
cf1a3bf4e7 Fix node types version in monorepo-scripts since it's used in test-installation and the latest version has a bug 2019-02-21 15:58:02 -08:00
fragosti
f5d668af31 Add radar_orderbook_usd_prices concept 2019-02-21 15:45:36 -08:00
Fabio Berger
b7bd4e5c51 Try fixing publish ci failure 2019-02-21 15:26:35 -08:00
fragosti
62373f969c Add concepts migrations 2019-02-21 12:51:27 -08:00
David Sun
ceb651fdd1 Merge pull request #1631 from dave4506/fix/website/remove-deplicate-meta-tags
Removed default meta tags in public/index.html
2019-02-21 10:43:40 -05:00
David Sun
8fa0f4a232 removed default meta tags in public/index.html 2019-02-21 10:20:29 -05:00
Fred Carlsen
30f2e3b606 Remove placeholder extensions 2019-02-21 13:49:35 +01:00
Fred Carlsen
7d3d997083 Merge remote-tracking branch 'upstream/development' into website-updates 2019-02-21 13:45:40 +01:00
Fred Carlsen
3955e2c84a Tweak padding 2019-02-21 13:43:47 +01:00
Fred Carlsen
6a6c41df26 Tweak extensions width 2019-02-21 13:42:03 +01:00
Fred Carlsen
1dfd2aec50 Tweak banner 2019-02-21 13:41:33 +01:00
askeluv
8885f543ae Pull exchange contract transactions from Etherscan 2019-02-21 20:37:55 +08:00
Fred Carlsen
8804e6c2ca Tweak banner 2019-02-21 11:17:01 +01:00
Fred Carlsen
88b7c214f7 Add extensions page 2019-02-21 11:16:52 +01:00
David Sun
297f3da5db Merge pull request #1626 from dave4506/fix/website/document-title-consistency-issue
Fix bug with document titles + add rich metadata for documents
2019-02-20 23:42:41 -05:00
David Sun
ec4d634677 fixed linting issue 2019-02-20 23:24:05 -05:00
David Sun
0ddec99704 updated documentTitle component 2019-02-20 23:08:04 -05:00
Fabio Berger
64cec1de3b Major version bump packages with modified exported type definitions 2019-02-20 18:07:01 -08:00
Fabio Berger
fdaf5d1fc8 Merge branch 'development' into supportEIP1193Providers
* development:
  Add constraint name to down phase as well
  Give the constraint an explicit name of token_orderbook_snapshots_pkey
  Remove comments
  Fix inconsistently named constraint
2019-02-20 18:01:23 -08:00
Fabio Berger
6baf71dca5 Make deprecation notice a warning message if used 2019-02-20 18:00:43 -08:00
Fabio Berger
9d75a72a02 Add back test 2019-02-20 17:59:53 -08:00
Francesco Agosti
4bf66d6a63 Merge pull request #1628 from 0xProject/fix/pipeline/fix-test-db-incorrectly-named-constraint
Fix inconsistently named constraint in migration
2019-02-20 17:17:16 -08:00
fragosti
8d9a550107 Add constraint name to down phase as well 2019-02-20 17:01:02 -08:00
fragosti
a076278026 Give the constraint an explicit name of token_orderbook_snapshots_pkey 2019-02-20 16:37:44 -08:00
fragosti
998dac44ee Remove comments 2019-02-20 16:09:33 -08:00
fragosti
871e81bd71 Fix inconsistently named constraint 2019-02-20 16:03:29 -08:00
Fabio Berger
d892d16b51 Merge branch 'development' into supportEIP1193Providers
* development: (37 commits)
  Factor out redundant source param in parse order functions
  Fix marquee typo
  Throw error if cannot find error in table
  Integrate one-time dump and API for nonfungible.com (#1603)
  Change optional text props to mandatory in LedgerSignNote
  Add radar_orders parseRadarOrder test
  Add parser test for Radar orderbook parsing
  Moved calculateSlippage from parsers to transformers
  Show greater than less than when minority has a vote
  Prettier
  Recieved -> Received
  Fix style for address table
  Hide ledger sign note on error
  Revert broken formatting
  Added ledger sign notification
  Fix bug in ledger address selector where provider does not exist.
  fix null column constraint issue
  Add parsing radar order test
  Rename migration to what it is called on prod and qa
  Fix type bug around Radar response
  ...
2019-02-20 14:52:58 -08:00
Fabio Berger
4cbf2781e5 Fix types so docs render 2019-02-20 14:31:40 -08:00
Fabio Berger
69653b1c7c Fix yarn.lock 2019-02-20 14:31:31 -08:00
Francesco Agosti
39390865da Merge pull request #1612 from 0xProject/feature/pipeline/add-radar
[pipeline] Add Radar orders and maker_address column to token_orderbook_snapshots
2019-02-20 14:17:42 -08:00
fragosti
4952cd5afb Factor out redundant source param in parse order functions 2019-02-20 13:45:14 -08:00
Fabio Berger
e86df96bfe Fix doc gen 2019-02-20 13:20:32 -08:00
fragosti
ef5195db90 Fix marquee typo 2019-02-20 11:43:32 -08:00
fragosti
bc7e62db9f Throw error if cannot find error in table 2019-02-20 11:40:49 -08:00
Fred Carlsen
9a7ccc20e8 Add new 404 page 2019-02-20 16:41:42 +01:00
Alex Svanevik
154e7a6a8a Merge pull request #1601 from askeluv/feature/pipeline/edps-slippage
Slippage calculations from Ethereum DEX Prices Service (EDPS)
2019-02-20 22:51:23 +08:00
Fabio Berger
ba56019f2d Add missing exported types 2019-02-19 23:59:12 -08:00
Fabio Berger
31d289c504 Add type import 2019-02-19 23:56:28 -08:00
Fabio Berger
a42b22966a Standardize bowser deps 2019-02-19 23:41:30 -08:00
Fabio Berger
17db62d463 Standardize web3-provider-engine deps 2019-02-19 23:40:45 -08:00
Fabio Berger
d6d40ea839 Improve commenty 2019-02-19 23:38:58 -08:00
Fabio Berger
eca8410dbb Update CHANGELOGs 2019-02-19 23:38:53 -08:00
Fabio Berger
eb3a530e6c Fix website build 2019-02-19 23:20:38 -08:00
Fabio Berger
26e17074c2 Fix linter issues 2019-02-19 23:09:26 -08:00
Fabio Berger
6b775628d5 Prettier fixes 2019-02-19 22:48:09 -08:00
Fabio Berger
13eb9103a7 Add back support for Web3@1.0-beta-37 and below 2019-02-19 22:48:02 -08:00
Fabio Berger
1fa82c1077 Fix up missing Provider interfaces and refactor providerUtils.standardizeOrThrow() 2019-02-19 22:34:31 -08:00
David Sun
426190181b added metadata for pages (incomplete) 2019-02-19 23:33:48 -05:00
F. Eugene Aumson
1232a9a03d Integrate one-time dump and API for nonfungible.com (#1603)
* Add script for pulling NFT trade data from nonfungible.com

* corrections for current state of API

* change data model to match data source

* change primary key

* pull data from initial dump first, then API

* pull all supported NFT's, not just cryptokitties

* disable problematic data sources

* rename function to satisfy linter

* Rename table to nonfungible_dot_com_trades

* rename parser module to nonfungible_dot_com from non_fungible_dot_com, for consistency

* correct mistaken reference to Bloxy

* rename NonfungibleDotComTrade to ...TradeResponse

* `NftTrade` -> `NonfungibleDotComTrade`

* rename files to match prior object renaming

* use fetchAsync instead of axios

* improve fetchAsync error message: include URL

* avoid non-null contraints in API trades too, not just for trades from the one-time dump

* disable mythereum publisher
2019-02-19 19:07:42 -08:00
Jacob Evans
e643c13292 Merge pull request #1622 from 0xProject/fix/governance-ledger-provider
[Governance] Ledger address selector ZRX balance
2019-02-19 17:52:42 -08:00
Jacob Evans
522736e367 Change optional text props to mandatory in LedgerSignNote 2019-02-19 17:34:06 -08:00
fragosti
12fd9c29f0 Add radar_orders parseRadarOrder test 2019-02-19 17:19:12 -08:00
fragosti
0c871b67ca Add parser test for Radar orderbook parsing 2019-02-19 16:58:11 -08:00
askeluv
379e828fc1 Moved calculateSlippage from parsers to transformers 2019-02-20 08:55:21 +08:00
Fabio Berger
fe1e8575ea Fix comments 2019-02-19 16:35:14 -08:00
Fabio Berger
8f14099adc Put all Web3.js provider interfaces next to eachother 2019-02-19 16:17:14 -08:00
Fabio Berger
852c1396ae Fix comments 2019-02-19 16:16:56 -08:00
Fabio Berger
b0f9195b57 merge development 2019-02-19 16:02:41 -08:00
Fabio Berger
98236736e0 Fix remaining Provider to SupportedProvider type 2019-02-19 15:25:47 -08:00
Jacob Evans
8b93a2816c Show greater than less than when minority has a vote 2019-02-19 14:53:18 -08:00
Leonid Logvinov
76d8a991c0 Merge pull request #1625 from 0xProject/feature/sol-compiler-offline
Sol-compiler offline mode
2019-02-19 14:21:09 -08:00
Leonid Logvinov
9186af1433 Fix a PR number 2019-02-19 14:20:13 -08:00
Alex Browne
6a473f4c57 Merge pull request #1617 from 0xProject/fix/devnet-readme-dockerhub
Update README for devnet
2019-02-19 13:47:46 -08:00
Alex Browne
42224ab534 Update README.md 2019-02-19 13:46:48 -08:00
Fabio Berger
20bcf09459 Modify providerUtils such that it simply guarentees a common sendAsync method but does not create a new instance since website depends on other properties being available 2019-02-19 13:25:57 -08:00
David Sun
5d1dd536e9 fixed title comment-out 2019-02-19 16:13:26 -05:00
David Sun
169b8807f7 removed react-document-title in favor of using react-helmet for consistency and bug fix 2019-02-19 16:10:35 -05:00
Jacob Evans
5acdab849e Prettier 2019-02-19 13:09:05 -08:00
Fabio Berger
2417084145 Rename public interface provider to supportedProvider and our internal provider to Provider 2019-02-19 12:47:01 -08:00
Jacob Evans
c16e62b5bf Recieved -> Received 2019-02-19 11:28:09 -08:00
Leonid Logvinov
6fa7d90f1f Define offlineMode as false in all smart contracts packages 2019-02-19 10:38:24 -08:00
Leonid Logvinov
1a3fd0227d Implement sol-compiler offline mode 2019-02-19 10:35:52 -08:00
Steve Klebanoff
2259b7dfcf Merge pull request #1624 from 0xProject/fix/instant-svg
[instant] Reset svg style
2019-02-19 10:08:47 -08:00
Steve Klebanoff
33fd70d0e1 reset svg because etherscan has a global svg style 2019-02-19 09:40:25 -08:00
Jacob Evans
fc906bcaae Governance tweaks 2019-02-19 09:23:28 -08:00
Jacob Evans
184e111e39 Fix style for address table 2019-02-19 09:12:29 -08:00
Fred Carlsen
ab62f50f5c Hide ledger sign note on error 2019-02-19 15:53:07 +01:00
Fred Carlsen
3eac854356 Revert broken formatting 2019-02-19 15:20:47 +01:00
Fred Carlsen
f7892cd86b Merge remote-tracking branch 'upstream/development' into governance-tweaks 2019-02-19 13:32:43 +01:00
Fred Carlsen
6e0260385c Added ledger sign notification 2019-02-19 13:32:25 +01:00
Jacob Evans
44300dabb0 Fix bug in ledger address selector where provider does not exist.
This can happen in browsers without metamask or a injected provider
2019-02-18 20:04:55 -08:00
David Sun
580c3038c8 Merge pull request #1621 from dave4506/fix/website/announcement-spacing
Added padding fix to announcements
2019-02-18 21:45:02 -05:00
David Sun
2a9175e964 added padding fix 2019-02-18 20:55:27 -05:00
Fabio Berger
5db20bbbe8 Add support for EIP1193 providers and clean up provider standardization logic 2019-02-18 15:12:29 -08:00
David Sun
ae144dff39 Merge pull request #1619 from dave4506/feature/website/add-banner-component
Adding announcement component for hero (for vote)
2019-02-18 09:13:57 -05:00
Jacob Evans
9f533efc92 Merge pull request #1620 from 0xProject/governance-vote-updates
Governance vote updates
2019-02-18 00:53:14 -08:00
Jacob Evans
76e15c4166 Yarn lock update 2019-02-18 00:41:36 -08:00
Jacob Evans
62bb2daf16 Add og-zeip23 for social sharing 2019-02-18 00:14:05 -08:00
Jacob Evans
59e292030a Update I voted badge svg 2019-02-18 00:08:55 -08:00
Jacob Evans
533fc7e444 Remove unused input 2019-02-17 23:31:02 -08:00
Jacob Evans
e5c5338eb6 Add governance to the footer 2019-02-17 23:29:47 -08:00
Jacob Evans
9463acb131 Update copy of Risk 2019-02-17 23:12:22 -08:00
Jacob Evans
e69749350b Update the formatting of ZRX (showing whole ZRX) 2019-02-17 23:09:45 -08:00
Jacob Evans
42749187ff Update copy on the banner 2019-02-17 22:51:42 -08:00
Jacob Evans
d5c2038d58 Update copy on the governance page 2019-02-17 22:24:38 -08:00
Jacob Evans
5843a61c9f Remove rounding (up) in total balance string 2019-02-17 22:16:56 -08:00
Jacob Evans
ecde2c9d7f Add todos for cleanup on duplicated code. Fix styling and typo 2019-02-17 21:53:25 -08:00
Jacob Evans
abd597c7a6 Update ZEIP from strings to numbers 2019-02-17 18:24:48 -08:00
Jacob Evans
b35e1d350b Remove unused 2019-02-17 13:26:27 -08:00
Jacob Evans
918399458d Submit the voting comment 2019-02-17 13:24:27 -08:00
Jacob Evans
72d9b7028b Handle Coinbase wallet inconsitency 2019-02-17 13:06:29 -08:00
Jacob Evans
ed9790c840 Vote: Added instant. Updated failure modes 2019-02-17 12:22:29 -08:00
Fred Carlsen
fd04bc4820 Fix linting errors 2019-02-17 12:22:29 -08:00
Fred Carlsen
58a213b7f9 Prevent overflowing content on error modal 2019-02-17 12:22:29 -08:00
Fred Carlsen
7f8bbfb4bd Fallback from EIP712 when signing 2019-02-17 12:22:29 -08:00
Fred Carlsen
8a3e64b3cd Update tally when user votes 2019-02-17 12:22:29 -08:00
Fred Carlsen
572de86d06 Add error modal 2019-02-17 12:22:28 -08:00
Fred Carlsen
88c33fa4d4 Add default color to icons 2019-02-17 12:22:28 -08:00
Jacob Evans
ee1c6a1ce1 Update copy
Co-Authored-By: sjelfull <fred@sjelfull.no>
2019-02-17 12:22:28 -08:00
Jacob Evans
09e90bea8b Update proposal title
Co-Authored-By: sjelfull <fred@sjelfull.no>
2019-02-17 12:22:28 -08:00
Fred Carlsen
bf758412c1 Import SignatureType from @0x/types 2019-02-17 12:22:28 -08:00
Fred Carlsen
0bbbf5b431 Fix no tally to prevent rounding 2019-02-17 12:22:27 -08:00
Fred Carlsen
87b2236cfb Cleanup 2019-02-17 12:22:27 -08:00
Fred Carlsen
855d2bb87f Add suffix to const name 2019-02-17 12:22:27 -08:00
Fred Carlsen
13b54a3b4d Remove Kovan prefix 2019-02-17 12:22:27 -08:00
Fred Carlsen
5d24ef4849 Remove web3 types 2019-02-17 12:22:27 -08:00
Fred Carlsen
b2da451e8d Tweak tabel formating of addres table 2019-02-17 12:22:27 -08:00
Fred Carlsen
139b66fa76 Format more links 2019-02-17 12:22:26 -08:00
Fred Carlsen
390ed5d7f1 Fix countdown and format in locale aware date 2019-02-17 12:22:26 -08:00
Fred Carlsen
16b5fb6b56 Fix countdown 2019-02-17 12:22:26 -08:00
Fred Carlsen
6205d6c885 Fix linting errors 2019-02-17 12:22:26 -08:00
Fred Carlsen
e5ea65da82 Cleanup unused parts 2019-02-17 12:22:12 -08:00
Fred Carlsen
9caa5feff5 Add derivation path change 2019-02-17 12:22:11 -08:00
Fred Carlsen
7f616356d2 Reset to voting screen when done 2019-02-17 12:21:40 -08:00
Fred Carlsen
155b5dd42f Tweak whitespace 2019-02-17 12:21:40 -08:00
Fred Carlsen
41aaf428bf Cleanup 2019-02-17 12:21:40 -08:00
Fred Carlsen
a17cdf33ea Fire onvoted callback 2019-02-17 12:21:39 -08:00
Fred Carlsen
3d5e879d5f Fix tally 2019-02-17 12:21:39 -08:00
Fred Carlsen
1a73ad3a32 Fix React errors on modal 2019-02-17 12:21:39 -08:00
Fred Carlsen
abb5e7cd39 Fix key on links 2019-02-17 12:21:39 -08:00
Fred Carlsen
cdae6de52e Lint 2019-02-17 12:21:39 -08:00
Fred Carlsen
910fe77ca3 Fix error 2019-02-17 12:21:39 -08:00
Fred Carlsen
b9a93c82d7 Linting fixes 2019-02-17 12:21:38 -08:00
Fred Carlsen
1c040bd616 Rename variable 2019-02-17 12:21:38 -08:00
Fred Carlsen
166c537938 Show balance on confirmation step 2019-02-17 12:21:38 -08:00
Fred Carlsen
79c8de5fd0 Update tally endpoint 2019-02-17 12:21:38 -08:00
Fred Carlsen
7e6d2102a5 Remove back button 2019-02-17 12:21:37 -08:00
Fred Carlsen
4f7d6132fc Remove python code 2019-02-17 12:21:37 -08:00
Fred Carlsen
b7fcc70cd9 Prettier + close button 2019-02-17 12:21:37 -08:00
Fred Carlsen
43ad27931c Update content base 2019-02-17 12:21:37 -08:00
Fred Carlsen
68dc3f75eb Use AWS endpoint when deployed 2019-02-17 12:21:37 -08:00
Fred Carlsen
e67eb6d5b4 Set strong to bold fontweight 2019-02-17 12:21:37 -08:00
Fred Carlsen
2e060bc85f Initial governance commit 2019-02-17 12:21:36 -08:00
Fred Carlsen
22f80e4b19 Fix type 2019-02-17 12:20:09 -08:00
Fred Carlsen
1ef434f95e WIP governance page 2019-02-17 12:20:08 -08:00
Tristan King
5676702da6 Add initial v0x backend and test frontend 2019-02-17 12:19:32 -08:00
David Sun
2fe0539600 added spacing + mobile changes 2019-02-16 22:34:50 -05:00
David Sun
13df5adecd added announcement component 2019-02-15 13:24:28 -05:00
fragosti
f33f808dc7 fix null column constraint issue 2019-02-14 17:17:35 -08:00
Francesco Agosti
82ed9ef25e Merge pull request #1618 from dave4506/bug/website/credit-leads-fix
Fix for credit lead form data
2019-02-14 17:15:23 -08:00
David Sun
0aa26d791d fix for credit lead form data 2019-02-14 20:14:37 -05:00
Alex Browne
255f278f5e Update README for devnet 2019-02-14 16:57:02 -08:00
Leonid Logvinov
1c76f9a0ff Merge pull request #1616 from 0xProject/feature/devnode-ws
Add WS endpoint to devnode
2019-02-15 01:47:29 +01:00
Leonid Logvinov
9a308e25a3 Add WS endpoint to devnode 2019-02-14 16:41:24 -08:00
David Sun
4b52f8c823 Merge pull request #1610 from dave4506/feature/website/infrastructure-deals
Infrastructure deals page
2019-02-14 18:21:09 -05:00
fragosti
8f7145f80a Add parsing radar order test 2019-02-14 15:07:09 -08:00
David Sun
eb17f053f7 Merged latest development to branch 2019-02-14 16:22:18 -05:00
David Sun
304e714331 changes to spacing 2019-02-14 16:02:39 -05:00
David Sun
525685f942 fixed code styling 2019-02-14 15:51:48 -05:00
David Sun
e2477b66c6 added polish to copy and mobile bugs 2019-02-14 15:36:58 -05:00
fragosti
58d51e039c Rename migration to what it is called on prod and qa 2019-02-14 10:45:48 -08:00
fragosti
cb5b5167fc Fix type bug around Radar response 2019-02-14 10:40:10 -08:00
fragosti
7d68378c3c Fix volume calculation bug 2019-02-14 09:40:38 -08:00
fragosti
87da6a947d Have migration to maker_address column working 2019-02-14 09:22:50 -08:00
askeluv
0e644da6ac Fixed linting issues 2019-02-14 17:39:12 +08:00
askeluv
d61a7c360e Self-hosted EDPS 2019-02-14 17:12:31 +08:00
askeluv
ab286d851d Changed Maps to EdpsWrappers 2019-02-14 15:30:58 +08:00
fragosti
e8b60ab292 Use remainingFillableAmount instead of maker/takerAssetAmount for amount field for Radar orders 2019-02-13 13:41:20 -08:00
fragosti
1cb7e70b42 increment MAX_PER_PAGE to 10000 2019-02-13 13:31:45 -08:00
Francesco Agosti
25b9c22845 Merge pull request #1614 from 0xProject/feature/website/faux-vote-page
Add vote placeholder page
2019-02-13 12:26:12 -08:00
fragosti
47166104fa run linter 2019-02-13 12:01:53 -08:00
fragosti
d0e0622058 PR feedback 2019-02-13 11:38:39 -08:00
fragosti
87c75a1e43 Add vote placeholder page 2019-02-13 11:25:18 -08:00
fragosti
d1cc08f1d9 Attempt to add maker_address token_orderbook_snapshots 2019-02-13 11:03:40 -08:00
David Sun
6619626486 changed dogfood s3 bucket and fixed linting issues 2019-02-13 12:14:13 -05:00
David Sun
1681ba090c changed check box 2019-02-13 11:35:05 -05:00
askeluv
c36e1ad056 Changes made as per comments - still have two minor things to fix 2019-02-13 20:23:07 +08:00
fragosti
d79c7f70be fix linting error 2019-02-12 14:58:05 -08:00
fragosti
b7eb2e4746 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/pipeline/add-radar 2019-02-12 14:56:02 -08:00
fragosti
4db9b8b0e3 Add script for pulling radar orderbook 2019-02-12 14:49:32 -08:00
fragosti
f3a537d5c2 Add radar parser 2019-02-12 14:35:50 -08:00
David Sun
6a704b8a77 Merge pull request #1611 from dave4506/feature/website/add-forum-link-footer
Added forum link
2019-02-12 17:32:25 -05:00
David Sun
df896877f8 added forum link 2019-02-12 17:24:57 -05:00
David Sun
3cb2d3dfff adding free credits page (incomplete) 2019-02-12 16:58:55 -05:00
fragosti
d5f5e79661 Add radar data source 2019-02-12 10:41:47 -08:00
askeluv
82dffe9d0e Added remaining tests + fixed linting issues 2019-02-12 19:34:05 +08:00
askeluv
d7825dd7db Added test for entity 2019-02-12 16:06:53 +08:00
askeluv
c0a2f429b6 Added saving to database 2019-02-12 12:30:10 +08:00
Fabio Berger
e909faa3ef Publish
- 0x.js@5.0.0
 - @0x/abi-gen@2.0.3
 - @0x/abi-gen-wrappers@3.0.3
 - @0x/assert@2.0.3
 - @0x/asset-buyer@5.0.4
 - @0x/base-contract@4.0.3
 - @0x/connect@4.0.4
 - @0x/contract-wrappers@7.1.0
 - @0x/contracts-gen@1.0.2
 - @0x/dev-tools-pages@0.0.19
 - @0x/dev-utils@2.1.0
 - @0x/fill-scenarios@2.0.4
 - @0x/instant@1.0.13
 - @0x/json-schemas@3.0.3
 - @0x/metacoin@0.0.40
 - @0x/migrations@3.0.4
 - @0x/monorepo-scripts@1.0.24
 - @0x/order-utils@6.1.0
 - @0x/order-watcher@3.0.4
 - @0x/pipeline@1.0.10
 - @0x/react-docs@2.0.4
 - @0x/react-shared@2.0.4
 - @0x/sol-compiler@3.0.3
 - @0x/sol-coverage@2.0.3
 - @0x/sol-doc@2.0.3
 - @0x/sol-profiler@2.0.4
 - @0x/sol-trace@2.0.4
 - @0x/sol-tracing-utils@6.0.3
 - @0x/sra-spec@2.0.3
 - @0x/subproviders@3.0.3
 - @0x/testnet-faucets@1.0.69
 - @0x/utils@4.1.0
 - @0x/web3-wrapper@5.0.0
 - @0x/website@0.0.72
 - @0x/contracts-asset-proxy@1.0.5
 - @0x/contracts-erc20@1.0.5
 - @0x/contracts-erc721@1.0.5
 - @0x/contracts-exchange@1.0.5
 - @0x/contracts-exchange-forwarder@1.0.5
 - @0x/contracts-exchange-libs@1.0.5
 - @0x/contracts-extensions@2.0.4
 - @0x/contracts-multisig@2.0.4
 - @0x/contracts-test-utils@3.0.4
 - @0x/contracts-utils@2.0.4
2019-02-09 18:44:40 +00:00
Fabio Berger
28d9fdf798 Updated CHANGELOGS 2019-02-09 18:44:28 +00:00
Fabio Berger
e9bfc44b90 Remove react deps from highlight 2019-02-09 17:28:52 +00:00
Fabio B
2a772b71f1 Merge pull request #1569 from 0xProject/feature/utils/decodeArbitrary0xCalldata
0x Transaction Data Decoder
2019-02-09 14:29:20 +00:00
Greg Hysen
233869ed80 updated changelog.json for 0x.js / order-utils / web3-wrapper 2019-02-08 17:12:58 -08:00
Greg Hysen
a9aaae7f97 Deduped random value generation from salt generation 2019-02-08 17:12:58 -08:00
Greg Hysen
500b4940a3 Improvements and conventions in utils package + abi decoder 2019-02-08 17:12:54 -08:00
Greg Hysen
6d0dc47157 updated changelog for contract wrappers 2019-02-08 16:25:30 -08:00
Greg Hysen
56e7e7d644 updated exports for contract wrappers 2019-02-08 16:25:30 -08:00
Greg Hysen
93c128ee21 Added exports for doc generation 2019-02-08 16:25:30 -08:00
Greg Hysen
c72e3667b8 ran prettier and linter 2019-02-08 16:25:30 -08:00
Greg Hysen
6406126ae3 Merged tx decoder into AbiDecoder in utils and merged zeroex tx decoder into ContractWrappers. 2019-02-08 16:25:30 -08:00
Greg Hysen
6bde77bb57 fix doc generation in contract-wrappers 2019-02-08 16:25:30 -08:00
Greg Hysen
831a628379 ran linter 2019-02-08 16:25:30 -08:00
Greg Hysen
3d2babd059 Tests for transaction decoder 2019-02-08 16:25:30 -08:00
Greg Hysen
d9c4c74a56 Added tests for ZeroExTransactionDecoder 2019-02-08 16:25:30 -08:00
Greg Hysen
5a231fb057 Prep for txData decoder tests 2019-02-08 16:25:30 -08:00
Greg Hysen
63f41df327 started writing tests for zeroex tx decoder 2019-02-08 16:25:30 -08:00
Greg Hysen
171618d32b Added comments for transaction decoder 2019-02-08 16:25:30 -08:00
Greg Hysen
f7b58e7f64 moved ZeroExTransactionDecoder into contract wrappers 2019-02-08 16:25:30 -08:00
Greg Hysen
436d87da98 Ran prettier and linter 2019-02-08 16:25:30 -08:00
Greg Hysen
896874fb99 separated tx decode classes and types into separate files 2019-02-08 16:25:30 -08:00
Greg Hysen
a9f8e80b1c Abstractd out ZeroExTransactionDecoder 2019-02-08 16:25:30 -08:00
Greg Hysen
f93cd1bb48 Can query decoder by contract address / network id OR contract name 2019-02-08 16:25:30 -08:00
Greg Hysen
8fc3a6b828 Expanding search parameters for transaction decoder 2019-02-08 16:25:30 -08:00
Greg Hysen
100840b743 Utility function to decode arbitrary 0x calldata 2019-02-08 16:25:30 -08:00
David Sun
8c8cab9309 added page [WIP] still 2019-02-08 18:06:58 -05:00
F. Eugene Aumson
629a8d6328 Add migration to fix exchange events primary keys (#1593)
* Add migration to fix exchange events primary key

* correct comment: "foreign key" -> "primary key"

* Refine hack to handle only the expected error

* Add tx hash to erc20 approval events primary key
2019-02-08 13:21:41 -05:00
Fabio B
ffdaec9f9f Merge pull request #1602 from 0xProject/feat/allow_using_existing_ganache_snapshot
Allow using Web3Factory in-process Ganache with existing snapshot
2019-02-08 17:49:33 +00:00
Fabio Berger
c794153221 Add CHANGELOG entry 2019-02-08 13:22:11 +00:00
Fabio Berger
d01837f42c Allow using Web3Factory in-process Ganache with existing snapshot 2019-02-08 13:19:47 +00:00
askeluv
7ad4cb0078 [WIP] Slippage calculations from Ethereum DEX Prices Service (EDPS) 2019-02-08 18:54:38 +08:00
David Sun
ffd8349889 Merge pull request #1581 from dave4506/feature/instant/bignumber-coerce-type
Big number input to Instant coercion to version utilized by 0x packages
2019-02-07 21:06:43 -05:00
David Sun
f3716fd813 fixed config orderSource assignment 2019-02-07 20:41:37 -05:00
Greg Hysen
1170cf1896 Merge pull request #1592 from 0xProject/feature/abiEncoder/simplifiedSigParsing
Simplified signature parsing + signature tests
2019-02-07 15:18:37 -08:00
Greg Hysen
b9ee9d2bd5 replaced typeof with _.isString 2019-02-07 15:01:29 -08:00
Greg Hysen
21c3f75efc Changelog for utils package 2019-02-07 15:01:29 -08:00
Greg Hysen
eb5f7e36e9 Signature parsing tests 2019-02-07 15:00:07 -08:00
Greg Hysen
4079563f5d More robust/simple signature parsing, using a parse tree 2019-02-07 15:00:07 -08:00
David Sun
6dabed5938 updated order coercion utils architecture and testing 2019-02-07 16:45:56 -05:00
Fabio B
3939d516e6 Merge pull request #1586 from 0xProject/addAnalyticsToDevToolsPages
Add Heap and Google analytics to Dev Tools Pages
2019-02-07 21:18:41 +00:00
Fabio Berger
5aba9d698b Only include analytics on production builds 2019-02-07 14:54:12 +00:00
Fabio Berger
3dd652e7cf Merge branch 'development' into addAnalyticsToDevToolsPages
* development: (51 commits)
  Publish
  Updated CHANGELOGS
  Updated CHANGELOGS
  Update packages/sol-compiler/CHANGELOG.json
  Update packages/sol-compiler/CHANGELOG.json
  Move from devDep to dep
  Fix linter
  Update CHANGELOG
  Re-run yarn since fails again on first run
  Add PR numbers
  Omit remapping in compiler settings equality checks
  Omit remapping in compiler settings equality checks
  Fix a bug when ast and legacyAST were not present in the artifacts even if requested
  Update yarn.lock
  Remove the bin_paths and fetch the solidity release list from github repo
  Remove postinstall hack
  Fix the undefined opts bug
  Fix sol-compiler bug with remappings causing smart recompilation to now work
  re-add postinstall hack
  Fix deps versions
  ...
2019-02-07 14:28:24 +00:00
Leonid Logvinov
f003298ce4 Publish
- 0x.js@4.0.3
 - @0x/abi-gen@2.0.2
 - @0x/abi-gen-wrappers@3.0.2
 - @0x/assert@2.0.2
 - @0x/asset-buyer@5.0.3
 - @0x/base-contract@4.0.2
 - @0x/connect@4.0.3
 - @0x/contract-wrappers@7.0.2
 - @0x/contracts-gen@1.0.1
 - @0x/dev-tools-pages@0.0.18
 - @0x/dev-utils@2.0.2
 - @0x/fill-scenarios@2.0.3
 - @0x/instant@1.0.12
 - @0x/json-schemas@3.0.2
 - @0x/metacoin@0.0.39
 - @0x/migrations@3.0.3
 - @0x/monorepo-scripts@1.0.23
 - @0x/order-utils@6.0.1
 - @0x/order-watcher@3.0.3
 - @0x/pipeline@1.0.9
 - @0x/react-docs@2.0.3
 - @0x/react-shared@2.0.3
 - @0x/sol-compiler@3.0.2
 - @0x/sol-coverage@2.0.2
 - @0x/sol-doc@2.0.2
 - @0x/sol-profiler@2.0.3
 - @0x/sol-resolver@2.0.2
 - @0x/sol-trace@2.0.3
 - @0x/sol-tracing-utils@6.0.2
 - @0x/sra-spec@2.0.2
 - @0x/subproviders@3.0.2
 - @0x/testnet-faucets@1.0.68
 - @0x/types@2.0.2
 - @0x/utils@4.0.3
 - @0x/web3-wrapper@4.0.2
 - @0x/website@0.0.71
 - @0x/contracts-asset-proxy@1.0.4
 - @0x/contracts-erc20@1.0.4
 - @0x/contracts-erc721@1.0.4
 - @0x/contracts-exchange@1.0.4
 - @0x/contracts-exchange-forwarder@1.0.4
 - @0x/contracts-exchange-libs@1.0.4
 - @0x/contracts-extensions@2.0.3
 - @0x/contracts-multisig@2.0.3
 - @0x/contracts-test-utils@3.0.3
 - @0x/contracts-utils@2.0.3
2019-02-07 15:02:05 +01:00
Leonid Logvinov
5f5ee0041f Updated CHANGELOGS 2019-02-07 15:01:53 +01:00
Leonid Logvinov
88497ddc52 Updated CHANGELOGS 2019-02-07 14:42:20 +01:00
Fabio B
e921d5ec13 Merge pull request #1589 from 0xProject/feat/lock-contract-deps
Lock dep versions in contracts packages (again)
2019-02-07 13:28:57 +00:00
Leonid Logvinov
c55974a485 Merge pull request #1596 from 0xProject/fix/sol-compiler-args
Sol-compiler bug fixes
2019-02-07 14:18:55 +01:00
Fabio B
2ff0f545f5 Update packages/sol-compiler/CHANGELOG.json
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-07 14:17:41 +01:00
Fabio B
7f2a011c3e Update packages/sol-compiler/CHANGELOG.json
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-07 14:17:23 +01:00
Fabio Berger
8af9a38c8e Move from devDep to dep 2019-02-07 13:07:36 +00:00
Leonid Logvinov
b54bafe1c5 Fix linter 2019-02-07 13:35:50 +01:00
Fabio Berger
7a9ff3846e Merge development 2019-02-07 12:33:44 +00:00
Leonid Logvinov
53fe08a348 Update CHANGELOG 2019-02-07 13:30:00 +01:00
Fabio Berger
f118e86cfe Re-run yarn since fails again on first run 2019-02-07 12:29:05 +00:00
Leonid Logvinov
2e60d5341e Add PR numbers 2019-02-07 13:24:57 +01:00
Leonid Logvinov
2ef3af0003 Omit remapping in compiler settings equality checks 2019-02-07 13:20:21 +01:00
Leonid Logvinov
2b7699c26a Omit remapping in compiler settings equality checks 2019-02-07 13:20:03 +01:00
Leonid Logvinov
d567c58d3b Fix a bug when ast and legacyAST were not present in the artifacts even if requested 2019-02-07 13:10:08 +01:00
Fabio Berger
bede3d7e29 Update yarn.lock 2019-02-07 12:01:57 +00:00
Leonid Logvinov
64d6dae672 Remove the bin_paths and fetch the solidity release list from github repo 2019-02-07 12:58:46 +01:00
Fabio Berger
b001fe2b08 Remove postinstall hack 2019-02-07 11:58:06 +00:00
Leonid Logvinov
c20285dd36 Fix the undefined opts bug 2019-02-07 12:30:54 +01:00
Leonid Logvinov
7e19c944b9 Merge pull request #1575 from 0xProject/feature/contracts-gen
Contracts generator
2019-02-07 12:23:00 +01:00
Leonid Logvinov
fd4d3cff88 Fix sol-compiler bug with remappings causing smart recompilation to now work 2019-02-07 12:13:24 +01:00
Fabio Berger
5ff646ca8e re-add postinstall hack 2019-02-07 10:53:14 +00:00
Leonid Logvinov
88432a5e67 Fix deps versions 2019-02-07 11:49:59 +01:00
Leonid Logvinov
7519d60fb7 Fix linter issues 2019-02-07 11:29:04 +01:00
Leonid Logvinov
de23428069 Merge development 2019-02-07 11:15:37 +01:00
Amir Bandeali
9089bf2c5f Lock dep versions in contracts packages 2019-02-06 21:10:35 -08:00
Fabio Berger
2a344e26cc Publish
- 0x.js@4.0.2
 - @0x/asset-buyer@5.0.2
 - @0x/connect@4.0.2
 - @0x/contract-wrappers@7.0.1
 - @0x/dev-tools-pages@0.0.17
 - @0x/fill-scenarios@2.0.2
 - @0x/instant@1.0.11
 - @0x/migrations@3.0.2
 - @0x/monorepo-scripts@1.0.22
 - @0x/order-utils@6.0.0
 - @0x/order-watcher@3.0.2
 - @0x/pipeline@1.0.8
 - @0x/react-docs@2.0.2
 - @0x/react-shared@2.0.2
 - @0x/testnet-faucets@1.0.67
 - @0x/website@0.0.70
 - @0x/contracts-asset-proxy@1.0.3
 - @0x/contracts-erc20@1.0.3
 - @0x/contracts-erc721@1.0.3
 - @0x/contracts-exchange@1.0.3
 - @0x/contracts-exchange-forwarder@1.0.3
 - @0x/contracts-exchange-libs@1.0.3
 - @0x/contracts-extensions@2.0.2
 - @0x/contracts-multisig@2.0.2
 - @0x/contracts-test-utils@3.0.2
 - @0x/contracts-utils@2.0.2
2019-02-07 01:53:15 +00:00
Fabio Berger
af26403a86 Updated CHANGELOGS 2019-02-07 01:53:02 +00:00
Fabio B
3af6c8fe1d Merge pull request #1595 from 0xProject/fix-order-utils-doc-rendering
Stop exporting EIP712 schemas
2019-02-07 01:24:32 +00:00
Fabio Berger
b883b183a6 Stop exporting EIP712 schemas 2019-02-07 01:03:43 +00:00
Fabio Berger
ac58ace8cf Add CHANGELOG entry about faux publish of contract packages 2019-02-07 00:16:39 +00:00
Fabio Berger
a50eefc44e Fix paragraph rendering on wiki 2019-02-06 14:08:45 +00:00
Fabio Berger
dbb3c5e32b Publish
- 0x.js@4.0.1
 - @0x/abi-gen@2.0.1
 - @0x/abi-gen-wrappers@3.0.1
 - @0x/assert@2.0.1
 - @0x/asset-buyer@5.0.1
 - @0x/base-contract@4.0.1
 - @0x/connect@4.0.1
 - @0x/contract-wrappers@7.0.0
 - @0x/dev-tools-pages@0.0.16
 - @0x/dev-utils@2.0.1
 - @0x/fill-scenarios@2.0.1
 - @0x/instant@1.0.10
 - @0x/json-schemas@3.0.1
 - @0x/metacoin@0.0.38
 - @0x/migrations@3.0.1
 - @0x/monorepo-scripts@1.0.21
 - @0x/order-utils@5.0.0
 - @0x/order-watcher@3.0.1
 - @0x/pipeline@1.0.7
 - @0x/react-docs@2.0.1
 - @0x/react-shared@2.0.1
 - @0x/sol-compiler@3.0.1
 - @0x/sol-coverage@2.0.1
 - @0x/sol-doc@2.0.1
 - @0x/sol-profiler@2.0.2
 - @0x/sol-resolver@2.0.1
 - @0x/sol-trace@2.0.2
 - @0x/sol-tracing-utils@6.0.1
 - @0x/sra-spec@2.0.1
 - @0x/subproviders@3.0.1
 - @0x/testnet-faucets@1.0.66
 - @0x/types@2.0.1
 - @0x/utils@4.0.2
 - @0x/web3-wrapper@4.0.1
 - @0x/website@0.0.69
 - @0x/contracts-asset-proxy@1.0.2
 - @0x/contracts-erc20@1.0.2
 - @0x/contracts-erc721@1.0.2
 - @0x/contracts-exchange@1.0.2
 - @0x/contracts-exchange-forwarder@1.0.2
 - @0x/contracts-exchange-libs@1.0.2
 - @0x/contracts-extensions@2.0.1
 - @0x/contracts-multisig@2.0.1
 - @0x/contracts-test-utils@3.0.1
 - @0x/contracts-utils@2.0.1
2019-02-06 11:41:24 +00:00
Fabio Berger
265df31750 Updated CHANGELOGS 2019-02-06 11:41:12 +00:00
Fabio Berger
9bbe56df0b Fix react-highlight dep 2019-02-06 11:24:40 +00:00
Fabio Berger
879c795fc4 Fix react-highlight dep 2019-02-06 11:07:16 +00:00
Fabio B
8b5bb97537 Merge pull request #1587 from 0xProject/fix/abiEncoder/DefaultTypesOnNullInput
Handle ABI decoding NULL for all data types
2019-02-06 10:23:21 +00:00
Greg Hysen
3d7a635543 Added NULL decoding tests for return values 2019-02-05 21:33:07 -08:00
Greg Hysen
b3ae9e6e25 updated changelog for utils 2019-02-05 19:18:00 -08:00
Greg Hysen
023ea5b3a1 Ran prettier + linter 2019-02-05 18:10:17 -08:00
Greg Hysen
2ad6bd3945 Test cases for handling NULL input for all data types 2019-02-05 18:01:38 -08:00
Greg Hysen
2326dcdb12 Handle NULL input for all data types 2019-02-05 17:30:54 -08:00
David Sun
d95af455f1 added coercion util functions 2019-02-05 16:46:51 -05:00
Fabio Berger
8de955f3d8 Add Heap and Google analytics to Dev Tools Pages 2019-02-05 21:34:29 +00:00
Amir Bandeali
b5eb47f609 Merge pull request #1576 from 0xProject/feat/transaction-hash
Add transactionHashUtils to order-utils package
2019-02-05 10:03:30 -08:00
Amir Bandeali
af4ed0f39c Update python JSON schema for 0x transactions 2019-02-05 09:26:03 -08:00
Amir Bandeali
eac254f925 Fix outdated comments and make verifyingContractAddress a required part of the 0x tx schema 2019-02-05 09:26:03 -08:00
Amir Bandeali
8246dec843 Rename getTransactionHex to getTransactionHashHex for clarity 2019-02-05 09:26:03 -08:00
Amir Bandeali
4514da0646 Update CHANGELOGs 2019-02-05 09:26:03 -08:00
Amir Bandeali
9abd6f5695 Allow custom domains in eip712Utils 2019-02-05 09:23:09 -08:00
Amir Bandeali
a394967268 Use new transaction schema throughout monorepo 2019-02-05 09:23:09 -08:00
Amir Bandeali
c7c4cb9bc6 Add transaction hash utils 2019-02-05 09:23:09 -08:00
Amir Bandeali
1ada679663 Update ZeroExTransactionSchema 2019-02-05 09:23:09 -08:00
Amir Bandeali
9552676783 Add schema validation to getOrderHashBuff 2019-02-05 09:23:09 -08:00
Fabio B
69c7c03fb3 Merge pull request #1580 from 0xProject/fix/preSignedSignatureBug
Fix preSigned signature bug in SignatureUtils
2019-02-05 14:36:06 +00:00
Fabio Berger
224a58bdf2 Fix dep version 2019-02-05 14:19:48 +00:00
Fabio Berger
98427b715d Merge branch 'fix/preSignedSignatureBug' of github.com:0xProject/0x-monorepo into fix/preSignedSignatureBug
* 'fix/preSignedSignatureBug' of github.com:0xProject/0x-monorepo:
  Update packages/order-utils/CHANGELOG.json
2019-02-05 13:57:40 +00:00
Fabio Berger
a8078aa151 merge development 2019-02-05 13:55:05 +00:00
Leonid Logvinov
3cb6744369 Update packages/order-utils/CHANGELOG.json
Co-Authored-By: fabioberger <kandinsky454@protonmail.ch>
2019-02-05 13:14:31 +00:00
Fabio Berger
e021460f03 Remove .only 2019-02-05 13:09:23 +00:00
Fabio Berger
0a93f3346f All CHANGELOG entry 2019-02-05 13:07:50 +00:00
Fabio Berger
332cc14dcd Add preSigned isValidSignature test for success case using smart contract & TS implementation 2019-02-05 13:07:40 +00:00
Fabio Berger
7885b2e3f8 Fix test 2019-02-05 12:56:04 +00:00
Fabio Berger
2447c72a5c Fix heap out of memory issue 2019-02-05 12:09:13 +00:00
Fabio Berger
d7c9d73349 Merge branch 'development' into fix/preSignedSignatureBug
* development:
  update error msg for dependency version check
  CI test for dependencies to have the same version (#1556)
  Add missing comma
  Decode NULL as false
  Update blog link to not be /latest, and use constant in mobile nav
2019-02-05 11:16:45 +00:00
Fabio Berger
a1bf5e8261 Merge branch 'development' into fix/preSignedSignatureBug
* development:
  Nit fixes to pipeline README
  fix typo
2019-02-04 19:33:08 +00:00
David Sun
59f48d6d57 working on big number coercion function 2019-02-04 11:19:18 -05:00
Fabio Berger
52f22aad81 Write failing preSign unit test 2019-02-04 16:03:48 +00:00
Fabio Berger
c03e24e10b Fix bug where passing in signerAddress instead of exchangeAddress 2019-02-04 16:03:25 +00:00
Leonid Logvinov
4d75681357 Add @0x/types dependency 2019-02-04 13:11:20 +01:00
Leonid Logvinov
1a88eac9c7 Make the banner more visible 2019-02-04 13:00:15 +01:00
Leonid Logvinov
47357ddec8 Remove redundant dependencies 2019-02-04 12:58:19 +01:00
Fabio B
129ae3a737 Update packages/contracts-gen/src/index.ts
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-04 12:56:18 +01:00
Fabio B
31d1390039 Update packages/contracts-gen/README.md
Co-Authored-By: LogvinovLeon <logvinov.leon@gmail.com>
2019-02-04 12:52:36 +01:00
Leonid Logvinov
6943bbcacb Temp 2019-02-04 10:38:02 +01:00
1244 changed files with 50436 additions and 6115 deletions

View File

@@ -11,12 +11,17 @@ jobs:
steps:
- checkout
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
- run:
# HACK(albrow): Without this, yarn commands will sometimes
# fail with a "permission denied" error.
name: Set npm path
command: npm set prefix=/home/circleci/npm && echo 'export PATH=$HOME/circleci/npm/bin:$PATH' >> /home/circleci/.bashrc
- run:
name: install-yarn
command: sudo npm install --global yarn@1.9.4
command: npm install --global yarn@1.9.4
- run:
name: yarn
command: yarn --frozen-lockfile --ignore-engines install
command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install
- setup_remote_docker
- run: yarn build:ci:no_website
- run: yarn build:ts
@@ -47,10 +52,12 @@ jobs:
- run: yarn wsrun test:circleci @0x/contracts-exchange-libs
- run: yarn wsrun test:circleci @0x/contracts-erc20
- run: yarn wsrun test:circleci @0x/contracts-erc721
- run: yarn wsrun test:circleci @0x/contracts-erc1155
- run: yarn wsrun test:circleci @0x/contracts-extensions
- run: yarn wsrun test:circleci @0x/contracts-asset-proxy
- run: yarn wsrun test:circleci @0x/contracts-exchange
- run: yarn wsrun test:circleci @0x/contracts-exchange-forwarder
- run: yarn wsrun test:circleci @0x/contracts-coordinator
test-contracts-geth:
docker:
- image: circleci/node:9-browsers
@@ -67,10 +74,12 @@ jobs:
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-libs
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc20
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc721
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc1155
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-extensions
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-asset-proxy
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-forwarder
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-coordinator
test-publish:
resource_class: medium+
docker:
@@ -115,6 +124,7 @@ jobs:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-test-utils
- run: yarn wsrun test:circleci @0x/abi-gen
- run: yarn wsrun test:circleci @0x/contract-artifacts
- run: yarn wsrun test:circleci @0x/assert
- run: yarn wsrun test:circleci @0x/base-contract
- run: yarn wsrun test:circleci @0x/connect
@@ -197,8 +207,11 @@ jobs:
- image: circleci/python
- image: 0xorg/ganache-cli:2.2.2
- image: 0xorg/launch-kit-ci
command: |
yarn start:ts -p 3000:3000
environment:
RPC_URL: http://localhost:8545
NETWORK_ID: 50
WHITELIST_ALL_TOKENS: True
command: bash -c "until curl -sfd'{\"method\":\"net_listening\"}' http://localhost:8545 | grep true; do continue; done; forever ts/lib/index.js"
steps:
- checkout
- run: sudo chown -R circleci:circleci /usr/local/bin
@@ -386,9 +399,11 @@ workflows:
- test-contracts-ganache:
requires:
- build
- test-contracts-geth:
requires:
- build
# TODO(albrow): Tests always fail on Geth right now because our fork
# is outdated. Uncomment once we have updated our Geth fork.
# - test-contracts-geth:
# requires:
# - build
- test-pipeline:
requires:
- build

View File

@@ -2,6 +2,7 @@ python: ['python-packages']
contracts: ['contracts']
sol-doc: ['packages/sol-doc']
sol-resolver: ['packages/sol-resolver']
contracts-gen: ['packages/contracts-gen']
sra-spec: ['packages/sra-spec']
subproviders: ['packages/subproviders']
contract-addresses: ['packages/contract-addresses']

4
.gitignore vendored
View File

@@ -83,6 +83,7 @@ packages/react-docs/example/public/bundle*
packages/testnet-faucets/server/
# generated contract artifacts/
contracts/coordinator/generated-artifacts/
contracts/exchange/generated-artifacts/
contracts/asset-proxy/generated-artifacts/
contracts/multisig/generated-artifacts/
@@ -90,6 +91,7 @@ contracts/utils/generated-artifacts/
contracts/exchange-libs/generated-artifacts/
contracts/erc20/generated-artifacts/
contracts/erc721/generated-artifacts/
contracts/erc1155/generated-artifacts/
contracts/extensions/generated-artifacts/
contracts/exchange-forwarder/generated-artifacts/
packages/sol-tracing-utils/test/fixtures/artifacts/
@@ -97,6 +99,7 @@ packages/metacoin/artifacts/
# generated contract wrappers
packages/abi-gen-wrappers/wrappers
contracts/coordinator/generated-wrappers/
contracts/exchange/generated-wrappers/
contracts/asset-proxy/generated-wrappers/
contracts/multisig/generated-wrappers/
@@ -104,6 +107,7 @@ contracts/utils/generated-wrappers/
contracts/exchange-libs/generated-wrappers/
contracts/erc20/generated-wrappers/
contracts/erc721/generated-wrappers/
contracts/erc1155/generated-wrappers/
contracts/extensions/generated-wrappers/
contracts/exchange-forwarder/generated-wrappers/
packages/metacoin/src/contract_wrappers

View File

@@ -1,5 +1,7 @@
lib
.nyc_output
/contracts/coordinator/generated-wrappers
/contracts/coordinator/generated-artifacts
/contracts/exchange/generated-wrappers
/contracts/exchange/generated-artifacts
/contracts/asset-proxy/generated-wrappers
@@ -14,6 +16,8 @@ lib
/contracts/erc20/generated-artifacts
/contracts/erc721/generated-wrappers
/contracts/erc721/generated-artifacts
/contracts/erc1155/generated-wrappers
/contracts/erc1155/generated-artifacts
/contracts/extensions/generated-wrappers
/contracts/extensions/generated-artifacts
/contracts/exchange-forwarder/generated-wrappers

View File

@@ -33,6 +33,8 @@ packages/subproviders/ @fabioberger @dekz
packages/verdaccio/ @albrow
packages/web3-wrapper/ @LogvinovLeon @fabioberger
python-packages/ @feuGeneA
packages/utils/ @hysz
# Protocol/smart contracts
contracts/core/test/ @albrow
contracts/ @abandeali1 @hysz

View File

@@ -34,18 +34,22 @@ Visit our [developer portal](https://0xproject.com/docs/order-utils) for a compr
### Solidity Packages
These packages are all under development. See [/contracts/README.md](/contracts/README.md) for a list of deployed packages.
| Package | Version | Description |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [![npm](https://img.shields.io/npm/v/@0x/contracts-asset-proxy.svg)](https://www.npmjs.com/package/@0x/contracts-asset-proxy) | [`AssetProxy`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy) contracts used within the protocol |
| [`@0x/contracts-erc20`](/contracts/erc20) | [![npm](https://img.shields.io/npm/v/@0x/contracts-erc20.svg)](https://www.npmjs.com/package/@0x/contracts-erc20) | Implementations of various ERC20 tokens |
| [`@0x/contracts-erc721`](/contracts/erc721) | [![npm](https://img.shields.io/npm/v/@0x/contracts-erc721.svg)](https://www.npmjs.com/package/@0x/contracts-erc721) | Implementations of various ERC721 tokens |
| [`@0x/contracts-erc1155`](/contracts/erc1155) | [![npm](https://img.shields.io/npm/v/@0x/contracts-erc1155.svg)](https://www.npmjs.com/package/@0x/contracts-erc1155) | Implementations of various ERC1155 tokens |
| [`@0x/contracts-exchange`](/contracts/exchange) | [![npm](https://img.shields.io/npm/v/@0x/contracts-exchange.svg)](https://www.npmjs.com/package/@0x/contracts-exchange) | The [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract used for settling trades within the protocol |
| [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [![npm](https://img.shields.io/npm/v/@0x/contracts-exchange-forwarder.svg)](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder) | A [`Forwarder`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract used to simplify UX for interacting with the protocol |
| [`@0x/contracts-exchange-libs`](/contracts/exchange-libs) | [![npm](https://img.shields.io/npm/v/@0x/contracts-exchange-libs.svg)](https://www.npmjs.com/package/@0x/contracts-exchange-libs) | Protocol specific Llbraries used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract |
| [`@0x/contracts-exchange-libs`](/contracts/exchange-libs) | [![npm](https://img.shields.io/npm/v/@0x/contracts-exchange-libs.svg)](https://www.npmjs.com/package/@0x/contracts-exchange-libs) | Protocol specific libraries used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract |
| [`@0x/contracts-extensions`](/contracts/extensions) | [![npm](https://img.shields.io/npm/v/@0x/contracts-extensions.svg)](https://www.npmjs.com/package/@0x/contracts-extensions) | Contracts that interact with and extend the functionality of the core protocol |
| [`@0x/contracts-multisig`](/contracts/multisig) | [![npm](https://img.shields.io/npm/v/@0x/contracts-multisig.svg)](https://www.npmjs.com/package/@0x/contracts-multisig) | Various implementations of multisignature wallets, including the [`AssetProxyOwner`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxyowner) contract that has permissions to upgrade the protocol |
| [`@0x/contracts-test-utils`](/contracts/test-utils) | [![npm](https://img.shields.io/npm/v/@0x/contracts-test-utils.svg)](https://www.npmjs.com/package/@0x/contracts-test-utils) | Typescript/Javascript shared utilities used for testing contracts |
| [`@0x/contracts-utils`](/contracts/utils) | [![npm](https://img.shields.io/npm/v/@0x/contracts-utils.svg)](https://www.npmjs.com/package/@0x/contracts-utils) | Generic libraries and utilities used throughout all of the contracts |
| [`@0x/contracts-coordinator`](/contracts/coordinator) | [![npm](https://img.shields.io/npm/v/@0x/contracts-coordinator.svg)](https://www.npmjs.com/package/@0x/contracts-coordinator) | A contract that allows users to execute 0x transactions with permission from a Coordinator |
### Typescript/Javascript Packages

12
contracts/README.md Normal file
View File

@@ -0,0 +1,12 @@
#### Deployed Contract Packages
| Contract | Package | Version | Git Tag |
| --------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| AssetProxyOwner | [`@0x/contracts-multisig`](/contracts/multisig) | [v1.0.2](https://www.npmjs.com/package/@0x/contracts-multisig/v/1.0.2) | [@0x/contracts-multisig@1.0.2](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-multisig@1.0.2) |
| ERC20Proxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
| ERC721Proxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
| Exchange | [`@0x/contracts-exchange`](/contracts/exchange) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange/v/1.0.1) | [@0x/contracts-exchange@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange@1.0.1) |
| DutchAuction | [`@0x/contracts-extensions`](/contracts/extensions) | [v1.0.2](https://www.npmjs.com/package/@0x/contracts-extensions/v/1.0.2) | [@0x/contracts-extensions@1.0.2](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-extensions@1.0.2) |
| Forwarder | [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder/v/1.0.1) | [@0x/contracts-exchange-forwarder@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange-forwarder@1.0.1) |
| MultiAssetProxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
| ZRXToken | [`@0x/contracts-erc20`](/contracts/erc20) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-erc20/v/1.0.1) | [@0x/contracts-erc20@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-erc20@1.0.1) |

View File

@@ -1,4 +1,127 @@
[
{
"version": "2.1.2",
"changes": [
{
"note": "Update tests to use contract-built-in `awaitTransactionSuccessAsync`",
"pr": 1797
}
],
"timestamp": 1557507213
},
{
"version": "2.1.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1554997931
},
{
"version": "2.1.0",
"changes": [
{
"note": "Run Web3ProviderEngine without excess block polling",
"pr": 1695
}
],
"timestamp": 1553183790
},
{
"version": "2.0.0",
"changes": [
{
"note": "Do not reexport external dependencies",
"pr": 1682
},
{
"note": "Add ERC1155Proxy",
"pr": 1661
},
{
"note": "Bumped solidity version to ^0.5.5",
"pr": 1701
},
{
"note": "Integration testing for ERC1155Proxy",
"pr": 1673
}
],
"timestamp": 1553091633
},
{
"timestamp": 1551479279,
"version": "1.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1551299797,
"version": "1.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1551220833,
"version": "1.0.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1551130135,
"version": "1.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1549733923,
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1549547375
},
{
"version": "1.0.3",
"changes": [
{
"note": "Fake publish to enable pinning"
}
],
"timestamp": 1549504360
},
{
"timestamp": 1549452781,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1549373905,
"version": "1.0.1",

View File

@@ -5,6 +5,57 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.1.2 - _May 10, 2019_
* Update tests to use contract-built-in `awaitTransactionSuccessAsync` (#1797)
## v2.1.1 - _April 11, 2019_
* Dependencies updated
## v2.1.0 - _March 21, 2019_
* Run Web3ProviderEngine without excess block polling (#1695)
## v2.0.0 - _March 20, 2019_
* Do not reexport external dependencies (#1682)
* Add ERC1155Proxy (#1661)
* Bumped solidity version to ^0.5.5 (#1701)
* Integration testing for ERC1155Proxy (#1673)
## v1.0.9 - _March 1, 2019_
* Dependencies updated
## v1.0.8 - _February 27, 2019_
* Dependencies updated
## v1.0.7 - _February 26, 2019_
* Dependencies updated
## v1.0.6 - _February 25, 2019_
* Dependencies updated
## v1.0.5 - _February 9, 2019_
* Dependencies updated
## v1.0.4 - _February 7, 2019_
* Dependencies updated
## v1.0.3 - _February 7, 2019_
* Fake publish to enable pinning
## v1.0.2 - _February 6, 2019_
* Dependencies updated
## v1.0.1 - _February 5, 2019_
* Dependencies updated

View File

@@ -1,11 +1,14 @@
{
"artifactsDir": "./generated-artifacts",
"contractsDir": "./contracts",
"useDockerisedSolc": true,
"useDockerisedSolc": false,
"isOfflineMode": false,
"compilerSettings": {
"evmVersion": "constantinople",
"optimizer": {
"enabled": true,
"runs": 1000000
"runs": 1000000,
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
},
"outputSelection": {
"*": {
@@ -20,12 +23,14 @@
}
},
"contracts": [
"IAssetData",
"IAssetProxy",
"IAuthorizable",
"ERC20Proxy",
"ERC721Proxy",
"MixinAuthorizable",
"MultiAssetProxy"
"src/ERC1155Proxy.sol",
"src/ERC20Proxy.sol",
"src/ERC721Proxy.sol",
"src/MixinAuthorizable.sol",
"src/MultiAssetProxy.sol",
"src/interfaces/IAssetData.sol",
"src/interfaces/IAssetProxy.sol",
"src/interfaces/IAuthorizable.sol",
"src/libs/LibAssetData.sol"
]
}

View File

@@ -0,0 +1,267 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "./MixinAuthorizable.sol";
contract ERC1155Proxy is
MixinAuthorizable
{
// Id of this proxy.
bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
function ()
external
{
// Input calldata to this function is encoded as follows:
// -- TABLE #1 --
// | Area | Offset (**) | Length | Contents |
// |----------|-------------|-------------|---------------------------------|
// | Header | 0 | 4 | function selector |
// | Params | | 4 * 32 | function parameters: |
// | | 4 | | 1. offset to assetData (*) |
// | | 36 | | 2. from |
// | | 68 | | 3. to |
// | | 100 | | 4. amount |
// | Data | | | assetData: |
// | | 132 | 32 | assetData Length |
// | | 164 | (see below) | assetData Contents |
//
//
// Asset data is encoded as follows:
// -- TABLE #2 --
// | Area | Offset | Length | Contents |
// |----------|-------------|---------|-------------------------------------|
// | Header | 0 | 4 | assetProxyId |
// | Params | | 4 * 32 | function parameters: |
// | | 4 | | 1. address of ERC1155 contract |
// | | 36 | | 2. offset to ids (*) |
// | | 68 | | 3. offset to values (*) |
// | | 100 | | 4. offset to data (*) |
// | Data | | | ids: |
// | | 132 | 32 | 1. ids Length |
// | | 164 | a | 2. ids Contents |
// | | | | values: |
// | | 164 + a | 32 | 1. values Length |
// | | 196 + a | b | 2. values Contents |
// | | | | data |
// | | 196 + a + b | 32 | 1. data Length |
// | | 228 + a + b | c | 2. data Contents |
//
//
// Calldata for target ERC155 asset is encoded for safeBatchTransferFrom:
// -- TABLE #3 --
// | Area | Offset (**) | Length | Contents |
// |----------|-------------|---------|-------------------------------------|
// | Header | 0 | 4 | safeBatchTransferFrom selector |
// | Params | | 5 * 32 | function parameters: |
// | | 4 | | 1. from address |
// | | 36 | | 2. to address |
// | | 68 | | 3. offset to ids (*) |
// | | 100 | | 4. offset to values (*) |
// | | 132 | | 5. offset to data (*) |
// | Data | | | ids: |
// | | 164 | 32 | 1. ids Length |
// | | 196 | a | 2. ids Contents |
// | | | | values: |
// | | 196 + a | 32 | 1. values Length |
// | | 228 + a | b | 2. values Contents |
// | | | | data |
// | | 228 + a + b | 32 | 1. data Length |
// | | 260 + a + b | c | 2. data Contents |
//
//
// (*): offset is computed from start of function parameters, so offset
// by an additional 4 bytes in the calldata.
//
// (**): the `Offset` column is computed assuming no calldata compression;
// offsets in the Data Area are dynamic and should be evaluated in
// real-time.
//
// WARNING: The ABIv2 specification allows additional padding between
// the Params and Data section. This will result in a larger
// offset to assetData.
//
// Note: Table #1 and Table #2 exists in Calldata. We construct Table #3 in memory.
//
//
assembly {
// The first 4 bytes of calldata holds the function selector
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
// `transferFrom` will be called with the following parameters:
// assetData Encoded byte array.
// from Address to transfer asset from.
// to Address to transfer asset to.
// amount Amount of asset to transfer.
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
// where k is the key left padded to 32 bytes and p is the storage slot
mstore(0, caller)
mstore(32, authorized_slot)
// Revert if authorized[msg.sender] == false
if iszero(sload(keccak256(0, 64))) {
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
mstore(96, 0)
revert(0, 100)
}
// Construct Table #3 in memory, starting at memory offset 0.
// The algorithm below maps asset data from Table #1 and Table #2 to Table #3, while
// scaling the `values` (Table #2) by `amount` (Table #1). Once Table #3 has
// been constructed in memory, the destination erc1155 contract is called using this
// as its calldata. This process is divided into four steps, below.
////////// STEP 1/4 //////////
// Map relevant fields from assetData (Table #2) into memory (Table #3)
// The Contents column of Table #2 is the same as Table #3,
// beginning from parameter 3 - `offset to ids (*)`
// The offsets in these rows are offset by 32 bytes in Table #3.
// Strategy:
// 1. Copy the assetData into memory at offset 32
// 2. Increment by 32 the offsets to `ids`, `values`, and `data`
// Load offset to `assetData`
let assetDataOffset := calldataload(4)
// Load length in bytes of `assetData`, computed by:
// 4 (function selector)
// + assetDataOffset
let assetDataLength := calldataload(add(4, assetDataOffset))
// This corresponds to the beginning of the Data Area for Table #3.
// Computed by:
// 4 (function selector)
// + assetDataOffset
// + 32 (length of assetData)
calldatacopy(
32, // aligned such that "offset to ids" is at the correct location for Table #3
add(36, assetDataOffset), // beginning of asset data contents
assetDataLength // length of asset data
)
// Increment by 32 the offsets to `ids`, `values`, and `data`
mstore(68, add(mload(68), 32))
mstore(100, add(mload(100), 32))
mstore(132, add(mload(132), 32))
// Record the address of the destination erc1155 asset for later.
let assetAddress := and(
mload(36),
0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
)
////////// STEP 2/4 //////////
let amount := calldataload(100)
let valuesOffset := add(mload(100), 4) // add 4 for calldata offset
let valuesLengthInBytes := mul(
mload(valuesOffset),
32
)
let valuesBegin := add(valuesOffset, 32)
let valuesEnd := add(valuesBegin, valuesLengthInBytes)
for { let tokenValueOffset := valuesBegin }
lt(tokenValueOffset, valuesEnd)
{ tokenValueOffset := add(tokenValueOffset, 32) }
{
// Load token value and generate scaled value
let tokenValue := mload(tokenValueOffset)
let scaledTokenValue := mul(tokenValue, amount)
// Revert if `amount` != 0 and multiplication resulted in an overflow
if iszero(or(
iszero(amount),
eq(div(scaledTokenValue, amount), tokenValue)
)) {
// Revert with `Error("UINT256_OVERFLOW")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
// There was no overflow, update `tokenValue` with its scaled counterpart
mstore(tokenValueOffset, scaledTokenValue)
}
////////// STEP 3/4 //////////
// Store the safeBatchTransferFrom function selector,
// and copy `from`/`to` fields from Table #1 to Table #3.
// The function selector is computed using:
// bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))
mstore(0, 0x2eb2c2d600000000000000000000000000000000000000000000000000000000)
// Copy `from` and `to` fields from Table #1 to Table #3
calldatacopy(
4, // aligned such that `from` and `to` are at the correct location for Table #3
36, // beginning of `from` field from Table #1
64 // 32 bytes for `from` + 32 bytes for `to` field
)
////////// STEP 4/4 //////////
// Call into the destination erc1155 contract using as calldata Table #3 (constructed in-memory above)
let success := call(
gas, // forward all gas
assetAddress, // call address of erc1155 asset
0, // don't send any ETH
0, // pointer to start of input
add(assetDataLength, 32), // length of input (Table #3) is 32 bytes longer than `assetData` (Table #2)
0, // write output over memory that won't be reused
0 // don't copy output to memory
)
// Revert with reason given by AssetProxy if `transferFrom` call failed
if iszero(success) {
returndatacopy(
0, // copy to memory at 0
0, // copy from return data at 0
returndatasize() // copy all return data
)
revert(0, returndatasize())
}
// Return if call was successful
return(0, 0)
}
// Revert if undefined function is called
revert(0, 0)
}
}
/// @dev Gets the proxy id associated with the proxy address.
/// @return Proxy id.
function getProxyId()
external
pure
returns (bytes4)
{
return PROXY_ID;
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity 0.4.24;
pragma solidity ^0.5.5;
import "./MixinAuthorizable.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity 0.4.24;
pragma solidity ^0.5.5;
import "./MixinAuthorizable.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/Ownable.sol";
import "./mixins/MAssetProxyDispatcher.sol";
@@ -28,7 +28,7 @@ contract MixinAssetProxyDispatcher is
MAssetProxyDispatcher
{
// Mapping from Asset Proxy Id's to their respective Asset Proxy
mapping (bytes4 => IAssetProxy) public assetProxies;
mapping (bytes4 => address) public assetProxies;
/// @dev Registers an asset proxy to its asset proxy id.
/// Once an asset proxy is registered, it cannot be unregistered.
@@ -37,10 +37,8 @@ contract MixinAssetProxyDispatcher is
external
onlyOwner
{
IAssetProxy assetProxyContract = IAssetProxy(assetProxy);
// Ensure that no asset proxy exists with current id.
bytes4 assetProxyId = assetProxyContract.getProxyId();
bytes4 assetProxyId = IAssetProxy(assetProxy).getProxyId();
address currentAssetProxy = assetProxies[assetProxyId];
require(
currentAssetProxy == address(0),
@@ -48,7 +46,7 @@ contract MixinAssetProxyDispatcher is
);
// Add asset proxy and log registration.
assetProxies[assetProxyId] = assetProxyContract;
assetProxies[assetProxyId] = assetProxy;
emit AssetProxyRegistered(
assetProxyId,
assetProxy

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/Ownable.sol";
import "./mixins/MAuthorizable.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity 0.4.24;
pragma solidity ^0.5.5;
import "./MixinAssetProxyDispatcher.sol";
import "./MixinAuthorizable.sol";

View File

@@ -17,7 +17,7 @@
*/
// solhint-disable
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
pragma experimental ABIEncoderV2;
@@ -36,8 +36,8 @@ interface IAssetData {
external;
function MultiAsset(
uint256[] amounts,
bytes[] nestedAssetData
uint256[] calldata amounts,
bytes[] calldata nestedAssetData
)
external;

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "./IAuthorizable.sol";
@@ -30,7 +30,7 @@ contract IAssetProxy is
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFrom(
bytes assetData,
bytes calldata assetData,
address from,
address to,
uint256 amount

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
contract IAssetProxyDispatcher {

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol";

View File

@@ -0,0 +1,420 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
library LibAssetData {
bytes4 constant public ERC20_PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
bytes4 constant public ERC721_PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
bytes4 constant public ERC1155_PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
bytes4 constant public MULTI_ASSET_PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
/// @dev Returns the owner's balance of the token(s) specified in
/// assetData. When the asset data contains multiple tokens (eg in
/// ERC1155 or Multi-Asset), the return value indicates how many
/// complete "baskets" of those tokens are owned by owner.
/// @param owner Owner of the tokens specified by assetData.
/// @param assetData Description of tokens, per the AssetProxy contract
/// specification.
/// @return Number of tokens (or token baskets) held by owner.
function getBalance(address owner, bytes memory assetData)
public
view
returns (uint256 balance)
{
bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
if (proxyId == ERC20_PROXY_ID) {
address tokenAddress = LibBytes.readAddress(assetData, 16);
return IERC20Token(tokenAddress).balanceOf(owner);
} else if (proxyId == ERC721_PROXY_ID) {
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
return getERC721TokenOwner(tokenAddress, tokenId) == owner ? 1 : 0;
} else if (proxyId == ERC1155_PROXY_ID) {
uint256 lowestTokenBalance = 0;
(
,
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
) = decodeERC1155AssetData(assetData);
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenBalance = IERC1155(tokenAddress).balanceOf(owner, tokenIds[i]) / tokenValues[i];
if (tokenBalance < lowestTokenBalance || lowestTokenBalance == 0) {
lowestTokenBalance = tokenBalance;
}
}
return lowestTokenBalance;
} else if (proxyId == MULTI_ASSET_PROXY_ID) {
uint256 lowestAssetBalance = 0;
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
for (uint256 i = 0; i < nestedAssetData.length; i++) {
uint256 assetBalance = getBalance(owner, nestedAssetData[i]) / assetAmounts[i];
if (assetBalance < lowestAssetBalance || lowestAssetBalance == 0) {
lowestAssetBalance = assetBalance;
}
}
return lowestAssetBalance;
} else {
revert("UNSUPPORTED_PROXY_IDENTIFIER");
}
}
/// @dev Calls getBalance() for each element of assetData.
/// @param owner Owner of the tokens specified by assetData.
/// @param assetData Array of token descriptors, each encoded per the
/// AssetProxy contract specification.
/// @return Array of token balances from getBalance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalances(address owner, bytes[] memory assetData)
public
view
returns (uint256[] memory balances)
{
balances = new uint256[](assetData.length);
for (uint256 i = 0; i < assetData.length; i++) {
balances[i] = getBalance(owner, assetData[i]);
}
}
/// @dev Returns the number of token(s) (described by assetData) that
/// spender is authorized to spend. When the asset data contains
/// multiple tokens (eg for Multi-Asset), the return value indicates
/// how many complete "baskets" of those tokens may be spent by spender.
/// @param owner Owner of the tokens specified by assetData.
/// @param spender Address whose authority to spend is in question.
/// @param assetData Description of tokens, per the AssetProxy contract
/// specification.
/// @return Number of tokens (or token baskets) that the spender is
/// authorized to spend.
function getAllowance(address owner, address spender, bytes memory assetData)
public
view
returns (uint256 allowance)
{
bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
if (proxyId == ERC20_PROXY_ID) {
address tokenAddress = LibBytes.readAddress(assetData, 16);
return IERC20Token(tokenAddress).allowance(owner, spender);
} else if (proxyId == ERC721_PROXY_ID) {
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
IERC721Token token = IERC721Token(tokenAddress);
if (spender == token.getApproved(tokenId) || token.isApprovedForAll(owner, spender)) {
return 1;
} else {
return 0;
}
} else if (proxyId == ERC1155_PROXY_ID) {
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
if (IERC1155(tokenAddress).isApprovedForAll(owner, spender)) {
return 1;
} else {
return 0;
}
} else if (proxyId == MULTI_ASSET_PROXY_ID) {
uint256 lowestAssetAllowance = 0;
// solhint-disable-next-line indent
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
for (uint256 i = 0; i < nestedAssetData.length; i++) {
uint256 assetAllowance = getAllowance(owner, spender, nestedAssetData[i]) / amounts[i];
if (assetAllowance < lowestAssetAllowance || lowestAssetAllowance == 0) {
lowestAssetAllowance = assetAllowance;
}
}
return lowestAssetAllowance;
} else {
revert("UNSUPPORTED_PROXY_IDENTIFIER");
}
}
/// @dev Calls getAllowance() for each element of assetData.
/// @param owner Owner of the tokens specified by assetData.
/// @param spender Address whose authority to spend is in question.
/// @param assetData Description of tokens, per the AssetProxy contract
/// specification.
/// @return An array of token allowances from getAllowance(), with each
/// element corresponding to the same-indexed element in the assetData
/// input.
function getBatchAllowances(address owner, address spender, bytes[] memory assetData)
public
view
returns (uint256[] memory allowances)
{
allowances = new uint256[](assetData.length);
for (uint256 i = 0; i < assetData.length; i++) {
allowances[i] = getAllowance(owner, spender, assetData[i]);
}
}
/// @dev Calls getBalance() and getAllowance() for assetData.
/// @param owner Owner of the tokens specified by assetData.
/// @param spender Address whose authority to spend is in question.
/// @param assetData Description of tokens, per the AssetProxy contract
/// specification.
/// @return Number of tokens (or token baskets) held by owner, and number
/// of tokens (or token baskets) that the spender is authorized to
/// spend.
function getBalanceAndAllowance(address owner, address spender, bytes memory assetData)
public
view
returns (uint256 balance, uint256 allowance)
{
balance = getBalance(owner, assetData);
allowance = getAllowance(owner, spender, assetData);
}
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element
/// of assetData.
/// @param owner Owner of the tokens specified by assetData.
/// @param spender Address whose authority to spend is in question.
/// @param assetData Description of tokens, per the AssetProxy contract
/// specification.
/// @return An array of token balances from getBalance(), and an array of
/// token allowances from getAllowance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalancesAndAllowances(address owner, address spender, bytes[] memory assetData)
public
view
returns (uint256[] memory balances, uint256[] memory allowances)
{
balances = getBatchBalances(owner, assetData);
allowances = getBatchAllowances(owner, spender, assetData);
}
/// @dev Encode ERC-20 asset data into the format described in the
/// AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-20 contract hosting the
/// token to be traded.
/// @return AssetProxy-compliant data describing the asset.
function encodeERC20AssetData(address tokenAddress)
public
pure
returns (bytes memory assetData)
{
return abi.encodeWithSelector(ERC20_PROXY_ID, tokenAddress);
}
/// @dev Decode ERC-20 asset data from the format described in the
/// AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20
/// asset.
/// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData)
public
pure
returns (
bytes4 proxyId,
address tokenAddress
)
{
proxyId = LibBytes.readBytes4(assetData, 0);
require(proxyId == ERC20_PROXY_ID, "WRONG_PROXY_ID");
tokenAddress = LibBytes.readAddress(assetData, 16);
}
/// @dev Encode ERC-721 asset data into the format described in the
/// AssetProxy specification.
/// @param tokenAddress The address of the ERC-721 contract hosting the
/// token to be traded.
/// @param tokenId The identifier of the specific token to be traded.
/// @return AssetProxy-compliant asset data describing the asset.
function encodeERC721AssetData(
address tokenAddress,
uint256 tokenId
)
public
pure
returns (bytes memory assetData)
{
return abi.encodeWithSelector(ERC721_PROXY_ID, tokenAddress, tokenId);
}
/// @dev Decode ERC-721 asset data from the format described in the
/// AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-721
/// asset.
/// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
/// contract hosting this asset, and the identifier of the specific
/// token to be traded.
function decodeERC721AssetData(bytes memory assetData)
public
pure
returns (
bytes4 proxyId,
address tokenAddress,
uint256 tokenId
)
{
proxyId = LibBytes.readBytes4(assetData, 0);
require(proxyId == ERC721_PROXY_ID, "WRONG_PROXY_ID");
tokenAddress = LibBytes.readAddress(assetData, 16);
tokenId = LibBytes.readUint256(assetData, 36);
}
/// @dev Encode ERC-1155 asset data into the format described in the
/// AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-1155 contract hosting the
/// token(s) to be traded.
/// @param tokenIds The identifiers of the specific tokens to be traded.
/// @param tokenValues The amounts of each token to be traded.
/// @param callbackData ...
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeERC1155AssetData(
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
public
pure
returns (bytes memory assetData)
{
return abi.encodeWithSelector(ERC1155_PROXY_ID, tokenAddress, tokenIds, tokenValues, callbackData);
}
/// @dev Decode ERC-1155 asset data from the format described in the
/// AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-1155
/// set of assets.
/// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
/// contract hosting the assets, an array of the identifiers of the
/// tokens to be traded, an array of token amounts to be traded, and
/// callback data. Each element of the arrays corresponds to the
/// same-indexed element of the other array. Return values specified as
/// `memory` are returned as pointers to locations within the memory of
/// the input parameter `assetData`.
function decodeERC1155AssetData(bytes memory assetData)
public
pure
returns (
bytes4 proxyId,
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
{
proxyId = LibBytes.readBytes4(assetData, 0);
require(proxyId == ERC1155_PROXY_ID, "WRONG_PROXY_ID");
assembly {
// Skip selector and length to get to the first parameter:
assetData := add(assetData, 36)
// Read the value of the first parameter:
tokenAddress := mload(assetData)
// Point to the next parameter's data:
tokenIds := add(assetData, mload(add(assetData, 32)))
// Point to the next parameter's data:
tokenValues := add(assetData, mload(add(assetData, 64)))
// Point to the next parameter's data:
callbackData := add(assetData, mload(add(assetData, 96)))
}
}
/// @dev Encode data for multiple assets, per the AssetProxy contract
/// specification.
/// @param amounts The amounts of each asset to be traded.
/// @param nestedAssetData AssetProxy-compliant data describing each asset
/// to be traded.
/// @return AssetProxy-compliant data describing the set of assets.
function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
public
pure
returns (bytes memory assetData)
{
assetData = abi.encodeWithSelector(MULTI_ASSET_PROXY_ID, amounts, nestedAssetData);
}
/// @dev Decode multi-asset data from the format described in the
/// AssetProxy contract specification.
/// @param assetData AssetProxy-compliant data describing a multi-asset
/// basket.
/// @return The Multi-Asset AssetProxy identifier, an array of the amounts
/// of the assets to be traded, and an array of the
/// AssetProxy-compliant data describing each asset to be traded. Each
/// element of the arrays corresponds to the same-indexed element of
/// the other array.
function decodeMultiAssetData(bytes memory assetData)
public
pure
returns (
bytes4 proxyId,
uint256[] memory amounts,
bytes[] memory nestedAssetData
)
{
proxyId = LibBytes.readBytes4(assetData, 0);
require(proxyId == MULTI_ASSET_PROXY_ID, "WRONG_PROXY_ID");
// solhint-disable-next-line indent
(amounts, nestedAssetData) = abi.decode(LibBytes.slice(assetData, 4, assetData.length), (uint256[], bytes[]));
}
/// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
/// @param token Address of ERC721 token.
/// @param tokenId The identifier for the specific NFT.
/// @return Owner of tokenId or null address if unowned.
function getERC721TokenOwner(address token, uint256 tokenId)
public
view
returns (address owner)
{
assembly {
// load free memory pointer
let cdStart := mload(64)
// bytes4(keccak256(ownerOf(uint256))) = 0x6352211e
mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)
mstore(add(cdStart, 4), tokenId)
// staticcall `ownerOf(tokenId)`
// `ownerOf` will revert if tokenId is not owned
let success := staticcall(
gas, // forward all gas
token, // call token contract
cdStart, // start of calldata
36, // length of input is 36 bytes
cdStart, // write output over input
32 // size of output is 32 bytes
)
// Success implies that tokenId is owned
// Copy owner from return data if successful
if success {
owner := mload(cdStart)
}
}
// Owner initialized to address(0), no need to modify if call is unsuccessful
return owner;
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "../interfaces/IAssetProxyDispatcher.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.5;
import "../interfaces/IAuthorizable.sol";

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-asset-proxy",
"version": "1.0.1",
"version": "2.1.2",
"engines": {
"node": ">=6.12"
},
@@ -24,15 +24,18 @@
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"profiler:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test",
"contracts:gen": "contracts-gen",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"config": {
"abis": "generated-artifacts/@(ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy).json"
"abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|LibAssetData|MixinAuthorizable|MultiAssetProxy).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
"type": "git",
@@ -44,10 +47,12 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^2.0.0",
"@0x/dev-utils": "^2.0.0",
"@0x/sol-compiler": "^3.0.0",
"@0x/tslint-config": "^3.0.0",
"@0x/abi-gen": "^2.0.10",
"@0x/contracts-gen": "^1.0.9",
"@0x/contracts-test-utils": "^3.1.3",
"@0x/dev-utils": "^2.2.2",
"@0x/sol-compiler": "^3.1.7",
"@0x/tslint-config": "^3.0.1",
"@types/lodash": "4.14.104",
"@types/node": "*",
"chai": "^4.0.1",
@@ -63,18 +68,18 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^4.0.0",
"@0x/contracts-erc20": "^1.0.1",
"@0x/contracts-erc721": "^1.0.1",
"@0x/contracts-test-utils": "^3.0.0",
"@0x/contracts-utils": "^2.0.0",
"@0x/order-utils": "^4.0.0",
"@0x/types": "^2.0.0",
"@0x/typescript-typings": "^4.0.0",
"@0x/utils": "^4.0.1",
"@0x/web3-wrapper": "^4.0.0",
"ethereum-types": "^2.0.0",
"lodash": "^4.17.5"
"@0x/base-contract": "^5.1.0",
"@0x/contracts-erc1155": "^1.1.2",
"@0x/contracts-erc20": "^2.2.1",
"@0x/contracts-erc721": "^2.1.2",
"@0x/contracts-utils": "^3.1.2",
"@0x/order-utils": "^8.0.0",
"@0x/types": "^2.2.2",
"@0x/typescript-typings": "^4.2.2",
"@0x/utils": "^4.3.3",
"@0x/web3-wrapper": "^6.0.6",
"ethereum-types": "^2.1.2",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"

View File

@@ -0,0 +1,27 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
import * as IAssetData from '../generated-artifacts/IAssetData.json';
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
export const artifacts = {
LibAssetData: LibAssetData as ContractArtifact,
ERC1155Proxy: ERC1155Proxy as ContractArtifact,
ERC20Proxy: ERC20Proxy as ContractArtifact,
ERC721Proxy: ERC721Proxy as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,
IAssetProxy: IAssetProxy as ContractArtifact,
IAuthorizable: IAuthorizable as ContractArtifact,
};

View File

@@ -1,19 +0,0 @@
import { ContractArtifact } from 'ethereum-types';
import * as ERC20Proxy from '../../generated-artifacts/ERC20Proxy.json';
import * as ERC721Proxy from '../../generated-artifacts/ERC721Proxy.json';
import * as IAssetData from '../../generated-artifacts/IAssetData.json';
import * as IAssetProxy from '../../generated-artifacts/IAssetProxy.json';
import * as IAuthorizable from '../../generated-artifacts/IAuthorizable.json';
import * as MixinAuthorizable from '../../generated-artifacts/MixinAuthorizable.json';
import * as MultiAssetProxy from '../../generated-artifacts/MultiAssetProxy.json';
export const artifacts = {
IAuthorizable: IAuthorizable as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,
IAssetProxy: IAssetProxy as ContractArtifact,
ERC20Proxy: ERC20Proxy as ContractArtifact,
ERC721Proxy: ERC721Proxy as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
};

View File

@@ -0,0 +1,14 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/erc1155_proxy';
export * from '../generated-wrappers/erc20_proxy';
export * from '../generated-wrappers/erc721_proxy';
export * from '../generated-wrappers/i_asset_data';
export * from '../generated-wrappers/i_asset_proxy';
export * from '../generated-wrappers/i_authorizable';
export * from '../generated-wrappers/lib_asset_data';
export * from '../generated-wrappers/mixin_authorizable';
export * from '../generated-wrappers/multi_asset_proxy';

View File

@@ -1,7 +0,0 @@
export * from '../../generated-wrappers/i_asset_data';
export * from '../../generated-wrappers/i_asset_proxy';
export * from '../../generated-wrappers/erc20_proxy';
export * from '../../generated-wrappers/erc721_proxy';
export * from '../../generated-wrappers/mixin_authorizable';
export * from '../../generated-wrappers/multi_asset_proxy';
export * from '../../generated-wrappers/i_authorizable';

View File

@@ -53,16 +53,18 @@ describe('Authorizable', () => {
);
});
it('should allow owner to add an authorized address', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const isAuthorized = await authorizable.authorized.callAsync(address);
expect(isAuthorized).to.be.true();
});
it('should throw if owner attempts to authorize a duplicate address', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
return expectTransactionFailedAsync(
@@ -74,8 +76,9 @@ describe('Authorizable', () => {
describe('removeAuthorizedAddress', () => {
it('should throw if not called by owner', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
return expectTransactionFailedAsync(
@@ -87,14 +90,14 @@ describe('Authorizable', () => {
});
it('should allow owner to remove an authorized address', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner,
}),
await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const isAuthorized = await authorizable.authorized.callAsync(address);
@@ -113,8 +116,9 @@ describe('Authorizable', () => {
describe('removeAuthorizedAddressAtIndex', () => {
it('should throw if not called by owner', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const index = new BigNumber(0);
@@ -126,8 +130,9 @@ describe('Authorizable', () => {
);
});
it('should throw if index is >= authorities.length', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const index = new BigNumber(1);
@@ -150,12 +155,14 @@ describe('Authorizable', () => {
it('should throw if address at index does not match target', async () => {
const address1 = address;
const address2 = notOwner;
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address1, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address1,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address2, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address2,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const address1Index = new BigNumber(0);
@@ -167,15 +174,16 @@ describe('Authorizable', () => {
);
});
it('should allow owner to remove an authorized address', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const index = new BigNumber(0);
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
from: owner,
}),
await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync(
address,
index,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const isAuthorized = await authorizable.authorized.callAsync(address);
@@ -187,20 +195,17 @@ describe('Authorizable', () => {
it('should return all authorized addresses', async () => {
const initial = await authorizable.getAuthorizedAddresses.callAsync();
expect(initial).to.have.length(0);
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, {
from: owner,
}),
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const afterAdd = await authorizable.getAuthorizedAddresses.callAsync();
expect(afterAdd).to.have.length(1);
expect(afterAdd).to.include(address);
await web3Wrapper.awaitTransactionSuccessAsync(
await authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner,
}),
await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(
address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const afterRemove = await authorizable.getAuthorizedAddresses.callAsync();

View File

@@ -0,0 +1,831 @@
import {
artifacts as erc1155Artifacts,
DummyERC1155ReceiverBatchTokenReceivedEventArgs,
DummyERC1155ReceiverContract,
ERC1155MintableContract,
Erc1155Wrapper,
} from '@0x/contracts-erc1155';
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
expectTransactionFailedWithoutReasonAsync,
provider,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { ERC1155ProxyWrapper, ERC721ProxyContract } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('ERC1155Proxy', () => {
// constant values used in transfer tests
const nftOwnerBalance = new BigNumber(1);
const nftNotOwnerBalance = new BigNumber(0);
const spenderInitialFungibleBalance = constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
const receiverInitialFungibleBalance = constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
const receiverContractInitialFungibleBalance = new BigNumber(0);
const fungibleValueToTransferSmall = spenderInitialFungibleBalance.div(100);
const fungibleValueToTransferLarge = spenderInitialFungibleBalance.div(4);
const valueMultiplierSmall = new BigNumber(2);
const valueMultiplierNft = new BigNumber(1);
const nonFungibleValueToTransfer = nftOwnerBalance;
const receiverCallbackData = '0x01020304';
// addresses
let owner: string;
let notAuthorized: string;
let authorized: string;
let spender: string;
let receiver: string;
let receiverContract: string;
// contracts & wrappers
let erc1155Proxy: ERC721ProxyContract;
let erc1155Receiver: DummyERC1155ReceiverContract;
let erc1155ProxyWrapper: ERC1155ProxyWrapper;
let erc1155Contract: ERC1155MintableContract;
let erc1155Wrapper: Erc1155Wrapper;
// tokens
let fungibleTokens: BigNumber[];
let nonFungibleTokensOwnedBySpender: BigNumber[];
// tests
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
/// deploy & configure ERC1155Proxy
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, notAuthorized, authorized, spender, receiver] = _.slice(accounts, 0, 5));
erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner);
erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync();
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
authorized,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
erc1155Proxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
// deploy & configure ERC1155 tokens and receiver
[erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync();
erc1155Contract = erc1155Wrapper.getContract();
erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
erc1155Artifacts.DummyERC1155Receiver,
provider,
txDefaults,
);
receiverContract = erc1155Receiver.address;
await erc1155ProxyWrapper.setBalancesAndAllowancesAsync();
fungibleTokens = erc1155ProxyWrapper.getFungibleTokenIds();
const nonFungibleTokens = erc1155ProxyWrapper.getNonFungibleTokenIds();
const tokenBalances = await erc1155ProxyWrapper.getBalancesAsync();
nonFungibleTokensOwnedBySpender = [];
_.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => {
const nonFungibleTokenAsString = nonFungibleToken.toString();
const nonFungibleTokenHeldBySpender =
tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
});
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('general', () => {
it('should revert if undefined function is called', async () => {
const undefinedSelector = '0x01020304';
await expectTransactionFailedWithoutReasonAsync(
web3Wrapper.sendTransactionAsync({
from: owner,
to: erc1155Proxy.address,
value: constants.ZERO_AMOUNT,
data: undefinedSelector,
}),
);
});
it('should have an id of 0x9645780d', async () => {
const proxyId = await erc1155Proxy.getProxyId.callAsync();
const expectedProxyId = AssetProxyId.ERC1155;
expect(proxyId).to.equal(expectedProxyId);
});
});
describe('transferFrom', () => {
it('should successfully transfer value for a single, fungible token', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier);
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(totalValueTransferred),
receiverInitialFungibleBalance.plus(totalValueTransferred),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer value for the same fungible token several times', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = fungibleTokens[0];
const tokensToTransfer = [tokenToTransfer, tokenToTransfer, tokenToTransfer];
const valuesToTransfer = [
fungibleValueToTransferSmall.plus(10),
fungibleValueToTransferSmall.plus(20),
fungibleValueToTransferSmall.plus(30),
];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [
// spender
spenderInitialFungibleBalance,
// receiver
receiverInitialFungibleBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
let totalValueTransferred = _.reduce(valuesToTransfer, (sum: BigNumber, value: BigNumber) => {
return sum.plus(value);
}) as BigNumber;
totalValueTransferred = totalValueTransferred.times(valueMultiplier);
const expectedFinalBalances = [
// spender
spenderInitialFungibleBalance.minus(totalValueTransferred),
// receiver
receiverInitialFungibleBalance.plus(totalValueTransferred),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
});
it('should successfully transfer value for several fungible tokens', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 3);
const valuesToTransfer = [
fungibleValueToTransferSmall.plus(10),
fungibleValueToTransferSmall.plus(20),
fungibleValueToTransferSmall.plus(30),
];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [
// spender
spenderInitialFungibleBalance,
spenderInitialFungibleBalance,
spenderInitialFungibleBalance,
// receiver
receiverInitialFungibleBalance,
receiverInitialFungibleBalance,
receiverInitialFungibleBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier);
});
const expectedFinalBalances = [
// spender
spenderInitialFungibleBalance.minus(totalValuesTransferred[0]),
spenderInitialFungibleBalance.minus(totalValuesTransferred[1]),
spenderInitialFungibleBalance.minus(totalValuesTransferred[2]),
// receiver
receiverInitialFungibleBalance.plus(totalValuesTransferred[0]),
receiverInitialFungibleBalance.plus(totalValuesTransferred[1]),
receiverInitialFungibleBalance.plus(totalValuesTransferred[2]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer a non-fungible token', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
const valuesToTransfer = [nonFungibleValueToTransfer];
const valueMultiplier = valueMultiplierNft;
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const expectedFinalBalances = [
// spender
nftNotOwnerBalance,
// receiver
nftOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple non-fungible tokens', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 3);
const valuesToTransfer = [
nonFungibleValueToTransfer,
nonFungibleValueToTransfer,
nonFungibleValueToTransfer,
];
const valueMultiplier = valueMultiplierNft;
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
nftOwnerBalance,
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
nftNotOwnerBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const expectedFinalBalances = [
// spender
nftNotOwnerBalance,
nftNotOwnerBalance,
nftNotOwnerBalance,
// receiver
nftOwnerBalance,
nftOwnerBalance,
nftOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer value for a combination of several fungible/non-fungible tokens', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const fungibleTokensToTransfer = fungibleTokens.slice(0, 3);
const nonFungibleTokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 2);
const tokensToTransfer = fungibleTokensToTransfer.concat(nonFungibleTokensToTransfer);
const valuesToTransfer = [
fungibleValueToTransferLarge,
fungibleValueToTransferSmall,
fungibleValueToTransferSmall,
nonFungibleValueToTransfer,
nonFungibleValueToTransfer,
];
const valueMultiplier = valueMultiplierNft;
// check balances before transfer
const expectedInitialBalances = [
// spender
spenderInitialFungibleBalance,
spenderInitialFungibleBalance,
spenderInitialFungibleBalance,
nftOwnerBalance,
nftOwnerBalance,
// receiver
receiverInitialFungibleBalance,
receiverInitialFungibleBalance,
receiverInitialFungibleBalance,
nftNotOwnerBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier);
});
const expectedFinalBalances = [
// spender
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].minus(totalValuesTransferred[1]),
expectedInitialBalances[2].minus(totalValuesTransferred[2]),
expectedInitialBalances[3].minus(totalValuesTransferred[3]),
expectedInitialBalances[4].minus(totalValuesTransferred[4]),
// receiver
expectedInitialBalances[5].plus(totalValuesTransferred[0]),
expectedInitialBalances[6].plus(totalValuesTransferred[1]),
expectedInitialBalances[7].plus(totalValuesTransferred[2]),
expectedInitialBalances[8].plus(totalValuesTransferred[3]),
expectedInitialBalances[9].plus(totalValuesTransferred[4]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer value to a smart contract and trigger its callback', async () => {
// setup test parameters
const tokenHolders = [spender, receiverContract];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier);
});
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
spender,
receiverContract,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check receiver log ignored extra asset data
expect(txReceipt.logs.length).to.be.equal(2);
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
DummyERC1155ReceiverBatchTokenReceivedEventArgs
>;
expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
expect(receiverLog.args.from).to.be.equal(spender);
expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]);
// note - if the `extraData` is ignored then the receiver log should ignore it as well.
expect(receiverLog.args.data).to.be.deep.equal(receiverCallbackData);
// check balances after transfer
const expectedFinalBalances = [
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].plus(totalValuesTransferred[0]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer value to a smart contract and trigger its callback, when callback `data` is NULL', async () => {
// setup test parameters
const tokenHolders = [spender, receiverContract];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier);
});
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
const nullReceiverCallbackData = '0x';
const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
spender,
receiverContract,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
nullReceiverCallbackData,
authorized,
);
// check receiver log ignored extra asset data
expect(txReceipt.logs.length).to.be.equal(2);
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
DummyERC1155ReceiverBatchTokenReceivedEventArgs
>;
expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
expect(receiverLog.args.from).to.be.equal(spender);
expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]);
// note - if the `extraData` is ignored then the receiver log should ignore it as well.
expect(receiverLog.args.data).to.be.deep.equal(nullReceiverCallbackData);
// check balances after transfer
const expectedFinalBalances = [
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].plus(totalValuesTransferred[0]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer value and ignore extra assetData', async () => {
// setup test parameters
const tokenHolders = [spender, receiverContract];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier);
});
const extraData = '0102030405060708';
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
spender,
receiverContract,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
extraData,
);
// check receiver log ignored extra asset data
expect(txReceipt.logs.length).to.be.equal(2);
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
DummyERC1155ReceiverBatchTokenReceivedEventArgs
>;
expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
expect(receiverLog.args.from).to.be.equal(spender);
expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]);
// note - if the `extraData` is ignored then the receiver log should ignore it as well.
expect(receiverLog.args.data).to.be.deep.equal(receiverCallbackData);
// check balances after transfer
const expectedFinalBalances = [
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].plus(totalValuesTransferred[0]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should transfer nothing if value is zero', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [new BigNumber(0)];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should transfer nothing if value multiplier is zero', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = new BigNumber(0);
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should transfer nothing if there are no tokens in asset data', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer: BigNumber[] = [];
const valuesToTransfer: BigNumber[] = [];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
);
// check balances after transfer
const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should propagate revert reason from erc1155 contract failure', async () => {
// disable transfers
const shouldRejectTransfer = true;
await erc1155Receiver.setRejectTransferFlag.awaitTransactionSuccessAsync(
shouldRejectTransfer,
constants.AWAIT_TRANSACTION_MINED_MS,
);
// setup test parameters
const tokenHolders = [spender, receiverContract];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiverContract,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.TransferRejected,
);
});
it('should revert if transferring the same non-fungible token more than once', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const nftToTransfer = nonFungibleTokensOwnedBySpender[0];
const tokensToTransfer = [nftToTransfer, nftToTransfer];
const valuesToTransfer = [nonFungibleValueToTransfer, nonFungibleValueToTransfer];
const valueMultiplier = valueMultiplierNft;
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.NFTNotOwnedByFromAddress,
);
});
it('should revert if there is a multiplication overflow', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 3);
const maxUintValue = new BigNumber(2).pow(256).minus(1);
const valuesToTransfer = [nonFungibleValueToTransfer, maxUintValue, nonFungibleValueToTransfer];
const valueMultiplier = new BigNumber(2);
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
nftOwnerBalance,
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
nftNotOwnerBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
// note - this will overflow because we are trying to transfer `maxUintValue * 2` of the 2nd token
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.Uint256Overflow,
);
});
it('should revert if transferring > 1 instances of a non-fungible token (valueMultiplier field >1)', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
const valuesToTransfer = [nonFungibleValueToTransfer];
const valueMultiplier = new BigNumber(2);
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.AmountEqualToOneRequired,
);
});
it('should revert if transferring > 1 instances of a non-fungible token (`valuesToTransfer` field >1)', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
const valuesToTransfer = [new BigNumber(2)];
const valueMultiplier = valueMultiplierNft;
// check balances before transfer
const expectedInitialBalances = [
// spender
nftOwnerBalance,
// receiver
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.AmountEqualToOneRequired,
);
});
it('should revert if sender balance is insufficient', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valueGreaterThanSpenderBalance = spenderInitialFungibleBalance.plus(1);
const valuesToTransfer = [valueGreaterThanSpenderBalance];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.Uint256Underflow,
);
});
it('should revert if sender allowance is insufficient', async () => {
// dremove allowance for ERC1155 proxy
const wrapper = erc1155ProxyWrapper.getContractWrapper(erc1155Contract.address);
const isApproved = false;
await wrapper.setApprovalForAllAsync(spender, erc1155Proxy.address, isApproved);
const isApprovedActualValue = await wrapper.isApprovedForAllAsync(spender, erc1155Proxy.address);
expect(isApprovedActualValue).to.be.equal(isApproved);
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorized,
),
RevertReason.InsufficientAllowance,
);
});
it('should revert if caller is not authorized', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = fungibleTokens.slice(0, 1);
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155ProxyWrapper.transferFromAsync(
spender,
receiver,
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
notAuthorized,
),
RevertReason.SenderNotAuthorized,
);
});
});
});
// tslint:enable:no-unnecessary-type-assertion
// tslint:disable:max-file-line-count

View File

@@ -1,8 +1,10 @@
import { env, EnvVars } from '@0x/dev-utils';
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
import { providerUtils } from '@0x/utils';
before('start web3 provider', () => {
provider.start();
providerUtils.startProviderEngine(provider);
});
after('generate coverage report', async () => {
if (env.parseBoolean(EnvVars.SolidityCoverage)) {

View File

@@ -0,0 +1,426 @@
// TODO: change test titles to say "... from asset data"
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import {
artifacts as erc1155Artifacts,
ERC1155MintableContract,
ERC1155TransferSingleEventArgs,
IERC1155MintableContract,
} from '@0x/contracts-erc1155';
import { artifacts as erc20Artifacts, DummyERC20TokenContract, IERC20TokenContract } from '@0x/contracts-erc20';
import { artifacts as erc721Artifacts, DummyERC721TokenContract, IERC721TokenContract } from '@0x/contracts-erc721';
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { artifacts, LibAssetDataContract } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const KNOWN_ERC20_ENCODING = {
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
};
const KNOWN_ERC721_ENCODING = {
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
tokenId: new BigNumber(1),
assetData:
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
};
const KNOWN_ERC1155_ENCODING = {
tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
callbackData:
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
assetData:
'0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
};
const KNOWN_MULTI_ASSET_ENCODING = {
amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
nestedAssetData: [
KNOWN_ERC20_ENCODING.assetData,
KNOWN_ERC721_ENCODING.assetData,
KNOWN_ERC1155_ENCODING.assetData,
],
assetData:
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
};
describe('LibAssetData', () => {
let libAssetData: LibAssetDataContract;
let tokenOwnerAddress: string;
let approvedSpenderAddress: string;
let anotherApprovedSpenderAddress: string;
let erc20TokenAddress: string;
const erc20TokenTotalSupply = new BigNumber(1);
let erc721TokenAddress: string;
const firstERC721TokenId = new BigNumber(1);
const numberOfERC721Tokens = 10;
let erc1155MintableAddress: string;
let erc1155TokenId: BigNumber;
before(async () => {
await blockchainLifecycle.startAsync();
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
artifacts.LibAssetData,
provider,
txDefaults,
);
[
tokenOwnerAddress,
approvedSpenderAddress,
anotherApprovedSpenderAddress,
] = await web3Wrapper.getAvailableAddressesAsync();
erc20TokenAddress = (await DummyERC20TokenContract.deployFrom0xArtifactAsync(
erc20Artifacts.DummyERC20Token,
provider,
txDefaults,
'Dummy',
'DUM',
new BigNumber(1),
erc20TokenTotalSupply,
)).address;
const erc721TokenContract = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
erc721Artifacts.DummyERC721Token,
provider,
txDefaults,
'Dummy',
'DUM',
);
erc721TokenAddress = erc721TokenContract.address;
// mint `numberOfERC721Tokens` tokens
const transactionMinedPromises = [];
for (let i = 0; i < numberOfERC721Tokens; i++) {
transactionMinedPromises.push(
web3Wrapper.awaitTransactionSuccessAsync(
await erc721TokenContract.mint.sendTransactionAsync(
tokenOwnerAddress,
firstERC721TokenId.plus(i - 1),
),
constants.AWAIT_TRANSACTION_MINED_MS,
),
);
}
await Promise.all(transactionMinedPromises);
const erc1155MintableContract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
erc1155Artifacts.ERC1155Mintable,
provider,
txDefaults,
);
erc1155MintableAddress = erc1155MintableContract.address;
// Somewhat re-inventing the wheel here, but the prior art currently
// exists only as an unexported test util in the erc1155 package
// (Erc1155Wrapper.mintFungibleTokensAsync() in erc1155/test/utils/).
// This is concise enough to justify duplication, but it sure is ugly.
// tslint:disable-next-line no-unnecessary-type-assertion
erc1155TokenId = ((await new LogDecoder(web3Wrapper, erc1155Artifacts).getTxWithDecodedLogsAsync(
await erc1155MintableContract.create.sendTransactionAsync('uri:Dummy', /*isNonFungible:*/ false),
)).logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
await web3Wrapper.awaitTransactionSuccessAsync(
await erc1155MintableContract.mintFungible.sendTransactionAsync(
erc1155TokenId,
[tokenOwnerAddress],
[new BigNumber(1)],
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
async function setERC20AllowanceAsync(): Promise<any> {
return web3Wrapper.awaitTransactionSuccessAsync(
await new IERC20TokenContract(
erc20Artifacts.IERC20Token.compilerOutput.abi,
erc20TokenAddress,
provider,
).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
async function setERC721AllowanceAsync(): Promise<any> {
return web3Wrapper.awaitTransactionSuccessAsync(
await new IERC721TokenContract(
erc721Artifacts.IERC721Token.compilerOutput.abi,
erc721TokenAddress,
provider,
).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
after(async () => {
await blockchainLifecycle.revertAsync();
});
it('should have a deployed-to address', () => {
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
});
it('should encode ERC20 asset data', async () => {
expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
KNOWN_ERC20_ENCODING.assetData,
);
});
it('should decode ERC20 asset data', async () => {
expect(await libAssetData.decodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.assetData)).to.deep.equal([
AssetProxyId.ERC20,
KNOWN_ERC20_ENCODING.address,
]);
});
it('should encode ERC721 asset data', async () => {
expect(
await libAssetData.encodeERC721AssetData.callAsync(
KNOWN_ERC721_ENCODING.address,
KNOWN_ERC721_ENCODING.tokenId,
),
).to.equal(KNOWN_ERC721_ENCODING.assetData);
});
it('should decode ERC721 asset data', async () => {
expect(await libAssetData.decodeERC721AssetData.callAsync(KNOWN_ERC721_ENCODING.assetData)).to.deep.equal([
AssetProxyId.ERC721,
KNOWN_ERC721_ENCODING.address,
KNOWN_ERC721_ENCODING.tokenId,
]);
});
it('should encode ERC1155 asset data', async () => {
expect(
await libAssetData.encodeERC1155AssetData.callAsync(
KNOWN_ERC1155_ENCODING.tokenAddress,
KNOWN_ERC1155_ENCODING.tokenIds,
KNOWN_ERC1155_ENCODING.tokenValues,
KNOWN_ERC1155_ENCODING.callbackData,
),
).to.equal(KNOWN_ERC1155_ENCODING.assetData);
});
it('should decode ERC1155 asset data', async () => {
expect(await libAssetData.decodeERC1155AssetData.callAsync(KNOWN_ERC1155_ENCODING.assetData)).to.deep.equal([
AssetProxyId.ERC1155,
KNOWN_ERC1155_ENCODING.tokenAddress,
KNOWN_ERC1155_ENCODING.tokenIds,
KNOWN_ERC1155_ENCODING.tokenValues,
KNOWN_ERC1155_ENCODING.callbackData,
]);
});
it('should encode multiasset data', async () => {
expect(
await libAssetData.encodeMultiAssetData.callAsync(
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
),
).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
});
it('should decode multiasset data', async () => {
expect(await libAssetData.decodeMultiAssetData.callAsync(KNOWN_MULTI_ASSET_ENCODING.assetData)).to.deep.equal([
AssetProxyId.MultiAsset,
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
]);
});
it('should query ERC20 balance by asset data', async () => {
expect(
await libAssetData.getBalance.callAsync(
tokenOwnerAddress,
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
),
).to.bignumber.equal(erc20TokenTotalSupply);
});
it('should query ERC721 balance by asset data', async () => {
expect(
await libAssetData.getBalance.callAsync(
tokenOwnerAddress,
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
),
).to.bignumber.equal(1);
});
it('should query ERC1155 balances by asset data', async () => {
expect(
await libAssetData.getBalance.callAsync(
tokenOwnerAddress,
await libAssetData.encodeERC1155AssetData.callAsync(
erc1155MintableAddress,
[erc1155TokenId],
[new BigNumber(1)], // token values
'0x', // callback data
),
),
).to.bignumber.equal(1);
});
it('should query multi-asset batch balance by asset data', async () => {
expect(
await libAssetData.getBalance.callAsync(
tokenOwnerAddress,
await libAssetData.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
],
),
),
).to.bignumber.equal(Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens));
});
it('should query ERC20 allowances by asset data', async () => {
await setERC20AllowanceAsync();
expect(
await libAssetData.getAllowance.callAsync(
tokenOwnerAddress,
approvedSpenderAddress,
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
),
).to.bignumber.equal(1);
});
it('should query ERC721 approval by asset data', async () => {
await setERC721AllowanceAsync();
expect(
await libAssetData.getAllowance.callAsync(
tokenOwnerAddress,
approvedSpenderAddress,
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
),
).to.bignumber.equal(1);
});
it('should query ERC721 approvalForAll by assetData', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await new IERC721TokenContract(
erc721Artifacts.IERC721Token.compilerOutput.abi,
erc721TokenAddress,
provider,
).setApprovalForAll.sendTransactionAsync(anotherApprovedSpenderAddress, true, {
from: tokenOwnerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
expect(
await libAssetData.getAllowance.callAsync(
tokenOwnerAddress,
anotherApprovedSpenderAddress,
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
),
).to.bignumber.equal(1);
});
it('should query ERC1155 allowances by asset data', async () => {
await web3Wrapper.awaitTransactionSuccessAsync(
await new IERC1155MintableContract(
erc1155Artifacts.IERC1155Mintable.compilerOutput.abi,
erc1155MintableAddress,
provider,
).setApprovalForAll.sendTransactionAsync(approvedSpenderAddress, true, { from: tokenOwnerAddress }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
expect(
await libAssetData.getAllowance.callAsync(
tokenOwnerAddress,
approvedSpenderAddress,
await libAssetData.encodeERC1155AssetData.callAsync(
erc1155MintableAddress,
[erc1155TokenId],
[new BigNumber(1)],
'0x',
),
),
).to.bignumber.equal(1);
});
it('should query multi-asset allowances by asset data', async () => {
await setERC20AllowanceAsync();
await setERC721AllowanceAsync();
expect(
await libAssetData.getAllowance.callAsync(
tokenOwnerAddress,
approvedSpenderAddress,
await libAssetData.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
],
),
),
).to.bignumber.equal(1);
return;
});
it('should query balances for a batch of asset data strings', async () => {
expect(
await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
]),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
});
it('should query allowances for a batch of asset data strings', async () => {
await setERC20AllowanceAsync();
await setERC721AllowanceAsync();
expect(
await libAssetData.getBatchAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
]),
).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
});
describe('getERC721TokenOwner', async () => {
it('should return the null address when tokenId is not owned', async () => {
const nonexistentTokenId = new BigNumber(1234567890);
expect(
await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, nonexistentTokenId),
).to.be.equal(constants.NULL_ADDRESS);
});
it('should return the owner address when tokenId is owned', async () => {
expect(
await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, firstERC721TokenId),
).to.be.equal(tokenOwnerAddress);
});
});
it('should query balance and allowance together, from asset data', async () => {
await setERC20AllowanceAsync();
expect(
await libAssetData.getBalanceAndAllowance.callAsync(
tokenOwnerAddress,
approvedSpenderAddress,
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
});
it('should query balances and allowances together, from an asset data array', async () => {
await setERC20AllowanceAsync();
expect(
await libAssetData.getBatchBalancesAndAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
]),
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [new BigNumber(1)]]);
});
});

View File

@@ -1,3 +1,4 @@
import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
artifacts as erc20Artifacts,
DummyERC20TokenContract,
@@ -30,6 +31,7 @@ import * as _ from 'lodash';
import {
artifacts,
ERC1155ProxyWrapper,
ERC20ProxyContract,
ERC20Wrapper,
ERC721ProxyContract,
@@ -77,6 +79,15 @@ describe('Asset Transfer Proxies', () => {
let erc721AFromTokenId: BigNumber;
let erc721BFromTokenId: BigNumber;
let erc1155Proxy: ERC721ProxyContract;
let erc1155ProxyWrapper: ERC1155ProxyWrapper;
let erc1155Contract: ERC1155MintableContract;
let erc1155Contract2: ERC1155MintableContract;
let erc1155Wrapper: Erc1155Wrapper;
let erc1155Wrapper2: Erc1155Wrapper;
let erc1155FungibleTokens: BigNumber[];
let erc1155NonFungibleTokensOwnedBySpender: BigNumber[];
before(async () => {
await blockchainLifecycle.startAsync();
});
@@ -100,50 +111,62 @@ describe('Asset Transfer Proxies', () => {
);
// Configure ERC20Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
from: owner,
}),
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
authorized,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
from: owner,
}),
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
multiAssetProxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure ERC721Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
from: owner,
}),
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
authorized,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
from: owner,
}),
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
multiAssetProxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure ERC115Proxy
erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner);
erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync();
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
authorized,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
multiAssetProxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure MultiAssetProxy
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
from: owner,
}),
await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
authorized,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
from: owner,
}),
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
erc20Proxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
from: owner,
}),
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
erc721Proxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(
erc1155Proxy.address,
{ from: owner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
@@ -173,31 +196,26 @@ describe('Asset Transfer Proxies', () => {
);
await erc20Wrapper.setBalancesAndAllowancesAsync();
await web3Wrapper.awaitTransactionSuccessAsync(
await noReturnErc20Token.setBalance.sendTransactionAsync(fromAddress, constants.INITIAL_ERC20_BALANCE),
await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
fromAddress,
constants.INITIAL_ERC20_BALANCE,
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await noReturnErc20Token.approve.sendTransactionAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: fromAddress },
),
await noReturnErc20Token.approve.awaitTransactionSuccessAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: fromAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multipleReturnErc20Token.setBalance.sendTransactionAsync(
fromAddress,
constants.INITIAL_ERC20_BALANCE,
),
await multipleReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
fromAddress,
constants.INITIAL_ERC20_BALANCE,
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multipleReturnErc20Token.approve.sendTransactionAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: fromAddress },
),
await multipleReturnErc20Token.approve.awaitTransactionSuccessAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: fromAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
@@ -213,6 +231,22 @@ describe('Asset Transfer Proxies', () => {
const erc721Balances = await erc721Wrapper.getBalancesAsync();
erc721AFromTokenId = erc721Balances[fromAddress][erc721TokenA.address][0];
erc721BFromTokenId = erc721Balances[fromAddress][erc721TokenB.address][0];
// Deploy & configure ERC1155 tokens and receiver
[erc1155Wrapper, erc1155Wrapper2] = await erc1155ProxyWrapper.deployDummyContractsAsync();
erc1155Contract = erc1155Wrapper.getContract();
erc1155Contract2 = erc1155Wrapper2.getContract();
await erc1155ProxyWrapper.setBalancesAndAllowancesAsync();
erc1155FungibleTokens = erc1155ProxyWrapper.getFungibleTokenIds();
const nonFungibleTokens = erc1155ProxyWrapper.getNonFungibleTokenIds();
const tokenBalances = await erc1155ProxyWrapper.getBalancesAsync();
erc1155NonFungibleTokensOwnedBySpender = [];
_.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => {
const nonFungibleTokenAsString = nonFungibleToken.toString();
const nonFungibleTokenHeldBySpender =
tokenBalances.nonFungible[fromAddress][erc1155Contract.address][nonFungibleTokenAsString][0];
erc1155NonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
});
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -370,10 +404,10 @@ describe('Asset Transfer Proxies', () => {
toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
from: fromAddress,
}),
await erc20TokenA.approve.awaitTransactionSuccessAsync(
erc20Proxy.address,
allowance,
{ from: fromAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -402,10 +436,10 @@ describe('Asset Transfer Proxies', () => {
toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await noReturnErc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
from: fromAddress,
}),
await noReturnErc20Token.approve.awaitTransactionSuccessAsync(
erc20Proxy.address,
allowance,
{ from: fromAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
@@ -643,10 +677,10 @@ describe('Asset Transfer Proxies', () => {
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress);
// Remove transfer approval for fromAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721TokenA.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721AFromTokenId, {
from: fromAddress,
}),
await erc721TokenA.approve.awaitTransactionSuccessAsync(
constants.NULL_ADDRESS,
erc721AFromTokenId,
{ from: fromAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Perform a transfer; expect this to fail.
@@ -944,6 +978,314 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerFromAsset1).to.be.equal(toAddress);
expect(newOwnerFromAsset2).to.be.equal(toAddress);
});
it('should transfer a fungible ERC1155 token', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const tokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const valuesToTransfer = [new BigNumber(25)];
const valueMultiplier = new BigNumber(23);
const receiverCallbackData = '0x0102030405';
// check balances before transfer
const expectedInitialBalances = [
// from
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
// to
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
fromAddress,
toAddress,
multiAssetAmount,
);
// execute transfer
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: multiAssetProxy.address,
data,
from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// check balances
const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier).times(multiAssetAmount);
const expectedFinalBalances = [
// from
expectedInitialBalances[0].minus(totalValueTransferred),
// to
expectedInitialBalances[1].plus(totalValueTransferred),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple fungible tokens of the same ERC1155 contract', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const tokensToTransfer = erc1155FungibleTokens.slice(0, 3);
const valuesToTransfer = [new BigNumber(25), new BigNumber(35), new BigNumber(45)];
const valueMultiplier = new BigNumber(23);
const receiverCallbackData = '0x0102030405';
// check balances before transfer
const expectedInitialBalances = [
// from
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
// to
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
fromAddress,
toAddress,
multiAssetAmount,
);
// execute transfer
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: multiAssetProxy.address,
data,
from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// check balances
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier).times(multiAssetAmount);
});
const expectedFinalBalances = [
// from
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].minus(totalValuesTransferred[1]),
expectedInitialBalances[2].minus(totalValuesTransferred[2]),
// to
expectedInitialBalances[3].plus(totalValuesTransferred[0]),
expectedInitialBalances[4].plus(totalValuesTransferred[1]),
expectedInitialBalances[5].plus(totalValuesTransferred[2]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple fungible/non-fungible tokens of the same ERC1155 contract', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const fungibleTokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const nonFungibleTokensToTransfer = erc1155NonFungibleTokensOwnedBySpender.slice(0, 1);
const tokensToTransfer = fungibleTokensToTransfer.concat(nonFungibleTokensToTransfer);
const valuesToTransfer = [new BigNumber(25), new BigNumber(1)];
const valueMultiplier = new BigNumber(1);
const receiverCallbackData = '0x0102030405';
// check balances before transfer
const nftOwnerBalance = new BigNumber(1);
const nftNotOwnerBalance = new BigNumber(0);
const expectedInitialBalances = [
// from
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
nftOwnerBalance,
// to
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(1);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
fromAddress,
toAddress,
multiAssetAmount,
);
// execute transfer
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: multiAssetProxy.address,
data,
from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// check balances
const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
return value.times(valueMultiplier).times(multiAssetAmount);
});
const expectedFinalBalances = [
// from
expectedInitialBalances[0].minus(totalValuesTransferred[0]),
expectedInitialBalances[1].minus(totalValuesTransferred[1]),
// to
expectedInitialBalances[2].plus(totalValuesTransferred[0]),
expectedInitialBalances[3].plus(totalValuesTransferred[1]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple different ERC1155 tokens', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const tokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const valuesToTransfer = [new BigNumber(25)];
const valueMultiplier = new BigNumber(23);
const receiverCallbackData = '0x0102030405';
// check balances before transfer
const expectedInitialBalances = [
// from
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
// to
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData1 = assetDataUtils.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
const erc1155AssetData2 = assetDataUtils.encodeERC1155AssetData(
erc1155Contract2.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier, valueMultiplier];
const nestedAssetData = [erc1155AssetData1, erc1155AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
fromAddress,
toAddress,
multiAssetAmount,
);
// execute transfer
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: multiAssetProxy.address,
data,
from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// check balances
const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier).times(multiAssetAmount);
const expectedFinalBalances = [
// from
expectedInitialBalances[0].minus(totalValueTransferred),
// to
expectedInitialBalances[1].plus(totalValueTransferred),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer a combination of ERC20, ERC721, and ERC1155 tokens', async () => {
// setup test parameters
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc1155TokenHolders = [fromAddress, toAddress];
const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const erc1155ValuesToTransfer = [new BigNumber(25)];
const erc1155Amount = new BigNumber(23);
const erc1155ReceiverCallbackData = '0x0102030405';
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData(
erc1155Contract.address,
erc1155TokensToTransfer,
erc1155ValuesToTransfer,
erc1155ReceiverCallbackData,
);
const amounts = [erc20Amount, erc721Amount, erc1155Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData,
fromAddress,
toAddress,
inputAmount,
);
// check balances before transfer
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress);
const erc1155ExpectedInitialBalances = [
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
];
await erc1155Wrapper.assertBalancesAsync(
erc1155TokenHolders,
erc1155TokensToTransfer,
erc1155ExpectedInitialBalances,
);
// execute transfer
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: multiAssetProxy.address,
data,
from: authorized,
gas: 1000000,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// check balances after transfer
const newBalances = await erc20Wrapper.getBalancesAsync();
const totalAmount = inputAmount.times(erc20Amount);
expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
erc20Balances[fromAddress][erc20TokenA.address].minus(totalAmount),
);
expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
erc20Balances[toAddress][erc20TokenA.address].plus(totalAmount),
);
const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(newOwnerFromAsset).to.be.equal(toAddress);
const erc1155TotalValueTransferred = erc1155ValuesToTransfer[0].times(erc1155Amount).times(inputAmount);
const expectedFinalBalances = [
erc1155ExpectedInitialBalances[0].minus(erc1155TotalValueTransferred),
erc1155ExpectedInitialBalances[1].plus(erc1155TotalValueTransferred),
];
await erc1155Wrapper.assertBalancesAsync(
erc1155TokenHolders,
erc1155TokensToTransfer,
expectedFinalBalances,
);
});
it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);

View File

@@ -0,0 +1,382 @@
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
constants,
ERC1155FungibleHoldingsByOwner,
ERC1155HoldingsByOwner,
ERC1155NonFungibleHoldingsByOwner,
LogDecoder,
txDefaults,
} from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts, ERC1155ProxyContract, IAssetProxyContract } from '../../src';
export class ERC1155ProxyWrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _fungibleTokenIds: string[];
private readonly _nonFungibleTokenIds: string[];
private readonly _nfts: Array<{ id: BigNumber; tokenId: BigNumber }>;
private readonly _contractOwnerAddress: string;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _provider: Provider;
private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract;
private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
const allArtifacts = _.merge(artifacts, erc1155Artifacts);
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(
artifacts.IAssetProxy.compilerOutput.abi,
constants.NULL_ADDRESS,
provider,
);
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = [];
this._nonFungibleTokenIds = [];
this._nfts = [];
}
/**
* @dev Deploys dummy ERC1155 contracts
* @return An array of ERC1155 wrappers; one for each deployed contract.
*/
public async deployDummyContractsAsync(): Promise<Erc1155Wrapper[]> {
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY)) {
const erc1155Contract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
erc1155Artifacts.ERC1155Mintable,
this._provider,
txDefaults,
);
const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._provider, this._contractOwnerAddress);
this._dummyTokenWrappers.push(erc1155Wrapper);
}
return this._dummyTokenWrappers;
}
/**
* @dev Deploys the ERC1155 proxy
* @return Deployed ERC1155 proxy contract instance
*/
public async deployProxyAsync(): Promise<ERC1155ProxyContract> {
this._proxyContract = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC1155Proxy,
this._provider,
txDefaults,
);
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
return this._proxyContract;
}
/**
* @dev Gets the ERC1155 proxy id
*/
public getProxyId(): string {
this._validateProxyContractExistsOrThrow();
return this._proxyIdIfExists as string;
}
/**
* @dev transfers erc1155 fungible/non-fungible tokens.
* @param from source address
* @param to destination address
* @param contractAddress address of erc155 contract
* @param tokensToTransfer array of erc1155 tokens to transfer
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
* @param receiverCallbackData callback data if `to` is a contract
* @param authorizedSender sender of `transferFrom` transaction
* @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return tranasction hash.
*/
public async transferFromAsync(
from: string,
to: string,
contractAddress: string,
tokensToTransfer: BigNumber[],
valuesToTransfer: BigNumber[],
valueMultiplier: BigNumber,
receiverCallbackData: string,
authorizedSender: string,
extraData?: string,
): Promise<string> {
this._validateProxyContractExistsOrThrow();
let encodedAssetData = assetDataUtils.encodeERC1155AssetData(
contractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
if (extraData !== undefined) {
encodedAssetData = `${encodedAssetData}${extraData}`;
}
const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
from,
to,
valueMultiplier,
);
const txHash = await this._web3Wrapper.sendTransactionAsync({
to: (this._proxyContract as ERC1155ProxyContract).address,
data,
from: authorizedSender,
});
return txHash;
}
/**
* @dev transfers erc1155 fungible/non-fungible tokens.
* @param from source address
* @param to destination address
* @param contractAddress address of erc155 contract
* @param tokensToTransfer array of erc1155 tokens to transfer
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
* @param receiverCallbackData callback data if `to` is a contract
* @param authorizedSender sender of `transferFrom` transaction
* @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return tranasction receipt with decoded logs.
*/
public async transferFromWithLogsAsync(
from: string,
to: string,
contractAddress: string,
tokensToTransfer: BigNumber[],
valuesToTransfer: BigNumber[],
valueMultiplier: BigNumber,
receiverCallbackData: string,
authorizedSender: string,
extraData?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
await this.transferFromAsync(
from,
to,
contractAddress,
tokensToTransfer,
valuesToTransfer,
valueMultiplier,
receiverCallbackData,
authorizedSender,
extraData,
),
);
return txReceipt;
}
/**
* @dev For each deployed ERC1155 contract, this function mints a set of fungible/non-fungible
* tokens for each token owner address (`_tokenOwnerAddresses`).
* @return Balances of each token owner, across all ERC1155 contracts and tokens.
*/
public async setBalancesAndAllowancesAsync(): Promise<ERC1155HoldingsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
this._initialTokenIdsByOwner = {
fungible: {},
nonFungible: {},
};
const fungibleHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
// Set balances accordingly
for (const dummyWrapper of this._dummyTokenWrappers) {
const dummyAddress = dummyWrapper.getContract().address;
// tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_ERC1155_FUNGIBLE_TOKENS_MINT)) {
// Create a fungible token
const tokenId = await dummyWrapper.mintFungibleTokensAsync(
this._tokenOwnerAddresses,
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
);
const tokenIdAsString = tokenId.toString();
this._fungibleTokenIds.push(tokenIdAsString);
// Mint tokens for each owner for this token
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
// tslint:disable-next-line:no-unused-variable
if (fungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
fungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] === undefined) {
fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
}
fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] =
constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
await dummyWrapper.setApprovalForAllAsync(
tokenOwnerAddress,
(this._proxyContract as ERC1155ProxyContract).address,
true,
);
}
}
// Non-fungible tokens
// tslint:disable-next-line:no-unused-variable
for (const j of _.times(constants.NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT)) {
const [tokenId, nftIds] = await dummyWrapper.mintNonFungibleTokensAsync(this._tokenOwnerAddresses);
const tokenIdAsString = tokenId.toString();
this._nonFungibleTokenIds.push(tokenIdAsString);
_.each(this._tokenOwnerAddresses, async (tokenOwnerAddress: string, i: number) => {
if (nonFungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] = [];
}
this._nfts.push({ id: nftIds[i], tokenId });
nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString].push(nftIds[i]);
await dummyWrapper.setApprovalForAllAsync(
tokenOwnerAddress,
(this._proxyContract as ERC1155ProxyContract).address,
true,
);
});
}
}
this._initialTokenIdsByOwner = {
fungible: fungibleHoldingsByOwner,
nonFungible: nonFungibleHoldingsByOwner,
};
return this._initialTokenIdsByOwner;
}
/**
* @dev For each deployed ERC1155 contract, this function quieries the set of fungible/non-fungible
* tokens for each token owner address (`_tokenOwnerAddresses`).
* @return Balances of each token owner, across all ERC1155 contracts and tokens.
*/
public async getBalancesAsync(): Promise<ERC1155HoldingsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateBalancesAndAllowancesSetOrThrow();
const tokenHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
for (const dummyTokenWrapper of this._dummyTokenWrappers) {
const tokenContract = dummyTokenWrapper.getContract();
const tokenAddress = tokenContract.address;
// Construct batch balance call
const tokenOwners: string[] = [];
const tokenIds: BigNumber[] = [];
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
for (const tokenId of this._fungibleTokenIds) {
tokenOwners.push(tokenOwnerAddress);
tokenIds.push(new BigNumber(tokenId));
}
for (const nft of this._nfts) {
tokenOwners.push(tokenOwnerAddress);
tokenIds.push(nft.id);
}
}
const balances = await dummyTokenWrapper.getBalancesAsync(tokenOwners, tokenIds);
// Parse out balances into fungible / non-fungible token holdings
let i = 0;
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
// Fungible tokens
for (const tokenId of this._fungibleTokenIds) {
if (tokenHoldingsByOwner[tokenOwnerAddress] === undefined) {
tokenHoldingsByOwner[tokenOwnerAddress] = {};
}
if (tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
}
tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress][tokenId] = balances[i++];
}
// Non-fungible tokens
for (const nft of this._nfts) {
if (nonFungibleHoldingsByOwner[tokenOwnerAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
}
if (nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
}
if (
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()] ===
undefined
) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()] = [];
}
const isOwner = balances[i++];
if (isOwner.isEqualTo(1)) {
nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()].push(
nft.id,
);
}
}
}
}
const holdingsByOwner = {
fungible: tokenHoldingsByOwner,
nonFungible: nonFungibleHoldingsByOwner,
};
return holdingsByOwner;
}
/**
* @dev Checks if proxy is approved to transfer tokens on behalf of `userAddress`.
* @param userAddress owner of ERC1155 tokens.
* @param contractAddress address of ERC1155 contract.
* @return True iff the proxy is approved for all. False otherwise.
*/
public async isProxyApprovedForAllAsync(userAddress: string, contractAddress: string): Promise<boolean> {
this._validateProxyContractExistsOrThrow();
const tokenContract = this._getContractFromAddress(contractAddress);
const operator = (this._proxyContract as ERC1155ProxyContract).address;
const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
return didApproveAll;
}
public getFungibleTokenIds(): BigNumber[] {
const fungibleTokenIds = _.map(this._fungibleTokenIds, (tokenIdAsString: string) => {
return new BigNumber(tokenIdAsString);
});
return fungibleTokenIds;
}
public getNonFungibleTokenIds(): BigNumber[] {
const nonFungibleTokenIds = _.map(this._nonFungibleTokenIds, (tokenIdAsString: string) => {
return new BigNumber(tokenIdAsString);
});
return nonFungibleTokenIds;
}
public getTokenOwnerAddresses(): string[] {
return this._tokenOwnerAddresses;
}
public getContractWrapper(contractAddress: string): Erc1155Wrapper {
const tokenWrapper = _.find(this._dummyTokenWrappers, (wrapper: Erc1155Wrapper) => {
return wrapper.getContract().address === contractAddress;
});
if (tokenWrapper === undefined) {
throw new Error(`Contract: ${contractAddress} was not deployed through ERC1155ProxyWrapper`);
}
return tokenWrapper;
}
private _getContractFromAddress(tokenAddress: string): ERC1155MintableContract {
const tokenContractIfExists = _.find(this._dummyTokenWrappers, c => c.getContract().address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC1155ProxyWrapper`);
}
return tokenContractIfExists.getContract();
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (this._dummyTokenWrappers === undefined) {
throw new Error('Dummy ERC1155 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (this._proxyContract === undefined) {
throw new Error('ERC1155 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}
private _validateBalancesAndAllowancesSetOrThrow(): void {
if (
_.keys(this._initialTokenIdsByOwner.fungible).length === 0 ||
_.keys(this._initialTokenIdsByOwner.nonFungible).length === 0
) {
throw new Error(
'Dummy ERC1155 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"',
);
}
}
}

View File

@@ -1,19 +1,16 @@
import { artifacts as tokensArtifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy';
import { artifacts } from '../../src/artifacts';
import { artifacts, ERC20ProxyContract } from '../../src';
export class ERC20Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _provider: Provider;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string;
@@ -24,9 +21,8 @@ export class ERC20Wrapper {
* @param contractOwnerAddress Desired owner of the contract
* Instance of ERC20Wrapper
*/
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
constructor(provider: ZeroExProvider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._dummyTokenContracts = [];
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
@@ -38,7 +34,7 @@ export class ERC20Wrapper {
for (let i = 0; i < numberToDeploy; i++) {
this._dummyTokenContracts.push(
await DummyERC20TokenContract.deployFrom0xArtifactAsync(
tokensArtifacts.DummyERC20Token,
erc20Artifacts.DummyERC20Token,
this._provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
@@ -68,20 +64,16 @@ export class ERC20Wrapper {
this._validateProxyContractExistsOrThrow();
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.setBalance.sendTransactionAsync(
tokenOwnerAddress,
constants.INITIAL_ERC20_BALANCE,
{ from: this._contractOwnerAddress },
),
await dummyTokenContract.setBalance.awaitTransactionSuccessAsync(
tokenOwnerAddress,
constants.INITIAL_ERC20_BALANCE,
{ from: this._contractOwnerAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.approve.sendTransactionAsync(
(this._proxyContract as ERC20ProxyContract).address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: tokenOwnerAddress },
),
await dummyTokenContract.approve.awaitTransactionSuccessAsync(
(this._proxyContract as ERC20ProxyContract).address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: tokenOwnerAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
@@ -94,10 +86,10 @@ export class ERC20Wrapper {
}
public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(assetData);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.setBalance.sendTransactionAsync(userAddress, amount, {
from: this._contractOwnerAddress,
}),
await tokenContract.setBalance.awaitTransactionSuccessAsync(
userAddress,
amount,
{ from: this._contractOwnerAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
@@ -110,10 +102,10 @@ export class ERC20Wrapper {
public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(assetData);
const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.approve.sendTransactionAsync(proxyAddress, amount, {
from: userAddress,
}),
await tokenContract.approve.awaitTransactionSuccessAsync(
proxyAddress,
amount,
{ from: userAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
@@ -134,7 +126,7 @@ export class ERC20Wrapper {
_.forEach(balances, (balance, balanceIndex) => {
const tokenAddress = balanceInfo[balanceIndex].tokenAddress;
const tokenOwnerAddress = balanceInfo[balanceIndex].tokenOwnerAddress;
if (_.isUndefined(balancesByOwner[tokenOwnerAddress])) {
if (balancesByOwner[tokenOwnerAddress] === undefined) {
balancesByOwner[tokenOwnerAddress] = {};
}
const wrappedBalance = new BigNumber(balance);
@@ -143,7 +135,7 @@ export class ERC20Wrapper {
return balancesByOwner;
}
public addDummyTokenContract(dummy: DummyERC20TokenContract): void {
if (!_.isUndefined(this._dummyTokenContracts)) {
if (this._dummyTokenContracts !== undefined) {
this._dummyTokenContracts.push(dummy);
}
}
@@ -161,18 +153,18 @@ export class ERC20Wrapper {
const erc20ProxyData = assetDataUtils.decodeERC20AssetData(assetData);
const tokenAddress = erc20ProxyData.tokenAddress;
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (_.isUndefined(tokenContractIfExists)) {
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);
}
return tokenContractIfExists;
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (_.isUndefined(this._dummyTokenContracts)) {
if (this._dummyTokenContracts === undefined) {
throw new Error('Dummy ERC20 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (_.isUndefined(this._proxyContract)) {
if (this._proxyContract === undefined) {
throw new Error('ERC20 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}

View File

@@ -1,25 +1,21 @@
import { artifacts as tokensArtifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
import { constants, ERC721TokenIdsByOwner, txDefaults } from '@0x/contracts-test-utils';
import { generatePseudoRandomSalt } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider } from 'ethereum-types';
import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
import { artifacts } from '../../src/artifacts';
import { artifacts, ERC721ProxyContract } from '../../src';
export class ERC721Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _provider: Provider;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC721TokenContract[];
private _proxyContract?: ERC721ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC721TokenIdsByOwner = {};
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._web3Wrapper = new Web3Wrapper(provider);
constructor(provider: ZeroExProvider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._provider = provider;
this._dummyTokenContracts = [];
this._tokenOwnerAddresses = tokenOwnerAddresses;
@@ -30,7 +26,7 @@ export class ERC721Wrapper {
for (const i of _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY)) {
this._dummyTokenContracts.push(
await DummyERC721TokenContract.deployFrom0xArtifactAsync(
tokensArtifacts.DummyERC721Token,
erc721Artifacts.DummyERC721Token,
this._provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
@@ -63,12 +59,12 @@ export class ERC721Wrapper {
for (const i of _.times(constants.NUM_ERC721_TOKENS_TO_MINT)) {
const tokenId = generatePseudoRandomSalt();
await this.mintAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) {
if (this._initialTokenIdsByOwner[tokenOwnerAddress] === undefined) {
this._initialTokenIdsByOwner[tokenOwnerAddress] = {
[dummyTokenContract.address]: [],
};
}
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address])) {
if (this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] === undefined) {
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] = [];
}
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address].push(tokenId);
@@ -92,20 +88,20 @@ export class ERC721Wrapper {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const tokenOwner = await this.ownerOfAsync(tokenAddress, tokenId);
const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.setApprovalForAll.sendTransactionAsync(proxyAddress, isApproved, {
from: tokenOwner,
}),
await tokenContract.setApprovalForAll.awaitTransactionSuccessAsync(
proxyAddress,
isApproved,
{ from: tokenOwner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
public async approveAsync(to: string, tokenAddress: string, tokenId: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
const tokenOwner = await this.ownerOfAsync(tokenAddress, tokenId);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.approve.sendTransactionAsync(to, tokenId, {
from: tokenOwner,
}),
await tokenContract.approve.awaitTransactionSuccessAsync(
to,
tokenId,
{ from: tokenOwner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
@@ -116,28 +112,29 @@ export class ERC721Wrapper {
userAddress: string,
): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.transferFrom.sendTransactionAsync(currentOwner, userAddress, tokenId, {
from: currentOwner,
}),
await tokenContract.transferFrom.awaitTransactionSuccessAsync(
currentOwner,
userAddress,
tokenId,
{ from: currentOwner },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
public async mintAsync(tokenAddress: string, tokenId: BigNumber, userAddress: string): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.mint.sendTransactionAsync(userAddress, tokenId, {
from: this._contractOwnerAddress,
}),
await tokenContract.mint.awaitTransactionSuccessAsync(
userAddress,
tokenId,
{ from: this._contractOwnerAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
public async burnAsync(tokenAddress: string, tokenId: BigNumber, owner: string): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
await this._web3Wrapper.awaitTransactionSuccessAsync(
await tokenContract.burn.sendTransactionAsync(owner, tokenId, {
from: this._contractOwnerAddress,
}),
await tokenContract.burn.awaitTransactionSuccessAsync(
owner,
tokenId,
{ from: this._contractOwnerAddress },
constants.AWAIT_TRANSACTION_MINED_MS,
);
}
@@ -190,12 +187,12 @@ export class ERC721Wrapper {
_.forEach(tokenOwnerAddresses, (tokenOwnerAddress, ownerIndex) => {
const tokenAddress = tokenInfo[ownerIndex].tokenAddress;
const tokenId = tokenInfo[ownerIndex].tokenId;
if (_.isUndefined(tokenIdsByOwner[tokenOwnerAddress])) {
if (tokenIdsByOwner[tokenOwnerAddress] === undefined) {
tokenIdsByOwner[tokenOwnerAddress] = {
[tokenAddress]: [],
};
}
if (_.isUndefined(tokenIdsByOwner[tokenOwnerAddress][tokenAddress])) {
if (tokenIdsByOwner[tokenOwnerAddress][tokenAddress] === undefined) {
tokenIdsByOwner[tokenOwnerAddress][tokenAddress] = [];
}
tokenIdsByOwner[tokenOwnerAddress][tokenAddress].push(tokenId);
@@ -211,18 +208,18 @@ export class ERC721Wrapper {
}
private _getTokenContractFromAssetData(tokenAddress: string): DummyERC721TokenContract {
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (_.isUndefined(tokenContractIfExists)) {
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);
}
return tokenContractIfExists;
}
private _validateDummyTokenContractsExistOrThrow(): void {
if (_.isUndefined(this._dummyTokenContracts)) {
if (this._dummyTokenContracts === undefined) {
throw new Error('Dummy ERC721 tokens not yet deployed, please call "deployDummyTokensAsync"');
}
}
private _validateProxyContractExistsOrThrow(): void {
if (_.isUndefined(this._proxyContract)) {
if (this._proxyContract === undefined) {
throw new Error('ERC721 proxy contract not yet deployed, please call "deployProxyAsync"');
}
}

View File

@@ -1,2 +1,3 @@
export * from './erc20_wrapper';
export * from './erc721_wrapper';
export * from './erc1155_proxy_wrapper';

View File

@@ -1,19 +1,17 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": ".",
"resolveJsonModule": true
},
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"./generated-artifacts/IAssetData.json",
"./generated-artifacts/IAssetProxy.json",
"./generated-artifacts/IAuthorizable.json",
"./generated-artifacts/ERC20Proxy.json",
"./generated-artifacts/ERC721Proxy.json",
"./generated-artifacts/MixinAuthorizable.json",
"./generated-artifacts/MultiAssetProxy.json"
"generated-artifacts/ERC1155Proxy.json",
"generated-artifacts/ERC20Proxy.json",
"generated-artifacts/ERC721Proxy.json",
"generated-artifacts/IAssetData.json",
"generated-artifacts/IAssetProxy.json",
"generated-artifacts/IAuthorizable.json",
"generated-artifacts/LibAssetData.json",
"generated-artifacts/MixinAuthorizable.json",
"generated-artifacts/MultiAssetProxy.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@@ -0,0 +1,56 @@
[
{
"timestamp": 1557507213,
"version": "2.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.0.0",
"changes": [
{
"note": "Make `decodeOrdersFromFillData`, `getCoordinatorApprovalHash`, and `getTransactionHash` public",
"pr": 1729
},
{
"note": "Make `assertValidTransactionOrdersApproval` internal",
"pr": 1729
}
],
"timestamp": 1554997931
},
{
"version": "1.1.0",
"changes": [
{
"note": "Run Web3ProviderEngine without excess block polling",
"pr": 1695
}
],
"timestamp": 1553183790
},
{
"version": "1.0.0",
"changes": [
{
"note": "Created Coordinator package"
},
{
"note": "Use separate EIP712 domains for transactions and approvals",
"pr": 1705
},
{
"note": "Add `SignatureType.Invalid`",
"pr": 1705
},
{
"note": "Set `evmVersion` to `constantinople`",
"pr": 1707
}
],
"timestamp": 1553091633
}
]

View File

@@ -0,0 +1,26 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v2.0.1 - _May 10, 2019_
* Dependencies updated
## v2.0.0 - _April 11, 2019_
* Make `decodeOrdersFromFillData`, `getCoordinatorApprovalHash`, and `getTransactionHash` public (#1729)
* Make `assertValidTransactionOrdersApproval` internal (#1729)
## v1.1.0 - _March 21, 2019_
* Run Web3ProviderEngine without excess block polling (#1695)
## v1.0.0 - _March 20, 2019_
* Created Coordinator package
* Use separate EIP712 domains for transactions and approvals (#1705)
* Add `SignatureType.Invalid` (#1705)
* Set `evmVersion` to `constantinople` (#1707)

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,73 @@
## Coordinator
This package contains a contract that allows users to call arbitrary functions on the Exchange contract with permission from one or more Coordinators. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
## Installation
**Install**
```bash
npm install @0x/contracts-coordinator --save
```
## Bug bounty
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
## Contributing
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
### Install Dependencies
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0x/contracts-coordinator yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0x/contracts-coordinator yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
```bash
yarn test
```
#### Testing options
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).

View File

@@ -0,0 +1,25 @@
{
"artifactsDir": "./generated-artifacts",
"contractsDir": "./contracts",
"useDockerisedSolc": false,
"compilerSettings": {
"evmVersion": "constantinople",
"optimizer": {
"enabled": true,
"runs": 1000000,
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode.object",
"evm.bytecode.sourceMap",
"evm.deployedBytecode.object",
"evm.deployedBytecode.sourceMap"
]
}
}
},
"contracts": ["src/Coordinator.sol", "src/registry/CoordinatorRegistry.sol"]
}

View File

@@ -0,0 +1,39 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "./libs/LibConstants.sol";
import "./MixinSignatureValidator.sol";
import "./MixinCoordinatorApprovalVerifier.sol";
import "./MixinCoordinatorCore.sol";
// solhint-disable no-empty-blocks
contract Coordinator is
LibConstants,
MixinSignatureValidator,
MixinCoordinatorApprovalVerifier,
MixinCoordinatorCore
{
constructor (address _exchange)
public
LibConstants(_exchange)
{}
}

View File

@@ -0,0 +1,203 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "@0x/contracts-exchange-libs/contracts/src/LibExchangeSelectors.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
import "./libs/LibCoordinatorApproval.sol";
import "./libs/LibZeroExTransaction.sol";
import "./mixins/MSignatureValidator.sol";
import "./mixins/MCoordinatorApprovalVerifier.sol";
// solhint-disable avoid-tx-origin
contract MixinCoordinatorApprovalVerifier is
LibExchangeSelectors,
LibCoordinatorApproval,
LibZeroExTransaction,
MSignatureValidator,
MCoordinatorApprovalVerifier
{
using LibBytes for bytes;
using LibAddressArray for address[];
/// @dev Validates that the 0x transaction has been approved by all of the feeRecipients
/// that correspond to each order in the transaction's Exchange calldata.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
function assertValidCoordinatorApprovals(
LibZeroExTransaction.ZeroExTransaction memory transaction,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
public
view
{
// Get the orders from the the Exchange calldata in the 0x transaction
LibOrder.Order[] memory orders = decodeOrdersFromFillData(transaction.data);
// No approval is required for non-fill methods
if (orders.length > 0) {
// Revert if approval is invalid for transaction orders
assertValidTransactionOrdersApproval(
transaction,
orders,
txOrigin,
transactionSignature,
approvalExpirationTimeSeconds,
approvalSignatures
);
}
}
/// @dev Decodes the orders from Exchange calldata representing any fill method.
/// @param data Exchange calldata representing a fill method.
/// @return The orders from the Exchange calldata.
function decodeOrdersFromFillData(bytes memory data)
public
pure
returns (LibOrder.Order[] memory orders)
{
bytes4 selector = data.readBytes4(0);
if (
selector == FILL_ORDER_SELECTOR ||
selector == FILL_ORDER_NO_THROW_SELECTOR ||
selector == FILL_OR_KILL_ORDER_SELECTOR
) {
// Decode single order
(LibOrder.Order memory order) = abi.decode(
data.slice(4, data.length),
(LibOrder.Order)
);
orders = new LibOrder.Order[](1);
orders[0] = order;
} else if (
selector == BATCH_FILL_ORDERS_SELECTOR ||
selector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR ||
selector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR ||
selector == MARKET_BUY_ORDERS_SELECTOR ||
selector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR ||
selector == MARKET_SELL_ORDERS_SELECTOR ||
selector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR
) {
// Decode all orders
// solhint-disable indent
(orders) = abi.decode(
data.slice(4, data.length),
(LibOrder.Order[])
);
} else if (selector == MATCH_ORDERS_SELECTOR) {
// Decode left and right orders
(LibOrder.Order memory leftOrder, LibOrder.Order memory rightOrder) = abi.decode(
data.slice(4, data.length),
(LibOrder.Order, LibOrder.Order)
);
// Create array of orders
orders = new LibOrder.Order[](2);
orders[0] = leftOrder;
orders[1] = rightOrder;
}
return orders;
}
/// @dev Validates that the feeRecipients of a batch of order have approved a 0x transaction.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param orders Array of order structs containing order specifications.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order.
function assertValidTransactionOrdersApproval(
LibZeroExTransaction.ZeroExTransaction memory transaction,
LibOrder.Order[] memory orders,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
internal
view
{
// Verify that Ethereum tx signer is the same as the approved txOrigin
require(
tx.origin == txOrigin,
"INVALID_ORIGIN"
);
// Hash 0x transaction
bytes32 transactionHash = getTransactionHash(transaction);
// Create empty list of approval signers
address[] memory approvalSignerAddresses = new address[](0);
uint256 signaturesLength = approvalSignatures.length;
for (uint256 i = 0; i != signaturesLength; i++) {
// Create approval message
uint256 currentApprovalExpirationTimeSeconds = approvalExpirationTimeSeconds[i];
CoordinatorApproval memory approval = CoordinatorApproval({
txOrigin: txOrigin,
transactionHash: transactionHash,
transactionSignature: transactionSignature,
approvalExpirationTimeSeconds: currentApprovalExpirationTimeSeconds
});
// Ensure approval has not expired
require(
// solhint-disable-next-line not-rely-on-time
currentApprovalExpirationTimeSeconds > block.timestamp,
"APPROVAL_EXPIRED"
);
// Hash approval message and recover signer address
bytes32 approvalHash = getCoordinatorApprovalHash(approval);
address approvalSignerAddress = getSignerAddress(approvalHash, approvalSignatures[i]);
// Add approval signer to list of signers
approvalSignerAddresses = approvalSignerAddresses.append(approvalSignerAddress);
}
// Ethereum transaction signer gives implicit signature of approval
approvalSignerAddresses = approvalSignerAddresses.append(tx.origin);
uint256 ordersLength = orders.length;
for (uint256 i = 0; i != ordersLength; i++) {
// Do not check approval if the order's senderAddress is null
if (orders[i].senderAddress == address(0)) {
continue;
}
// Ensure feeRecipient of order has approved this 0x transaction
address approverAddress = orders[i].feeRecipientAddress;
bool isOrderApproved = approvalSignerAddresses.contains(approverAddress);
require(
isOrderApproved,
"INVALID_APPROVAL_SIGNATURE"
);
}
}
}

View File

@@ -0,0 +1,65 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "./libs/LibZeroExTransaction.sol";
import "./libs/LibConstants.sol";
import "./mixins/MCoordinatorApprovalVerifier.sol";
import "./interfaces/ICoordinatorCore.sol";
contract MixinCoordinatorCore is
LibConstants,
MCoordinatorApprovalVerifier,
ICoordinatorCore
{
/// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
function executeTransaction(
LibZeroExTransaction.ZeroExTransaction memory transaction,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
public
{
// Validate that the 0x transaction has been approves by each feeRecipient
assertValidCoordinatorApprovals(
transaction,
txOrigin,
transactionSignature,
approvalExpirationTimeSeconds,
approvalSignatures
);
// Execute the transaction
EXCHANGE.executeTransaction(
transaction.salt,
transaction.signerAddress,
transaction.data,
transactionSignature
);
}
}

View File

@@ -0,0 +1,118 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./mixins/MSignatureValidator.sol";
contract MixinSignatureValidator is
MSignatureValidator
{
using LibBytes for bytes;
/// @dev Recovers the address of a signer given a hash and signature.
/// @param hash Any 32 byte hash.
/// @param signature Proof that the hash has been signed by signer.
function getSignerAddress(bytes32 hash, bytes memory signature)
public
pure
returns (address signerAddress)
{
require(
signature.length > 0,
"LENGTH_GREATER_THAN_0_REQUIRED"
);
// Pop last byte off of signature byte array.
uint8 signatureTypeRaw = uint8(signature.popLastByte());
// Ensure signature is supported
require(
signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
"SIGNATURE_UNSUPPORTED"
);
SignatureType signatureType = SignatureType(signatureTypeRaw);
// Always illegal signature.
// This is always an implicit option since a signer can create a
// signature array with invalid type or length. We may as well make
// it an explicit option. This aids testing and analysis. It is
// also the initialization value for the enum type.
if (signatureType == SignatureType.Illegal) {
revert("SIGNATURE_ILLEGAL");
// Always invalid signature.
// Like Illegal, this is always implicitly available and therefore
// offered explicitly. It can be implicitly created by providing
// a correctly formatted but incorrect signature.
} else if (signatureType == SignatureType.Invalid) {
require(
signature.length == 0,
"LENGTH_0_REQUIRED"
);
revert("SIGNATURE_INVALID");
// Signature using EIP712
} else if (signatureType == SignatureType.EIP712) {
require(
signature.length == 65,
"LENGTH_65_REQUIRED"
);
uint8 v = uint8(signature[0]);
bytes32 r = signature.readBytes32(1);
bytes32 s = signature.readBytes32(33);
signerAddress = ecrecover(
hash,
v,
r,
s
);
return signerAddress;
// Signed using web3.eth_sign
} else if (signatureType == SignatureType.EthSign) {
require(
signature.length == 65,
"LENGTH_65_REQUIRED"
);
uint8 v = uint8(signature[0]);
bytes32 r = signature.readBytes32(1);
bytes32 s = signature.readBytes32(33);
signerAddress = ecrecover(
keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
hash
)),
v,
r,
s
);
return signerAddress;
}
// Anything else is illegal (We do not return false because
// the signature may actually be valid, just not in a format
// that we currently support. In this case returning false
// may lead the caller to incorrectly believe that the
// signature was invalid.)
revert("SIGNATURE_UNSUPPORTED");
}
}

View File

@@ -0,0 +1,52 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../libs/LibZeroExTransaction.sol";
contract ICoordinatorApprovalVerifier {
/// @dev Validates that the 0x transaction has been approved by all of the feeRecipients
/// that correspond to each order in the transaction's Exchange calldata.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
function assertValidCoordinatorApprovals(
LibZeroExTransaction.ZeroExTransaction memory transaction,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
public
view;
/// @dev Decodes the orders from Exchange calldata representing any fill method.
/// @param data Exchange calldata representing a fill method.
/// @return The orders from the Exchange calldata.
function decodeOrdersFromFillData(bytes memory data)
public
pure
returns (LibOrder.Order[] memory orders);
}

View File

@@ -0,0 +1,41 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "../libs/LibZeroExTransaction.sol";
contract ICoordinatorCore {
/// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
function executeTransaction(
LibZeroExTransaction.ZeroExTransaction memory transaction,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
public;
}

View File

@@ -0,0 +1,31 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
contract ISignatureValidator {
/// @dev Recovers the address of a signer given a hash and signature.
/// @param hash Any 32 byte hash.
/// @param signature Proof that the hash has been signed by signer.
function getSignerAddress(bytes32 hash, bytes memory signature)
public
pure
returns (address signerAddress);
}

View File

@@ -0,0 +1,35 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
contract ITransactions {
/// @dev Executes an exchange method call in the context of signer.
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
/// @param signerAddress Address of transaction signer.
/// @param data AbiV2 encoded calldata.
/// @param signature Proof of signer transaction by signer.
function executeTransaction(
uint256 salt,
address signerAddress,
bytes calldata data,
bytes calldata signature
)
external;
}

View File

@@ -0,0 +1,34 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "../interfaces/ITransactions.sol";
contract LibConstants {
// solhint-disable-next-line var-name-mixedcase
ITransactions internal EXCHANGE;
constructor (address _exchange)
public
{
EXCHANGE = ITransactions(_exchange);
}
}

View File

@@ -0,0 +1,98 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "./LibEIP712Domain.sol";
contract LibCoordinatorApproval is
LibEIP712Domain
{
// Hash for the EIP712 Coordinator approval message
// keccak256(abi.encodePacked(
// "CoordinatorApproval(",
// "address txOrigin,",
// "bytes32 transactionHash,",
// "bytes transactionSignature,",
// "uint256 approvalExpirationTimeSeconds",
// ")"
// ));
bytes32 constant internal EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05;
struct CoordinatorApproval {
address txOrigin; // Required signer of Ethereum transaction that is submitting approval.
bytes32 transactionHash; // EIP712 hash of the transaction.
bytes transactionSignature; // Signature of the 0x transaction.
uint256 approvalExpirationTimeSeconds; // Timestamp in seconds for which the approval expires.
}
/// @dev Calculated the EIP712 hash of the Coordinator approval mesasage using the domain separator of this contract.
/// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval.
/// @return EIP712 hash of the Coordinator approval message with the domain separator of this contract.
function getCoordinatorApprovalHash(CoordinatorApproval memory approval)
public
view
returns (bytes32 approvalHash)
{
approvalHash = hashEIP712CoordinatorMessage(hashCoordinatorApproval(approval));
return approvalHash;
}
/// @dev Calculated the EIP712 hash of the Coordinator approval mesasage with no domain separator.
/// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval.
/// @return EIP712 hash of the Coordinator approval message with no domain separator.
function hashCoordinatorApproval(CoordinatorApproval memory approval)
internal
pure
returns (bytes32 result)
{
bytes32 schemaHash = EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH;
bytes memory transactionSignature = approval.transactionSignature;
address txOrigin = approval.txOrigin;
bytes32 transactionHash = approval.transactionHash;
uint256 approvalExpirationTimeSeconds = approval.approvalExpirationTimeSeconds;
// Assembly for more efficiently computing:
// keccak256(abi.encodePacked(
// EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH,
// approval.txOrigin,
// approval.transactionHash,
// keccak256(approval.transactionSignature)
// approval.approvalExpirationTimeSeconds,
// ));
assembly {
// Compute hash of transaction signature
let transactionSignatureHash := keccak256(add(transactionSignature, 32), mload(transactionSignature))
// Load free memory pointer
let memPtr := mload(64)
mstore(memPtr, schemaHash) // hash of schema
mstore(add(memPtr, 32), txOrigin) // txOrigin
mstore(add(memPtr, 64), transactionHash) // transactionHash
mstore(add(memPtr, 96), transactionSignatureHash) // transactionSignatureHash
mstore(add(memPtr, 128), approvalExpirationTimeSeconds) // approvalExpirationTimeSeconds
// Compute hash
result := keccak256(memPtr, 160)
}
return result;
}
}

View File

@@ -0,0 +1,131 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "./LibConstants.sol";
contract LibEIP712Domain is
LibConstants
{
// EIP191 header for EIP712 prefix
string constant internal EIP191_HEADER = "\x19\x01";
// EIP712 Domain Name value for the Coordinator
string constant internal EIP712_COORDINATOR_DOMAIN_NAME = "0x Protocol Coordinator";
// EIP712 Domain Version value for the Coordinator
string constant internal EIP712_COORDINATOR_DOMAIN_VERSION = "1.0.0";
// EIP712 Domain Name value for the Exchange
string constant internal EIP712_EXCHANGE_DOMAIN_NAME = "0x Protocol";
// EIP712 Domain Version value for the Exchange
string constant internal EIP712_EXCHANGE_DOMAIN_VERSION = "2";
// Hash of the EIP712 Domain Separator Schema
bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
"EIP712Domain(",
"string name,",
"string version,",
"address verifyingContract",
")"
));
// Hash of the EIP712 Domain Separator data for the Coordinator
// solhint-disable-next-line var-name-mixedcase
bytes32 public EIP712_COORDINATOR_DOMAIN_HASH;
// Hash of the EIP712 Domain Separator data for the Exchange
// solhint-disable-next-line var-name-mixedcase
bytes32 public EIP712_EXCHANGE_DOMAIN_HASH;
constructor ()
public
{
EIP712_COORDINATOR_DOMAIN_HASH = keccak256(abi.encodePacked(
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
keccak256(bytes(EIP712_COORDINATOR_DOMAIN_NAME)),
keccak256(bytes(EIP712_COORDINATOR_DOMAIN_VERSION)),
uint256(address(this))
));
EIP712_EXCHANGE_DOMAIN_HASH = keccak256(abi.encodePacked(
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
keccak256(bytes(EIP712_EXCHANGE_DOMAIN_NAME)),
keccak256(bytes(EIP712_EXCHANGE_DOMAIN_VERSION)),
uint256(address(EXCHANGE))
));
}
/// @dev Calculates EIP712 encoding for a hash struct in the EIP712 domain
/// of this contract.
/// @param hashStruct The EIP712 hash struct.
/// @return EIP712 hash applied to this EIP712 Domain.
function hashEIP712CoordinatorMessage(bytes32 hashStruct)
internal
view
returns (bytes32 result)
{
return hashEIP712Message(EIP712_COORDINATOR_DOMAIN_HASH, hashStruct);
}
/// @dev Calculates EIP712 encoding for a hash struct in the EIP712 domain
/// of the Exchange contract.
/// @param hashStruct The EIP712 hash struct.
/// @return EIP712 hash applied to the Exchange EIP712 Domain.
function hashEIP712ExchangeMessage(bytes32 hashStruct)
internal
view
returns (bytes32 result)
{
return hashEIP712Message(EIP712_EXCHANGE_DOMAIN_HASH, hashStruct);
}
/// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.
/// @param eip712DomainHash Hash of the domain domain separator data.
/// @param hashStruct The EIP712 hash struct.
/// @return EIP712 hash applied to the Exchange EIP712 Domain.
function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
internal
pure
returns (bytes32 result)
{
// Assembly for more efficient computing:
// keccak256(abi.encodePacked(
// EIP191_HEADER,
// EIP712_DOMAIN_HASH,
// hashStruct
// ));
assembly {
// Load free memory pointer
let memPtr := mload(64)
mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
mstore(add(memPtr, 34), hashStruct) // Hash of struct
// Compute hash
result := keccak256(memPtr, 66)
}
return result;
}
}

View File

@@ -0,0 +1,95 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "./LibEIP712Domain.sol";
contract LibZeroExTransaction is
LibEIP712Domain
{
// Hash for the EIP712 0x transaction schema
// keccak256(abi.encodePacked(
// "ZeroExTransaction(",
// "uint256 salt,",
// "address signerAddress,",
// "bytes data",
// ")"
// ));
bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = 0x213c6f636f3ea94e701c0adf9b2624aa45a6c694f9a292c094f9a81c24b5df4c;
struct ZeroExTransaction {
uint256 salt; // Arbitrary number to ensure uniqueness of transaction hash.
address signerAddress; // Address of transaction signer.
bytes data; // AbiV2 encoded calldata.
}
/// @dev Calculates the EIP712 hash of a 0x transaction using the domain separator of the Exchange contract.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @return EIP712 hash of the transaction with the domain separator of this contract.
function getTransactionHash(ZeroExTransaction memory transaction)
public
view
returns (bytes32 transactionHash)
{
// Hash the transaction with the domain separator of the Exchange contract.
transactionHash = hashEIP712ExchangeMessage(hashZeroExTransaction(transaction));
return transactionHash;
}
/// @dev Calculates EIP712 hash of the 0x transaction with no domain separator.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @return EIP712 hash of the transaction with no domain separator.
function hashZeroExTransaction(ZeroExTransaction memory transaction)
internal
pure
returns (bytes32 result)
{
bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;
bytes memory data = transaction.data;
uint256 salt = transaction.salt;
address signerAddress = transaction.signerAddress;
// Assembly for more efficiently computing:
// keccak256(abi.encodePacked(
// EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,
// transaction.salt,
// uint256(transaction.signerAddress),
// keccak256(transaction.data)
// ));
assembly {
// Compute hash of data
let dataHash := keccak256(add(data, 32), mload(data))
// Load free memory pointer
let memPtr := mload(64)
mstore(memPtr, schemaHash) // hash of schema
mstore(add(memPtr, 32), salt) // salt
mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress
mstore(add(memPtr, 96), dataHash) // hash of data
// Compute hash
result := keccak256(memPtr, 128)
}
return result;
}
}

View File

@@ -0,0 +1,46 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
pragma experimental "ABIEncoderV2";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../interfaces/ICoordinatorApprovalVerifier.sol";
contract MCoordinatorApprovalVerifier is
ICoordinatorApprovalVerifier
{
/// @dev Validates that the feeRecipients of a batch of order have approved a 0x transaction.
/// @param transaction 0x transaction containing salt, signerAddress, and data.
/// @param orders Array of order structs containing order specifications.
/// @param txOrigin Required signer of Ethereum transaction calling this function.
/// @param transactionSignature Proof that the transaction has been signed by the signer.
/// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
/// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order.
function assertValidTransactionOrdersApproval(
LibZeroExTransaction.ZeroExTransaction memory transaction,
LibOrder.Order[] memory orders,
address txOrigin,
bytes memory transactionSignature,
uint256[] memory approvalExpirationTimeSeconds,
bytes[] memory approvalSignatures
)
internal
view;
}

View File

@@ -0,0 +1,35 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "../interfaces/ISignatureValidator.sol";
contract MSignatureValidator is
ISignatureValidator
{
// Allowed signature types.
enum SignatureType {
Illegal, // 0x00, default value
Invalid, // 0x01
EIP712, // 0x02
EthSign, // 0x03
NSignatureTypes // 0x04, number of signature types. Always leave at end.
}
}

View File

@@ -0,0 +1,32 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "./MixinCoordinatorRegistryCore.sol";
// solhint-disable no-empty-blocks
contract CoordinatorRegistry is
MixinCoordinatorRegistryCore
{
constructor ()
public
MixinCoordinatorRegistryCore()
{}
}

View File

@@ -0,0 +1,48 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "./interfaces/ICoordinatorRegistryCore.sol";
// solhint-disable no-empty-blocks
contract MixinCoordinatorRegistryCore is
ICoordinatorRegistryCore
{
// mapping from `coordinatorOperator` -> `coordinatorEndpoint`
mapping (address => string) internal coordinatorEndpoints;
/// @dev Called by a Coordinator operator to set the endpoint of their Coordinator.
/// @param coordinatorEndpoint endpoint of the Coordinator.
function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external {
address coordinatorOperator = msg.sender;
coordinatorEndpoints[coordinatorOperator] = coordinatorEndpoint;
emit CoordinatorEndpointSet(coordinatorOperator, coordinatorEndpoint);
}
/// @dev Gets the endpoint for a Coordinator.
/// @param coordinatorOperator operator of the Coordinator endpoint.
function getCoordinatorEndpoint(address coordinatorOperator)
external
view
returns (string memory coordinatorEndpoint)
{
return coordinatorEndpoints[coordinatorOperator];
}
}

View File

@@ -0,0 +1,41 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
// solhint-disable no-empty-blocks
contract ICoordinatorRegistryCore
{
/// @dev Emitted when a Coordinator endpoint is set.
event CoordinatorEndpointSet(
address coordinatorOperator,
string coordinatorEndpoint
);
/// @dev Called by a Coordinator operator to set the endpoint of their Coordinator.
/// @param coordinatorEndpoint endpoint of the Coordinator.
function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external;
/// @dev Gets the endpoint for a Coordinator.
/// @param coordinatorOperator operator of the Coordinator endpoint.
function getCoordinatorEndpoint(address coordinatorOperator)
external
view
returns (string memory coordinatorEndpoint);
}

View File

@@ -0,0 +1,89 @@
{
"name": "@0x/contracts-coordinator",
"version": "2.0.1",
"engines": {
"node": ">=6.12"
},
"description": "Smart contract extensions of 0x protocol",
"main": "lib/src/index.js",
"directories": {
"test": "test"
},
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile generate_contract_wrappers",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler",
"watch": "sol-compiler -w",
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"profiler:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test",
"contracts:gen": "contracts-gen",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"config": {
"abis": "./generated-artifacts/@(Coordinator|CoordinatorRegistry).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^2.0.10",
"@0x/contracts-gen": "^1.0.9",
"@0x/contracts-test-utils": "^3.1.3",
"@0x/dev-utils": "^2.2.2",
"@0x/sol-compiler": "^3.1.7",
"@0x/tslint-config": "^3.0.1",
"@types/lodash": "4.14.104",
"@types/node": "*",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"solhint": "^1.4.1",
"tslint": "5.11.0",
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^5.1.0",
"@0x/contracts-asset-proxy": "^2.1.2",
"@0x/contracts-erc20": "^2.2.1",
"@0x/contracts-exchange": "1.0.2",
"@0x/contracts-exchange-libs": "^2.1.2",
"@0x/contracts-utils": "^3.1.2",
"@0x/order-utils": "^8.0.0",
"@0x/types": "^2.2.2",
"@0x/typescript-typings": "^4.2.2",
"@0x/utils": "^4.3.3",
"@0x/web3-wrapper": "^6.0.6",
"ethereum-types": "^2.1.2",
"ethereumjs-util": "^5.1.1",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,13 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as Coordinator from '../generated-artifacts/Coordinator.json';
import * as CoordinatorRegistry from '../generated-artifacts/CoordinatorRegistry.json';
export const artifacts = {
Coordinator: Coordinator as ContractArtifact,
CoordinatorRegistry: CoordinatorRegistry as ContractArtifact,
};

View File

@@ -0,0 +1,3 @@
export * from './artifacts';
export * from './wrappers';
export * from '../test/utils';

View File

@@ -0,0 +1,7 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/coordinator';
export * from '../generated-wrappers/coordinator_registry';

View File

@@ -0,0 +1,521 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import {
artifacts as exchangeArtifacts,
ExchangeCancelEventArgs,
ExchangeCancelUpToEventArgs,
ExchangeContract,
ExchangeFillEventArgs,
} from '@0x/contracts-exchange';
import {
chaiSetup,
constants as devConstants,
expectTransactionFailedAsync,
getLatestBlockTimestampAsync,
OrderFactory,
provider,
TransactionFactory,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import { ApprovalFactory, artifacts, constants, CoordinatorContract, exchangeDataEncoder } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi);
// tslint:disable:no-unnecessary-type-assertion
describe('Coordinator tests', () => {
let makerAddress: string;
let owner: string;
let takerAddress: string;
let feeRecipientAddress: string;
let erc20Proxy: ERC20ProxyContract;
let erc20TokenA: DummyERC20TokenContract;
let erc20TokenB: DummyERC20TokenContract;
let zrxToken: DummyERC20TokenContract;
let coordinatorContract: CoordinatorContract;
let exchange: ExchangeContract;
let erc20Wrapper: ERC20Wrapper;
let orderFactory: OrderFactory;
let takerTransactionFactory: TransactionFactory;
let makerTransactionFactory: TransactionFactory;
let approvalFactory: ApprovalFactory;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts.slice(0, 4));
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc20Proxy = await erc20Wrapper.deployProxyAsync();
const numDummyErc20ToDeploy = 3;
[erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
numDummyErc20ToDeploy,
devConstants.DUMMY_TOKEN_DECIMALS,
);
await erc20Wrapper.setBalancesAndAllowancesAsync();
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange,
provider,
txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address),
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await exchange.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator,
provider,
txDefaults,
exchange.address,
);
// Configure order defaults
const defaultOrderParams = {
...devConstants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address,
senderAddress: coordinatorContract.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
};
const makerPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
const takerPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
const feeRecipientPrivateKey = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(feeRecipientAddress)];
orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address);
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address);
approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('single order fills', () => {
for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
it(`${fnName} should fill the order with a signed approval`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: takerAddress },
),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
const fillLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
);
expect(fillLogs.length).to.eq(1);
const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
expect(fillLogArgs.makerAddress).to.eq(makerAddress);
expect(fillLogArgs.takerAddress).to.eq(takerAddress);
expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount);
expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount);
expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee);
expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee);
expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
});
it(`${fnName} should fill the order if called by approver`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
feeRecipientAddress,
transaction.signature,
[],
[],
{ from: feeRecipientAddress },
),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
const fillLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
);
expect(fillLogs.length).to.eq(1);
const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
expect(fillLogArgs.makerAddress).to.eq(makerAddress);
expect(fillLogArgs.takerAddress).to.eq(takerAddress);
expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount);
expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount);
expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee);
expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee);
expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
});
it(`${fnName} should revert with no approval signature`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[],
[],
{
from: takerAddress,
gas: devConstants.MAX_EXECUTE_TRANSACTION_GAS,
},
),
RevertReason.InvalidApprovalSignature,
);
});
it(`${fnName} should revert with an invalid approval signature`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[signature],
{ from: takerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`${fnName} should revert with an expired approval`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: takerAddress },
),
RevertReason.ApprovalExpired,
);
});
it(`${fnName} should revert if not called by tx signer or approver`, async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: owner },
),
RevertReason.InvalidOrigin,
);
});
}
});
describe('batch order fills', () => {
for (const fnName of [...constants.MARKET_FILL_FN_NAMES, ...constants.BATCH_FILL_FN_NAMES]) {
it(`${fnName} should fill the orders with a signed approval`, async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: takerAddress, gas: devConstants.MAX_EXECUTE_TRANSACTION_GAS },
),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
const fillLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
);
expect(fillLogs.length).to.eq(orders.length);
orders.forEach((order, index) => {
const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
expect(fillLogArgs.makerAddress).to.eq(makerAddress);
expect(fillLogArgs.takerAddress).to.eq(takerAddress);
expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData);
expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData);
expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount);
expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount);
expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee);
expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee);
expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
});
});
it(`${fnName} should fill the orders if called by approver`, async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
feeRecipientAddress,
transaction.signature,
[],
[],
{ from: feeRecipientAddress, gas: devConstants.MAX_EXECUTE_TRANSACTION_GAS },
),
devConstants.AWAIT_TRANSACTION_MINED_MS,
);
const fillLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
);
expect(fillLogs.length).to.eq(orders.length);
orders.forEach((order, index) => {
const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
expect(fillLogArgs.makerAddress).to.eq(makerAddress);
expect(fillLogArgs.takerAddress).to.eq(takerAddress);
expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData);
expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData);
expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount);
expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount);
expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee);
expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee);
expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
});
});
it(`${fnName} should revert with an invalid approval signature`, async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[signature],
{ from: takerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`${fnName} should revert with an expired approval`, async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: takerAddress },
),
RevertReason.ApprovalExpired,
);
});
it(`${fnName} should revert if not called by tx signer or approver`, async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = takerTransactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory.newSignedApproval(
transaction,
takerAddress,
approvalExpirationTimeSeconds,
);
await expectTransactionFailedAsync(
coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
takerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: owner },
),
RevertReason.InvalidOrigin,
);
});
}
});
describe('cancels', () => {
it('cancelOrder call should be successful without an approval', async () => {
const orders = [await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDER, orders);
const transaction = makerTransactionFactory.newSignedTransaction(data);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
makerAddress,
transaction.signature,
[],
[],
{
from: makerAddress,
},
),
);
const cancelLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeCancelEventArgs>).event === 'Cancel',
);
expect(cancelLogs.length).to.eq(1);
const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs<ExchangeCancelEventArgs>).args;
expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(cancelLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
expect(cancelLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
});
it('batchCancelOrders call should be successful without an approval', async () => {
const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.BATCH_CANCEL_ORDERS, orders);
const transaction = makerTransactionFactory.newSignedTransaction(data);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
makerAddress,
transaction.signature,
[],
[],
{
from: makerAddress,
},
),
);
const cancelLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeCancelEventArgs>).event === 'Cancel',
);
expect(cancelLogs.length).to.eq(orders.length);
orders.forEach((order, index) => {
const cancelLogArgs = (cancelLogs[index] as LogWithDecodedArgs<ExchangeCancelEventArgs>).args;
expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
expect(cancelLogArgs.makerAssetData).to.eq(order.makerAssetData);
expect(cancelLogArgs.takerAssetData).to.eq(order.takerAssetData);
expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
});
});
it('cancelOrdersUpTo call should be successful without an approval', async () => {
const orders: SignedOrder[] = [];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS_UP_TO, orders);
const transaction = makerTransactionFactory.newSignedTransaction(data);
const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
await coordinatorContract.executeTransaction.sendTransactionAsync(
transaction,
makerAddress,
transaction.signature,
[],
[],
{
from: makerAddress,
},
),
);
const cancelLogs = transactionReceipt.logs.filter(
log => (log as LogWithDecodedArgs<ExchangeCancelUpToEventArgs>).event === 'CancelUpTo',
);
expect(cancelLogs.length).to.eq(1);
const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs<ExchangeCancelUpToEventArgs>).args;
expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address);
expect(cancelLogArgs.orderEpoch).to.bignumber.eq(new BigNumber(1));
});
});
});
// tslint:disable:max-file-line-count

View File

@@ -0,0 +1,81 @@
import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange';
import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import { CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src';
import { CoordinatorRegistryWrapper } from './utils/coordinator_registry_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi);
// tslint:disable:no-unnecessary-type-assertion
describe('Coordinator Registry tests', () => {
let coordinatorOperator: string;
const coordinatorEndpoint = 'http://sometec.0x.org';
const nilCoordinatorEndpoint = '';
let coordinatorRegistryWrapper: CoordinatorRegistryWrapper;
// tests
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
// setup accounts (skip owner)
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[, coordinatorOperator] = accounts;
// deploy coordinator registry
coordinatorRegistryWrapper = new CoordinatorRegistryWrapper(provider);
await coordinatorRegistryWrapper.deployCoordinatorRegistryAsync();
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('core', () => {
it('Should successfully set a Coordinator endpoint', async () => {
await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint);
const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
coordinatorOperator,
);
expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
});
it('Should successfully unset a Coordinator endpoint', async () => {
// set Coordinator endpoint
await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint);
let recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
coordinatorOperator,
);
expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
// unset Coordinator endpoint
await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, nilCoordinatorEndpoint);
recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
coordinatorOperator,
);
expect(recordedCoordinatorEndpoint).to.be.equal(nilCoordinatorEndpoint);
});
it('Should emit an event when setting Coordinator endpoint', async () => {
// set Coordinator endpoint
const txReceipt = await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(
coordinatorOperator,
coordinatorEndpoint,
);
const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
coordinatorOperator,
);
expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
// validate event
expect(txReceipt.logs.length).to.be.equal(1);
const log = txReceipt.logs[0] as LogWithDecodedArgs<CoordinatorRegistryCoordinatorEndpointSetEventArgs>;
expect(log.args.coordinatorOperator).to.be.equal(coordinatorOperator);
expect(log.args.coordinatorEndpoint).to.be.equal(coordinatorEndpoint);
});
});
});

View File

@@ -0,0 +1,19 @@
import { env, EnvVars } from '@0x/dev-utils';
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
import { providerUtils } from '@0x/utils';
before('start web3 provider', () => {
providerUtils.startProviderEngine(provider);
});
after('generate coverage report', async () => {
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
await coverageSubprovider.writeCoverageAsync();
}
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
await profilerSubprovider.writeProfilerOutputAsync();
}
provider.stop();
});

View File

@@ -0,0 +1,79 @@
import { addressUtils, chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { artifacts, CoordinatorContract, hashUtils } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Libs tests', () => {
let coordinatorContract: CoordinatorContract;
const exchangeAddress = addressUtils.generatePseudoRandomAddress();
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator,
provider,
txDefaults,
exchangeAddress,
);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('getTransactionHash', () => {
it('should return the correct transaction hash', async () => {
const tx = {
verifyingContractAddress: exchangeAddress,
salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS,
data: '0x1234',
};
const expectedTxHash = transactionHashUtils.getTransactionHashHex(tx);
const txHash = await coordinatorContract.getTransactionHash.callAsync(tx);
expect(expectedTxHash).to.eq(txHash);
});
});
describe('getApprovalHash', () => {
it('should return the correct approval hash', async () => {
const signedTx = {
verifyingContractAddress: exchangeAddress,
salt: new BigNumber(0),
signerAddress: constants.NULL_ADDRESS,
data: '0x1234',
signature: '0x5678',
};
const approvalExpirationTimeSeconds = new BigNumber(0);
const txOrigin = constants.NULL_ADDRESS;
const approval = {
txOrigin,
transactionHash: transactionHashUtils.getTransactionHashHex(signedTx),
transactionSignature: signedTx.signature,
approvalExpirationTimeSeconds,
};
const expectedApprovalHash = hashUtils.getApprovalHashHex(
signedTx,
coordinatorContract.address,
txOrigin,
approvalExpirationTimeSeconds,
);
const approvalHash = await coordinatorContract.getCoordinatorApprovalHash.callAsync(approval);
expect(expectedApprovalHash).to.eq(approvalHash);
});
});
});

View File

@@ -0,0 +1,728 @@
import {
addressUtils,
chaiSetup,
constants as devConstants,
expectContractCallFailedAsync,
getLatestBlockTimestampAsync,
provider,
TransactionFactory,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
import { ApprovalFactory, artifacts, constants, CoordinatorContract, exchangeDataEncoder } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Mixins tests', () => {
let transactionSignerAddress: string;
let approvalSignerAddress1: string;
let approvalSignerAddress2: string;
let mixins: CoordinatorContract;
let transactionFactory: TransactionFactory;
let approvalFactory1: ApprovalFactory;
let approvalFactory2: ApprovalFactory;
let defaultOrder: SignedOrder;
const exchangeAddress = addressUtils.generatePseudoRandomAddress();
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
mixins = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator,
provider,
txDefaults,
exchangeAddress,
);
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3);
defaultOrder = {
exchangeAddress: devConstants.NULL_ADDRESS,
makerAddress: devConstants.NULL_ADDRESS,
takerAddress: devConstants.NULL_ADDRESS,
senderAddress: mixins.address,
feeRecipientAddress: approvalSignerAddress1,
makerAssetData: devConstants.NULL_BYTES,
takerAssetData: devConstants.NULL_BYTES,
makerAssetAmount: devConstants.ZERO_AMOUNT,
takerAssetAmount: devConstants.ZERO_AMOUNT,
makerFee: devConstants.ZERO_AMOUNT,
takerFee: devConstants.ZERO_AMOUNT,
expirationTimeSeconds: devConstants.ZERO_AMOUNT,
salt: devConstants.ZERO_AMOUNT,
signature: devConstants.NULL_BYTES,
};
const transactionSignerPrivateKey =
devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(transactionSignerAddress)];
const approvalSignerPrivateKey1 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress1)];
const approvalSignerPrivateKey2 = devConstants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress2)];
transactionFactory = new TransactionFactory(transactionSignerPrivateKey, exchangeAddress);
approvalFactory1 = new ApprovalFactory(approvalSignerPrivateKey1, mixins.address);
approvalFactory2 = new ApprovalFactory(approvalSignerPrivateKey2, mixins.address);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('getSignerAddress', () => {
it('should return the correct address using the EthSign signature type', async () => {
const data = devConstants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data, SignatureType.EthSign);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
expect(transaction.signerAddress).to.eq(signerAddress);
});
it('should return the correct address using the EIP712 signature type', async () => {
const data = devConstants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data, SignatureType.EIP712);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
expect(transaction.signerAddress).to.eq(signerAddress);
});
it('should revert with with the Illegal signature type', async () => {
const data = devConstants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data);
const illegalSignatureByte = ethUtil.toBuffer(SignatureType.Illegal).toString('hex');
transaction.signature = `${transaction.signature.slice(
0,
transaction.signature.length - 2,
)}${illegalSignatureByte}`;
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expectContractCallFailedAsync(
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
RevertReason.SignatureIllegal,
);
});
it('should revert with with the Invalid signature type', async () => {
const data = devConstants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data);
const invalidSignatureByte = ethUtil.toBuffer(SignatureType.Invalid).toString('hex');
transaction.signature = `0x${invalidSignatureByte}`;
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expectContractCallFailedAsync(
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
RevertReason.SignatureInvalid,
);
});
it("should revert with with a signature type that doesn't exist", async () => {
const data = devConstants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data);
const invalidSignatureByte = '04';
transaction.signature = `${transaction.signature.slice(
0,
transaction.signature.length - 2,
)}${invalidSignatureByte}`;
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expectContractCallFailedAsync(
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
RevertReason.SignatureUnsupported,
);
});
});
describe('decodeOrdersFromFillData', () => {
for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
it(`should correctly decode the orders for ${fnName} data`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
const decodedSignedOrders = decodedOrders.map(order => ({
...order,
exchangeAddress: devConstants.NULL_ADDRESS,
signature: devConstants.NULL_BYTES,
}));
expect(orders).to.deep.eq(decodedSignedOrders);
});
}
for (const fnName of constants.BATCH_FILL_FN_NAMES) {
it(`should correctly decode the orders for ${fnName} data`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
const decodedSignedOrders = decodedOrders.map(order => ({
...order,
exchangeAddress: devConstants.NULL_ADDRESS,
signature: devConstants.NULL_BYTES,
}));
expect(orders).to.deep.eq(decodedSignedOrders);
});
}
for (const fnName of constants.MARKET_FILL_FN_NAMES) {
it(`should correctly decode the orders for ${fnName} data`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
const decodedSignedOrders = decodedOrders.map(order => ({
...order,
exchangeAddress: devConstants.NULL_ADDRESS,
signature: devConstants.NULL_BYTES,
}));
expect(orders).to.deep.eq(decodedSignedOrders);
});
}
for (const fnName of [constants.CANCEL_ORDER, constants.BATCH_CANCEL_ORDERS, constants.CANCEL_ORDERS_UP_TO]) {
it(`should correctly decode the orders for ${fnName} data`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
const emptyArray: any[] = [];
expect(emptyArray).to.deep.eq(decodedOrders);
});
}
it('should decode an empty array for invalid data', async () => {
const data = '0x0123456789';
const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
const emptyArray: any[] = [];
expect(emptyArray).to.deep.eq(decodedOrders);
});
it('should revert if data is less than 4 bytes long', async () => {
const data = '0x010203';
await expectContractCallFailedAsync(
mixins.decodeOrdersFromFillData.callAsync(data),
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
);
});
});
describe('Single order approvals', () => {
for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1], expiration=[valid]`, async () => {
const order = {
...defaultOrder,
senderAddress: devConstants.NULL_ADDRESS,
};
const orders = [order];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[],
[],
{
from: approvalSignerAddress1,
},
);
});
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: approvalSignerAddress1 },
);
});
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[],
[],
{
from: approvalSignerAddress1,
},
);
});
it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[signature],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
),
RevertReason.ApprovalExpired,
);
});
it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidOrigin,
);
});
}
});
describe('Batch order approvals', () => {
for (const fnName of [
...constants.BATCH_FILL_FN_NAMES,
...constants.MARKET_FILL_FN_NAMES,
constants.MATCH_ORDERS,
]) {
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder].map(order => ({
...order,
senderAddress: devConstants.NULL_ADDRESS,
}));
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder].map(order => ({
...order,
senderAddress: devConstants.NULL_ADDRESS,
}));
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, senderAddress: devConstants.NULL_ADDRESS }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2], expiration=[valid,valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval1 = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
[approval1.signature, approval2.signature],
{ from: transactionSignerAddress },
);
});
it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[],
[],
{ from: approvalSignerAddress1 },
);
});
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval2.signature],
{ from: approvalSignerAddress1 },
),
RevertReason.InvalidOrigin,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[signature],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid], expiration=[valid,valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval1 = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
[approval1.signature, approvalSignature2],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[approvalExpirationTimeSeconds],
[approvalSignature2],
{ from: approvalSignerAddress1 },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,valid], expiration=[valid,invalid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds1 = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approvalExpirationTimeSeconds2 = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
const approval1 = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds1,
);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds2,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2],
[approval1.signature, approval2.signature],
{ from: transactionSignerAddress },
),
RevertReason.ApprovalExpired,
);
});
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid], expiration=[invalid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
const approval2 = approvalFactory2.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
approvalSignerAddress1,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval2.signature],
{ from: approvalSignerAddress1 },
),
RevertReason.ApprovalExpired,
);
});
it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
const approval1 = approvalFactory1.newSignedApproval(
transaction,
transactionSignerAddress,
approvalExpirationTimeSeconds,
);
expectContractCallFailedAsync(
mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval1.signature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidOrigin,
);
});
}
});
describe('cancels', () => {
it('should allow the tx signer to call `cancelOrder` without approval', async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDER, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
);
});
it('should allow the tx signer to call `batchCancelOrders` without approval', async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.BATCH_CANCEL_ORDERS, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
);
});
it('should allow the tx signer to call `cancelOrdersUpTo` without approval', async () => {
const orders: SignedOrder[] = [];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS_UP_TO, orders);
const transaction = transactionFactory.newSignedTransaction(data);
await mixins.assertValidCoordinatorApprovals.callAsync(
transaction,
transactionSignerAddress,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
);
});
});
});
// tslint:disable:max-file-line-count

View File

@@ -0,0 +1,38 @@
import { signingUtils } from '@0x/contracts-test-utils';
import { SignatureType, SignedZeroExTransaction } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as ethUtil from 'ethereumjs-util';
import { hashUtils, SignedCoordinatorApproval } from './index';
export class ApprovalFactory {
private readonly _privateKey: Buffer;
private readonly _verifyingContractAddress: string;
constructor(privateKey: Buffer, verifyingContractAddress: string) {
this._privateKey = privateKey;
this._verifyingContractAddress = verifyingContractAddress;
}
public newSignedApproval(
transaction: SignedZeroExTransaction,
txOrigin: string,
approvalExpirationTimeSeconds: BigNumber,
signatureType: SignatureType = SignatureType.EthSign,
): SignedCoordinatorApproval {
const approvalHashBuff = hashUtils.getApprovalHashBuffer(
transaction,
this._verifyingContractAddress,
txOrigin,
approvalExpirationTimeSeconds,
);
const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
const signedApproval = {
txOrigin,
transaction,
approvalExpirationTimeSeconds,
signature: ethUtil.addHexPrefix(signatureBuff.toString('hex')),
};
return signedApproval;
}
}

View File

@@ -0,0 +1,12 @@
import { BigNumber } from '@0x/utils';
export const constants = {
SINGLE_FILL_FN_NAMES: ['fillOrder', 'fillOrKillOrder', 'fillOrderNoThrow'],
BATCH_FILL_FN_NAMES: ['batchFillOrders', 'batchFillOrKillOrders', 'batchFillOrdersNoThrow'],
MARKET_FILL_FN_NAMES: ['marketBuyOrders', 'marketBuyOrdersNoThrow', 'marketSellOrders', 'marketSellOrdersNoThrow'],
MATCH_ORDERS: 'matchOrders',
CANCEL_ORDER: 'cancelOrder',
BATCH_CANCEL_ORDERS: 'batchCancelOrders',
CANCEL_ORDERS_UP_TO: 'cancelOrdersUpTo',
TIME_BUFFER: new BigNumber(1000),
};

View File

@@ -0,0 +1,64 @@
import { LogDecoder, txDefaults } from '@0x/contracts-test-utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types';
import { artifacts, CoordinatorRegistryContract } from '../../src';
export class CoordinatorRegistryWrapper {
private readonly _web3Wrapper: Web3Wrapper;
private readonly _provider: ZeroExProvider;
private readonly _logDecoder: LogDecoder;
private _coordinatorRegistryContract?: CoordinatorRegistryContract;
/**
* Instanitates an CoordinatorRegistryWrapper
* @param provider Web3 provider to use for all JSON RPC requests
* Instance of CoordinatorRegistryWrapper
*/
constructor(provider: ZeroExProvider) {
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
}
public async deployCoordinatorRegistryAsync(): Promise<CoordinatorRegistryContract> {
this._coordinatorRegistryContract = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
artifacts.CoordinatorRegistry,
this._provider,
txDefaults,
);
if (this._coordinatorRegistryContract === undefined) {
throw new Error(`Failed to deploy Coordinator Registry contract.`);
}
return this._coordinatorRegistryContract;
}
public async setCoordinatorEndpointAsync(
coordinatorOperator: string,
coordinatorEndpoint: string,
): Promise<TransactionReceiptWithDecodedLogs> {
this._assertCoordinatorRegistryDeployed();
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
await (this
._coordinatorRegistryContract as CoordinatorRegistryContract).setCoordinatorEndpoint.sendTransactionAsync(
coordinatorEndpoint,
{
from: coordinatorOperator,
},
),
);
return txReceipt;
}
public async getCoordinatorEndpointAsync(coordinatorOperator: string): Promise<string> {
this._assertCoordinatorRegistryDeployed();
const coordinatorEndpoint = await (this
._coordinatorRegistryContract as CoordinatorRegistryContract).getCoordinatorEndpoint.callAsync(
coordinatorOperator,
);
return coordinatorEndpoint;
}
private _assertCoordinatorRegistryDeployed(): void {
if (this._coordinatorRegistryContract === undefined) {
throw new Error(
'The Coordinator Registry contract was not deployed through the CoordinatorRegistryWrapper. Call `deployCoordinatorRegistryAsync` to deploy.',
);
}
}
}

View File

@@ -0,0 +1,51 @@
import { artifacts, IExchangeContract } from '@0x/contracts-exchange';
import { constants as devConstants, provider } from '@0x/contracts-test-utils';
import { SignedOrder } from '@0x/types';
import { constants } from './index';
export const exchangeDataEncoder = {
encodeOrdersToExchangeData(fnName: string, orders: SignedOrder[]): string {
const exchangeInstance = new IExchangeContract(
artifacts.IExchange.compilerOutput.abi,
devConstants.NULL_ADDRESS,
provider,
);
let data;
if (constants.SINGLE_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders[0],
orders[0].takerAssetAmount,
orders[0].signature,
);
} else if (constants.BATCH_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders,
orders.map(order => order.takerAssetAmount),
orders.map(order => order.signature),
);
} else if (constants.MARKET_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders,
orders.map(order => order.takerAssetAmount).reduce((prev, curr) => prev.plus(curr)),
orders.map(order => order.signature),
);
} else if (fnName === constants.MATCH_ORDERS) {
data = exchangeInstance.matchOrders.getABIEncodedTransactionData(
orders[0],
orders[1],
orders[0].signature,
orders[1].signature,
);
} else if (fnName === constants.CANCEL_ORDER) {
data = exchangeInstance.cancelOrder.getABIEncodedTransactionData(orders[0]);
} else if (fnName === constants.BATCH_CANCEL_ORDERS) {
data = exchangeInstance.batchCancelOrders.getABIEncodedTransactionData(orders);
} else if (fnName === constants.CANCEL_ORDERS_UP_TO) {
data = exchangeInstance.cancelOrdersUpTo.getABIEncodedTransactionData(devConstants.ZERO_AMOUNT);
} else {
throw new Error(`Error: ${fnName} not a supported function`);
}
return data;
},
};

View File

@@ -0,0 +1,33 @@
import { eip712Utils } from '@0x/order-utils';
import { SignedZeroExTransaction } from '@0x/types';
import { BigNumber, signTypedDataUtils } from '@0x/utils';
import * as _ from 'lodash';
export const hashUtils = {
getApprovalHashBuffer(
transaction: SignedZeroExTransaction,
verifyingContractAddress: string,
txOrigin: string,
approvalExpirationTimeSeconds: BigNumber,
): Buffer {
const typedData = eip712Utils.createCoordinatorApprovalTypedData(
transaction,
verifyingContractAddress,
txOrigin,
approvalExpirationTimeSeconds,
);
const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
return hashBuffer;
},
getApprovalHashHex(
transaction: SignedZeroExTransaction,
verifyingContractAddress: string,
txOrigin: string,
approvalExpirationTimeSeconds: BigNumber,
): string {
const hashHex = `0x${hashUtils
.getApprovalHashBuffer(transaction, verifyingContractAddress, txOrigin, approvalExpirationTimeSeconds)
.toString('hex')}`;
return hashHex;
},
};

View File

@@ -0,0 +1,5 @@
export { hashUtils } from './hash_utils';
export { ApprovalFactory } from './approval_factory';
export { constants } from './constants';
export { exchangeDataEncoder } from './exchange_data_encoder';
export * from './types';

View File

@@ -0,0 +1,12 @@
import { SignedZeroExTransaction } from '@0x/types';
import { BigNumber } from '@0x/utils';
export interface CoordinatorApproval {
transaction: SignedZeroExTransaction;
txOrigin: string;
approvalExpirationTimeSeconds: BigNumber;
}
export interface SignedCoordinatorApproval extends CoordinatorApproval {
signature: string;
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig",
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": ["generated-artifacts/Coordinator.json", "generated-artifacts/CoordinatorRegistry.json"],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@@ -0,0 +1,6 @@
{
"extends": ["@0x/tslint-config"],
"rules": {
"custom-no-magic-numbers": false
}
}

View File

@@ -0,0 +1,48 @@
[
{
"timestamp": 1557507213,
"version": "1.1.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.1.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1554997931
},
{
"version": "1.1.0",
"changes": [
{
"note": "Run Web3ProviderEngine without excess block polling",
"pr": 1695
}
],
"timestamp": 1553183790
},
{
"timestamp": 1553091633,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.0",
"changes": [
{
"note": "Created ERC1155 contracts package",
"pr": 1657
}
]
}
]

View File

@@ -0,0 +1,26 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.1.2 - _May 10, 2019_
* Dependencies updated
## v1.1.1 - _April 11, 2019_
* Dependencies updated
## v1.1.0 - _March 21, 2019_
* Run Web3ProviderEngine without excess block polling (#1695)
## v1.0.1 - _March 20, 2019_
* Dependencies updated
## v1.0.0 - _Invalid date_
* Created ERC1155 contracts package (#1657)

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,73 @@
## ERC1155 Tokens
This package contains implementations of various [ERC1155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) tokens. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
## Installation
**Install**
```bash
npm install @0x/contracts-erc1155 --save
```
## Bug bounty
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
## Contributing
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
### Install Dependencies
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0x/contracts-erc1155 yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0x/contracts-erc1155 yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
```bash
yarn test
```
#### Testing options
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).

View File

@@ -0,0 +1,30 @@
{
"artifactsDir": "generated-artifacts",
"contractsDir": "contracts",
"useDockerisedSolc": false,
"compilerSettings": {
"evmVersion": "constantinople",
"optimizer": { "enabled": true, "runs": 1000000 },
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode.object",
"evm.bytecode.sourceMap",
"evm.deployedBytecode.object",
"evm.deployedBytecode.sourceMap"
]
}
}
},
"contracts": [
"src/ERC1155.sol",
"src/ERC1155Mintable.sol",
"src/MixinNonFungibleToken.sol",
"src/interfaces/IERC1155.sol",
"src/interfaces/IERC1155Mintable.sol",
"src/interfaces/IERC1155Receiver.sol",
"src/mixins/MNonFungibleToken.sol",
"test/DummyERC1155Receiver.sol"
]
}

View File

@@ -0,0 +1,247 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "@0x/contracts-utils/contracts/src/Address.sol";
import "./interfaces/IERC1155.sol";
import "./interfaces/IERC1155Receiver.sol";
import "./MixinNonFungibleToken.sol";
contract ERC1155 is
SafeMath,
IERC1155,
MixinNonFungibleToken
{
using Address for address;
// selectors for receiver callbacks
bytes4 constant public ERC1155_RECEIVED = 0xf23a6e61;
bytes4 constant public ERC1155_BATCH_RECEIVED = 0xbc197c81;
// id => (owner => balance)
mapping (uint256 => mapping(address => uint256)) internal balances;
// owner => (operator => approved)
mapping (address => mapping(address => bool)) internal operatorApproval;
/// @notice Transfers value amount of an _id from the _from address to the _to address specified.
/// @dev MUST emit TransferSingle event on success.
/// Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
/// MUST throw if `_to` is the zero address.
/// MUST throw if balance of sender for token `_id` is lower than the `_value` sent.
/// MUST throw on any other error.
/// When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0).
/// If so, it MUST call `onERC1155Received` on `_to` and revert if the return value
/// is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
/// @param from Source address
/// @param to Target address
/// @param id ID of the token type
/// @param value Transfer amount
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 value,
bytes calldata data
)
external
{
// sanity checks
require(
to != address(0x0),
"CANNOT_TRANSFER_TO_ADDRESS_ZERO"
);
require(
from == msg.sender || operatorApproval[from][msg.sender] == true,
"INSUFFICIENT_ALLOWANCE"
);
// perform transfer
if (isNonFungible(id)) {
require(
value == 1,
"AMOUNT_EQUAL_TO_ONE_REQUIRED"
);
require(
nfOwners[id] == from,
"NFT_NOT_OWNED_BY_FROM_ADDRESS"
);
nfOwners[id] = to;
// You could keep balance of NF type in base type id like so:
// uint256 baseType = getNonFungibleBaseType(_id);
// balances[baseType][_from] = balances[baseType][_from].safeSub(_value);
// balances[baseType][_to] = balances[baseType][_to].safeAdd(_value);
} else {
balances[id][from] = safeSub(balances[id][from], value);
balances[id][to] = safeAdd(balances[id][to], value);
}
emit TransferSingle(msg.sender, from, to, id, value);
// if `to` is a contract then trigger its callback
if (to.isContract()) {
bytes4 callbackReturnValue = IERC1155Receiver(to).onERC1155Received(
msg.sender,
from,
id,
value,
data
);
require(
callbackReturnValue == ERC1155_RECEIVED,
"BAD_RECEIVER_RETURN_VALUE"
);
}
}
/// @notice Send multiple types of Tokens from a 3rd party in one transfer (with safety call).
/// @dev MUST emit TransferBatch event on success.
/// Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
/// MUST throw if `_to` is the zero address.
/// MUST throw if length of `_ids` is not the same as length of `_values`.
/// MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent.
/// MUST throw on any other error.
/// When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0).
/// If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value
/// is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
/// @param from Source addresses
/// @param to Target addresses
/// @param ids IDs of each token type
/// @param values Transfer amounts per token type
/// @param data Additional data with no specified format, sent in call to `_to`
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
{
// sanity checks
require(
to != address(0x0),
"CANNOT_TRANSFER_TO_ADDRESS_ZERO"
);
require(
ids.length == values.length,
"TOKEN_AND_VALUES_LENGTH_MISMATCH"
);
// Only supporting a global operator approval allows us to do
// only 1 check and not to touch storage to handle allowances.
require(
from == msg.sender || operatorApproval[from][msg.sender] == true,
"INSUFFICIENT_ALLOWANCE"
);
// perform transfers
for (uint256 i = 0; i < ids.length; ++i) {
// Cache value to local variable to reduce read costs.
uint256 id = ids[i];
uint256 value = values[i];
if (isNonFungible(id)) {
require(
value == 1,
"AMOUNT_EQUAL_TO_ONE_REQUIRED"
);
require(
nfOwners[id] == from,
"NFT_NOT_OWNED_BY_FROM_ADDRESS"
);
nfOwners[id] = to;
} else {
balances[id][from] = safeSub(balances[id][from], value);
balances[id][to] = safeAdd(balances[id][to], value);
}
}
emit TransferBatch(msg.sender, from, to, ids, values);
// if `to` is a contract then trigger its callback
if (to.isContract()) {
bytes4 callbackReturnValue = IERC1155Receiver(to).onERC1155BatchReceived(
msg.sender,
from,
ids,
values,
data
);
require(
callbackReturnValue == ERC1155_BATCH_RECEIVED,
"BAD_RECEIVER_RETURN_VALUE"
);
}
}
/// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
/// @dev MUST emit the ApprovalForAll event on success.
/// @param operator Address to add to the set of authorized operators
/// @param approved True if the operator is approved, false to revoke approval
function setApprovalForAll(address operator, bool approved) external {
operatorApproval[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
/// @notice Queries the approval status of an operator for a given owner.
/// @param owner The owner of the Tokens
/// @param operator Address of authorized operator
/// @return True if the operator is approved, false if not
function isApprovedForAll(address owner, address operator) external view returns (bool) {
return operatorApproval[owner][operator];
}
/// @notice Get the balance of an account's Tokens.
/// @param owner The address of the token holder
/// @param id ID of the Token
/// @return The _owner's balance of the Token type requested
function balanceOf(address owner, uint256 id) external view returns (uint256) {
if (isNonFungibleItem(id)) {
return nfOwners[id] == owner ? 1 : 0;
}
return balances[id][owner];
}
/// @notice Get the balance of multiple account/token pairs
/// @param owners The addresses of the token holders
/// @param ids ID of the Tokens
/// @return The _owner's balance of the Token types requested
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory balances_) {
// sanity check
require(
owners.length == ids.length,
"OWNERS_AND_IDS_MUST_HAVE_SAME_LENGTH"
);
// get balances
balances_ = new uint256[](owners.length);
for (uint256 i = 0; i < owners.length; ++i) {
uint256 id = ids[i];
if (isNonFungibleItem(id)) {
balances_[i] = nfOwners[id] == owners[i] ? 1 : 0;
} else {
balances_[i] = balances[id][owners[i]];
}
}
return balances_;
}
}

View File

@@ -0,0 +1,173 @@
pragma solidity ^0.5.5;
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./ERC1155.sol";
import "./interfaces/IERC1155Mintable.sol";
/// @dev Mintable form of ERC1155
/// Shows how easy it is to mint new items
contract ERC1155Mintable is
IERC1155Mintable,
ERC1155
{
/// token nonce
uint256 internal nonce;
/// mapping from token to creator
mapping (uint256 => address) public creators;
/// mapping from token to max index
mapping (uint256 => uint256) public maxIndex;
/// asserts token is owned by msg.sender
modifier creatorOnly(uint256 _id) {
require(creators[_id] == msg.sender);
_;
}
/// @dev creates a new token
/// @param uri URI of token
/// @param isNF is non-fungible token
/// @return type_ of token (a unique identifier)
function create(
string calldata uri,
bool isNF
)
external
returns (uint256 type_)
{
// Store the type in the upper 128 bits
type_ = (++nonce << 128);
// Set a flag if this is an NFI.
if (isNF) {
type_ = type_ | TYPE_NF_BIT;
}
// This will allow restricted access to creators.
creators[type_] = msg.sender;
// emit a Transfer event with Create semantic to help with discovery.
emit TransferSingle(
msg.sender,
address(0x0),
address(0x0),
type_,
0
);
if (bytes(uri).length > 0) {
emit URI(uri, type_);
}
}
/// @dev mints fungible tokens
/// @param id token type
/// @param to beneficiaries of minted tokens
/// @param quantities amounts of minted tokens
function mintFungible(
uint256 id,
address[] calldata to,
uint256[] calldata quantities
)
external
creatorOnly(id)
{
// sanity checks
require(
isFungible(id),
"TRIED_TO_MINT_FUNGIBLE_FOR_NON_FUNGIBLE_TOKEN"
);
// mint tokens
for (uint256 i = 0; i < to.length; ++i) {
// cache to reduce number of loads
address dst = to[i];
uint256 quantity = quantities[i];
// Grant the items to the caller
balances[id][dst] = safeAdd(quantity, balances[id][dst]);
// Emit the Transfer/Mint event.
// the 0x0 source address implies a mint
// It will also provide the circulating supply info.
emit TransferSingle(
msg.sender,
address(0x0),
dst,
id,
quantity
);
// if `to` is a contract then trigger its callback
if (dst.isContract()) {
bytes4 callbackReturnValue = IERC1155Receiver(dst).onERC1155Received(
msg.sender,
msg.sender,
id,
quantity,
""
);
require(
callbackReturnValue == ERC1155_RECEIVED,
"BAD_RECEIVER_RETURN_VALUE"
);
}
}
}
/// @dev mints a non-fungible token
/// @param type_ token type
/// @param to beneficiaries of minted tokens
function mintNonFungible(
uint256 type_,
address[] calldata to
)
external
creatorOnly(type_)
{
// No need to check this is a nf type rather than an id since
// creatorOnly() will only let a type pass through.
require(
isNonFungible(type_),
"TRIED_TO_MINT_NON_FUNGIBLE_FOR_FUNGIBLE_TOKEN"
);
// Index are 1-based.
uint256 index = maxIndex[type_] + 1;
for (uint256 i = 0; i < to.length; ++i) {
// cache to reduce number of loads
address dst = to[i];
uint256 id = type_ | index + i;
nfOwners[id] = dst;
// You could use base-type id to store NF type balances if you wish.
// balances[_type][dst] = quantity.safeAdd(balances[_type][dst]);
emit TransferSingle(msg.sender, address(0x0), dst, id, 1);
// if `to` is a contract then trigger its callback
if (dst.isContract()) {
bytes4 callbackReturnValue = IERC1155Receiver(dst).onERC1155Received(
msg.sender,
msg.sender,
id,
1,
""
);
require(
callbackReturnValue == ERC1155_RECEIVED,
"BAD_RECEIVER_RETURN_VALUE"
);
}
}
// record the `maxIndex` of this nft type
// this allows us to mint more nft's of this type in a subsequent call.
maxIndex[type_] = safeAdd(to.length, maxIndex[type_]);
}
}

View File

@@ -0,0 +1,76 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "./mixins/MNonFungibleToken.sol";
contract MixinNonFungibleToken is
MNonFungibleToken
{
/// Use a split bit implementation.
/// Store the type in the upper 128 bits..
uint256 constant internal TYPE_MASK = uint256(uint128(~0)) << 128;
/// ..and the non-fungible index in the lower 128
uint256 constant internal NF_INDEX_MASK = uint128(~0);
/// The top bit is a flag to tell if this is a NFI.
uint256 constant internal TYPE_NF_BIT = 1 << 255;
/// mapping of nft to owner
mapping (uint256 => address) internal nfOwners;
/// @dev Returns true if token is non-fungible
function isNonFungible(uint256 id) public pure returns(bool) {
return id & TYPE_NF_BIT == TYPE_NF_BIT;
}
/// @dev Returns true if token is fungible
function isFungible(uint256 id) public pure returns(bool) {
return id & TYPE_NF_BIT == 0;
}
/// @dev Returns index of non-fungible token
function getNonFungibleIndex(uint256 id) public pure returns(uint256) {
return id & NF_INDEX_MASK;
}
/// @dev Returns base type of non-fungible token
function getNonFungibleBaseType(uint256 id) public pure returns(uint256) {
return id & TYPE_MASK;
}
/// @dev Returns true if input is base-type of a non-fungible token
function isNonFungibleBaseType(uint256 id) public pure returns(bool) {
// A base type has the NF bit but does not have an index.
return (id & TYPE_NF_BIT == TYPE_NF_BIT) && (id & NF_INDEX_MASK == 0);
}
/// @dev Returns true if input is a non-fungible token
function isNonFungibleItem(uint256 id) public pure returns(bool) {
// A base type has the NF bit but does has an index.
return (id & TYPE_NF_BIT == TYPE_NF_BIT) && (id & NF_INDEX_MASK != 0);
}
/// @dev returns owner of a non-fungible token
function ownerOf(uint256 id) public view returns (address) {
return nfOwners[id];
}
}

View File

@@ -0,0 +1,152 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
/// @title ERC-1155 Multi Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
/// Note: The ERC-165 identifier for this interface is 0xd9b67a26.
interface IERC1155 {
/// @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred,
/// including zero value transfers as well as minting or burning.
/// Operator will always be msg.sender.
/// Either event from address `0x0` signifies a minting operation.
/// An event to address `0x0` signifies a burning or melting operation.
/// The total value transferred from address 0x0 minus the total value transferred to 0x0 may
/// be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
/// To define a token ID with no initial balance, the contract SHOULD emit the TransferSingle event
/// from `0x0` to `0x0`, with the token creator as `_operator`.
event TransferSingle(
address indexed operator,
address indexed from,
address indexed to,
uint256 id,
uint256 value
);
/// @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred,
/// including zero value transfers as well as minting or burning.
///Operator will always be msg.sender.
/// Either event from address `0x0` signifies a minting operation.
/// An event to address `0x0` signifies a burning or melting operation.
/// The total value transferred from address 0x0 minus the total value transferred to 0x0 may
/// be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
/// To define multiple token IDs with no initial balance, this SHOULD emit the TransferBatch event
/// from `0x0` to `0x0`, with the token creator as `_operator`.
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/// @dev MUST emit when an approval is updated.
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
);
/// @dev MUST emit when the URI is updated for a token ID.
/// URIs are defined in RFC 3986.
/// The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata JSON Schema".
event URI(
string value,
uint256 indexed id
);
/// @notice Transfers value amount of an _id from the _from address to the _to address specified.
/// @dev MUST emit TransferSingle event on success.
/// Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
/// MUST throw if `_to` is the zero address.
/// MUST throw if balance of sender for token `_id` is lower than the `_value` sent.
/// MUST throw on any other error.
/// When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0).
/// If so, it MUST call `onERC1155Received` on `_to` and revert if the return value
/// is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
/// @param from Source address
/// @param to Target address
/// @param id ID of the token type
/// @param value Transfer amount
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 value,
bytes calldata data
)
external;
/// @notice Send multiple types of Tokens from a 3rd party in one transfer (with safety call).
/// @dev MUST emit TransferBatch event on success.
/// Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
/// MUST throw if `_to` is the zero address.
/// MUST throw if length of `_ids` is not the same as length of `_values`.
/// MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent.
/// MUST throw on any other error.
/// When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0).
/// If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value
/// is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
/// @param from Source addresses
/// @param to Target addresses
/// @param ids IDs of each token type
/// @param values Transfer amounts per token type
/// @param data Additional data with no specified format, sent in call to `_to`
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external;
/// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
/// @dev MUST emit the ApprovalForAll event on success.
/// @param operator Address to add to the set of authorized operators
/// @param approved True if the operator is approved, false to revoke approval
function setApprovalForAll(address operator, bool approved) external;
/// @notice Queries the approval status of an operator for a given owner.
/// @param owner The owner of the Tokens
/// @param operator Address of authorized operator
/// @return True if the operator is approved, false if not
function isApprovedForAll(address owner, address operator) external view returns (bool);
/// @notice Get the balance of an account's Tokens.
/// @param owner The address of the token holder
/// @param id ID of the Token
/// @return The _owner's balance of the Token type requested
function balanceOf(address owner, uint256 id) external view returns (uint256);
/// @notice Get the balance of multiple account/token pairs
/// @param owners The addresses of the token holders
/// @param ids ID of the Tokens
/// @return The _owner's balance of the Token types requested
function balanceOfBatch(
address[] calldata owners,
uint256[] calldata ids
)
external
view
returns (uint256[] memory balances_);
}

View File

@@ -0,0 +1,42 @@
pragma solidity ^0.5.5;
import "./IERC1155.sol";
/// @dev Mintable form of ERC1155
/// Shows how easy it is to mint new items
contract IERC1155Mintable is
IERC1155
{
/// @dev creates a new token
/// @param uri URI of token
/// @param isNF is non-fungible token
/// @return _type of token (a unique identifier)
function create(
string calldata uri,
bool isNF
)
external
returns (uint256 type_);
/// @dev mints fungible tokens
/// @param id token type
/// @param to beneficiaries of minted tokens
/// @param quantities amounts of minted tokens
function mintFungible(
uint256 id,
address[] calldata to,
uint256[] calldata quantities
)
external;
/// @dev mints a non-fungible token
/// @param type_ token type
/// @param to beneficiaries of minted tokens
function mintNonFungible(
uint256 type_,
address[] calldata to
)
external;
}

View File

@@ -0,0 +1,67 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
interface IERC1155Receiver {
/// @notice Handle the receipt of a single ERC1155 token type
/// @dev The smart contract calls this function on the recipient
/// after a `safeTransferFrom`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
///transaction being reverted
/// Note: the contract address is always the message sender
/// @param operator The address which called `safeTransferFrom` function
/// @param from The address which previously owned the token
/// @param id An array containing the ids of the token being transferred
/// @param value An array containing the amount of tokens being transferred
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
)
external
returns(bytes4);
/// @notice Handle the receipt of multiple ERC1155 token types
/// @dev The smart contract calls this function on the recipient
/// after a `safeTransferFrom`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
/// transaction being reverted
/// Note: the contract address is always the message sender
/// @param operator The address which called `safeTransferFrom` function
/// @param from The address which previously owned the token
/// @param ids An array containing ids of each token being transferred
/// @param values An array containing amounts of each token being transferred
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
returns(bytes4);
}

View File

@@ -0,0 +1,44 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
contract MNonFungibleToken {
/// @dev Returns true if token is non-fungible
function isNonFungible(uint256 id) public pure returns(bool);
/// @dev Returns true if token is fungible
function isFungible(uint256 _d) public pure returns(bool);
/// @dev Returns index of non-fungible token
function getNonFungibleIndex(uint256 id) public pure returns(uint256);
/// @dev Returns base type of non-fungible token
function getNonFungibleBaseType(uint256 id) public pure returns(uint256);
/// @dev Returns true if input is base-type of a non-fungible token
function isNonFungibleBaseType(uint256 id) public pure returns(bool);
/// @dev Returns true if input is a non-fungible token
function isNonFungibleItem(uint256 id) public pure returns(bool);
/// @dev returns owner of a non-fungible token
function ownerOf(uint256 id) public view returns (address);
}

View File

@@ -0,0 +1,126 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.5;
import "../src/interfaces/IERC1155Receiver.sol";
contract DummyERC1155Receiver is
IERC1155Receiver
{
bytes4 constant public ERC1155_RECEIVED = 0xf23a6e61;
bytes4 constant public ERC1155_BATCH_RECEIVED = 0xbc197c81;
bool internal shouldRejectTransfer;
event TokenReceived(
address operator,
address from,
uint256 tokenId,
uint256 tokenValue,
bytes data
);
event BatchTokenReceived(
address operator,
address from,
uint256[] tokenIds,
uint256[] tokenValues,
bytes data
);
constructor () public {
shouldRejectTransfer = false;
}
/// @notice Handle the receipt of a single ERC1155 token type
/// @dev The smart contract calls this function on the recipient
/// after a `safeTransferFrom`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
///transaction being reverted
/// Note: the contract address is always the message sender
/// @param operator The address which called `safeTransferFrom` function
/// @param from The address which previously owned the token
/// @param id An array containing the ids of the token being transferred
/// @param value An array containing the amount of tokens being transferred
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
)
external
returns(bytes4)
{
if (shouldRejectTransfer) {
revert("TRANSFER_REJECTED");
}
emit TokenReceived(
operator,
from,
id,
value,
data
);
return ERC1155_RECEIVED;
}
/// @notice Handle the receipt of multiple ERC1155 token types
/// @dev The smart contract calls this function on the recipient
/// after a `safeTransferFrom`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
/// transaction being reverted
/// Note: the contract address is always the message sender
/// @param operator The address which called `safeTransferFrom` function
/// @param from The address which previously owned the token
/// @param ids An array containing ids of each token being transferred
/// @param values An array containing amounts of each token being transferred
/// @param data Additional data with no specified format
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
returns (bytes4)
{
if (shouldRejectTransfer) {
revert("TRANSFER_REJECTED");
}
emit BatchTokenReceived(
operator,
from,
ids,
values,
data
);
return ERC1155_BATCH_RECEIVED;
}
// @dev If set to true then all future transfers will be rejected.
function setRejectTransferFlag(bool _shouldRejectTransfer) external {
shouldRejectTransfer = _shouldRejectTransfer;
}
}

View File

@@ -0,0 +1,83 @@
{
"name": "@0x/contracts-erc1155",
"version": "1.1.2",
"engines": {
"node": ">=6.12"
},
"description": "Token contracts used by 0x protocol",
"main": "lib/src/index.js",
"directories": {
"test": "test"
},
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile generate_contract_wrappers",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler",
"watch": "sol-compiler -w",
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html",
"profiler:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov",
"test:circleci": "yarn test",
"contracts:gen": "contracts-gen",
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"config": {
"abis": "generated-artifacts/@(DummyERC1155Receiver|ERC1155|ERC1155Mintable|IERC1155|IERC1155Mintable|IERC1155Receiver|MNonFungibleToken|MixinNonFungibleToken).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^2.0.10",
"@0x/contracts-gen": "^1.0.9",
"@0x/dev-utils": "^2.2.2",
"@0x/sol-compiler": "^3.1.7",
"@0x/tslint-config": "^3.0.1",
"@types/lodash": "4.14.104",
"@types/node": "*",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"solhint": "^1.4.1",
"tslint": "5.11.0",
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^5.1.0",
"@0x/contracts-test-utils": "^3.1.3",
"@0x/contracts-utils": "^3.1.2",
"@0x/types": "^2.2.2",
"@0x/typescript-typings": "^4.2.2",
"@0x/utils": "^4.3.3",
"@0x/web3-wrapper": "^6.0.6",
"ethereum-types": "^2.1.2",
"lodash": "^4.17.11"
},
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,25 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as DummyERC1155Receiver from '../generated-artifacts/DummyERC1155Receiver.json';
import * as ERC1155 from '../generated-artifacts/ERC1155.json';
import * as ERC1155Mintable from '../generated-artifacts/ERC1155Mintable.json';
import * as IERC1155 from '../generated-artifacts/IERC1155.json';
import * as IERC1155Mintable from '../generated-artifacts/IERC1155Mintable.json';
import * as IERC1155Receiver from '../generated-artifacts/IERC1155Receiver.json';
import * as MixinNonFungibleToken from '../generated-artifacts/MixinNonFungibleToken.json';
import * as MNonFungibleToken from '../generated-artifacts/MNonFungibleToken.json';
export const artifacts = {
DummyERC1155Receiver: DummyERC1155Receiver as ContractArtifact,
ERC1155: ERC1155 as ContractArtifact,
MNonFungibleToken: MNonFungibleToken as ContractArtifact,
ERC1155Mintable: ERC1155Mintable as ContractArtifact,
MixinNonFungibleToken: MixinNonFungibleToken as ContractArtifact,
IERC1155Mintable: IERC1155Mintable as ContractArtifact,
IERC1155Receiver: IERC1155Receiver as ContractArtifact,
IERC1155: IERC1155 as ContractArtifact,
};

View File

@@ -0,0 +1,3 @@
export * from './wrappers';
export * from './artifacts';
export { Erc1155Wrapper } from '../test/utils/erc1155_wrapper';

View File

@@ -0,0 +1,13 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/dummy_erc1155_receiver';
export * from '../generated-wrappers/erc1155';
export * from '../generated-wrappers/erc1155_mintable';
export * from '../generated-wrappers/i_erc1155_mintable';
export * from '../generated-wrappers/i_erc1155_receiver';
export * from '../generated-wrappers/ierc1155';
export * from '../generated-wrappers/m_non_fungible_token';
export * from '../generated-wrappers/mixin_non_fungible_token';

View File

@@ -0,0 +1,492 @@
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
provider,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import {
artifacts,
DummyERC1155ReceiverBatchTokenReceivedEventArgs,
DummyERC1155ReceiverContract,
ERC1155MintableContract,
} from '../src';
import { Erc1155Wrapper } from './utils/erc1155_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('ERC1155Token', () => {
// constant values used in transfer tests
const nftOwnerBalance = new BigNumber(1);
const nftNotOwnerBalance = new BigNumber(0);
const spenderInitialFungibleBalance = new BigNumber(500);
const receiverInitialFungibleBalance = new BigNumber(0);
const fungibleValueToTransfer = spenderInitialFungibleBalance.div(2);
const nonFungibleValueToTransfer = nftOwnerBalance;
const receiverCallbackData = '0x01020304';
// tokens & addresses
let owner: string;
let spender: string;
let delegatedSpender: string;
let receiver: string;
let erc1155Contract: ERC1155MintableContract;
let erc1155Receiver: DummyERC1155ReceiverContract;
let nonFungibleToken: BigNumber;
let erc1155Wrapper: Erc1155Wrapper;
let fungibleToken: BigNumber;
// tests
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
// deploy erc1155 contract & receiver
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[owner, spender, delegatedSpender] = accounts;
erc1155Contract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
artifacts.ERC1155Mintable,
provider,
txDefaults,
);
erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
artifacts.DummyERC1155Receiver,
provider,
txDefaults,
);
receiver = erc1155Receiver.address;
// create wrapper & mint erc1155 tokens
erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, provider, owner);
fungibleToken = await erc1155Wrapper.mintFungibleTokensAsync([spender], spenderInitialFungibleBalance);
let nonFungibleTokens: BigNumber[];
[, nonFungibleTokens] = await erc1155Wrapper.mintNonFungibleTokensAsync([spender]);
nonFungibleToken = nonFungibleTokens[0];
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('safeTransferFrom', () => {
it('should transfer fungible token if called by token owner', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = fungibleToken;
const valueToTransfer = fungibleValueToTransfer;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeTransferFromAsync(
spender,
receiver,
fungibleToken,
valueToTransfer,
receiverCallbackData,
);
// check balances after transfer
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(valueToTransfer),
receiverInitialFungibleBalance.plus(valueToTransfer),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
});
it('should transfer non-fungible token if called by token owner', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = nonFungibleToken;
const valueToTransfer = nonFungibleValueToTransfer;
// check balances before transfer
const expectedInitialBalances = [nftOwnerBalance, nftNotOwnerBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeTransferFromAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
);
// check balances after transfer
const expectedFinalBalances = [nftNotOwnerBalance, nftOwnerBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
});
it('should trigger callback if transferring to a contract', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = fungibleToken;
const valueToTransfer = fungibleValueToTransfer;
// check balances before transfer
const expectedInitialBalances = [
spenderInitialFungibleBalance,
receiverInitialFungibleBalance,
nftOwnerBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
const tx = await erc1155Wrapper.safeTransferFromAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
);
expect(tx.logs.length).to.be.equal(2);
const receiverLog = tx.logs[1] as LogWithDecodedArgs<DummyERC1155ReceiverBatchTokenReceivedEventArgs>;
// check callback logs
const expectedCallbackLog = {
operator: spender,
from: spender,
tokenId: tokenToTransfer,
tokenValue: valueToTransfer,
data: receiverCallbackData,
};
expect(receiverLog.args.operator).to.be.equal(expectedCallbackLog.operator);
expect(receiverLog.args.from).to.be.equal(expectedCallbackLog.from);
expect(receiverLog.args.tokenId).to.be.bignumber.equal(expectedCallbackLog.tokenId);
expect(receiverLog.args.tokenValue).to.be.bignumber.equal(expectedCallbackLog.tokenValue);
expect(receiverLog.args.data).to.be.deep.equal(expectedCallbackLog.data);
// check balances after transfer
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(valueToTransfer),
receiverInitialFungibleBalance.plus(valueToTransfer),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
});
it('should throw if transfer reverts', async () => {
// setup test parameters
const tokenToTransfer = fungibleToken;
const valueToTransfer = spenderInitialFungibleBalance.plus(1);
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeTransferFrom.sendTransactionAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
{ from: spender },
),
RevertReason.Uint256Underflow,
);
});
it('should throw if callback reverts', async () => {
// setup test parameters
const tokenToTransfer = fungibleToken;
const valueToTransfer = fungibleValueToTransfer;
// set receiver to reject balances
const shouldRejectTransfer = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await erc1155Receiver.setRejectTransferFlag.sendTransactionAsync(shouldRejectTransfer),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeTransferFrom.sendTransactionAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
{ from: spender },
),
RevertReason.TransferRejected,
);
});
});
describe('batchSafeTransferFrom', () => {
it('should transfer fungible tokens if called by token owner', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [fungibleToken];
const valuesToTransfer = [fungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeBatchTransferFromAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// check balances after transfer
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(valuesToTransfer[0]),
receiverInitialFungibleBalance.plus(valuesToTransfer[0]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should transfer non-fungible token if called by token owner', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [nonFungibleToken];
const valuesToTransfer = [nonFungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [nftOwnerBalance, nftNotOwnerBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeBatchTransferFromAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// check balances after transfer
const expectedFinalBalances = [nftNotOwnerBalance, nftOwnerBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should transfer mix of fungible / non-fungible tokens if called by token owner', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [fungibleToken, nonFungibleToken];
const valuesToTransfer = [fungibleValueToTransfer, nonFungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [
// spender
spenderInitialFungibleBalance,
nftOwnerBalance,
// receiver
receiverInitialFungibleBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeBatchTransferFromAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// check balances after transfer
const expectedFinalBalances = [
// spender
spenderInitialFungibleBalance.minus(valuesToTransfer[0]),
nftNotOwnerBalance,
// receiver
receiverInitialFungibleBalance.plus(valuesToTransfer[0]),
nftOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should trigger callback if transferring to a contract', async () => {
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [fungibleToken, nonFungibleToken];
const valuesToTransfer = [fungibleValueToTransfer, nonFungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [
// spender
spenderInitialFungibleBalance,
nftOwnerBalance,
// receiver
receiverInitialFungibleBalance,
nftNotOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
const tx = await erc1155Wrapper.safeBatchTransferFromAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
expect(tx.logs.length).to.be.equal(2);
const receiverLog = tx.logs[1] as LogWithDecodedArgs<DummyERC1155ReceiverBatchTokenReceivedEventArgs>;
// check callback logs
const expectedCallbackLog = {
operator: spender,
from: spender,
tokenIds: tokensToTransfer,
tokenValues: valuesToTransfer,
data: receiverCallbackData,
};
expect(receiverLog.args.operator).to.be.equal(expectedCallbackLog.operator);
expect(receiverLog.args.from).to.be.equal(expectedCallbackLog.from);
expect(receiverLog.args.tokenIds.length).to.be.equal(2);
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(expectedCallbackLog.tokenIds[0]);
expect(receiverLog.args.tokenIds[1]).to.be.bignumber.equal(expectedCallbackLog.tokenIds[1]);
expect(receiverLog.args.tokenValues.length).to.be.equal(2);
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(expectedCallbackLog.tokenValues[0]);
expect(receiverLog.args.tokenValues[1]).to.be.bignumber.equal(expectedCallbackLog.tokenValues[1]);
expect(receiverLog.args.data).to.be.deep.equal(expectedCallbackLog.data);
// check balances after transfer
const expectedFinalBalances = [
// spender
spenderInitialFungibleBalance.minus(valuesToTransfer[0]),
nftNotOwnerBalance,
// receiver
receiverInitialFungibleBalance.plus(valuesToTransfer[0]),
nftOwnerBalance,
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should throw if transfer reverts', async () => {
// setup test parameters
const tokensToTransfer = [fungibleToken];
const valuesToTransfer = [spenderInitialFungibleBalance.plus(1)];
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
{ from: spender },
),
RevertReason.Uint256Underflow,
);
});
it('should throw if callback reverts', async () => {
// setup test parameters
const tokensToTransfer = [fungibleToken];
const valuesToTransfer = [fungibleValueToTransfer];
// set receiver to reject balances
const shouldRejectTransfer = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await erc1155Receiver.setRejectTransferFlag.sendTransactionAsync(shouldRejectTransfer),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
{ from: spender },
),
RevertReason.TransferRejected,
);
});
});
describe('setApprovalForAll', () => {
it('should transfer token via safeTransferFrom if called by approved account', async () => {
// set approval
const isApprovedForAll = true;
await erc1155Wrapper.setApprovalForAllAsync(spender, delegatedSpender, isApprovedForAll);
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
expect(isApprovedForAllCheck).to.be.true();
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = fungibleToken;
const valueToTransfer = fungibleValueToTransfer;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeTransferFromAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
delegatedSpender,
);
// check balances after transfer
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(valueToTransfer),
receiverInitialFungibleBalance.plus(valueToTransfer),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
});
it('should throw if trying to transfer tokens via safeTransferFrom by an unapproved account', async () => {
// check approval not set
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
expect(isApprovedForAllCheck).to.be.false();
// setup test parameters
const tokenHolders = [spender, receiver];
const tokenToTransfer = fungibleToken;
const valueToTransfer = fungibleValueToTransfer;
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeTransferFrom.sendTransactionAsync(
spender,
receiver,
tokenToTransfer,
valueToTransfer,
receiverCallbackData,
{ from: delegatedSpender },
),
RevertReason.InsufficientAllowance,
);
});
it('should transfer token via safeBatchTransferFrom if called by approved account', async () => {
// set approval
const isApprovedForAll = true;
await erc1155Wrapper.setApprovalForAllAsync(spender, delegatedSpender, isApprovedForAll);
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
expect(isApprovedForAllCheck).to.be.true();
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [fungibleToken];
const valuesToTransfer = [fungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await erc1155Wrapper.safeBatchTransferFromAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
delegatedSpender,
);
// check balances after transfer
const expectedFinalBalances = [
spenderInitialFungibleBalance.minus(valuesToTransfer[0]),
receiverInitialFungibleBalance.plus(valuesToTransfer[0]),
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should throw if trying to transfer tokens via safeBatchTransferFrom by an unapproved account', async () => {
// check approval not set
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
expect(isApprovedForAllCheck).to.be.false();
// setup test parameters
const tokenHolders = [spender, receiver];
const tokensToTransfer = [fungibleToken];
const valuesToTransfer = [fungibleValueToTransfer];
// check balances before transfer
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
spender,
receiver,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
{ from: delegatedSpender },
),
RevertReason.InsufficientAllowance,
);
});
});
});
// tslint:enable:no-unnecessary-type-assertion

View File

@@ -0,0 +1,19 @@
import { env, EnvVars } from '@0x/dev-utils';
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
import { providerUtils } from '@0x/utils';
before('start web3 provider', () => {
providerUtils.startProviderEngine(provider);
});
after('generate coverage report', async () => {
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
await coverageSubprovider.writeCoverageAsync();
}
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
await profilerSubprovider.writeProfilerOutputAsync();
}
provider.stop();
});

View File

@@ -0,0 +1,159 @@
import { constants, LogDecoder } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts, ERC1155MintableContract, ERC1155TransferSingleEventArgs } from '../../src';
const expect = chai.expect;
export class Erc1155Wrapper {
private readonly _erc1155Contract: ERC1155MintableContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _contractOwner: string;
private readonly _logDecoder: LogDecoder;
constructor(contractInstance: ERC1155MintableContract, provider: Provider, contractOwner: string) {
this._erc1155Contract = contractInstance;
this._web3Wrapper = new Web3Wrapper(provider);
this._contractOwner = contractOwner;
this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
}
public getContract(): ERC1155MintableContract {
return this._erc1155Contract;
}
public async getBalancesAsync(owners: string[], tokens: BigNumber[]): Promise<BigNumber[]> {
const balances = await this._erc1155Contract.balanceOfBatch.callAsync(owners, tokens);
return balances;
}
public async safeTransferFromAsync(
from: string,
to: string,
token: BigNumber,
value: BigNumber,
callbackData?: string,
delegatedSpender?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const spender = delegatedSpender === undefined ? from : delegatedSpender;
const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
await this._erc1155Contract.safeTransferFrom.sendTransactionAsync(from, to, token, value, callbackDataHex, {
from: spender,
}),
);
return tx;
}
public async safeBatchTransferFromAsync(
from: string,
to: string,
tokens: BigNumber[],
values: BigNumber[],
callbackData?: string,
delegatedSpender?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const spender = delegatedSpender === undefined ? from : delegatedSpender;
const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
await this._erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
from,
to,
tokens,
values,
callbackDataHex,
{ from: spender },
),
);
return tx;
}
public async mintFungibleTokensAsync(
beneficiaries: string[],
tokenAmounts: BigNumber | BigNumber[],
): Promise<BigNumber> {
const tokenUri = 'dummyFungibleToken';
const tokenIsNonFungible = false;
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
await this._erc1155Contract.create.sendTransactionAsync(tokenUri, tokenIsNonFungible, {
from: this._contractOwner,
}),
);
// tslint:disable-next-line no-unnecessary-type-assertion
const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
const token = createFungibleTokenLog.args.id;
const tokenAmountsAsArray = _.isArray(tokenAmounts) ? tokenAmounts : [];
if (!_.isArray(tokenAmounts)) {
_.each(_.range(0, beneficiaries.length), () => {
tokenAmountsAsArray.push(tokenAmounts);
});
}
await this._web3Wrapper.awaitTransactionSuccessAsync(
await this._erc1155Contract.mintFungible.sendTransactionAsync(token, beneficiaries, tokenAmountsAsArray, {
from: this._contractOwner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
return token;
}
public async mintNonFungibleTokensAsync(beneficiaries: string[]): Promise<[BigNumber, BigNumber[]]> {
const tokenUri = 'dummyNonFungibleToken';
const tokenIsNonFungible = true;
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
await this._erc1155Contract.create.sendTransactionAsync(tokenUri, tokenIsNonFungible, {
from: this._contractOwner,
}),
);
// tslint:disable-next-line no-unnecessary-type-assertion
const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
const token = createFungibleTokenLog.args.id;
await this._web3Wrapper.awaitTransactionSuccessAsync(
await this._erc1155Contract.mintNonFungible.sendTransactionAsync(token, beneficiaries, {
from: this._contractOwner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const encodedNftIds: BigNumber[] = [];
const nftIdBegin = 1;
const nftIdEnd = beneficiaries.length + 1;
const nftIdRange = _.range(nftIdBegin, nftIdEnd);
_.each(nftIdRange, (nftId: number) => {
const encodedNftId = token.plus(nftId);
encodedNftIds.push(encodedNftId);
});
return [token, encodedNftIds];
}
public async setApprovalForAllAsync(
owner: string,
beneficiary: string,
isApproved: boolean,
): Promise<TransactionReceiptWithDecodedLogs> {
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
await this._erc1155Contract.setApprovalForAll.sendTransactionAsync(beneficiary, isApproved, {
from: owner,
}),
);
return tx;
}
public async isApprovedForAllAsync(owner: string, beneficiary: string): Promise<boolean> {
const isApprovedForAll = await this._erc1155Contract.isApprovedForAll.callAsync(owner, beneficiary);
return isApprovedForAll;
}
public async assertBalancesAsync(
owners: string[],
tokens: BigNumber[],
expectedBalances: BigNumber[],
): Promise<void> {
const ownersExtended: string[] = [];
let tokensExtended: BigNumber[] = [];
_.each(owners, (owner: string) => {
tokensExtended = tokensExtended.concat(tokens);
_.each(_.range(0, tokens.length), () => {
ownersExtended.push(owner);
});
});
const balances = await this.getBalancesAsync(ownersExtended, tokensExtended);
_.each(balances, (balance: BigNumber, i: number) => {
expect(balance, `${ownersExtended[i]}${tokensExtended[i]}`).to.be.bignumber.equal(expectedBalances[i]);
});
}
}

View File

@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig",
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/DummyERC1155Receiver.json",
"generated-artifacts/ERC1155.json",
"generated-artifacts/ERC1155Mintable.json",
"generated-artifacts/IERC1155.json",
"generated-artifacts/IERC1155Mintable.json",
"generated-artifacts/IERC1155Receiver.json",
"generated-artifacts/MNonFungibleToken.json",
"generated-artifacts/MixinNonFungibleToken.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@@ -0,0 +1,6 @@
{
"extends": ["@0x/tslint-config"],
"rules": {
"custom-no-magic-numbers": false
}
}

Some files were not shown because too many files have changed in this diff Show More