Compare commits
	
		
			364 Commits
		
	
	
		
			@0xproject
			...
			monorepo@e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e2559798df | ||
|  | ccc18620bf | ||
|  | febe00db4f | ||
|  | 6f36048a8e | ||
|  | 2457ecb7e7 | ||
|  | 2378747570 | ||
|  | 2df569b727 | ||
|  | 65aecc0024 | ||
|  | 074082ec94 | ||
|  | 6b9f0af828 | ||
|  | bfabf765e3 | ||
|  | e74f736eff | ||
|  | 45483557a5 | ||
|  | 07942a7aec | ||
|  | 3d1b7c10e8 | ||
|  | cf46d2c704 | ||
|  | 4434856add | ||
|  | 52d511df21 | ||
|  | 50f58f9121 | ||
|  | 7a20c7b946 | ||
|  | ce0e60ed84 | ||
|  | 4ad0a6c7b7 | ||
|  | b8d8651e43 | ||
|  | 45b68832aa | ||
|  | 6dfcaaf889 | ||
|  | 8131c5d6bc | ||
|  | df5779b6d1 | ||
|  | 4a5a0c8c78 | ||
|  | b3a17624c8 | ||
|  | e63841a604 | ||
|  | 7ec95e8c29 | ||
|  | b217495465 | ||
|  | db6ddc0c4b | ||
|  | 174b360593 | ||
|  | 481a752e70 | ||
|  | 38acdfd632 | ||
|  | 561e525778 | ||
|  | 69eb820d0d | ||
|  | 447f16fc4f | ||
|  | 1769609245 | ||
|  | e1dcdac1bb | ||
|  | 9d45d19c80 | ||
|  | 9858bb0ce4 | ||
|  | a3527a77a6 | ||
|  | 33a45fa739 | ||
|  | e70882a657 | ||
|  | e456332da7 | ||
|  | 4ed84c5dc5 | ||
|  | 2fe3f40be9 | ||
|  | 44bfdb718f | ||
|  | 3524efc41c | ||
|  | 01210c291c | ||
|  | 192d4b4dbf | ||
|  | 68246fc335 | ||
|  | 7ef86636aa | ||
|  | a5859c6cee | ||
|  | 3463903d02 | ||
|  | 4b0f1a8431 | ||
|  | 603e8aa671 | ||
|  | 6eb980abe2 | ||
|  | 46b168e10f | ||
|  | 508e6ccf89 | ||
|  | a173c5fc38 | ||
|  | f5237f7971 | ||
|  | 6f7a5d00e6 | ||
|  | 4061723863 | ||
|  | ab1b52ba87 | ||
|  | 16e94ecb40 | ||
|  | 6bb2c5877c | ||
|  | a14450f367 | ||
|  | 85df313a7a | ||
|  | 66ed6b9b88 | ||
|  | 9304d09da6 | ||
|  | e61dbbb6cf | ||
|  | 1690f59857 | ||
|  | c916dd6ebb | ||
|  | 8a683b8541 | ||
|  | 4883b8be10 | ||
|  | 51760f9bdd | ||
|  | 6a619a4084 | ||
|  | feeafa193a | ||
|  | 8d8528996a | ||
|  | 965d609829 | ||
|  | a52714bcf3 | ||
|  | bbfd7647a8 | ||
|  | 0aba5a3be4 | ||
|  | 61bf5864a8 | ||
|  | 56847a53f4 | ||
|  | 8324ab3af7 | ||
|  | d496a7585c | ||
|  | 8d7f2a993a | ||
|  | ed786f3e8f | ||
|  | 539c243733 | ||
|  | 40e0c829b3 | ||
|  | e34b1f2f8b | ||
|  | f6b6619c08 | ||
|  | e480e08aa4 | ||
|  | 652cf7a976 | ||
|  | 7a8ab6fbe8 | ||
|  | 9deec8ec35 | ||
|  | 3f1586045c | ||
|  | ada5563b1f | ||
|  | 6b41a570a5 | ||
|  | cebf6bfb34 | ||
|  | 47a1b48ad8 | ||
|  | ef82a9d2a6 | ||
|  | ba6351841d | ||
|  | cdc786a1e3 | ||
|  | 3ea137a78f | ||
|  | b525ccc825 | ||
|  | 77acbdd3ea | ||
|  | c13190ceab | ||
|  | 78d4fc59a5 | ||
|  | f9e86c057d | ||
|  | 1d8e133a30 | ||
|  | 99fbf384fd | ||
|  | cb4fcf4de7 | ||
|  | 675964dc5c | ||
|  | 6432f85eb0 | ||
|  | 66eef758c6 | ||
|  | c64f0ba34b | ||
|  | 6deffb6b28 | ||
|  | 5802713801 | ||
|  | 11df29fa8e | ||
|  | f4a41e80b8 | ||
|  | 5c655b55d3 | ||
|  | 63c15b6f4f | ||
|  | 4f2bc29744 | ||
|  | 2cac431c41 | ||
|  | 80b7a7842c | ||
|  | 8c7cec9822 | ||
|  | 971a4087d2 | ||
|  | 660e670d38 | ||
|  | 052824f4e3 | ||
|  | 1d5ef4d0ca | ||
|  | a6440b94f4 | ||
|  | 01685b7622 | ||
|  | 397fefa8d7 | ||
|  | 82a01ef020 | ||
|  | a224ce347e | ||
|  | 81ba2a8411 | ||
|  | a6e8b28da5 | ||
|  | e90dbf66f3 | ||
|  | 0be2219beb | ||
|  | 09b4d5e0e4 | ||
|  | 60f1bcf51f | ||
|  | 431ac3b401 | ||
|  | 50781bd77a | ||
|  | c3361bb86e | ||
|  | fd5ad69c26 | ||
|  | b1f97a27f3 | ||
|  | febddcb356 | ||
|  | 74d5af34eb | ||
|  | 365890291f | ||
|  | 0368de701f | ||
|  | f5e7b7e7e0 | ||
|  | 038c21324e | ||
|  | 5d008ee83e | ||
|  | d0f6933980 | ||
|  | 14793f30b5 | ||
|  | 86319291e3 | ||
|  | afa2dd7374 | ||
|  | 1312e4caf2 | ||
|  | eb4517d737 | ||
|  | d80701c277 | ||
|  | bf3ab1127d | ||
|  | dcb12b6ad6 | ||
|  | f87420a776 | ||
|  | 6cedf5362b | ||
|  | aa833ef074 | ||
|  | 5f1c9cfee5 | ||
|  | 62b93cf2eb | ||
|  | b1c5f6e8f1 | ||
|  | 3bc9b309f6 | ||
|  | 6924a2b681 | ||
|  | d93d4c34f5 | ||
|  | 557267477e | ||
|  | b9f7979e91 | ||
|  | 8c803ab232 | ||
|  | 422e5e4dd7 | ||
|  | 2aea820d89 | ||
|  | 1c3b2b7141 | ||
|  | e7d5ceb9c5 | ||
|  | 68af0e9eb7 | ||
|  | a18d0f6229 | ||
|  | 031807df9c | ||
|  | 72710be04b | ||
|  | ac135d55d3 | ||
|  | 1d55e94659 | ||
|  | 86284f1c7e | ||
|  | 61a4ae7fc4 | ||
|  | 55fab3d98f | ||
|  | de11b62e30 | ||
|  | 8e14e65b60 | ||
|  | 2d1d14d2e4 | ||
|  | f44644ad90 | ||
|  | ac1640140c | ||
|  | 1402a0aa22 | ||
|  | f225f9e7c8 | ||
|  | 14fdb71a71 | ||
|  | 9c4c4fb19a | ||
|  | 5785ec0713 | ||
|  | 2eab0e30b7 | ||
|  | 2c846ff145 | ||
|  | ca0dfc6610 | ||
|  | 0fd44ee2c1 | ||
|  | 7271fc0bab | ||
|  | 6c039bbeb1 | ||
|  | 38e6d26145 | ||
|  | b0f210dea9 | ||
|  | f7469080f9 | ||
|  | fb5ea5d99f | ||
|  | be2f4cbdca | ||
|  | 68f2dc11b4 | ||
|  | d6c670dfcb | ||
|  | 0736c41357 | ||
|  | 898bd75a18 | ||
|  | 260313a6ae | ||
|  | 6a99bfa68e | ||
|  | f60adbdd72 | ||
|  | 1be310cef4 | ||
|  | ff4f86f1d6 | ||
|  | f4a4fefe42 | ||
|  | 00a4fa5f7c | ||
|  | 4475fefd07 | ||
|  | cd08a9c121 | ||
|  | b0c4eb8333 | ||
|  | 368dbda8f0 | ||
|  | bc4149683e | ||
|  | 6174d9ebb7 | ||
|  | e4fc8a8414 | ||
|  | 907972c466 | ||
|  | 49f5fe635f | ||
|  | 77290c1efa | ||
|  | 4ac43a9fd2 | ||
|  | cc77d1dd49 | ||
|  | 51161784e8 | ||
|  | cb7660fbe7 | ||
|  | 82e51b8787 | ||
|  | fffa96bba7 | ||
|  | e6cb2e0fcd | ||
|  | 38abeaed9c | ||
|  | 90c9e3496a | ||
|  | 9fc8a6e214 | ||
|  | 9df87a199a | ||
|  | 7e9ba50502 | ||
|  | 41559c39b9 | ||
|  | 6a6b424c86 | ||
|  | 3a5c6ed00f | ||
|  | db54588d05 | ||
|  | 52fde551e4 | ||
|  | 40cf805e5e | ||
|  | 09d6496135 | ||
|  | c4dadf4bfd | ||
|  | 35ba3e6f7c | ||
|  | 3ac182ee91 | ||
|  | 00e7c70b4d | ||
|  | 0aa9ed3839 | ||
|  | d652deea23 | ||
|  | 878db3b849 | ||
|  | ec2e726be0 | ||
|  | 287830d6e0 | ||
|  | c7a7ae7e18 | ||
|  | 1c7ba6a315 | ||
|  | 0a6f107243 | ||
|  | a93f95c55e | ||
|  | 6833e243b7 | ||
|  | 81dc893d1d | ||
|  | f8e565bc06 | ||
|  | ba15fb6a06 | ||
|  | 1e6b83719a | ||
|  | 9fcb2dda73 | ||
|  | 9a5ec8d030 | ||
|  | ac872e5181 | ||
|  | 70863cca08 | ||
|  | 5a1dce15be | ||
|  | d291256158 | ||
|  | 8c706ac639 | ||
|  | f697814849 | ||
|  | ca5c9e77c0 | ||
|  | a32b201afe | ||
|  | 0ecdf1e213 | ||
|  | 057891b342 | ||
|  | 407f63ef20 | ||
|  | f938c989e3 | ||
|  | c8500cab10 | ||
|  | c28c3db63f | ||
|  | a09ee90739 | ||
|  | 7d5a23969d | ||
|  | 56c3c29feb | ||
|  | c75212bef0 | ||
|  | 6d0dedc62c | ||
|  | cf12daea2f | ||
|  | 6f88e9bdbd | ||
|  | d8cb56caa3 | ||
|  | 044415e23d | ||
|  | 6b866d6053 | ||
|  | 74ce893f52 | ||
|  | cc1fac9bbe | ||
|  | 94e01be9ed | ||
|  | 91a9014a50 | ||
|  | e215992859 | ||
|  | e6f5cac878 | ||
|  | 29971f36cf | ||
|  | 3e4493b389 | ||
|  | 749c6ecc30 | ||
|  | e6e7bae445 | ||
|  | a1d8943552 | ||
|  | 07e56b3cc7 | ||
|  | b16f5f55fb | ||
|  | d92fd43791 | ||
|  | e706fa76ac | ||
|  | 11328bd93d | ||
|  | bc686fcbf3 | ||
|  | 80291caf7c | ||
|  | cd5e9a5115 | ||
|  | ad161a973e | ||
|  | 103e1aa250 | ||
|  | 641d86cb98 | ||
|  | 813b2ca1fb | ||
|  | ec96c3bb77 | ||
|  | 65120e84e2 | ||
|  | 82b51db17e | ||
|  | 374ee2db32 | ||
|  | 3557cd93fc | ||
|  | 0629a7d143 | ||
|  | a27112cbef | ||
|  | d039a1adda | ||
|  | bb4d449e92 | ||
|  | 241534a63d | ||
|  | 1932aff35c | ||
|  | 4f27991959 | ||
|  | 8ce4f9c784 | ||
|  | 7351bf0b14 | ||
|  | 48ab151ec2 | ||
|  | f6080367fe | ||
|  | 7f78d7da9d | ||
|  | 6734f2f1bc | ||
|  | 0fb7617a78 | ||
|  | 4219af1430 | ||
|  | c109d1f545 | ||
|  | 50fab9feb3 | ||
|  | 3dad6ee55e | ||
|  | 5d70df771b | ||
|  | ab5df342e1 | ||
|  | 6a9669a409 | ||
|  | e68942ee78 | ||
|  | 4159e45aff | ||
|  | 92497d7df4 | ||
|  | 44a430802e | ||
|  | 070eff6f3a | ||
|  | 681ed822ec | ||
|  | 0a1ae2c311 | ||
|  | c5f8b9c2d2 | ||
|  | 6b03cfd40d | ||
|  | 7f36574a57 | ||
|  | b637ca105a | ||
|  | 9ffddb47b8 | ||
|  | 7bcaac4e10 | ||
|  | d4592c0a60 | ||
|  | 1d6699585e | ||
|  | a75c298de0 | ||
|  | d603d8da47 | ||
|  | a551d0a6dd | 
| @@ -2,6 +2,7 @@ version: 2 | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     resource_class: medium+ | ||||
|     docker: | ||||
|       - image: circleci/node:9 | ||||
|     environment: | ||||
| @@ -18,11 +19,11 @@ jobs: | ||||
|             - yarn-packages-master | ||||
|             - yarn-packages- | ||||
|       - run: | ||||
|           name: yarn | ||||
|           command: yarn --frozen-lockfile install || true | ||||
|           name: install-yarn | ||||
|           command: sudo npm install --global yarn@1.9.4 | ||||
|       - run: | ||||
|           name: yarn | ||||
|           command: yarn --frozen-lockfile install | ||||
|           command: yarn --frozen-lockfile install || yarn --frozen-lockfile install | ||||
|       - save_cache: | ||||
|           name: Save Yarn Package Cache | ||||
|           key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }} | ||||
| @@ -60,6 +61,7 @@ jobs: | ||||
|       # initialized | ||||
|       - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts | ||||
|   test-publish: | ||||
|     resource_class: medium+ | ||||
|     docker: | ||||
|       - image: circleci/node:9 | ||||
|       - image: verdaccio/verdaccio | ||||
| @@ -254,4 +256,4 @@ workflows: | ||||
|             - build | ||||
|       - submit-coverage: | ||||
|           requires: | ||||
|             - test-rest | ||||
|             - test-rest | ||||
|   | ||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -88,7 +88,7 @@ packages/0x.js/src/artifacts/ | ||||
| packages/order-utils/src/artifacts/ | ||||
|  | ||||
| # unstable generated contract artifacts: | ||||
| packages/migrations/artifacts/2.0.0/ | ||||
| packages/migrations/artifacts/development/ | ||||
|  | ||||
| # generated contract watcher | ||||
| packages/0x.js/src/generated_contract_wrappers/ | ||||
| @@ -99,8 +99,9 @@ packages/fill-scenarios/src/generated_contract_wrappers/ | ||||
| packages/order-watcher/src/generated_contract_wrappers/ | ||||
| packages/order-utils/src/generated_contract_wrappers/ | ||||
| packages/migrations/src/1.0.0/contract_wrappers | ||||
| packages/migrations/src/2.0.0-testnet/contract_wrappers | ||||
| packages/migrations/src/2.0.0/contract_wrappers | ||||
| packages/migrations/src/2.0.0-beta-testnet/contract_wrappers | ||||
| packages/migrations/src/development/contract_wrappers | ||||
|  | ||||
| # solc-bin in sol-compiler | ||||
| packages/sol-compiler/solc_bin/ | ||||
|   | ||||
| @@ -8,18 +8,20 @@ lib | ||||
| /packages/order-watcher/src/generated_contract_wrappers/ | ||||
| /packages/order-utils/src/generated_contract_wrappers/ | ||||
| /packages/migrations/src/1.0.0/contract_wrappers | ||||
| /packages/migrations/src/2.0.0-testnet/contract_wrappers | ||||
| /packages/migrations/src/2.0.0/contract_wrappers | ||||
| /packages/migrations/src/2.0.0-beta-testnet/contract_wrappers | ||||
| /packages/0x.js/src/artifacts | ||||
| /packages/contracts/src/artifacts | ||||
| /packages/contract-wrappers/src/artifacts | ||||
| /packages/order-watcher/src/artifacts | ||||
| /packages/metacoin/artifacts | ||||
| /packages/sra-api/public/ | ||||
| /packages/sra-spec/public/ | ||||
| /packages/contract-wrappers/test/artifacts | ||||
| /packages/order-watcher/test/artifacts | ||||
| /packages/migrations/artifacts/1.0.0 | ||||
| /packages/migrations/artifacts/2.0.0-testnet | ||||
| /packages/migrations/artifacts/2.0.0 | ||||
| /packages/migrations/artifacts/2.0.0-beta-testnet | ||||
| /packages/migrations/artifacts/development | ||||
| package.json | ||||
| scripts/postpublish_utils.js | ||||
| packages/sol-cov/test/fixtures/artifacts | ||||
|   | ||||
| @@ -33,7 +33,7 @@ If you're developing on 0x now or are interested in using 0x infrastructure in t | ||||
| | [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts)     | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts)     | Monorepo scripts                                                                                                          | | ||||
| | [`@0xproject/react-docs`](/packages/react-docs)                 | [](https://www.npmjs.com/package/@0xproject/react-docs)                 | React documentation component for rendering TypeDoc & Doxity generated JSON                                               | | ||||
| | [`@0xproject/react-shared`](/packages/react-shared)             | [](https://www.npmjs.com/package/@0xproject/react-shared)             | 0x shared react components                                                                                                | | ||||
| | [`@0xproject/sra-api`](/packages/sra-api)                       | [](https://www.npmjs.com/package/@0xproject/sra-api)                       | OpenAPI specification for the standard relayer API                                                                        | | ||||
| | [`@0xproject/sra-spec`](/packages/sra-spec)                     | [](https://www.npmjs.com/package/@0xproject/sra-spec)                     | OpenAPI specification for the standard relayer API                                                                        | | ||||
| | [`@0xproject/sra-report`](/packages/sra-report)                 | [](https://www.npmjs.com/package/@0xproject/sra-report)                 | Generate reports for standard relayer API compliance                                                                      | | ||||
| | [`@0xproject/sol-cov`](/packages/sol-cov)                       | [](https://www.npmjs.com/package/@0xproject/sol-cov)                       | Solidity test coverage tool                                                                                               | | ||||
| | [`@0xproject/subproviders`](/packages/subproviders)             | [](https://www.npmjs.com/package/@0xproject/subproviders)             | Useful web3 subproviders (e.g LedgerSubprovider)                                                                          | | ||||
|   | ||||
| @@ -23,10 +23,11 @@ | ||||
|         "install:all": "yarn install", | ||||
|         "wsrun": "wsrun", | ||||
|         "lerna": "lerna", | ||||
|         "watch": "wsrun watch_without_deps $PKG --fast-exit -r --stages --done-criteria='complete|successfully'", | ||||
|         "build": "wsrun build $PKG --fast-exit -r --stages", | ||||
|         "build:no_website": "wsrun build $PKG --fast-exit -r --stages --exclude @0xproject/website", | ||||
|         "build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build", | ||||
|         "build:ts": "tsc -b", | ||||
|         "watch:ts": "tsc -b -w", | ||||
|         "clean": "wsrun clean $PKG --fast-exit -r --parallel", | ||||
|         "remove_node_modules": "lerna clean --yes; rm -rf node_modules", | ||||
|         "rebuild": "run-s clean build", | ||||
| @@ -51,6 +52,7 @@ | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "prettier": "^1.11.1", | ||||
|         "source-map-support": "^0.5.6", | ||||
|         "typescript": "3.0.1", | ||||
|         "wsrun": "^2.2.0" | ||||
|     }, | ||||
|     "resolutions": { | ||||
|   | ||||
| @@ -1,4 +1,40 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "1.0.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add ZRX & WETH mainnet contract addresses into the included artifacts" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1537265493 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1536142250, | ||||
|         "version": "1.0.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1-rc.6", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Fix missing `BlockParamLiteral` type import issue" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1535377027 | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1-rc.5", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": | ||||
|                     "Fix `main` and `types` package.json entries so that they point to the new location of index.d.ts and index.js" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1-rc.4", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.0.2 - _September 18, 2018_ | ||||
|  | ||||
|     * Add ZRX & WETH mainnet contract addresses into the included artifacts | ||||
|  | ||||
| ## v1.0.1 - _September 5, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.0.1-rc.6 - _August 27, 2018_ | ||||
|  | ||||
|     * Fix missing `BlockParamLiteral` type import issue | ||||
|  | ||||
| ## v1.0.1-rc.5 - _Invalid date_ | ||||
|  | ||||
|     * Fix `main` and `types` package.json entries so that they point to the new location of index.d.ts and index.js | ||||
|  | ||||
| ## v1.0.1-rc.4 - _August 24, 2018_ | ||||
|  | ||||
|     * Re-organize the exported interface of 0x.js. Remove the `ZeroEx` class, and instead export the same exports as `0x.js`'s sub-packages: `@0xproject/contract-wrappers`, `@0xproject/order-utils` and `@0xproject/order-watcher` (#963) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| ## 0x.js | ||||
|  | ||||
| A TypeScript/Javascript library for interacting with the 0x protocol. | ||||
| A TypeScript/Javascript library for interacting with the 0x protocol. It is a high level package which combines a number of underlying packages such as order-utils and order-watcher. | ||||
|  | ||||
| ### Read the [Documentation](https://0xproject.com/docs/0x.js). | ||||
|  | ||||
| @@ -19,7 +19,14 @@ npm install 0x.js --save | ||||
| **Import** | ||||
|  | ||||
| ```javascript | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { | ||||
|     assetDataUtils, | ||||
|     BigNumber, | ||||
|     ContractWrappers, | ||||
|     generatePseudoRandomSalt, | ||||
|     orderHashUtils, | ||||
|     signatureUtils, | ||||
| } from '0x.js'; | ||||
| ``` | ||||
|  | ||||
| If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "0x.js", | ||||
|     "version": "1.0.1-rc.4", | ||||
|     "version": "1.0.2", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -12,10 +12,9 @@ | ||||
|         "tokens", | ||||
|         "exchange" | ||||
|     ], | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "main": "lib/index.js", | ||||
|     "types": "lib/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "tsc -w", | ||||
|         "build": "yarn build:all", | ||||
|         "build:all": "run-p build:umd:prod build:commonjs", | ||||
|         "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*", | ||||
| @@ -25,8 +24,8 @@ | ||||
|         "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", | ||||
|         "clean": "shx rm -rf _bundles lib test_temp src/generated_contract_wrappers generated_docs", | ||||
|         "build:umd:prod": "NODE_ENV=production webpack", | ||||
|         "build:commonjs": "tsc", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|         "build:commonjs": "tsc -b", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|     }, | ||||
|     "config": { | ||||
|         "postpublish": { | ||||
| @@ -42,15 +41,16 @@ | ||||
|     }, | ||||
|     "license": "Apache-2.0", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/abi-gen": "^1.0.6", | ||||
|         "@0xproject/dev-utils": "^1.0.5", | ||||
|         "@0xproject/migrations": "^1.0.5", | ||||
|         "@0xproject/monorepo-scripts": "^1.0.6", | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/abi-gen": "^1.0.8", | ||||
|         "@0xproject/dev-utils": "^1.0.7", | ||||
|         "@0xproject/migrations": "^1.0.8", | ||||
|         "@0xproject/monorepo-scripts": "^1.0.8", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^2.2.42", | ||||
|         "@types/node": "^8.0.53", | ||||
|         "@types/sinon": "^2.2.2", | ||||
|         "@types/web3-provider-engine": "^14.0.0", | ||||
|         "awesome-typescript-loader": "^3.1.3", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
| @@ -73,17 +73,17 @@ | ||||
|         "webpack": "^3.1.0" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/assert": "^1.0.6", | ||||
|         "@0xproject/base-contract": "^2.0.0", | ||||
|         "@0xproject/contract-wrappers": "^1.0.1-rc.4", | ||||
|         "@0xproject/order-utils": "^1.0.1-rc.4", | ||||
|         "@0xproject/order-watcher": "^1.0.1-rc.4", | ||||
|         "@0xproject/subproviders": "^2.0.0", | ||||
|         "@0xproject/types": "^1.0.1-rc.5", | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/web3-wrapper": "^2.0.0", | ||||
|         "ethereum-types": "^1.0.5", | ||||
|         "@0xproject/assert": "^1.0.8", | ||||
|         "@0xproject/base-contract": "^2.0.2", | ||||
|         "@0xproject/contract-wrappers": "^1.0.2", | ||||
|         "@0xproject/order-utils": "^1.0.1", | ||||
|         "@0xproject/order-watcher": "^1.0.2", | ||||
|         "@0xproject/subproviders": "^2.0.2", | ||||
|         "@0xproject/types": "^1.0.1", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "@0xproject/web3-wrapper": "^2.0.2", | ||||
|         "ethereum-types": "^1.0.6", | ||||
|         "ethers": "3.0.22", | ||||
|         "lodash": "^4.17.5", | ||||
|         "web3-provider-engine": "14.0.6" | ||||
|   | ||||
| @@ -9,6 +9,7 @@ export { | ||||
|     ERC20ProxyWrapper, | ||||
|     ERC721ProxyWrapper, | ||||
|     ForwarderWrapper, | ||||
|     OrderValidatorWrapper, | ||||
|     IndexedFilterValues, | ||||
|     BlockRange, | ||||
|     ContractWrappersConfig, | ||||
| @@ -42,6 +43,10 @@ export { | ||||
|     DecodedLogEvent, | ||||
|     ExchangeEventArgs, | ||||
|     TransactionEncoder, | ||||
|     BalanceAndAllowance, | ||||
|     OrderAndTraderInfo, | ||||
|     TraderInfo, | ||||
|     ValidateOrderFillableOpts, | ||||
| } from '@0xproject/contract-wrappers'; | ||||
|  | ||||
| export { OrderWatcher, OnOrderStateChangeCallback, OrderWatcherConfig } from '@0xproject/order-watcher'; | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "src" | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
|     "include": ["./src/**/*"] | ||||
| } | ||||
|   | ||||
							
								
								
									
										7
									
								
								packages/0x.js/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/0x.js/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|     "extends": "../../typedoc-tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
| @@ -47,8 +47,13 @@ module.exports = { | ||||
|                 use: [ | ||||
|                     { | ||||
|                         loader: 'awesome-typescript-loader', | ||||
|                         // tsconfig.json contains some options required for | ||||
|                         // project references which do not work with webback. | ||||
|                         // We override those options here. | ||||
|                         query: { | ||||
|                             declaration: false, | ||||
|                             declarationMap: false, | ||||
|                             composite: false, | ||||
|                         }, | ||||
|                     }, | ||||
|                 ], | ||||
|   | ||||
| @@ -1,4 +1,22 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1536142250, | ||||
|         "version": "1.0.8", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535377027, | ||||
|         "version": "1.0.7", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535133899, | ||||
|         "version": "1.0.6", | ||||
|   | ||||
| @@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.0.8 - _September 5, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.0.7 - _August 27, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.0.6 - _August 24, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/abi-gen", | ||||
|     "version": "1.0.6", | ||||
|     "version": "1.0.8", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -8,10 +8,9 @@ | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "tsc -w", | ||||
|         "lint": "tslint --project .", | ||||
|         "clean": "shx rm -rf lib", | ||||
|         "build": "tsc", | ||||
|         "build": "tsc -b", | ||||
|         "test": "yarn run_mocha", | ||||
|         "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit", | ||||
|         "test:circleci": "yarn test:coverage", | ||||
| @@ -31,10 +30,10 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md", | ||||
|     "dependencies": { | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "chalk": "^2.3.0", | ||||
|         "ethereum-types": "^1.0.5", | ||||
|         "ethereum-types": "^1.0.6", | ||||
|         "glob": "^7.1.2", | ||||
|         "handlebars": "^4.0.11", | ||||
|         "lodash": "^4.17.5", | ||||
| @@ -45,7 +44,7 @@ | ||||
|         "yargs": "^10.0.3" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/glob": "5.0.35", | ||||
|         "@types/handlebars": "^4.0.36", | ||||
|         "@types/mkdirp": "^0.5.1", | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "." | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,22 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1536142250, | ||||
|         "version": "1.0.8", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535377027, | ||||
|         "version": "1.0.7", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535133899, | ||||
|         "version": "1.0.6", | ||||
|   | ||||
| @@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.0.8 - _September 5, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.0.7 - _August 27, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.0.6 - _August 24, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/assert", | ||||
|     "version": "1.0.6", | ||||
|     "version": "1.0.8", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -8,8 +8,7 @@ | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "tsc -w", | ||||
|         "build": "tsc", | ||||
|         "build": "tsc -b", | ||||
|         "clean": "shx rm -rf lib test_temp", | ||||
|         "lint": "tslint --project .", | ||||
|         "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit", | ||||
| @@ -29,7 +28,7 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^2.2.42", | ||||
|         "@types/valid-url": "^1.0.2", | ||||
| @@ -45,9 +44,9 @@ | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/json-schemas": "^1.0.1-rc.5", | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/json-schemas": "^1.0.1", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "lodash": "^4.17.5", | ||||
|         "valid-url": "^1.0.9" | ||||
|     }, | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "." | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,22 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1536142250, | ||||
|         "version": "2.0.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535377027, | ||||
|         "version": "2.0.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1535133899, | ||||
|         "version": "2.0.0", | ||||
|   | ||||
| @@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v2.0.2 - _September 5, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.0.1 - _August 27, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.0.0 - _August 24, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/base-contract", | ||||
|     "version": "2.0.0", | ||||
|     "version": "2.0.2", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -8,8 +8,7 @@ | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "tsc -w", | ||||
|         "build": "tsc", | ||||
|         "build": "tsc -b", | ||||
|         "clean": "shx rm -rf lib", | ||||
|         "test": "yarn run_mocha", | ||||
|         "rebuild_and_test": "run-s clean build test", | ||||
| @@ -29,7 +28,7 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "chai": "^4.0.1", | ||||
|         "copyfiles": "^2.0.0", | ||||
| @@ -41,10 +40,10 @@ | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/web3-wrapper": "^2.0.0", | ||||
|         "ethereum-types": "^1.0.5", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "@0xproject/web3-wrapper": "^2.0.2", | ||||
|         "ethereum-types": "^1.0.6", | ||||
|         "ethers": "3.0.22", | ||||
|         "lodash": "^4.17.5" | ||||
|     }, | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "." | ||||
|     }, | ||||
|     "include": ["src/**/*", "test/**/*"] | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,23 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "2.0.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Change `OrderConfigRequest` to use BigNumber instead of string for relevant fields.", | ||||
|                 "pr": 1058 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1536142250 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.0.0-rc.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1535377027 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.0.0-rc.1", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v2.0.0 - _September 5, 2018_ | ||||
|  | ||||
|     * Change `OrderConfigRequest` to use BigNumber instead of string for relevant fields. (#1058) | ||||
|  | ||||
| ## v2.0.0-rc.2 - _August 27, 2018_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.0.0-rc.1 - _August 24, 2018_ | ||||
|  | ||||
|     * Updated for SRA v2 (#974) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/connect", | ||||
|     "version": "2.0.0-rc.1", | ||||
|     "version": "2.0.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -15,8 +15,7 @@ | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "tsc -w", | ||||
|         "build": "tsc", | ||||
|         "build": "tsc -b", | ||||
|         "clean": "shx rm -rf lib test_temp generated_docs", | ||||
|         "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", | ||||
|         "lint": "tslint --project .", | ||||
| @@ -26,7 +25,7 @@ | ||||
|         "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", | ||||
|         "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", | ||||
|         "test:circleci": "yarn test:coverage", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|     }, | ||||
|     "config": { | ||||
|         "postpublish": { | ||||
| @@ -44,11 +43,12 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md", | ||||
|     "dependencies": { | ||||
|         "@0xproject/assert": "^1.0.6", | ||||
|         "@0xproject/json-schemas": "^1.0.1-rc.5", | ||||
|         "@0xproject/types": "^1.0.1-rc.5", | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/assert": "^1.0.8", | ||||
|         "@0xproject/json-schemas": "^1.0.1", | ||||
|         "@0xproject/order-utils": "^1.0.1", | ||||
|         "@0xproject/types": "^1.0.1", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "lodash": "^4.17.5", | ||||
|         "query-string": "^5.0.1", | ||||
|         "sinon": "^4.0.0", | ||||
| @@ -56,7 +56,7 @@ | ||||
|         "websocket": "^1.0.25" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/fetch-mock": "^6.0.3", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^2.2.42", | ||||
|   | ||||
| @@ -151,7 +151,7 @@ export class HttpClient implements Client { | ||||
|             params: requestOpts, | ||||
|             payload: request, | ||||
|         }; | ||||
|         const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts); | ||||
|         const responseJson = await this._requestAsync('/order_config', HttpRequestType.Get, httpRequestOpts); | ||||
|         const fees = relayerResponseJsonParsers.parseOrderConfigResponseJson(responseJson); | ||||
|         return fees; | ||||
|     } | ||||
|   | ||||
| @@ -126,12 +126,12 @@ export interface PaginatedCollection<T> { | ||||
| export interface OrderConfigRequest { | ||||
|     makerAddress: string; | ||||
|     takerAddress: string; | ||||
|     makerAssetAmount: string; | ||||
|     takerAssetAmount: string; | ||||
|     makerAssetAmount: BigNumber; | ||||
|     takerAssetAmount: BigNumber; | ||||
|     makerAssetData: string; | ||||
|     takerAssetData: string; | ||||
|     exchangeAddress: string; | ||||
|     expirationTimeSeconds: string; | ||||
|     expirationTimeSeconds: BigNumber; | ||||
| } | ||||
|  | ||||
| export interface OrderConfigResponse { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { assert } from '@0xproject/assert'; | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { orderParsingUtils } from '@0xproject/order-utils'; | ||||
|  | ||||
| import { | ||||
|     APIOrder, | ||||
| @@ -19,7 +20,7 @@ export const relayerResponseJsonParsers = { | ||||
|     }, | ||||
|     parseAssetPairsItemsJson(json: any): AssetPairsItem[] { | ||||
|         return json.map((assetDataPair: any) => { | ||||
|             return typeConverters.convertStringsFieldsToBigNumbers(assetDataPair, [ | ||||
|             return orderParsingUtils.convertStringsFieldsToBigNumbers(assetDataPair, [ | ||||
|                 'assetDataA.minAmount', | ||||
|                 'assetDataA.maxAmount', | ||||
|                 'assetDataB.minAmount', | ||||
| @@ -44,6 +45,6 @@ export const relayerResponseJsonParsers = { | ||||
|     }, | ||||
|     parseOrderConfigResponseJson(json: any): OrderConfigResponse { | ||||
|         assert.doesConformToSchema('orderConfigResponse', json, schemas.relayerApiOrderConfigResponseSchema); | ||||
|         return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']); | ||||
|         return orderParsingUtils.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']); | ||||
|     }, | ||||
| }; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { orderParsingUtils } from '@0xproject/order-utils'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { APIOrder } from '../types'; | ||||
| @@ -21,28 +21,6 @@ export const typeConverters = { | ||||
|         }; | ||||
|     }, | ||||
|     convertAPIOrderStringFieldsToBigNumber(apiOrder: any): APIOrder { | ||||
|         return { ...apiOrder, order: typeConverters.convertOrderStringFieldsToBigNumber(apiOrder.order) }; | ||||
|     }, | ||||
|     convertOrderStringFieldsToBigNumber(order: any): any { | ||||
|         return typeConverters.convertStringsFieldsToBigNumbers(order, [ | ||||
|             'makerAssetAmount', | ||||
|             'takerAssetAmount', | ||||
|             'makerFee', | ||||
|             'takerFee', | ||||
|             'expirationTimeSeconds', | ||||
|             'salt', | ||||
|         ]); | ||||
|     }, | ||||
|     convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any { | ||||
|         const result = _.assign({}, obj); | ||||
|         _.each(fields, field => { | ||||
|             _.update(result, field, (value: string) => { | ||||
|                 if (_.isUndefined(value)) { | ||||
|                     throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`); | ||||
|                 } | ||||
|                 return new BigNumber(value); | ||||
|             }); | ||||
|         }); | ||||
|         return result; | ||||
|         return { ...apiOrder, order: orderParsingUtils.convertOrderStringFieldsToBigNumber(apiOrder.order) }; | ||||
|     }, | ||||
| }; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as chaiAsPromised from 'chai-as-promised'; | ||||
| import * as dirtyChai from 'dirty-chai'; | ||||
| @@ -138,21 +139,21 @@ describe('HttpClient', () => { | ||||
|         const request = { | ||||
|             makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b', | ||||
|             takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', | ||||
|             makerAssetAmount: '10000000000000000', | ||||
|             takerAssetAmount: '20000000000000000', | ||||
|             expirationTimeSeconds: '1532560590', | ||||
|             makerAssetAmount: new BigNumber('10000000000000000'), | ||||
|             takerAssetAmount: new BigNumber('20000000000000000'), | ||||
|             expirationTimeSeconds: new BigNumber('1532560590'), | ||||
|             makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d', | ||||
|             takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990', | ||||
|             exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093', | ||||
|         }; | ||||
|         const url = `${relayUrl}/order_config`; | ||||
|         it('gets order config', async () => { | ||||
|             fetchMock.post(url, orderConfigResponseJSON); | ||||
|             fetchMock.get(url, orderConfigResponseJSON); | ||||
|             const fees = await relayerClient.getOrderConfigAsync(request); | ||||
|             expect(fees).to.be.deep.equal(orderConfigResponse); | ||||
|         }); | ||||
|         it('does not mutate input', async () => { | ||||
|             fetchMock.post(url, orderConfigResponseJSON); | ||||
|             fetchMock.get(url, orderConfigResponseJSON); | ||||
|             const makerAssetAmountBefore = request.makerAssetAmount; | ||||
|             const takerAssetAmountBefore = request.takerAssetAmount; | ||||
|             const expirationTimeSecondsBefore = request.expirationTimeSeconds; | ||||
| @@ -162,7 +163,7 @@ describe('HttpClient', () => { | ||||
|             expect(expirationTimeSecondsBefore).to.be.deep.equal(request.expirationTimeSeconds); | ||||
|         }); | ||||
|         it('throws an error for invalid JSON response', async () => { | ||||
|             fetchMock.post(url, { test: 'dummy' }); | ||||
|             fetchMock.get(url, { test: 'dummy' }); | ||||
|             expect(relayerClient.getOrderConfigAsync(request)).to.be.rejected(); | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "." | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
|   | ||||
							
								
								
									
										7
									
								
								packages/connect/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/connect/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|     "extends": "../../typedoc-tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
| @@ -1,4 +1,46 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "1.0.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add ZRX & WETH mainnet contract addresses into the included artifacts" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1537265493 | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add `OrderValidatorWrapper`" | ||||
|             }, | ||||
|             { | ||||
|                 "note": | ||||
|                     "Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK`", | ||||
|                 "pr": 1044 | ||||
|             }, | ||||
|             { | ||||
|                 "note": | ||||
|                     "Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations", | ||||
|                 "pr": 1054 | ||||
|             }, | ||||
|             { | ||||
|                 "note": | ||||
|                     "Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper", | ||||
|                 "pr": 1054 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1536142250 | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1-rc.5", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Fix missing `BlockParamLiteral` type import issue" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1535377027 | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.0.1-rc.4", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,6 +5,21 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.0.2 - _September 18, 2018_ | ||||
|  | ||||
|     * Add ZRX & WETH mainnet contract addresses into the included artifacts | ||||
|  | ||||
| ## v1.0.1 - _September 5, 2018_ | ||||
|  | ||||
|     * Add `OrderValidatorWrapper` | ||||
|     * Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK` (#1044) | ||||
|     * Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations (#1054) | ||||
|     * Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper (#1054) | ||||
|  | ||||
| ## v1.0.1-rc.5 - _August 27, 2018_ | ||||
|  | ||||
|     * Fix missing `BlockParamLiteral` type import issue | ||||
|  | ||||
| ## v1.0.1-rc.4 - _August 24, 2018_ | ||||
|  | ||||
|     * Export missing types: `TransactionEncoder`, `ContractAbi`, `JSONRPCRequestPayload`, `JSONRPCResponsePayload`, `JSONRPCErrorCallback`, `AbiDefinition`, `FunctionAbi`, `EventAbi`, `EventParameter`, `DecodedLogArgs`, `MethodAbi`, `ConstructorAbi`, `FallbackAbi`, `DataItem`, `ConstructorStateMutability`, `StateMutability` & `ExchangeSignatureValidatorApprovalEventArgs` (#924) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/contract-wrappers", | ||||
|     "version": "1.0.1-rc.4", | ||||
|     "version": "1.0.2", | ||||
|     "description": "Smart TS wrappers for 0x smart contracts", | ||||
|     "keywords": [ | ||||
|         "0xproject", | ||||
| @@ -11,26 +11,23 @@ | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "yarn pre_build && tsc -w", | ||||
|         "build": "yarn pre_build && tsc", | ||||
|         "pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts", | ||||
|         "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", | ||||
|         "build": "yarn pre_build && tsc -b", | ||||
|         "pre_build": "run-s update_artifacts generate_contract_wrappers copy_artifacts", | ||||
|         "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder|OrderValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", | ||||
|         "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*", | ||||
|         "test:circleci": "run-s test:coverage", | ||||
|         "test": "yarn run_mocha", | ||||
|         "rebuild_and_test": "run-s build test", | ||||
|         "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", | ||||
|         "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", | ||||
|         "update_artifacts_v2_beta": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json src/artifacts; done;", | ||||
|         "update_artifacts_v2": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;", | ||||
|         "update_artifacts": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;", | ||||
|         "copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts", | ||||
|         "clean": "shx rm -rf _bundles lib test_temp test/artifacts src/contract_wrappers/generated src/artifacts generated_docs", | ||||
|         "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|     }, | ||||
|     "config": { | ||||
|         "contracts_v2_beta": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator", | ||||
|         "contracts_v2": "DummyERC20Token DummyERC721Token", | ||||
|         "contracts_v2": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator DummyERC20Token DummyERC721Token", | ||||
|         "postpublish": { | ||||
|             "assets": [] | ||||
|         } | ||||
| @@ -44,16 +41,17 @@ | ||||
|         "node": ">=6.0.0" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/abi-gen": "^1.0.6", | ||||
|         "@0xproject/dev-utils": "^1.0.5", | ||||
|         "@0xproject/migrations": "^1.0.5", | ||||
|         "@0xproject/subproviders": "^2.0.0", | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/abi-gen": "^1.0.8", | ||||
|         "@0xproject/dev-utils": "^1.0.7", | ||||
|         "@0xproject/migrations": "^1.0.8", | ||||
|         "@0xproject/subproviders": "^2.0.2", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^2.2.42", | ||||
|         "@types/node": "^8.0.53", | ||||
|         "@types/sinon": "^2.2.2", | ||||
|         "@types/uuid": "^3.4.2", | ||||
|         "@types/web3-provider-engine": "^14.0.0", | ||||
|         "awesome-typescript-loader": "^3.1.3", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
| @@ -74,16 +72,16 @@ | ||||
|         "web3-provider-engine": "14.0.6" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/assert": "^1.0.6", | ||||
|         "@0xproject/base-contract": "^2.0.0", | ||||
|         "@0xproject/fill-scenarios": "^1.0.1-rc.4", | ||||
|         "@0xproject/json-schemas": "^1.0.1-rc.5", | ||||
|         "@0xproject/order-utils": "^1.0.1-rc.4", | ||||
|         "@0xproject/types": "^1.0.1-rc.5", | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/web3-wrapper": "^2.0.0", | ||||
|         "ethereum-types": "^1.0.5", | ||||
|         "@0xproject/assert": "^1.0.8", | ||||
|         "@0xproject/base-contract": "^2.0.2", | ||||
|         "@0xproject/fill-scenarios": "^1.0.1", | ||||
|         "@0xproject/json-schemas": "^1.0.1", | ||||
|         "@0xproject/order-utils": "^1.0.1", | ||||
|         "@0xproject/types": "^1.0.1", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "@0xproject/web3-wrapper": "^2.0.2", | ||||
|         "ethereum-types": "^1.0.6", | ||||
|         "ethereumjs-blockstream": "5.0.0", | ||||
|         "ethereumjs-util": "^5.1.1", | ||||
|         "ethers": "3.0.22", | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import * as ERC721Proxy from './artifacts/ERC721Proxy.json'; | ||||
| import * as ERC721Token from './artifacts/ERC721Token.json'; | ||||
| import * as Exchange from './artifacts/Exchange.json'; | ||||
| import * as Forwarder from './artifacts/Forwarder.json'; | ||||
| import * as OrderValidator from './artifacts/OrderValidator.json'; | ||||
| import * as EtherToken from './artifacts/WETH9.json'; | ||||
| import * as ZRXToken from './artifacts/ZRXToken.json'; | ||||
|  | ||||
| @@ -22,4 +23,5 @@ export const artifacts = { | ||||
|     ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, | ||||
|     ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, | ||||
|     Forwarder: (Forwarder as any) as ContractArtifact, | ||||
|     OrderValidator: (OrderValidator as any) as ContractArtifact, | ||||
| }; | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper'; | ||||
| import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; | ||||
| import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; | ||||
| import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; | ||||
| import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; | ||||
| import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; | ||||
| import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema'; | ||||
| import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema'; | ||||
| @@ -52,6 +53,10 @@ export class ContractWrappers { | ||||
|      * An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract. | ||||
|      */ | ||||
|     public forwarder: ForwarderWrapper; | ||||
|     /** | ||||
|      * An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract. | ||||
|      */ | ||||
|     public orderValidator: OrderValidatorWrapper; | ||||
|  | ||||
|     private _web3Wrapper: Web3Wrapper; | ||||
|     /** | ||||
| @@ -106,6 +111,8 @@ export class ContractWrappers { | ||||
|         this.exchange = new ExchangeWrapper( | ||||
|             this._web3Wrapper, | ||||
|             config.networkId, | ||||
|             this.erc20Token, | ||||
|             this.erc721Token, | ||||
|             config.exchangeContractAddress, | ||||
|             config.zrxContractAddress, | ||||
|             blockPollingIntervalMs, | ||||
| @@ -116,6 +123,7 @@ export class ContractWrappers { | ||||
|             config.forwarderContractAddress, | ||||
|             config.zrxContractAddress, | ||||
|         ); | ||||
|         this.orderValidator = new OrderValidatorWrapper(this._web3Wrapper, config.networkId); | ||||
|     } | ||||
|     /** | ||||
|      * Sets a new web3 provider for 0x.js. Updating the provider will stop all | ||||
|   | ||||
| @@ -1,7 +1,14 @@ | ||||
| import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import { ContractArtifact } from 'ethereum-types'; | ||||
| import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types'; | ||||
| import { | ||||
|     BlockParamLiteral, | ||||
|     ContractAbi, | ||||
|     ContractArtifact, | ||||
|     FilterObject, | ||||
|     LogEntry, | ||||
|     LogWithDecodedArgs, | ||||
|     RawLog, | ||||
| } from 'ethereum-types'; | ||||
| import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| @@ -138,9 +145,12 @@ export abstract class ContractWrapper { | ||||
|     } | ||||
|     protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string { | ||||
|         if (_.isUndefined(addressIfExists)) { | ||||
|             if (_.isUndefined(artifact.networks[this._networkId])) { | ||||
|                 throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork); | ||||
|             } | ||||
|             const contractAddress = artifact.networks[this._networkId].address; | ||||
|             if (_.isUndefined(contractAddress)) { | ||||
|                 throw new Error(ContractWrappersError.ExchangeContractDoesNotExist); | ||||
|                 throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]); | ||||
|             } | ||||
|             return contractAddress; | ||||
|         } else { | ||||
|   | ||||
| @@ -1,12 +1,19 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { assetDataUtils } from '@0xproject/order-utils'; | ||||
| import { | ||||
|     assetDataUtils, | ||||
|     BalanceAndProxyAllowanceLazyStore, | ||||
|     ExchangeTransferSimulator, | ||||
|     OrderValidationUtils, | ||||
| } from '@0xproject/order-utils'; | ||||
| import { AssetProxyId, Order, SignedOrder } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; | ||||
| import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from '../artifacts'; | ||||
| import { AssetBalanceAndProxyAllowanceFetcher } from '../fetchers/asset_balance_and_proxy_allowance_fetcher'; | ||||
| import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_fetcher'; | ||||
| import { methodOptsSchema } from '../schemas/method_opts_schema'; | ||||
| import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; | ||||
| import { txOptsSchema } from '../schemas/tx_opts_schema'; | ||||
| @@ -17,13 +24,17 @@ import { | ||||
|     IndexedFilterValues, | ||||
|     MethodOpts, | ||||
|     OrderInfo, | ||||
|     OrderStatus, | ||||
|     OrderTransactionOpts, | ||||
|     ValidateOrderFillableOpts, | ||||
| } from '../types'; | ||||
| import { assert } from '../utils/assert'; | ||||
| import { decorators } from '../utils/decorators'; | ||||
| import { TransactionEncoder } from '../utils/transaction_encoder'; | ||||
|  | ||||
| import { ContractWrapper } from './contract_wrapper'; | ||||
| import { ERC20TokenWrapper } from './erc20_token_wrapper'; | ||||
| import { ERC721TokenWrapper } from './erc721_token_wrapper'; | ||||
| import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated/exchange'; | ||||
|  | ||||
| /** | ||||
| @@ -33,6 +44,8 @@ import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated | ||||
| export class ExchangeWrapper extends ContractWrapper { | ||||
|     public abi: ContractAbi = artifacts.Exchange.compilerOutput.abi; | ||||
|     private _exchangeContractIfExists?: ExchangeContract; | ||||
|     private _erc721TokenWrapper: ERC721TokenWrapper; | ||||
|     private _erc20TokenWrapper: ERC20TokenWrapper; | ||||
|     private _contractAddressIfExists?: string; | ||||
|     private _zrxContractAddressIfExists?: string; | ||||
|     /** | ||||
| @@ -48,11 +61,15 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|     constructor( | ||||
|         web3Wrapper: Web3Wrapper, | ||||
|         networkId: number, | ||||
|         erc20TokenWrapper: ERC20TokenWrapper, | ||||
|         erc721TokenWrapper: ERC721TokenWrapper, | ||||
|         contractAddressIfExists?: string, | ||||
|         zrxContractAddressIfExists?: string, | ||||
|         blockPollingIntervalMs?: number, | ||||
|     ) { | ||||
|         super(web3Wrapper, networkId, blockPollingIntervalMs); | ||||
|         this._erc20TokenWrapper = erc20TokenWrapper; | ||||
|         this._erc721TokenWrapper = erc721TokenWrapper; | ||||
|         this._contractAddressIfExists = contractAddressIfExists; | ||||
|         this._zrxContractAddressIfExists = zrxContractAddressIfExists; | ||||
|     } | ||||
| @@ -1084,6 +1101,64 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         ); | ||||
|         return logs; | ||||
|     } | ||||
|     /** | ||||
|      * Validate if the supplied order is fillable, and throw if it isn't | ||||
|      * @param signedOrder SignedOrder of interest | ||||
|      * @param opts ValidateOrderFillableOpts options (e.g expectedFillTakerTokenAmount. | ||||
|      * If it isn't supplied, we check if the order is fillable for a non-zero amount) | ||||
|      */ | ||||
|     public async validateOrderFillableOrThrowAsync( | ||||
|         signedOrder: SignedOrder, | ||||
|         opts: ValidateOrderFillableOpts = {}, | ||||
|     ): Promise<void> { | ||||
|         const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher( | ||||
|             this._erc20TokenWrapper, | ||||
|             this._erc721TokenWrapper, | ||||
|             BlockParamLiteral.Latest, | ||||
|         ); | ||||
|         const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher); | ||||
|         const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore); | ||||
|  | ||||
|         const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount; | ||||
|         const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest); | ||||
|         const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher); | ||||
|         await orderValidationUtils.validateOrderFillableOrThrowAsync( | ||||
|             exchangeTradeSimulator, | ||||
|             signedOrder, | ||||
|             this.getZRXAssetData(), | ||||
|             expectedFillTakerTokenAmountIfExists, | ||||
|         ); | ||||
|     } | ||||
|     /** | ||||
|      * Validate a call to FillOrder and throw if it wouldn't succeed | ||||
|      * @param signedOrder SignedOrder of interest | ||||
|      * @param fillTakerAssetAmount Amount we'd like to fill the order for | ||||
|      * @param takerAddress The taker of the order | ||||
|      */ | ||||
|     public async validateFillOrderThrowIfInvalidAsync( | ||||
|         signedOrder: SignedOrder, | ||||
|         fillTakerAssetAmount: BigNumber, | ||||
|         takerAddress: string, | ||||
|     ): Promise<void> { | ||||
|         const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher( | ||||
|             this._erc20TokenWrapper, | ||||
|             this._erc721TokenWrapper, | ||||
|             BlockParamLiteral.Latest, | ||||
|         ); | ||||
|         const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher); | ||||
|         const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore); | ||||
|  | ||||
|         const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest); | ||||
|         const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher); | ||||
|         await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( | ||||
|             exchangeTradeSimulator, | ||||
|             this._web3Wrapper.getProvider(), | ||||
|             signedOrder, | ||||
|             fillTakerAssetAmount, | ||||
|             takerAddress, | ||||
|             this.getZRXAssetData(), | ||||
|         ); | ||||
|     } | ||||
|     /** | ||||
|      * Retrieves the Ethereum address of the Exchange contract deployed on the network | ||||
|      * that the user-passed web3 provider is connected to. | ||||
|   | ||||
| @@ -0,0 +1,187 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { SignedOrder } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import { ContractAbi } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from '../artifacts'; | ||||
| import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types'; | ||||
| import { assert } from '../utils/assert'; | ||||
|  | ||||
| import { ContractWrapper } from './contract_wrapper'; | ||||
| import { OrderValidatorContract } from './generated/order_validator'; | ||||
|  | ||||
| /** | ||||
|  * This class includes the functionality related to interacting with the OrderValidator contract. | ||||
|  */ | ||||
| export class OrderValidatorWrapper extends ContractWrapper { | ||||
|     public abi: ContractAbi = artifacts.OrderValidator.compilerOutput.abi; | ||||
|     private _orderValidatorContractIfExists?: OrderValidatorContract; | ||||
|     /** | ||||
|      * Instantiate OrderValidatorWrapper | ||||
|      * @param web3Wrapper Web3Wrapper instance to use | ||||
|      * @param networkId Desired networkId | ||||
|      */ | ||||
|     constructor(web3Wrapper: Web3Wrapper, networkId: number) { | ||||
|         super(web3Wrapper, networkId); | ||||
|     } | ||||
|     /** | ||||
|      * Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address | ||||
|      * @param   order           An object conforming to SignedOrder | ||||
|      * @param   takerAddress    An ethereum address | ||||
|      * @return  OrderAndTraderInfo | ||||
|      */ | ||||
|     public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> { | ||||
|         assert.doesConformToSchema('order', order, schemas.signedOrderSchema); | ||||
|         assert.isETHAddressHex('takerAddress', takerAddress); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync( | ||||
|             order, | ||||
|             takerAddress, | ||||
|         ); | ||||
|         const result = { | ||||
|             orderInfo: orderAndTraderInfo[0], | ||||
|             traderInfo: orderAndTraderInfo[1], | ||||
|         }; | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get an array of objects conforming to OrderAndTraderInfo containing on-chain information of the provided orders and addresses | ||||
|      * @param   orders          An array of objects conforming to SignedOrder | ||||
|      * @param   takerAddresses  An array of ethereum addresses | ||||
|      * @return  array of OrderAndTraderInfo | ||||
|      */ | ||||
|     public async getOrdersAndTradersInfoAsync( | ||||
|         orders: SignedOrder[], | ||||
|         takerAddresses: string[], | ||||
|     ): Promise<OrderAndTraderInfo[]> { | ||||
|         assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); | ||||
|         _.forEach(takerAddresses, (takerAddress, index) => | ||||
|             assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), | ||||
|         ); | ||||
|         assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync( | ||||
|             orders, | ||||
|             takerAddresses, | ||||
|         ); | ||||
|         const orderInfos = ordersAndTradersInfo[0]; | ||||
|         const traderInfos = ordersAndTradersInfo[1]; | ||||
|         const result = _.map(orderInfos, (orderInfo, index) => { | ||||
|             const traderInfo = traderInfos[index]; | ||||
|             return { | ||||
|                 orderInfo, | ||||
|                 traderInfo, | ||||
|             }; | ||||
|         }); | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get an object conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order | ||||
|      * @param   order           An object conforming to SignedOrder | ||||
|      * @param   takerAddress    An ethereum address | ||||
|      * @return  TraderInfo | ||||
|      */ | ||||
|     public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> { | ||||
|         assert.doesConformToSchema('order', order, schemas.signedOrderSchema); | ||||
|         assert.isETHAddressHex('takerAddress', takerAddress); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress); | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get an array of objects conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order | ||||
|      * @param   orders          An array of objects conforming to SignedOrder | ||||
|      * @param   takerAddresses  An array of ethereum addresses | ||||
|      * @return  array of TraderInfo | ||||
|      */ | ||||
|     public async getTradersInfoAsync(orders: SignedOrder[], takerAddresses: string[]): Promise<TraderInfo[]> { | ||||
|         assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); | ||||
|         _.forEach(takerAddresses, (takerAddress, index) => | ||||
|             assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), | ||||
|         ); | ||||
|         assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses); | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get an object conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and assetData | ||||
|      * @param   address     An ethereum address | ||||
|      * @param   assetData   An encoded string that can be decoded by a specified proxy contract | ||||
|      * @return  BalanceAndAllowance | ||||
|      */ | ||||
|     public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> { | ||||
|         assert.isETHAddressHex('address', address); | ||||
|         assert.isHexString('assetData', assetData); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync( | ||||
|             address, | ||||
|             assetData, | ||||
|         ); | ||||
|         const result = { | ||||
|             balance: balanceAndAllowance[0], | ||||
|             allowance: balanceAndAllowance[1], | ||||
|         }; | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get an array of objects conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and array of assetDatas | ||||
|      * @param   address     An ethereum address | ||||
|      * @param   assetDatas  An array of encoded strings that can be decoded by a specified proxy contract | ||||
|      * @return  BalanceAndAllowance | ||||
|      */ | ||||
|     public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> { | ||||
|         assert.isETHAddressHex('address', address); | ||||
|         _.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData)); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync( | ||||
|             address, | ||||
|             assetDatas, | ||||
|         ); | ||||
|         const balances = balancesAndAllowances[0]; | ||||
|         const allowances = balancesAndAllowances[1]; | ||||
|         const result = _.map(balances, (balance, index) => { | ||||
|             const allowance = allowances[index]; | ||||
|             return { | ||||
|                 balance, | ||||
|                 allowance, | ||||
|             }; | ||||
|         }); | ||||
|         return result; | ||||
|     } | ||||
|     /** | ||||
|      * Get owner address of tokenId by calling `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token. | ||||
|      * @param   tokenAddress    An ethereum address | ||||
|      * @param   tokenId         An ERC721 tokenId | ||||
|      * @return  Owner of tokenId or null address if unowned | ||||
|      */ | ||||
|     public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> { | ||||
|         assert.isETHAddressHex('tokenAddress', tokenAddress); | ||||
|         assert.isBigNumber('tokenId', tokenId); | ||||
|         const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); | ||||
|         const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId); | ||||
|         return result; | ||||
|     } | ||||
|     // HACK: We don't want this method to be visible to the other units within that package but not to the end user. | ||||
|     // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. | ||||
|     // tslint:disable-next-line:no-unused-variable | ||||
|     private _invalidateContractInstance(): void { | ||||
|         delete this._orderValidatorContractIfExists; | ||||
|     } | ||||
|     private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> { | ||||
|         if (!_.isUndefined(this._orderValidatorContractIfExists)) { | ||||
|             return this._orderValidatorContractIfExists; | ||||
|         } | ||||
|         const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(artifacts.OrderValidator); | ||||
|         const contractInstance = new OrderValidatorContract( | ||||
|             abi, | ||||
|             address, | ||||
|             this._web3Wrapper.getProvider(), | ||||
|             this._web3Wrapper.getContractDefaults(), | ||||
|         ); | ||||
|         this._orderValidatorContractIfExists = contractInstance; | ||||
|         return this._orderValidatorContractIfExists; | ||||
|     } | ||||
| } | ||||
| @@ -1,8 +1,11 @@ | ||||
| // tslint:disable:no-unnecessary-type-assertion
 | ||||
| import { BlockParamLiteral, ERC20TokenWrapper, ERC721TokenWrapper } from '@0xproject/contract-wrappers'; | ||||
| import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0xproject/order-utils'; | ||||
| import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { BlockParamLiteral } from 'ethereum-types'; | ||||
| 
 | ||||
| import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper'; | ||||
| import { ERC721TokenWrapper } from '../contract_wrappers/erc721_token_wrapper'; | ||||
| 
 | ||||
| export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { | ||||
|     private readonly _erc20Token: ERC20TokenWrapper; | ||||
| @@ -1,7 +1,10 @@ | ||||
| // tslint:disable:no-unnecessary-type-assertion
 | ||||
| import { BlockParamLiteral, ExchangeWrapper } from '@0xproject/contract-wrappers'; | ||||
| import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { BlockParamLiteral } from 'ethereum-types'; | ||||
| 
 | ||||
| import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper'; | ||||
| import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; | ||||
| 
 | ||||
| export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher { | ||||
|     private readonly _exchange: ExchangeWrapper; | ||||
| @@ -6,6 +6,7 @@ export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; | ||||
| export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; | ||||
| export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; | ||||
| export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; | ||||
| export { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; | ||||
|  | ||||
| export { TransactionEncoder } from './utils/transaction_encoder'; | ||||
|  | ||||
| @@ -21,6 +22,10 @@ export { | ||||
|     OrderInfo, | ||||
|     EventCallback, | ||||
|     DecodedLogEvent, | ||||
|     BalanceAndAllowance, | ||||
|     OrderAndTraderInfo, | ||||
|     TraderInfo, | ||||
|     ValidateOrderFillableOpts, | ||||
| } from './types'; | ||||
|  | ||||
| export { Order, SignedOrder, AssetProxyId } from '@0xproject/types'; | ||||
| @@ -81,3 +86,8 @@ export { | ||||
|     ExchangeEventArgs, | ||||
|     ExchangeEvents, | ||||
| } from './contract_wrappers/generated/exchange'; | ||||
|  | ||||
| export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; | ||||
|  | ||||
| export { AssetBalanceAndProxyAllowanceFetcher } from './fetchers/asset_balance_and_proxy_allowance_fetcher'; | ||||
| export { OrderFilledCancelledFetcher } from './fetchers/order_filled_cancelled_fetcher'; | ||||
|   | ||||
| @@ -188,3 +188,24 @@ export enum OrderStatus { | ||||
|     FULLY_FILLED, | ||||
|     CANCELLED, | ||||
| } | ||||
|  | ||||
| export interface TraderInfo { | ||||
|     makerBalance: BigNumber; | ||||
|     makerAllowance: BigNumber; | ||||
|     takerBalance: BigNumber; | ||||
|     takerAllowance: BigNumber; | ||||
|     makerZrxBalance: BigNumber; | ||||
|     makerZrxAllowance: BigNumber; | ||||
|     takerZrxBalance: BigNumber; | ||||
|     takerZrxAllowance: BigNumber; | ||||
| } | ||||
|  | ||||
| export interface OrderAndTraderInfo { | ||||
|     orderInfo: OrderInfo; | ||||
|     traderInfo: TraderInfo; | ||||
| } | ||||
|  | ||||
| export interface BalanceAndAllowance { | ||||
|     balance: BigNumber; | ||||
|     allowance: BigNumber; | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ const contractCallErrorTransformer = (error: Error) => { | ||||
| const schemaErrorTransformer = (error: Error) => { | ||||
|     if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) { | ||||
|         const errMsg = | ||||
|             'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS'; | ||||
|             'Order taker must be of type string. If you want anyone to be able to fill an order - pass NULL_ADDRESS'; | ||||
|         return new Error(errMsg); | ||||
|     } | ||||
|     return error; | ||||
|   | ||||
| @@ -358,7 +358,7 @@ describe('ExchangeWrapper', () => { | ||||
|     describe('#getVersionAsync', () => { | ||||
|         it('should return version the hash', async () => { | ||||
|             const version = await contractWrappers.exchange.getVersionAsync(); | ||||
|             const VERSION = '2.0.1-alpha'; | ||||
|             const VERSION = '2.0.0'; | ||||
|             expect(version).to.be.equal(VERSION); | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -25,10 +25,8 @@ describe('ForwarderWrapper', () => { | ||||
|         blockPollingIntervalMs: 0, | ||||
|     }; | ||||
|     const fillableAmount = new BigNumber(5); | ||||
|     const takerTokenFillAmount = new BigNumber(5); | ||||
|     let contractWrappers: ContractWrappers; | ||||
|     let fillScenarios: FillScenarios; | ||||
|     let forwarderContractAddress: string; | ||||
|     let exchangeContractAddress: string; | ||||
|     let zrxTokenAddress: string; | ||||
|     let userAddresses: string[]; | ||||
| @@ -46,7 +44,6 @@ describe('ForwarderWrapper', () => { | ||||
|     before(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|         contractWrappers = new ContractWrappers(provider, contractWrappersConfig); | ||||
|         forwarderContractAddress = contractWrappers.forwarder.getContractAddress(); | ||||
|         exchangeContractAddress = contractWrappers.exchange.getContractAddress(); | ||||
|         userAddresses = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); | ||||
|   | ||||
							
								
								
									
										142
									
								
								packages/contract-wrappers/test/order_validator_wrapper_test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								packages/contract-wrappers/test/order_validator_wrapper_test.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; | ||||
| import { FillScenarios } from '@0xproject/fill-scenarios'; | ||||
| import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; | ||||
| import { DoneCallback, SignedOrder } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import { BlockParamLiteral } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
| import 'mocha'; | ||||
|  | ||||
| import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src'; | ||||
| import { DecodedLogEvent, OrderInfo, TraderInfo } from '../src/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { tokenUtils } from './utils/token_utils'; | ||||
| import { provider, web3Wrapper } from './utils/web3_wrapper'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); | ||||
|  | ||||
| describe('OrderValidator', () => { | ||||
|     const contractWrappersConfig = { | ||||
|         networkId: constants.TESTRPC_NETWORK_ID, | ||||
|         blockPollingIntervalMs: 0, | ||||
|     }; | ||||
|     const fillableAmount = new BigNumber(5); | ||||
|     const partialFillAmount = new BigNumber(2); | ||||
|     let contractWrappers: ContractWrappers; | ||||
|     let fillScenarios: FillScenarios; | ||||
|     let exchangeContractAddress: string; | ||||
|     let zrxTokenAddress: string; | ||||
|     let zrxTokenAssetData: string; | ||||
|     let userAddresses: string[]; | ||||
|     let coinbase: string; | ||||
|     let makerAddress: string; | ||||
|     let takerAddress: string; | ||||
|     let feeRecipient: string; | ||||
|     let anotherMakerAddress: string; | ||||
|     let makerTokenAddress: string; | ||||
|     let takerTokenAddress: string; | ||||
|     let makerAssetData: string; | ||||
|     let takerAssetData: string; | ||||
|     let signedOrder: SignedOrder; | ||||
|     let anotherSignedOrder: SignedOrder; | ||||
|     before(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|         contractWrappers = new ContractWrappers(provider, contractWrappersConfig); | ||||
|         exchangeContractAddress = contractWrappers.exchange.getContractAddress(); | ||||
|         userAddresses = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); | ||||
|         zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); | ||||
|         fillScenarios = new FillScenarios( | ||||
|             provider, | ||||
|             userAddresses, | ||||
|             zrxTokenAddress, | ||||
|             exchangeContractAddress, | ||||
|             contractWrappers.erc20Proxy.getContractAddress(), | ||||
|             contractWrappers.erc721Proxy.getContractAddress(), | ||||
|         ); | ||||
|         [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; | ||||
|         [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); | ||||
|         takerTokenAddress = tokenUtils.getWethTokenAddress(); | ||||
|         [makerAssetData, takerAssetData] = [ | ||||
|             assetDataUtils.encodeERC20AssetData(makerTokenAddress), | ||||
|             assetDataUtils.encodeERC20AssetData(takerTokenAddress), | ||||
|         ]; | ||||
|  | ||||
|         signedOrder = await fillScenarios.createFillableSignedOrderAsync( | ||||
|             makerAssetData, | ||||
|             takerAssetData, | ||||
|             makerAddress, | ||||
|             constants.NULL_ADDRESS, | ||||
|             fillableAmount, | ||||
|         ); | ||||
|         anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( | ||||
|             zrxTokenAssetData, | ||||
|             takerAssetData, | ||||
|             makerAddress, | ||||
|             constants.NULL_ADDRESS, | ||||
|             fillableAmount, | ||||
|         ); | ||||
|     }); | ||||
|     after(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('#getOrdersAndTradersInfoAsync', () => { | ||||
|         let signedOrders: SignedOrder[]; | ||||
|         let takerAddresses: string[]; | ||||
|         let ordersInfo: OrderInfo[]; | ||||
|         let tradersInfo: TraderInfo[]; | ||||
|         beforeEach(async () => { | ||||
|             signedOrders = [signedOrder, anotherSignedOrder]; | ||||
|             takerAddresses = [takerAddress, takerAddress]; | ||||
|             const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync( | ||||
|                 signedOrders, | ||||
|                 takerAddresses, | ||||
|             ); | ||||
|             ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo); | ||||
|             tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo); | ||||
|         }); | ||||
|         it('should return the same number of order infos and trader infos as input orders', async () => { | ||||
|             expect(ordersInfo.length).to.be.equal(signedOrders.length); | ||||
|             expect(tradersInfo.length).to.be.equal(takerAddresses.length); | ||||
|         }); | ||||
|         it('should return correct on-chain order info for input orders', async () => { | ||||
|             const firstOrderInfo = ordersInfo[0]; | ||||
|             const secondOrderInfo = ordersInfo[1]; | ||||
|             expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); | ||||
|             expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); | ||||
|             expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); | ||||
|             expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); | ||||
|         }); | ||||
|         it('should return correct on-chain trader info for input takers', async () => { | ||||
|             const firstTraderInfo = tradersInfo[0]; | ||||
|             const secondTraderInfo = tradersInfo[1]; | ||||
|             expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); | ||||
|             expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); | ||||
|             expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -15,4 +15,5 @@ export const constants = { | ||||
|     DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers | ||||
|     NUM_DUMMY_ERC20_TO_DEPLOY: 3, | ||||
|     NUM_DUMMY_ERC721_TO_DEPLOY: 1, | ||||
|     ZERO_AMOUNT: new BigNumber(0), | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { | ||||
|     "extends": "../../tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|         "outDir": "lib", | ||||
|         "rootDir": "." | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
|   | ||||
							
								
								
									
										7
									
								
								packages/contract-wrappers/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/contract-wrappers/typedoc-tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|     "extends": "../../typedoc-tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*"] | ||||
| } | ||||
| @@ -2,7 +2,7 @@ | ||||
| // tslint:disable:no-unused-variable | ||||
| // tslint:disable:no-unbound-method | ||||
| import { BaseContract } from '@0xproject/base-contract'; | ||||
| import { BlockParam, CallData, ContractAbi, ContractArtifact, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types'; | ||||
| import { BlockParam, BlockParamLiteral, CallData, ContractAbi, ContractArtifact, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types'; | ||||
| import { BigNumber, classUtils, logUtils } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as ethers from 'ethers'; | ||||
|   | ||||
| @@ -1,14 +1,35 @@ | ||||
| ## Contracts | ||||
|  | ||||
| Smart contracts that implement the 0x protocol. | ||||
| Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found [here](https://0xproject.com/wiki#Deployed-Addresses). | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| *   [Docs](https://0xproject.com/docs/contracts) | ||||
| *   [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture) | ||||
| *   [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions) | ||||
| *   [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses) | ||||
| *   [0x protocol message format](https://0xproject.com/wiki#Message-Format) | ||||
| ### 2.0.0 | ||||
|  | ||||
| Contracts that make up and interact with version 2.0.0 of the protocol can be found in the `src/2.0.0` directory. The contents of this directory are broken down into the following subdirectories: | ||||
|  | ||||
| *   protocol | ||||
|     *   This directory contains the contracts that make up version 2.0.0. A full specification can be found [here](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md). | ||||
| *   extensions | ||||
|     *   This directory contains contracts that interact with the 2.0.0 contracts and will be used in production, such as the [Forwarder](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract. | ||||
| *   examples | ||||
|     *   This directory contains example implementations of contracts that interact with the protocol but are _not_ intended for use in production. Examples include [filter](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#filter-contracts) contracts, a [Wallet](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#wallet) contract, and a [Validator](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#validator) contract, among others. | ||||
| *   tokens | ||||
|     *   This directory contains implementations of different tokens and token standards, including [wETH](https://weth.io/), ZRX, [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md), and [ERC721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md). | ||||
| *   multisig | ||||
|     *   This directory contains the [Gnosis MultiSigWallet](https://github.com/gnosis/MultiSigWallet) and a custom extension that adds a timelock to transactions within the MultiSigWallet. | ||||
| *   utils | ||||
|     *   This directory contains libraries and utils that are shared across all of the other directories. | ||||
| *   test | ||||
|     *   This directory contains mocks and other contracts that are used solely for testing contracts within the other directories. | ||||
|  | ||||
| ### 1.0.0 | ||||
|  | ||||
| Contracts that make up version 1.0.0 of the protocol can be found in `src/1.0.0`. These contracts are considered deprecated and will have limited support going forward. | ||||
|  | ||||
| ## 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 | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|     "artifactsDir": "../migrations/artifacts/2.0.0", | ||||
|     "artifactsDir": "../migrations/artifacts/development", | ||||
|     "contractsDir": "src/", | ||||
|     "compilerSettings": { | ||||
|         "optimizer": { | ||||
| @@ -23,6 +23,7 @@ | ||||
|         "DummyERC20Token", | ||||
|         "DummyERC721Receiver", | ||||
|         "DummyERC721Token", | ||||
|         "DummyMultipleReturnERC20Token", | ||||
|         "DummyNoReturnERC20Token", | ||||
|         "ERC20Proxy", | ||||
|         "ERC20Token", | ||||
| @@ -40,6 +41,7 @@ | ||||
|         "MultiSigWallet", | ||||
|         "MultiSigWalletWithTimeLock", | ||||
|         "OrderValidator", | ||||
|         "ReentrantERC20Token", | ||||
|         "TestAssetProxyOwner", | ||||
|         "TestAssetProxyDispatcher", | ||||
|         "TestConstants", | ||||
| @@ -47,6 +49,7 @@ | ||||
|         "TestLibs", | ||||
|         "TestExchangeInternals", | ||||
|         "TestSignatureValidator", | ||||
|         "TestStaticCallReceiver", | ||||
|         "TokenRegistry", | ||||
|         "Validator", | ||||
|         "Wallet", | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "private": true, | ||||
|     "name": "contracts", | ||||
|     "version": "2.1.41", | ||||
|     "version": "2.1.43", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -11,10 +11,9 @@ | ||||
|         "test": "test" | ||||
|     }, | ||||
|     "scripts": { | ||||
|         "watch_without_deps": "yarn pre_build && tsc -w", | ||||
|         "build": "yarn pre_build && tsc", | ||||
|         "build": "yarn pre_build && tsc -b", | ||||
|         "pre_build": "run-s compile copy_artifacts generate_contract_wrappers", | ||||
|         "copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/2.0.0/**/*' ./lib/artifacts;", | ||||
|         "copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/development/**/*' ./lib/artifacts;", | ||||
|         "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", | ||||
| @@ -33,7 +32,7 @@ | ||||
|         "lint-contracts": "solhint src/2.0.0/**/**/**/**/*.sol" | ||||
|     }, | ||||
|     "config": { | ||||
|         "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json" | ||||
|         "abis": "../migrations/artifacts/development/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json" | ||||
|     }, | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
| @@ -46,12 +45,12 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/abi-gen": "^1.0.6", | ||||
|         "@0xproject/dev-utils": "^1.0.5", | ||||
|         "@0xproject/sol-compiler": "^1.1.0", | ||||
|         "@0xproject/sol-cov": "^2.1.0", | ||||
|         "@0xproject/subproviders": "^2.0.0", | ||||
|         "@0xproject/tslint-config": "^1.0.6", | ||||
|         "@0xproject/abi-gen": "^1.0.8", | ||||
|         "@0xproject/dev-utils": "^1.0.7", | ||||
|         "@0xproject/sol-compiler": "^1.1.2", | ||||
|         "@0xproject/sol-cov": "^2.1.2", | ||||
|         "@0xproject/subproviders": "^2.0.2", | ||||
|         "@0xproject/tslint-config": "^1.0.7", | ||||
|         "@types/bn.js": "^4.11.0", | ||||
|         "@types/ethereumjs-abi": "^0.6.0", | ||||
|         "@types/lodash": "4.14.104", | ||||
| @@ -73,15 +72,15 @@ | ||||
|         "yargs": "^10.0.3" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/base-contract": "^2.0.0", | ||||
|         "@0xproject/order-utils": "^1.0.1-rc.4", | ||||
|         "@0xproject/types": "^1.0.1-rc.5", | ||||
|         "@0xproject/typescript-typings": "^1.0.5", | ||||
|         "@0xproject/utils": "^1.0.6", | ||||
|         "@0xproject/web3-wrapper": "^2.0.0", | ||||
|         "@0xproject/base-contract": "^2.0.2", | ||||
|         "@0xproject/order-utils": "^1.0.1", | ||||
|         "@0xproject/types": "^1.0.1", | ||||
|         "@0xproject/typescript-typings": "^2.0.0", | ||||
|         "@0xproject/utils": "^1.0.8", | ||||
|         "@0xproject/web3-wrapper": "^2.0.2", | ||||
|         "@types/js-combinatorics": "^0.5.29", | ||||
|         "bn.js": "^4.11.8", | ||||
|         "ethereum-types": "^1.0.5", | ||||
|         "ethereum-types": "^1.0.6", | ||||
|         "ethereumjs-abi": "0.6.5", | ||||
|         "ethereumjs-util": "^5.1.1", | ||||
|         "ethers": "3.0.22", | ||||
|   | ||||
| @@ -37,7 +37,7 @@ contract Whitelist is | ||||
|     bytes internal TX_ORIGIN_SIGNATURE; | ||||
|     // solhint-enable var-name-mixedcase | ||||
|  | ||||
|     byte constant internal VALIDATOR_SIGNATURE_BYTE = "\x06"; | ||||
|     byte constant internal VALIDATOR_SIGNATURE_BYTE = "\x05"; | ||||
|  | ||||
|     constructor (address _exchange) | ||||
|         public | ||||
|   | ||||
| @@ -34,7 +34,6 @@ contract Forwarder is | ||||
|     MixinExchangeWrapper, | ||||
|     MixinForwarderCore | ||||
| { | ||||
|  | ||||
|     constructor ( | ||||
|         address _exchange, | ||||
|         bytes memory _zrxAssetData, | ||||
|   | ||||
| @@ -31,7 +31,6 @@ contract MixinAssets is | ||||
|     LibConstants, | ||||
|     MAssets | ||||
| { | ||||
|  | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)")); | ||||
|   | ||||
| @@ -34,7 +34,6 @@ contract MixinExchangeWrapper is | ||||
|     LibConstants, | ||||
|     MExchangeWrapper | ||||
| { | ||||
|  | ||||
|     /// @dev Fills the input order. | ||||
|     ///      Returns false if the transaction would otherwise revert. | ||||
|     /// @param order Order struct containing order specifications. | ||||
| @@ -61,7 +60,7 @@ contract MixinExchangeWrapper is | ||||
|         // Call `fillOrder` and handle any exceptions gracefully | ||||
|         assembly { | ||||
|             let success := call( | ||||
|                 gas,                                // forward all gas, TODO: look into gas consumption of assert/throw | ||||
|                 gas,                                // forward all gas | ||||
|                 exchange,                           // call address of Exchange contract | ||||
|                 0,                                  // transfer 0 wei | ||||
|                 add(fillOrderCalldata, 32),         // pointer to start of input (skip array length in first 32 bytes) | ||||
| @@ -69,20 +68,14 @@ contract MixinExchangeWrapper is | ||||
|                 fillOrderCalldata,                  // write output over input | ||||
|                 128                                 // output size is 128 bytes | ||||
|             ) | ||||
|             switch success | ||||
|             case 0 { | ||||
|                 mstore(fillResults, 0) | ||||
|                 mstore(add(fillResults, 32), 0) | ||||
|                 mstore(add(fillResults, 64), 0) | ||||
|                 mstore(add(fillResults, 96), 0) | ||||
|             } | ||||
|             case 1 { | ||||
|             if success { | ||||
|                 mstore(fillResults, mload(fillOrderCalldata)) | ||||
|                 mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32))) | ||||
|                 mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64))) | ||||
|                 mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96))) | ||||
|             } | ||||
|         } | ||||
|         // fillResults values will be 0 by default if call was unsuccessful | ||||
|         return fillResults; | ||||
|     } | ||||
|  | ||||
| @@ -163,7 +156,7 @@ contract MixinExchangeWrapper is | ||||
|  | ||||
|             // Convert the remaining amount of makerAsset to buy into remaining amount | ||||
|             // of takerAsset to sell, assuming entire amount can be sold in the current order | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmount( | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmountFloor( | ||||
|                 orders[i].takerAssetAmount, | ||||
|                 orders[i].makerAssetAmount, | ||||
|                 remainingMakerAssetFillAmount | ||||
| @@ -231,7 +224,7 @@ contract MixinExchangeWrapper is | ||||
|  | ||||
|             // Convert the remaining amount of ZRX to buy into remaining amount | ||||
|             // of WETH to sell, assuming entire amount can be sold in the current order. | ||||
|             uint256 remainingWethSellAmount = getPartialAmount( | ||||
|             uint256 remainingWethSellAmount = getPartialAmountFloor( | ||||
|                 orders[i].takerAssetAmount, | ||||
|                 safeSub(orders[i].makerAssetAmount, orders[i].takerFee),  // our exchange rate after fees  | ||||
|                 remainingZrxBuyAmount | ||||
|   | ||||
| @@ -39,7 +39,6 @@ contract MixinForwarderCore is | ||||
|     MExchangeWrapper, | ||||
|     IForwarderCore | ||||
| { | ||||
|  | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     /// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf. | ||||
| @@ -47,10 +46,12 @@ contract MixinForwarderCore is | ||||
|         public | ||||
|     { | ||||
|         address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID); | ||||
|         if (proxyAddress != address(0)) { | ||||
|             ETHER_TOKEN.approve(proxyAddress, MAX_UINT); | ||||
|             ZRX_TOKEN.approve(proxyAddress, MAX_UINT); | ||||
|         } | ||||
|         require( | ||||
|             proxyAddress != address(0), | ||||
|             "UNREGISTERED_ASSET_PROXY" | ||||
|         ); | ||||
|         ETHER_TOKEN.approve(proxyAddress, MAX_UINT); | ||||
|         ZRX_TOKEN.approve(proxyAddress, MAX_UINT); | ||||
|     } | ||||
|  | ||||
|     /// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value. | ||||
| @@ -87,7 +88,7 @@ contract MixinForwarderCore is | ||||
|         uint256 makerAssetAmountPurchased; | ||||
|         if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) { | ||||
|             // Calculate amount of WETH that won't be spent on ETH fees. | ||||
|             wethSellAmount = getPartialAmount( | ||||
|             wethSellAmount = getPartialAmountFloor( | ||||
|                 PERCENTAGE_DENOMINATOR, | ||||
|                 safeAdd(PERCENTAGE_DENOMINATOR, feePercentage), | ||||
|                 msg.value | ||||
| @@ -103,7 +104,7 @@ contract MixinForwarderCore is | ||||
|             makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid); | ||||
|         } else { | ||||
|             // 5% of WETH is reserved for filling feeOrders and paying feeRecipient. | ||||
|             wethSellAmount = getPartialAmount( | ||||
|             wethSellAmount = getPartialAmountFloor( | ||||
|                 MAX_WETH_FILL_PERCENTAGE, | ||||
|                 PERCENTAGE_DENOMINATOR, | ||||
|                 msg.value | ||||
|   | ||||
| @@ -28,7 +28,6 @@ contract MixinWeth is | ||||
|     LibConstants, | ||||
|     MWeth | ||||
| { | ||||
|  | ||||
|     /// @dev Default payabale function, this allows us to withdraw WETH | ||||
|     function () | ||||
|         public | ||||
| @@ -82,7 +81,7 @@ contract MixinWeth is | ||||
|         uint256 wethRemaining = safeSub(msg.value, wethSold); | ||||
|  | ||||
|         // Calculate ETH fee to pay to feeRecipient. | ||||
|         uint256 ethFee = getPartialAmount( | ||||
|         uint256 ethFee = getPartialAmountFloor( | ||||
|             feePercentage, | ||||
|             PERCENTAGE_DENOMINATOR, | ||||
|             wethSoldExcludingFeeOrders | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../interfaces/IAssets.sol"; | ||||
| contract MAssets is | ||||
|     IAssets | ||||
| { | ||||
|  | ||||
|     /// @dev Transfers given amount of asset to sender. | ||||
|     /// @param assetData Byte array encoded for the respective asset proxy. | ||||
|     /// @param amount Amount of asset to transfer to sender. | ||||
|   | ||||
| @@ -28,11 +28,11 @@ import "../../utils/LibBytes/LibBytes.sol"; | ||||
|  | ||||
| contract OrderValidator { | ||||
|  | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256("ERC20Token(address)")); | ||||
|     bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256("ERC721Token(address,uint256)")); | ||||
|  | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     struct TraderInfo { | ||||
|         uint256 makerBalance;       // Maker's balance of makerAsset | ||||
|         uint256 makerAllowance;     // Maker's allowance to corresponding AssetProxy | ||||
|   | ||||
| @@ -1,13 +1,14 @@ | ||||
| // solhint-disable | ||||
| pragma solidity ^0.4.10; | ||||
| pragma solidity ^0.4.15; | ||||
|  | ||||
|  | ||||
| /// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. | ||||
| /// @author Stefan George - <stefan.george@consensys.net> | ||||
| contract MultiSigWallet { | ||||
|  | ||||
|     uint constant public MAX_OWNER_COUNT = 50; | ||||
|  | ||||
|     /* | ||||
|      *  Events | ||||
|      */ | ||||
|     event Confirmation(address indexed sender, uint indexed transactionId); | ||||
|     event Revocation(address indexed sender, uint indexed transactionId); | ||||
|     event Submission(uint indexed transactionId); | ||||
| @@ -18,6 +19,14 @@ contract MultiSigWallet { | ||||
|     event OwnerRemoval(address indexed owner); | ||||
|     event RequirementChange(uint required); | ||||
|  | ||||
|     /* | ||||
|      *  Constants | ||||
|      */ | ||||
|     uint constant public MAX_OWNER_COUNT = 50; | ||||
|  | ||||
|     /* | ||||
|      *  Storage | ||||
|      */ | ||||
|     mapping (uint => Transaction) public transactions; | ||||
|     mapping (uint => mapping (address => bool)) public confirmations; | ||||
|     mapping (address => bool) public isOwner; | ||||
| @@ -32,60 +41,54 @@ contract MultiSigWallet { | ||||
|         bool executed; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      *  Modifiers | ||||
|      */ | ||||
|     modifier onlyWallet() { | ||||
|         if (msg.sender != address(this)) | ||||
|             throw; | ||||
|         require(msg.sender == address(this)); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier ownerDoesNotExist(address owner) { | ||||
|         if (isOwner[owner]) | ||||
|             throw; | ||||
|         require(!isOwner[owner]); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier ownerExists(address owner) { | ||||
|         if (!isOwner[owner]) | ||||
|             throw; | ||||
|         require(isOwner[owner]); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier transactionExists(uint transactionId) { | ||||
|         if (transactions[transactionId].destination == 0) | ||||
|             throw; | ||||
|         require(transactions[transactionId].destination != 0); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier confirmed(uint transactionId, address owner) { | ||||
|         if (!confirmations[transactionId][owner]) | ||||
|             throw; | ||||
|         require(confirmations[transactionId][owner]); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier notConfirmed(uint transactionId, address owner) { | ||||
|         if (confirmations[transactionId][owner]) | ||||
|             throw; | ||||
|         require(!confirmations[transactionId][owner]); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier notExecuted(uint transactionId) { | ||||
|         if (transactions[transactionId].executed) | ||||
|             throw; | ||||
|         require(!transactions[transactionId].executed); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier notNull(address _address) { | ||||
|         if (_address == 0) | ||||
|             throw; | ||||
|         require(_address != 0); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier validRequirement(uint ownerCount, uint _required) { | ||||
|         if (   ownerCount > MAX_OWNER_COUNT | ||||
|             || _required > ownerCount | ||||
|             || _required == 0 | ||||
|             || ownerCount == 0) | ||||
|             throw; | ||||
|         require(ownerCount <= MAX_OWNER_COUNT | ||||
|             && _required <= ownerCount | ||||
|             && _required != 0 | ||||
|             && ownerCount != 0); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
| @@ -108,8 +111,7 @@ contract MultiSigWallet { | ||||
|         validRequirement(_owners.length, _required) | ||||
|     { | ||||
|         for (uint i=0; i<_owners.length; i++) { | ||||
|             if (isOwner[_owners[i]] || _owners[i] == 0) | ||||
|                 throw; | ||||
|             require(!isOwner[_owners[i]] && _owners[i] != 0); | ||||
|             isOwner[_owners[i]] = true; | ||||
|         } | ||||
|         owners = _owners; | ||||
| @@ -151,7 +153,7 @@ contract MultiSigWallet { | ||||
|  | ||||
|     /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. | ||||
|     /// @param owner Address of owner to be replaced. | ||||
|     /// @param owner Address of new owner. | ||||
|     /// @param newOwner Address of new owner. | ||||
|     function replaceOwner(address owner, address newOwner) | ||||
|         public | ||||
|         onlyWallet | ||||
| @@ -222,20 +224,44 @@ contract MultiSigWallet { | ||||
|     /// @param transactionId Transaction ID. | ||||
|     function executeTransaction(uint transactionId) | ||||
|         public | ||||
|         ownerExists(msg.sender) | ||||
|         confirmed(transactionId, msg.sender) | ||||
|         notExecuted(transactionId) | ||||
|     { | ||||
|         if (isConfirmed(transactionId)) { | ||||
|             Transaction tx = transactions[transactionId]; | ||||
|             tx.executed = true; | ||||
|             if (tx.destination.call.value(tx.value)(tx.data)) | ||||
|             Transaction storage txn = transactions[transactionId]; | ||||
|             txn.executed = true; | ||||
|             if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) | ||||
|                 Execution(transactionId); | ||||
|             else { | ||||
|                 ExecutionFailure(transactionId); | ||||
|                 tx.executed = false; | ||||
|                 txn.executed = false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // call has been separated into its own function in order to take advantage | ||||
|     // of the Solidity's code generator to produce a loop that copies tx.data into memory. | ||||
|     function external_call(address destination, uint value, uint dataLength, bytes data) internal returns (bool) { | ||||
|         bool result; | ||||
|         assembly { | ||||
|             let x := mload(0x40)   // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention) | ||||
|             let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that | ||||
|             result := call( | ||||
|                 sub(gas, 34710),   // 34710 is the value that solidity is currently emitting | ||||
|                                    // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) + | ||||
|                                    // callNewAccountGas (25000, in case the destination address does not exist and needs creating) | ||||
|                 destination, | ||||
|                 value, | ||||
|                 d, | ||||
|                 dataLength,        // Size of the input (in bytes) - this is what fixes the padding problem | ||||
|                 x, | ||||
|                 0                  // Output is ignored, therefore the output size is zero | ||||
|             ) | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns the confirmation status of a transaction. | ||||
|     /// @param transactionId Transaction ID. | ||||
|     /// @return Confirmation status. | ||||
| @@ -364,4 +390,4 @@ contract MultiSigWallet { | ||||
|         for (i=from; i<to; i++) | ||||
|             _transactionIds[i - from] = transactionIdsTemp[i]; | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -16,47 +16,57 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| // solhint-disable | ||||
| pragma solidity ^0.4.10; | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "./MultiSigWallet.sol"; | ||||
|  | ||||
|  | ||||
| /// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed. | ||||
| /// @author Amir Bandeali - <amir@0xProject.com> | ||||
| contract MultiSigWalletWithTimeLock is MultiSigWallet { | ||||
| // solhint-disable not-rely-on-time | ||||
| contract MultiSigWalletWithTimeLock is | ||||
|     MultiSigWallet | ||||
| { | ||||
|     event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime); | ||||
|     event TimeLockChange(uint256 secondsTimeLocked); | ||||
|  | ||||
|     event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime); | ||||
|     event TimeLockChange(uint secondsTimeLocked); | ||||
|     uint256 public secondsTimeLocked; | ||||
|  | ||||
|     uint public secondsTimeLocked; | ||||
|     mapping (uint256 => uint256) public confirmationTimes; | ||||
|  | ||||
|     mapping (uint => uint) public confirmationTimes; | ||||
|  | ||||
|     modifier notFullyConfirmed(uint transactionId) { | ||||
|         require(!isConfirmed(transactionId)); | ||||
|     modifier notFullyConfirmed(uint256 transactionId) { | ||||
|         require( | ||||
|             !isConfirmed(transactionId), | ||||
|             "TX_FULLY_CONFIRMED" | ||||
|         ); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier fullyConfirmed(uint transactionId) { | ||||
|         require(isConfirmed(transactionId)); | ||||
|     modifier fullyConfirmed(uint256 transactionId) { | ||||
|         require( | ||||
|             isConfirmed(transactionId), | ||||
|             "TX_NOT_FULLY_CONFIRMED" | ||||
|         ); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     modifier pastTimeLock(uint transactionId) { | ||||
|         require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked); | ||||
|     modifier pastTimeLock(uint256 transactionId) { | ||||
|         require( | ||||
|             block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked, | ||||
|             "TIME_LOCK_INCOMPLETE" | ||||
|         ); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Public functions | ||||
|      */ | ||||
|  | ||||
|     /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock. | ||||
|     /// @param _owners List of initial owners. | ||||
|     /// @param _required Number of required confirmations. | ||||
|     /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. | ||||
|     function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked) | ||||
|     constructor ( | ||||
|         address[] _owners, | ||||
|         uint256 _required, | ||||
|         uint256 _secondsTimeLocked | ||||
|     ) | ||||
|         public | ||||
|         MultiSigWallet(_owners, _required) | ||||
|     { | ||||
| @@ -65,17 +75,17 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet { | ||||
|  | ||||
|     /// @dev Changes the duration of the time lock for transactions. | ||||
|     /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. | ||||
|     function changeTimeLock(uint _secondsTimeLocked) | ||||
|     function changeTimeLock(uint256 _secondsTimeLocked) | ||||
|         public | ||||
|         onlyWallet | ||||
|     { | ||||
|         secondsTimeLocked = _secondsTimeLocked; | ||||
|         TimeLockChange(_secondsTimeLocked); | ||||
|         emit TimeLockChange(_secondsTimeLocked); | ||||
|     } | ||||
|  | ||||
|     /// @dev Allows an owner to confirm a transaction. | ||||
|     /// @param transactionId Transaction ID. | ||||
|     function confirmTransaction(uint transactionId) | ||||
|     function confirmTransaction(uint256 transactionId) | ||||
|         public | ||||
|         ownerExists(msg.sender) | ||||
|         transactionExists(transactionId) | ||||
| @@ -83,52 +93,35 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet { | ||||
|         notFullyConfirmed(transactionId) | ||||
|     { | ||||
|         confirmations[transactionId][msg.sender] = true; | ||||
|         Confirmation(msg.sender, transactionId); | ||||
|         emit Confirmation(msg.sender, transactionId); | ||||
|         if (isConfirmed(transactionId)) { | ||||
|             setConfirmationTime(transactionId, block.timestamp); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Allows an owner to revoke a confirmation for a transaction. | ||||
|     /// @param transactionId Transaction ID. | ||||
|     function revokeConfirmation(uint transactionId) | ||||
|         public | ||||
|         ownerExists(msg.sender) | ||||
|         confirmed(transactionId, msg.sender) | ||||
|         notExecuted(transactionId) | ||||
|         notFullyConfirmed(transactionId) | ||||
|     { | ||||
|         confirmations[transactionId][msg.sender] = false; | ||||
|         Revocation(msg.sender, transactionId); | ||||
|     } | ||||
|  | ||||
|     /// @dev Allows anyone to execute a confirmed transaction. | ||||
|     /// @param transactionId Transaction ID. | ||||
|     function executeTransaction(uint transactionId) | ||||
|     function executeTransaction(uint256 transactionId) | ||||
|         public | ||||
|         notExecuted(transactionId) | ||||
|         fullyConfirmed(transactionId) | ||||
|         pastTimeLock(transactionId) | ||||
|     { | ||||
|         Transaction storage tx = transactions[transactionId]; | ||||
|         tx.executed = true; | ||||
|         if (tx.destination.call.value(tx.value)(tx.data)) | ||||
|             Execution(transactionId); | ||||
|         else { | ||||
|             ExecutionFailure(transactionId); | ||||
|             tx.executed = false; | ||||
|         Transaction storage txn = transactions[transactionId]; | ||||
|         txn.executed = true; | ||||
|         if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) { | ||||
|             emit Execution(transactionId); | ||||
|         } else { | ||||
|             emit ExecutionFailure(transactionId); | ||||
|             txn.executed = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Internal functions | ||||
|      */ | ||||
|  | ||||
|     /// @dev Sets the time of when a submission first passed. | ||||
|     function setConfirmationTime(uint transactionId, uint confirmationTime) | ||||
|     function setConfirmationTime(uint256 transactionId, uint256 confirmationTime) | ||||
|         internal | ||||
|     { | ||||
|         confirmationTimes[transactionId] = confirmationTime; | ||||
|         ConfirmationTimeSet(transactionId, confirmationTime); | ||||
|         emit ConfirmationTimeSet(transactionId, confirmationTime); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| @@ -59,15 +58,64 @@ contract ERC20Proxy is | ||||
|                     mstore(96, 0) | ||||
|                     revert(0, 100) | ||||
|                 } | ||||
|                  | ||||
|                 /////// Token contract address /////// | ||||
|                 // The token address is found as follows: | ||||
|                 // * It is stored at offset 4 in `assetData` contents. | ||||
|                 // * This is stored at offset 32 from `assetData`. | ||||
|                 // * The offset to `assetData` from Params is stored at offset | ||||
|                 //   4 in calldata. | ||||
|                 // * The offset of Params in calldata is 4. | ||||
|                 // So we read location 4 and add 32 + 4 + 4 to it. | ||||
|  | ||||
|                 // `transferFrom`. | ||||
|                 // The function is marked `external`, so no abi decodeding is done for | ||||
|                 // us. Instead, we expect the `calldata` memory to contain the | ||||
|                 // following: | ||||
|                 // | ||||
|                 // | 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    | **      | assetData Contents                  | | ||||
|                 // | ||||
|                 // (*): offset is computed from start of function parameters, so offset | ||||
|                 //      by an additional 4 bytes in the calldata. | ||||
|                 // | ||||
|                 // (**): see table below to compute length of assetData Contents | ||||
|                 // | ||||
|                 // WARNING: The ABIv2 specification allows additional padding between | ||||
|                 //          the Params and Data section. This will result in a larger | ||||
|                 //          offset to assetData. | ||||
|  | ||||
|                 // Asset data itself is encoded as follows: | ||||
|                 // | ||||
|                 // | Area     | Offset | Length  | Contents                            | | ||||
|                 // |----------|--------|---------|-------------------------------------| | ||||
|                 // | Header   | 0      | 4       | function selector                   | | ||||
|                 // | Params   |        | 1 * 32  | function parameters:                | | ||||
|                 // |          | 4      | 12 + 20 |   1. token address                  | | ||||
|  | ||||
|                 // We construct calldata for the `token.transferFrom` ABI. | ||||
|                 // The layout of this calldata is in the table below. | ||||
|                 // | ||||
|                 // | Area     | Offset | Length  | Contents                            | | ||||
|                 // |----------|--------|---------|-------------------------------------| | ||||
|                 // | Header   | 0      | 4       | function selector                   | | ||||
|                 // | Params   |        | 3 * 32  | function parameters:                | | ||||
|                 // |          | 4      |         |   1. from                           | | ||||
|                 // |          | 36     |         |   2. to                             | | ||||
|                 // |          | 68     |         |   3. amount                         | | ||||
|  | ||||
|                 /////// Read token address from calldata /////// | ||||
|                 // * The token address is stored in `assetData`. | ||||
|                 // | ||||
|                 // * The "offset to assetData" is stored at offset 4 in the calldata (table 1). | ||||
|                 //   [assetDataOffsetFromParams = calldataload(4)] | ||||
|                 // | ||||
|                 // * Notes that the "offset to assetData" is relative to the "Params" area of calldata; | ||||
|                 //   add 4 bytes to account for the length of the "Header" area (table 1). | ||||
|                 //   [assetDataOffsetFromHeader = assetDataOffsetFromParams + 4] | ||||
|                 // | ||||
|                 // * The "token address" is offset 32+4=36 bytes into "assetData" (tables 1 & 2). | ||||
|                 //   [tokenOffset = assetDataOffsetFromHeader + 36 = calldataload(4) + 4 + 36] | ||||
|                 let token := calldataload(add(calldataload(4), 40)) | ||||
|                  | ||||
|                 /////// Setup Header Area /////// | ||||
| @@ -118,6 +166,9 @@ contract ERC20Proxy is | ||||
|                 mstore(96, 0) | ||||
|                 revert(0, 100) | ||||
|             } | ||||
|  | ||||
|             // Revert if undefined function is called | ||||
|             revert(0, 0) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| @@ -80,6 +79,8 @@ contract ERC721Proxy is | ||||
|                 // (*): offset is computed from start of function parameters, so offset | ||||
|                 //      by an additional 4 bytes in the calldata. | ||||
|                 // | ||||
|                 // (**): see table below to compute length of assetData Contents | ||||
|                 // | ||||
|                 // WARNING: The ABIv2 specification allows additional padding between | ||||
|                 //          the Params and Data section. This will result in a larger | ||||
|                 //          offset to assetData. | ||||
| @@ -152,6 +153,9 @@ contract ERC721Proxy is | ||||
|                 mstore(96, 0) | ||||
|                 revert(0, 100) | ||||
|             } | ||||
|  | ||||
|             // Revert if undefined function is called | ||||
|             revert(0, 0) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -26,7 +26,6 @@ contract MixinAuthorizable is | ||||
|     Ownable, | ||||
|     MAuthorizable | ||||
| { | ||||
|  | ||||
|     /// @dev Only authorized addresses can invoke functions with this modifier. | ||||
|     modifier onlyAuthorized { | ||||
|         require( | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "./IAuthorizable.sol"; | ||||
| contract IAssetProxy is | ||||
|     IAuthorizable | ||||
| { | ||||
|  | ||||
|     /// @dev Transfers assets. Either succeeds or throws. | ||||
|     /// @param assetData Byte array encoded for the respective asset proxy. | ||||
|     /// @param from Address to transfer asset from. | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../../../utils/Ownable/IOwnable.sol"; | ||||
| contract IAuthorizable is | ||||
|     IOwnable | ||||
| { | ||||
|  | ||||
|     /// @dev Authorizes an address. | ||||
|     /// @param target Address to authorize. | ||||
|     function addAuthorizedAddress(address target) | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../interfaces/IAuthorizable.sol"; | ||||
| contract MAuthorizable is | ||||
|     IAuthorizable | ||||
| { | ||||
|  | ||||
|     // Event logged when a new address is authorized. | ||||
|     event AuthorizedAddressAdded( | ||||
|         address indexed target, | ||||
|   | ||||
| @@ -16,14 +16,16 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity 0.4.10; | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../multisig/MultiSigWalletWithTimeLock.sol"; | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
|  | ||||
|  | ||||
| contract AssetProxyOwner is | ||||
|     MultiSigWalletWithTimeLock | ||||
| { | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     event AssetProxyRegistration(address assetProxyContract, bool isRegistered); | ||||
|  | ||||
| @@ -36,9 +38,15 @@ contract AssetProxyOwner is | ||||
|     /// @dev Function will revert if the transaction does not call `removeAuthorizedAddressAtIndex` | ||||
|     ///      on an approved AssetProxy contract. | ||||
|     modifier validRemoveAuthorizedAddressAtIndexTx(uint256 transactionId) { | ||||
|         Transaction storage tx = transactions[transactionId]; | ||||
|         require(isAssetProxyRegistered[tx.destination]); | ||||
|         require(readBytes4(tx.data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR); | ||||
|         Transaction storage txn = transactions[transactionId]; | ||||
|         require( | ||||
|             isAssetProxyRegistered[txn.destination], | ||||
|             "UNREGISTERED_ASSET_PROXY" | ||||
|         ); | ||||
|         require( | ||||
|             txn.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR, | ||||
|             "INVALID_FUNCTION_SELECTOR" | ||||
|         ); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
| @@ -48,7 +56,7 @@ contract AssetProxyOwner is | ||||
|     /// @param _assetProxyContracts Array of AssetProxy contract addresses. | ||||
|     /// @param _required Number of required confirmations. | ||||
|     /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. | ||||
|     function AssetProxyOwner( | ||||
|     constructor ( | ||||
|         address[] memory _owners, | ||||
|         address[] memory _assetProxyContracts, | ||||
|         uint256 _required, | ||||
| @@ -59,7 +67,10 @@ contract AssetProxyOwner is | ||||
|     { | ||||
|         for (uint256 i = 0; i < _assetProxyContracts.length; i++) { | ||||
|             address assetProxy = _assetProxyContracts[i]; | ||||
|             require(assetProxy != address(0)); | ||||
|             require( | ||||
|                 assetProxy != address(0), | ||||
|                 "INVALID_ASSET_PROXY" | ||||
|             ); | ||||
|             isAssetProxyRegistered[assetProxy] = true; | ||||
|         } | ||||
|     } | ||||
| @@ -74,7 +85,7 @@ contract AssetProxyOwner is | ||||
|         notNull(assetProxyContract) | ||||
|     { | ||||
|         isAssetProxyRegistered[assetProxyContract] = isRegistered; | ||||
|         AssetProxyRegistration(assetProxyContract, isRegistered); | ||||
|         emit AssetProxyRegistration(assetProxyContract, isRegistered); | ||||
|     } | ||||
|  | ||||
|     /// @dev Allows execution of `removeAuthorizedAddressAtIndex` without time lock. | ||||
| @@ -85,35 +96,13 @@ contract AssetProxyOwner is | ||||
|         fullyConfirmed(transactionId) | ||||
|         validRemoveAuthorizedAddressAtIndexTx(transactionId) | ||||
|     { | ||||
|         Transaction storage tx = transactions[transactionId]; | ||||
|         tx.executed = true; | ||||
|         // solhint-disable-next-line avoid-call-value | ||||
|         if (tx.destination.call.value(tx.value)(tx.data)) | ||||
|             Execution(transactionId); | ||||
|         else { | ||||
|             ExecutionFailure(transactionId); | ||||
|             tx.executed = false; | ||||
|         Transaction storage txn = transactions[transactionId]; | ||||
|         txn.executed = true; | ||||
|         if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) { | ||||
|             emit Execution(transactionId); | ||||
|         } else { | ||||
|             emit ExecutionFailure(transactionId); | ||||
|             txn.executed = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Reads an unpadded bytes4 value from a position in a byte array. | ||||
|     /// @param b Byte array containing a bytes4 value. | ||||
|     /// @param index Index in byte array of bytes4 value. | ||||
|     /// @return bytes4 value from byte array. | ||||
|     function readBytes4( | ||||
|         bytes memory b, | ||||
|         uint256 index | ||||
|     ) | ||||
|         internal | ||||
|         returns (bytes4 result) | ||||
|     { | ||||
|         require(b.length >= index + 4); | ||||
|         assembly { | ||||
|             result := mload(add(b, 32)) | ||||
|             // Solidity does not require us to clean the trailing bytes. | ||||
|             // We do it anyway | ||||
|             result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000) | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -37,7 +37,6 @@ contract Exchange is | ||||
|     MixinAssetProxyDispatcher, | ||||
|     MixinWrapperFunctions | ||||
| { | ||||
|  | ||||
|     string constant public VERSION = "2.0.1-alpha"; | ||||
|  | ||||
|     // Mixins are instantiated in the order they are inherited | ||||
|   | ||||
| @@ -19,7 +19,6 @@ | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../utils/Ownable/Ownable.sol"; | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
| import "./mixins/MAssetProxyDispatcher.sol"; | ||||
| import "../AssetProxy/interfaces/IAssetProxy.sol"; | ||||
|  | ||||
| @@ -28,8 +27,6 @@ contract MixinAssetProxyDispatcher is | ||||
|     Ownable, | ||||
|     MAssetProxyDispatcher | ||||
| { | ||||
|     using LibBytes for bytes; | ||||
|      | ||||
|     // Mapping from Asset Proxy Id's to their respective Asset Proxy | ||||
|     mapping (bytes4 => IAssetProxy) public assetProxies; | ||||
|  | ||||
| @@ -83,14 +80,14 @@ contract MixinAssetProxyDispatcher is | ||||
|         internal | ||||
|     { | ||||
|         // Do nothing if no amount should be transferred. | ||||
|         if (amount > 0) { | ||||
|         if (amount > 0 && from != to) { | ||||
|             // Ensure assetData length is valid | ||||
|             require( | ||||
|                 assetData.length > 3, | ||||
|                 "LENGTH_GREATER_THAN_3_REQUIRED" | ||||
|             ); | ||||
|              | ||||
|             // Lookup assetProxy | ||||
|             // Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons. | ||||
|             bytes4 assetProxyId; | ||||
|             assembly { | ||||
|                 assetProxyId := and(mload( | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| pragma solidity 0.4.24; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../../utils/ReentrancyGuard/ReentrancyGuard.sol"; | ||||
| import "./libs/LibConstants.sol"; | ||||
| import "./libs/LibFillResults.sol"; | ||||
| import "./libs/LibOrder.sol"; | ||||
| @@ -30,6 +31,7 @@ import "./mixins/MAssetProxyDispatcher.sol"; | ||||
|  | ||||
|  | ||||
| contract MixinExchangeCore is | ||||
|     ReentrancyGuard, | ||||
|     LibConstants, | ||||
|     LibMath, | ||||
|     LibOrder, | ||||
| @@ -54,6 +56,7 @@ contract MixinExchangeCore is | ||||
|     /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. | ||||
|     function cancelOrdersUpTo(uint256 targetOrderEpoch) | ||||
|         external | ||||
|         nonReentrant | ||||
|     { | ||||
|         address makerAddress = getCurrentContextAddress(); | ||||
|         // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination. | ||||
| @@ -72,7 +75,11 @@ contract MixinExchangeCore is | ||||
|  | ||||
|         // Update orderEpoch | ||||
|         orderEpoch[makerAddress][senderAddress] = newOrderEpoch; | ||||
|         emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch); | ||||
|         emit CancelUpTo( | ||||
|             makerAddress, | ||||
|             senderAddress, | ||||
|             newOrderEpoch | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Fills the input order. | ||||
| @@ -86,43 +93,14 @@ contract MixinExchangeCore is | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory fillResults) | ||||
|     { | ||||
|         // Fetch order info | ||||
|         OrderInfo memory orderInfo = getOrderInfo(order); | ||||
|  | ||||
|         // Fetch taker address | ||||
|         address takerAddress = getCurrentContextAddress(); | ||||
|  | ||||
|         // Get amount of takerAsset to fill | ||||
|         uint256 remainingTakerAssetAmount = safeSub(order.takerAssetAmount, orderInfo.orderTakerAssetFilledAmount); | ||||
|         uint256 takerAssetFilledAmount = min256(takerAssetFillAmount, remainingTakerAssetAmount); | ||||
|  | ||||
|         // Validate context | ||||
|         assertValidFill( | ||||
|         fillResults = fillOrderInternal( | ||||
|             order, | ||||
|             orderInfo, | ||||
|             takerAddress, | ||||
|             takerAssetFillAmount, | ||||
|             takerAssetFilledAmount, | ||||
|             signature | ||||
|         ); | ||||
|  | ||||
|         // Compute proportional fill amounts | ||||
|         fillResults = calculateFillResults(order, takerAssetFilledAmount); | ||||
|  | ||||
|         // Update exchange internal state | ||||
|         updateFilledState( | ||||
|             order, | ||||
|             takerAddress, | ||||
|             orderInfo.orderHash, | ||||
|             orderInfo.orderTakerAssetFilledAmount, | ||||
|             fillResults | ||||
|         ); | ||||
|      | ||||
|         // Settle order | ||||
|         settleOrder(order, takerAddress, fillResults); | ||||
|  | ||||
|         return fillResults; | ||||
|     } | ||||
|  | ||||
| @@ -131,15 +109,9 @@ contract MixinExchangeCore is | ||||
|     /// @param order Order to cancel. Order must be OrderStatus.FILLABLE. | ||||
|     function cancelOrder(Order memory order) | ||||
|         public | ||||
|         nonReentrant | ||||
|     { | ||||
|         // Fetch current order status | ||||
|         OrderInfo memory orderInfo = getOrderInfo(order); | ||||
|  | ||||
|         // Validate context | ||||
|         assertValidCancel(order, orderInfo); | ||||
|  | ||||
|         // Perform cancel | ||||
|         updateCancelledState(order, orderInfo.orderHash); | ||||
|         cancelOrderInternal(order); | ||||
|     } | ||||
|  | ||||
|     /// @dev Gets information about an order: status, hash, and amount filled. | ||||
| @@ -203,6 +175,84 @@ contract MixinExchangeCore is | ||||
|         return orderInfo; | ||||
|     } | ||||
|  | ||||
|     /// @dev Fills the input order. | ||||
|     /// @param order Order struct containing order specifications. | ||||
|     /// @param takerAssetFillAmount Desired amount of takerAsset to sell. | ||||
|     /// @param signature Proof that order has been created by maker. | ||||
|     /// @return Amounts filled and fees paid by maker and taker. | ||||
|     function fillOrderInternal( | ||||
|         Order memory order, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
|         returns (FillResults memory fillResults) | ||||
|     { | ||||
|         // Fetch order info | ||||
|         OrderInfo memory orderInfo = getOrderInfo(order); | ||||
|  | ||||
|         // Fetch taker address | ||||
|         address takerAddress = getCurrentContextAddress(); | ||||
|          | ||||
|         // Assert that the order is fillable by taker | ||||
|         assertFillableOrder( | ||||
|             order, | ||||
|             orderInfo, | ||||
|             takerAddress, | ||||
|             signature | ||||
|         ); | ||||
|          | ||||
|         // Get amount of takerAsset to fill | ||||
|         uint256 remainingTakerAssetAmount = safeSub(order.takerAssetAmount, orderInfo.orderTakerAssetFilledAmount); | ||||
|         uint256 takerAssetFilledAmount = min256(takerAssetFillAmount, remainingTakerAssetAmount); | ||||
|  | ||||
|         // Validate context | ||||
|         assertValidFill( | ||||
|             order, | ||||
|             orderInfo, | ||||
|             takerAssetFillAmount, | ||||
|             takerAssetFilledAmount, | ||||
|             fillResults.makerAssetFilledAmount | ||||
|         ); | ||||
|  | ||||
|         // Compute proportional fill amounts | ||||
|         fillResults = calculateFillResults(order, takerAssetFilledAmount); | ||||
|  | ||||
|         // Update exchange internal state | ||||
|         updateFilledState( | ||||
|             order, | ||||
|             takerAddress, | ||||
|             orderInfo.orderHash, | ||||
|             orderInfo.orderTakerAssetFilledAmount, | ||||
|             fillResults | ||||
|         ); | ||||
|      | ||||
|         // Settle order | ||||
|         settleOrder( | ||||
|             order, | ||||
|             takerAddress, | ||||
|             fillResults | ||||
|         ); | ||||
|  | ||||
|         return fillResults; | ||||
|     } | ||||
|  | ||||
|     /// @dev After calling, the order can not be filled anymore. | ||||
|     ///      Throws if order is invalid or sender does not have permission to cancel. | ||||
|     /// @param order Order to cancel. Order must be OrderStatus.FILLABLE. | ||||
|     function cancelOrderInternal(Order memory order) | ||||
|         internal | ||||
|     { | ||||
|         // Fetch current order status | ||||
|         OrderInfo memory orderInfo = getOrderInfo(order); | ||||
|  | ||||
|         // Validate context | ||||
|         assertValidCancel(order, orderInfo); | ||||
|  | ||||
|         // Perform cancel | ||||
|         updateCancelledState(order, orderInfo.orderHash); | ||||
|     } | ||||
|  | ||||
|     /// @dev Updates state with results of a fill order. | ||||
|     /// @param order that was filled. | ||||
|     /// @param takerAddress Address of taker who filled the order. | ||||
| @@ -259,20 +309,16 @@ contract MixinExchangeCore is | ||||
|             order.takerAssetData | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     /// @dev Validates context for fillOrder. Succeeds or throws. | ||||
|     /// @param order to be filled. | ||||
|     /// @param orderInfo OrderStatus, orderHash, and amount already filled of order. | ||||
|     /// @param takerAddress Address of order taker. | ||||
|     /// @param takerAssetFillAmount Desired amount of order to fill by taker. | ||||
|     /// @param takerAssetFilledAmount Amount of takerAsset that will be filled. | ||||
|     /// @param signature Proof that the orders was created by its maker. | ||||
|     function assertValidFill( | ||||
|     function assertFillableOrder( | ||||
|         Order memory order, | ||||
|         OrderInfo memory orderInfo, | ||||
|         address takerAddress, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         uint256 takerAssetFilledAmount, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
| @@ -283,13 +329,7 @@ contract MixinExchangeCore is | ||||
|             orderInfo.orderStatus == uint8(OrderStatus.FILLABLE), | ||||
|             "ORDER_UNFILLABLE" | ||||
|         ); | ||||
|  | ||||
|         // Revert if fill amount is invalid | ||||
|         require( | ||||
|             takerAssetFillAmount != 0, | ||||
|             "INVALID_TAKER_AMOUNT" | ||||
|         ); | ||||
|  | ||||
|          | ||||
|         // Validate sender is allowed to fill this order | ||||
|         if (order.senderAddress != address(0)) { | ||||
|             require( | ||||
| @@ -297,7 +337,7 @@ contract MixinExchangeCore is | ||||
|                 "INVALID_SENDER" | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|          | ||||
|         // Validate taker is allowed to fill this order | ||||
|         if (order.takerAddress != address(0)) { | ||||
|             require( | ||||
| @@ -305,7 +345,7 @@ contract MixinExchangeCore is | ||||
|                 "INVALID_TAKER" | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|          | ||||
|         // Validate Maker signature (check only if first time seen) | ||||
|         if (orderInfo.orderTakerAssetFilledAmount == 0) { | ||||
|             require( | ||||
| @@ -317,15 +357,69 @@ contract MixinExchangeCore is | ||||
|                 "INVALID_ORDER_SIGNATURE" | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         // Validate fill order rounding | ||||
|     } | ||||
|      | ||||
|     /// @dev Validates context for fillOrder. Succeeds or throws. | ||||
|     /// @param order to be filled. | ||||
|     /// @param orderInfo OrderStatus, orderHash, and amount already filled of order. | ||||
|     /// @param takerAssetFillAmount Desired amount of order to fill by taker. | ||||
|     /// @param takerAssetFilledAmount Amount of takerAsset that will be filled. | ||||
|     /// @param makerAssetFilledAmount Amount of makerAsset that will be transfered. | ||||
|     function assertValidFill( | ||||
|         Order memory order, | ||||
|         OrderInfo memory orderInfo, | ||||
|         uint256 takerAssetFillAmount,  // TODO: use FillResults | ||||
|         uint256 takerAssetFilledAmount, | ||||
|         uint256 makerAssetFilledAmount | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|     { | ||||
|         // Revert if fill amount is invalid | ||||
|         // TODO: reconsider necessity for v2.1 | ||||
|         require( | ||||
|             !isRoundingError( | ||||
|                 takerAssetFilledAmount, | ||||
|                 order.takerAssetAmount, | ||||
|                 order.makerAssetAmount | ||||
|             ), | ||||
|             "ROUNDING_ERROR" | ||||
|             takerAssetFillAmount != 0, | ||||
|             "INVALID_TAKER_AMOUNT" | ||||
|         ); | ||||
|          | ||||
|         // Make sure taker does not pay more than desired amount | ||||
|         // NOTE: This assertion should never fail, it is here | ||||
|         //       as an extra defence against potential bugs. | ||||
|         require( | ||||
|             takerAssetFilledAmount <= takerAssetFillAmount, | ||||
|             "TAKER_OVERPAY" | ||||
|         ); | ||||
|          | ||||
|         // Make sure order is not overfilled | ||||
|         // NOTE: This assertion should never fail, it is here | ||||
|         //       as an extra defence against potential bugs. | ||||
|         require( | ||||
|             safeAdd(orderInfo.orderTakerAssetFilledAmount, takerAssetFilledAmount) <= order.takerAssetAmount, | ||||
|             "ORDER_OVERFILL" | ||||
|         ); | ||||
|          | ||||
|         // Make sure order is filled at acceptable price. | ||||
|         // The order has an implied price from the makers perspective: | ||||
|         //    order price = order.makerAssetAmount / order.takerAssetAmount | ||||
|         // i.e. the number of makerAsset maker is paying per takerAsset. The | ||||
|         // maker is guaranteed to get this price or a better (lower) one. The | ||||
|         // actual price maker is getting in this fill is: | ||||
|         //    fill price = makerAssetFilledAmount / takerAssetFilledAmount | ||||
|         // We need `fill price <= order price` for the fill to be fair to maker. | ||||
|         // This amounts to: | ||||
|         //     makerAssetFilledAmount        order.makerAssetAmount | ||||
|         //    ------------------------  <=  ----------------------- | ||||
|         //     takerAssetFilledAmount        order.takerAssetAmount | ||||
|         // or, equivalently: | ||||
|         //     makerAssetFilledAmount * order.takerAssetAmount <= | ||||
|         //     order.makerAssetAmount * takerAssetFilledAmount | ||||
|         // NOTE: This assertion should never fail, it is here | ||||
|         //       as an extra defence against potential bugs. | ||||
|         require( | ||||
|             safeMul(makerAssetFilledAmount, order.takerAssetAmount) | ||||
|             <=  | ||||
|             safeMul(order.makerAssetAmount, takerAssetFilledAmount), | ||||
|             "INVALID_FILL_PRICE" | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -376,17 +470,17 @@ contract MixinExchangeCore is | ||||
|     { | ||||
|         // Compute proportional transfer amounts | ||||
|         fillResults.takerAssetFilledAmount = takerAssetFilledAmount; | ||||
|         fillResults.makerAssetFilledAmount = getPartialAmount( | ||||
|         fillResults.makerAssetFilledAmount = safeGetPartialAmountFloor( | ||||
|             takerAssetFilledAmount, | ||||
|             order.takerAssetAmount, | ||||
|             order.makerAssetAmount | ||||
|         ); | ||||
|         fillResults.makerFeePaid = getPartialAmount( | ||||
|             takerAssetFilledAmount, | ||||
|             order.takerAssetAmount, | ||||
|         fillResults.makerFeePaid = safeGetPartialAmountFloor( | ||||
|             fillResults.makerAssetFilledAmount, | ||||
|             order.makerAssetAmount, | ||||
|             order.makerFee | ||||
|         ); | ||||
|         fillResults.takerFeePaid = getPartialAmount( | ||||
|         fillResults.takerFeePaid = safeGetPartialAmountFloor( | ||||
|             takerAssetFilledAmount, | ||||
|             order.takerAssetAmount, | ||||
|             order.takerFee | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| pragma solidity 0.4.24; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../../utils/ReentrancyGuard/ReentrancyGuard.sol"; | ||||
| import "./libs/LibConstants.sol"; | ||||
| import "./libs/LibMath.sol"; | ||||
| import "./libs/LibOrder.sol"; | ||||
| @@ -25,6 +26,7 @@ import "./mixins/MAssetProxyDispatcher.sol"; | ||||
|  | ||||
|  | ||||
| contract MixinMatchOrders is | ||||
|     ReentrancyGuard, | ||||
|     LibConstants, | ||||
|     LibMath, | ||||
|     MAssetProxyDispatcher, | ||||
| @@ -48,6 +50,7 @@ contract MixinMatchOrders is | ||||
|         bytes memory rightSignature | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (LibFillResults.MatchedFillResults memory matchedFillResults) | ||||
|     { | ||||
|         // We assume that rightOrder.takerAssetData == leftOrder.makerAssetData and rightOrder.makerAssetData == leftOrder.takerAssetData. | ||||
| @@ -61,8 +64,20 @@ contract MixinMatchOrders is | ||||
|  | ||||
|         // Fetch taker address | ||||
|         address takerAddress = getCurrentContextAddress(); | ||||
|  | ||||
|          | ||||
|         // Either our context is valid or we revert | ||||
|         assertFillableOrder( | ||||
|             leftOrder, | ||||
|             leftOrderInfo, | ||||
|             takerAddress, | ||||
|             leftSignature | ||||
|         ); | ||||
|         assertFillableOrder( | ||||
|             rightOrder, | ||||
|             rightOrderInfo, | ||||
|             takerAddress, | ||||
|             rightSignature | ||||
|         ); | ||||
|         assertValidMatch(leftOrder, rightOrder); | ||||
|  | ||||
|         // Compute proportional fill amounts | ||||
| @@ -77,20 +92,18 @@ contract MixinMatchOrders is | ||||
|         assertValidFill( | ||||
|             leftOrder, | ||||
|             leftOrderInfo, | ||||
|             takerAddress, | ||||
|             matchedFillResults.left.takerAssetFilledAmount, | ||||
|             matchedFillResults.left.takerAssetFilledAmount, | ||||
|             leftSignature | ||||
|             matchedFillResults.left.makerAssetFilledAmount | ||||
|         ); | ||||
|         assertValidFill( | ||||
|             rightOrder, | ||||
|             rightOrderInfo, | ||||
|             takerAddress, | ||||
|             matchedFillResults.right.takerAssetFilledAmount, | ||||
|             matchedFillResults.right.takerAssetFilledAmount, | ||||
|             rightSignature | ||||
|             matchedFillResults.right.makerAssetFilledAmount | ||||
|         ); | ||||
|  | ||||
|          | ||||
|         // Update exchange state | ||||
|         updateFilledState( | ||||
|             leftOrder, | ||||
| @@ -106,7 +119,7 @@ contract MixinMatchOrders is | ||||
|             rightOrderInfo.orderTakerAssetFilledAmount, | ||||
|             matchedFillResults.right | ||||
|         ); | ||||
|      | ||||
|  | ||||
|         // Settle matched orders. Succeeds or throws. | ||||
|         settleMatchedOrders( | ||||
|             leftOrder, | ||||
| @@ -162,62 +175,85 @@ contract MixinMatchOrders is | ||||
|         pure | ||||
|         returns (LibFillResults.MatchedFillResults memory matchedFillResults) | ||||
|     { | ||||
|         // We settle orders at the exchange rate of the right order. | ||||
|         // The amount saved by the left maker goes to the taker. | ||||
|         // Either the left or right order will be fully filled; possibly both. | ||||
|         // The left order is fully filled iff the right order can sell more than left can buy. | ||||
|         // That is: the amount required to fill the left order is less than or equal to | ||||
|         //          the amount we can spend from the right order: | ||||
|         //          <leftTakerAssetAmountRemaining> <= <rightTakerAssetAmountRemaining> * <rightMakerToTakerRatio> | ||||
|         //          <leftTakerAssetAmountRemaining> <= <rightTakerAssetAmountRemaining> * <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount> | ||||
|         //          <leftTakerAssetAmountRemaining> * <rightOrder.takerAssetAmount> <= <rightTakerAssetAmountRemaining> * <rightOrder.makerAssetAmount> | ||||
|         // Derive maker asset amounts for left & right orders, given store taker assert amounts | ||||
|         uint256 leftTakerAssetAmountRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount); | ||||
|         uint256 leftMakerAssetAmountRemaining = safeGetPartialAmountFloor( | ||||
|             leftOrder.makerAssetAmount, | ||||
|             leftOrder.takerAssetAmount, | ||||
|             leftTakerAssetAmountRemaining | ||||
|         ); | ||||
|         uint256 rightTakerAssetAmountRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount); | ||||
|         uint256 leftTakerAssetFilledAmount; | ||||
|         uint256 rightTakerAssetFilledAmount; | ||||
|         if ( | ||||
|             safeMul(leftTakerAssetAmountRemaining, rightOrder.takerAssetAmount) <= | ||||
|             safeMul(rightTakerAssetAmountRemaining, rightOrder.makerAssetAmount) | ||||
|         ) { | ||||
|             // Left order will be fully filled: maximally fill left | ||||
|             leftTakerAssetFilledAmount = leftTakerAssetAmountRemaining; | ||||
|         uint256 rightMakerAssetAmountRemaining = safeGetPartialAmountFloor( | ||||
|             rightOrder.makerAssetAmount, | ||||
|             rightOrder.takerAssetAmount, | ||||
|             rightTakerAssetAmountRemaining | ||||
|         ); | ||||
|  | ||||
|             // The right order receives an amount proportional to how much was spent. | ||||
|             rightTakerAssetFilledAmount = getPartialAmount( | ||||
|                 rightOrder.takerAssetAmount, | ||||
|                 rightOrder.makerAssetAmount, | ||||
|                 leftTakerAssetFilledAmount | ||||
|         // Calculate fill results for maker and taker assets: at least one order will be fully filled. | ||||
|         // The maximum amount the left maker can buy is `leftTakerAssetAmountRemaining` | ||||
|         // The maximum amount the right maker can sell is `rightMakerAssetAmountRemaining` | ||||
|         // We have two distinct cases for calculating the fill results: | ||||
|         // Case 1. | ||||
|         //   If the left maker can buy more than the right maker can sell, then only the right order is fully filled. | ||||
|         //   If the left maker can buy exactly what the right maker can sell, then both orders are fully filled. | ||||
|         // Case 2. | ||||
|         //   If the left maker cannot buy more than the right maker can sell, then only the left order is fully filled. | ||||
|         if (leftTakerAssetAmountRemaining >= rightMakerAssetAmountRemaining) { | ||||
|             // Case 1: Right order is fully filled | ||||
|             matchedFillResults.right.makerAssetFilledAmount = rightMakerAssetAmountRemaining; | ||||
|             matchedFillResults.right.takerAssetFilledAmount = rightTakerAssetAmountRemaining; | ||||
|             matchedFillResults.left.takerAssetFilledAmount = matchedFillResults.right.makerAssetFilledAmount; | ||||
|             // Round down to ensure the maker's exchange rate does not exceed the price specified by the order.  | ||||
|             // We favor the maker when the exchange rate must be rounded. | ||||
|             matchedFillResults.left.makerAssetFilledAmount = safeGetPartialAmountFloor( | ||||
|                 leftOrder.makerAssetAmount, | ||||
|                 leftOrder.takerAssetAmount, | ||||
|                 matchedFillResults.left.takerAssetFilledAmount | ||||
|             ); | ||||
|         } else { | ||||
|             // Right order will be fully filled: maximally fill right | ||||
|             rightTakerAssetFilledAmount = rightTakerAssetAmountRemaining; | ||||
|  | ||||
|             // The left order receives an amount proportional to how much was spent. | ||||
|             leftTakerAssetFilledAmount = getPartialAmount( | ||||
|                 rightOrder.makerAssetAmount, | ||||
|             // Case 2: Left order is fully filled | ||||
|             matchedFillResults.left.makerAssetFilledAmount = leftMakerAssetAmountRemaining; | ||||
|             matchedFillResults.left.takerAssetFilledAmount = leftTakerAssetAmountRemaining; | ||||
|             matchedFillResults.right.makerAssetFilledAmount = matchedFillResults.left.takerAssetFilledAmount; | ||||
|             // Round up to ensure the maker's exchange rate does not exceed the price specified by the order. | ||||
|             // We favor the maker when the exchange rate must be rounded. | ||||
|             matchedFillResults.right.takerAssetFilledAmount = safeGetPartialAmountCeil( | ||||
|                 rightOrder.takerAssetAmount, | ||||
|                 rightTakerAssetFilledAmount | ||||
|                 rightOrder.makerAssetAmount, | ||||
|                 matchedFillResults.right.makerAssetFilledAmount | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         // Calculate fill results for left order | ||||
|         matchedFillResults.left = calculateFillResults( | ||||
|             leftOrder, | ||||
|             leftTakerAssetFilledAmount | ||||
|         ); | ||||
|  | ||||
|         // Calculate fill results for right order | ||||
|         matchedFillResults.right = calculateFillResults( | ||||
|             rightOrder, | ||||
|             rightTakerAssetFilledAmount | ||||
|         ); | ||||
|  | ||||
|         // Calculate amount given to taker | ||||
|         matchedFillResults.leftMakerAssetSpreadAmount = safeSub( | ||||
|             matchedFillResults.left.makerAssetFilledAmount, | ||||
|             matchedFillResults.right.takerAssetFilledAmount | ||||
|         ); | ||||
|  | ||||
|         // Compute fees for left order | ||||
|         matchedFillResults.left.makerFeePaid = safeGetPartialAmountFloor( | ||||
|             matchedFillResults.left.makerAssetFilledAmount, | ||||
|             leftOrder.makerAssetAmount, | ||||
|             leftOrder.makerFee | ||||
|         ); | ||||
|         matchedFillResults.left.takerFeePaid = safeGetPartialAmountFloor( | ||||
|             matchedFillResults.left.takerAssetFilledAmount, | ||||
|             leftOrder.takerAssetAmount, | ||||
|             leftOrder.takerFee | ||||
|         ); | ||||
|  | ||||
|         // Compute fees for right order | ||||
|         matchedFillResults.right.makerFeePaid = safeGetPartialAmountFloor( | ||||
|             matchedFillResults.right.makerAssetFilledAmount, | ||||
|             rightOrder.makerAssetAmount, | ||||
|             rightOrder.makerFee | ||||
|         ); | ||||
|         matchedFillResults.right.takerFeePaid = safeGetPartialAmountFloor( | ||||
|             matchedFillResults.right.takerAssetFilledAmount, | ||||
|             rightOrder.takerAssetAmount, | ||||
|             rightOrder.takerFee | ||||
|         ); | ||||
|  | ||||
|         // Return fill results | ||||
|         return matchedFillResults; | ||||
|     } | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
| import "../../utils/ReentrancyGuard/ReentrancyGuard.sol"; | ||||
| import "./mixins/MSignatureValidator.sol"; | ||||
| import "./mixins/MTransactions.sol"; | ||||
| import "./interfaces/IWallet.sol"; | ||||
| @@ -26,6 +27,7 @@ import "./interfaces/IValidator.sol"; | ||||
|  | ||||
|  | ||||
| contract MixinSignatureValidator is | ||||
|     ReentrancyGuard, | ||||
|     MSignatureValidator, | ||||
|     MTransactions | ||||
| { | ||||
| @@ -48,14 +50,16 @@ contract MixinSignatureValidator is | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         require( | ||||
|             isValidSignature( | ||||
|                 hash, | ||||
|                 signerAddress, | ||||
|                 signature | ||||
|             ), | ||||
|             "INVALID_SIGNATURE" | ||||
|         ); | ||||
|         if (signerAddress != msg.sender) { | ||||
|             require( | ||||
|                 isValidSignature( | ||||
|                     hash, | ||||
|                     signerAddress, | ||||
|                     signature | ||||
|                 ), | ||||
|                 "INVALID_SIGNATURE" | ||||
|             ); | ||||
|         } | ||||
|         preSigned[hash][signerAddress] = true; | ||||
|     } | ||||
|  | ||||
| @@ -67,6 +71,7 @@ contract MixinSignatureValidator is | ||||
|         bool approval | ||||
|     ) | ||||
|         external | ||||
|         nonReentrant | ||||
|     { | ||||
|         address signerAddress = getCurrentContextAddress(); | ||||
|         allowedValidators[signerAddress][validatorAddress] = approval; | ||||
| @@ -172,26 +177,14 @@ contract MixinSignatureValidator is | ||||
|             isValid = signerAddress == recovered; | ||||
|             return isValid; | ||||
|  | ||||
|         // Implicitly signed by caller. | ||||
|         // The signer has initiated the call. In the case of non-contract | ||||
|         // accounts it means the transaction itself was signed. | ||||
|         // Example: let's say for a particular operation three signatures | ||||
|         // A, B and C are required. To submit the transaction, A and B can | ||||
|         // give a signature to C, who can then submit the transaction using | ||||
|         // `Caller` for his own signature. Or A and C can sign and B can | ||||
|         // submit using `Caller`. Having `Caller` allows this flexibility. | ||||
|         } else if (signatureType == SignatureType.Caller) { | ||||
|             require( | ||||
|                 signature.length == 0, | ||||
|                 "LENGTH_0_REQUIRED" | ||||
|             ); | ||||
|             isValid = signerAddress == msg.sender; | ||||
|             return isValid; | ||||
|  | ||||
|         // Signature verified by wallet contract. | ||||
|         // If used with an order, the maker of the order is the wallet contract. | ||||
|         } else if (signatureType == SignatureType.Wallet) { | ||||
|             isValid = IWallet(signerAddress).isValidSignature(hash, signature); | ||||
|             isValid = isValidWalletSignature( | ||||
|                 hash, | ||||
|                 signerAddress, | ||||
|                 signature | ||||
|             ); | ||||
|             return isValid; | ||||
|  | ||||
|         // Signature verified by validator contract. | ||||
| @@ -209,7 +202,8 @@ contract MixinSignatureValidator is | ||||
|             if (!allowedValidators[signerAddress][validatorAddress]) { | ||||
|                 return false; | ||||
|             } | ||||
|             isValid = IValidator(validatorAddress).isValidSignature( | ||||
|             isValid = isValidValidatorSignature( | ||||
|                 validatorAddress, | ||||
|                 hash, | ||||
|                 signerAddress, | ||||
|                 signature | ||||
| @@ -220,34 +214,6 @@ contract MixinSignatureValidator is | ||||
|         } else if (signatureType == SignatureType.PreSigned) { | ||||
|             isValid = preSigned[hash][signerAddress]; | ||||
|             return isValid; | ||||
|  | ||||
|         // Signature from Trezor hardware wallet. | ||||
|         // It differs from web3.eth_sign in the encoding of message length | ||||
|         // (Bitcoin varint encoding vs ascii-decimal, the latter is not | ||||
|         // self-terminating which leads to ambiguities). | ||||
|         // See also: | ||||
|         // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer | ||||
|         // https://github.com/trezor/trezor-mcu/blob/master/firmware/ethereum.c#L602 | ||||
|         // https://github.com/trezor/trezor-mcu/blob/master/firmware/crypto.c#L36 | ||||
|         } else if (signatureType == SignatureType.Trezor) { | ||||
|             require( | ||||
|                 signature.length == 65, | ||||
|                 "LENGTH_65_REQUIRED" | ||||
|             ); | ||||
|             v = uint8(signature[0]); | ||||
|             r = signature.readBytes32(1); | ||||
|             s = signature.readBytes32(33); | ||||
|             recovered = ecrecover( | ||||
|                 keccak256(abi.encodePacked( | ||||
|                     "\x19Ethereum Signed Message:\n\x20", | ||||
|                     hash | ||||
|                 )), | ||||
|                 v, | ||||
|                 r, | ||||
|                 s | ||||
|             ); | ||||
|             isValid = signerAddress == recovered; | ||||
|             return isValid; | ||||
|         } | ||||
|  | ||||
|         // Anything else is illegal (We do not return false because | ||||
| @@ -257,4 +223,102 @@ contract MixinSignatureValidator is | ||||
|         // signature was invalid.) | ||||
|         revert("SIGNATURE_UNSUPPORTED"); | ||||
|     } | ||||
|  | ||||
|     /// @dev Verifies signature using logic defined by Wallet contract. | ||||
|     /// @param hash Any 32 byte hash. | ||||
|     /// @param walletAddress Address that should have signed the given hash | ||||
|     ///                      and defines its own signature verification method. | ||||
|     /// @param signature Proof that the hash has been signed by signer. | ||||
|     /// @return True if signature is valid for given wallet.. | ||||
|     function isValidWalletSignature( | ||||
|         bytes32 hash, | ||||
|         address walletAddress, | ||||
|         bytes signature | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|         returns (bool isValid) | ||||
|     { | ||||
|         bytes memory calldata = abi.encodeWithSelector( | ||||
|             IWallet(walletAddress).isValidSignature.selector, | ||||
|             hash, | ||||
|             signature | ||||
|         ); | ||||
|         assembly { | ||||
|             let cdStart := add(calldata, 32) | ||||
|             let success := staticcall( | ||||
|                 gas,              // forward all gas | ||||
|                 walletAddress,    // address of Wallet contract | ||||
|                 cdStart,          // pointer to start of input | ||||
|                 mload(calldata),  // length of input | ||||
|                 cdStart,          // write output over input | ||||
|                 32                // output size is 32 bytes | ||||
|             ) | ||||
|  | ||||
|             switch success | ||||
|             case 0 { | ||||
|                 // Revert with `Error("WALLET_ERROR")` | ||||
|                 mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(64, 0x0000000c57414c4c45545f4552524f5200000000000000000000000000000000) | ||||
|                 mstore(96, 0) | ||||
|                 revert(0, 100) | ||||
|             } | ||||
|             case 1 { | ||||
|                 // Signature is valid if call did not revert and returned true | ||||
|                 isValid := mload(cdStart) | ||||
|             } | ||||
|         } | ||||
|         return isValid; | ||||
|     } | ||||
|  | ||||
|     /// @dev Verifies signature using logic defined by Validator contract. | ||||
|     /// @param validatorAddress Address of validator contract. | ||||
|     /// @param hash Any 32 byte hash. | ||||
|     /// @param signerAddress Address that should have signed the given hash. | ||||
|     /// @param signature Proof that the hash has been signed by signer. | ||||
|     /// @return True if the address recovered from the provided signature matches the input signer address. | ||||
|     function isValidValidatorSignature( | ||||
|         address validatorAddress, | ||||
|         bytes32 hash, | ||||
|         address signerAddress, | ||||
|         bytes signature | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|         returns (bool isValid) | ||||
|     { | ||||
|         bytes memory calldata = abi.encodeWithSelector( | ||||
|             IValidator(signerAddress).isValidSignature.selector, | ||||
|             hash, | ||||
|             signerAddress, | ||||
|             signature | ||||
|         ); | ||||
|         assembly { | ||||
|             let cdStart := add(calldata, 32) | ||||
|             let success := staticcall( | ||||
|                 gas,               // forward all gas | ||||
|                 validatorAddress,  // address of Validator contract | ||||
|                 cdStart,           // pointer to start of input | ||||
|                 mload(calldata),   // length of input | ||||
|                 cdStart,           // write output over input | ||||
|                 32                 // output size is 32 bytes | ||||
|             ) | ||||
|  | ||||
|             switch success | ||||
|             case 0 { | ||||
|                 // Revert with `Error("VALIDATOR_ERROR")` | ||||
|                 mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(64, 0x0000000f56414c494441544f525f4552524f5200000000000000000000000000) | ||||
|                 mstore(96, 0) | ||||
|                 revert(0, 100) | ||||
|             } | ||||
|             case 1 { | ||||
|                 // Signature is valid if call did not revert and returned true | ||||
|                 isValid := mload(cdStart) | ||||
|             } | ||||
|         } | ||||
|         return isValid; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ contract MixinTransactions is | ||||
|     MSignatureValidator, | ||||
|     MTransactions | ||||
| { | ||||
|  | ||||
|     // Mapping of transaction hash => executed | ||||
|     // This prevents transactions from being executed more than once. | ||||
|     mapping (bytes32 => bool) public transactions; | ||||
| @@ -36,15 +35,6 @@ contract MixinTransactions is | ||||
|     // Address of current transaction signer | ||||
|     address public currentContextAddress; | ||||
|  | ||||
|     // Hash for the EIP712 ZeroEx Transaction Schema | ||||
|     bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked( | ||||
|         "ZeroExTransaction(", | ||||
|         "uint256 salt,", | ||||
|         "address signerAddress,", | ||||
|         "bytes data", | ||||
|         ")" | ||||
|     )); | ||||
|  | ||||
|     /// @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. | ||||
| @@ -155,7 +145,8 @@ contract MixinTransactions is | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         address contextAddress = currentContextAddress == address(0) ? msg.sender : currentContextAddress; | ||||
|         address currentContextAddress_ = currentContextAddress; | ||||
|         address contextAddress = currentContextAddress_ == address(0) ? msg.sender : currentContextAddress_; | ||||
|         return contextAddress; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,20 +19,23 @@ | ||||
| pragma solidity 0.4.24; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../../utils/ReentrancyGuard/ReentrancyGuard.sol"; | ||||
| import "./libs/LibMath.sol"; | ||||
| import "./libs/LibOrder.sol"; | ||||
| import "./libs/LibFillResults.sol"; | ||||
| import "./libs/LibAbiEncoder.sol"; | ||||
| import "./mixins/MExchangeCore.sol"; | ||||
| import "./mixins/MWrapperFunctions.sol"; | ||||
|  | ||||
|  | ||||
| contract MixinWrapperFunctions is | ||||
|     ReentrancyGuard, | ||||
|     LibMath, | ||||
|     LibFillResults, | ||||
|     LibAbiEncoder, | ||||
|     MExchangeCore | ||||
|     MExchangeCore, | ||||
|     MWrapperFunctions | ||||
| { | ||||
|  | ||||
|     /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. | ||||
|     /// @param order Order struct containing order specifications. | ||||
|     /// @param takerAssetFillAmount Desired amount of takerAsset to sell. | ||||
| @@ -43,17 +46,14 @@ contract MixinWrapperFunctions is | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory fillResults) | ||||
|     { | ||||
|         fillResults = fillOrder( | ||||
|         fillResults = fillOrKillOrderInternal( | ||||
|             order, | ||||
|             takerAssetFillAmount, | ||||
|             signature | ||||
|         ); | ||||
|         require( | ||||
|             fillResults.takerAssetFilledAmount == takerAssetFillAmount, | ||||
|             "COMPLETE_FILL_FAILED" | ||||
|         ); | ||||
|         return fillResults; | ||||
|     } | ||||
|  | ||||
| @@ -81,27 +81,21 @@ contract MixinWrapperFunctions is | ||||
|         // Delegate to `fillOrder` and handle any exceptions gracefully | ||||
|         assembly { | ||||
|             let success := delegatecall( | ||||
|                 gas,                                // forward all gas, TODO: look into gas consumption of assert/throw | ||||
|                 gas,                                // forward all gas | ||||
|                 address,                            // call address of this contract | ||||
|                 add(fillOrderCalldata, 32),         // pointer to start of input (skip array length in first 32 bytes) | ||||
|                 mload(fillOrderCalldata),           // length of input | ||||
|                 fillOrderCalldata,                  // write output over input | ||||
|                 128                                 // output size is 128 bytes | ||||
|             ) | ||||
|             switch success | ||||
|             case 0 { | ||||
|                 mstore(fillResults, 0) | ||||
|                 mstore(add(fillResults, 32), 0) | ||||
|                 mstore(add(fillResults, 64), 0) | ||||
|                 mstore(add(fillResults, 96), 0) | ||||
|             } | ||||
|             case 1 { | ||||
|             if success { | ||||
|                 mstore(fillResults, mload(fillOrderCalldata)) | ||||
|                 mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32))) | ||||
|                 mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64))) | ||||
|                 mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96))) | ||||
|             } | ||||
|         } | ||||
|         // fillResults values will be 0 by default if call was unsuccessful | ||||
|         return fillResults; | ||||
|     } | ||||
|  | ||||
| @@ -117,11 +111,12 @@ contract MixinWrapperFunctions is | ||||
|         bytes[] memory signatures | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory totalFillResults) | ||||
|     { | ||||
|         uint256 ordersLength = orders.length; | ||||
|         for (uint256 i = 0; i != ordersLength; i++) { | ||||
|             FillResults memory singleFillResults = fillOrder( | ||||
|             FillResults memory singleFillResults = fillOrderInternal( | ||||
|                 orders[i], | ||||
|                 takerAssetFillAmounts[i], | ||||
|                 signatures[i] | ||||
| @@ -143,11 +138,12 @@ contract MixinWrapperFunctions is | ||||
|         bytes[] memory signatures | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory totalFillResults) | ||||
|     { | ||||
|         uint256 ordersLength = orders.length; | ||||
|         for (uint256 i = 0; i != ordersLength; i++) { | ||||
|             FillResults memory singleFillResults = fillOrKillOrder( | ||||
|             FillResults memory singleFillResults = fillOrKillOrderInternal( | ||||
|                 orders[i], | ||||
|                 takerAssetFillAmounts[i], | ||||
|                 signatures[i] | ||||
| @@ -195,6 +191,7 @@ contract MixinWrapperFunctions is | ||||
|         bytes[] memory signatures | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory totalFillResults) | ||||
|     { | ||||
|         bytes memory takerAssetData = orders[0].takerAssetData; | ||||
| @@ -210,7 +207,7 @@ contract MixinWrapperFunctions is | ||||
|             uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount); | ||||
|  | ||||
|             // Attempt to sell the remaining amount of takerAsset | ||||
|             FillResults memory singleFillResults = fillOrder( | ||||
|             FillResults memory singleFillResults = fillOrderInternal( | ||||
|                 orders[i], | ||||
|                 remainingTakerAssetFillAmount, | ||||
|                 signatures[i] | ||||
| @@ -282,6 +279,7 @@ contract MixinWrapperFunctions is | ||||
|         bytes[] memory signatures | ||||
|     ) | ||||
|         public | ||||
|         nonReentrant | ||||
|         returns (FillResults memory totalFillResults) | ||||
|     { | ||||
|         bytes memory makerAssetData = orders[0].makerAssetData; | ||||
| @@ -298,14 +296,14 @@ contract MixinWrapperFunctions is | ||||
|  | ||||
|             // Convert the remaining amount of makerAsset to buy into remaining amount | ||||
|             // of takerAsset to sell, assuming entire amount can be sold in the current order | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmount( | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmountFloor( | ||||
|                 orders[i].takerAssetAmount, | ||||
|                 orders[i].makerAssetAmount, | ||||
|                 remainingMakerAssetFillAmount | ||||
|             ); | ||||
|  | ||||
|             // Attempt to sell the remaining amount of takerAsset | ||||
|             FillResults memory singleFillResults = fillOrder( | ||||
|             FillResults memory singleFillResults = fillOrderInternal( | ||||
|                 orders[i], | ||||
|                 remainingTakerAssetFillAmount, | ||||
|                 signatures[i] | ||||
| @@ -350,7 +348,7 @@ contract MixinWrapperFunctions is | ||||
|  | ||||
|             // Convert the remaining amount of makerAsset to buy into remaining amount | ||||
|             // of takerAsset to sell, assuming entire amount can be sold in the current order | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmount( | ||||
|             uint256 remainingTakerAssetFillAmount = getPartialAmountFloor( | ||||
|                 orders[i].takerAssetAmount, | ||||
|                 orders[i].makerAssetAmount, | ||||
|                 remainingMakerAssetFillAmount | ||||
| @@ -378,10 +376,11 @@ contract MixinWrapperFunctions is | ||||
|     /// @param orders Array of order specifications. | ||||
|     function batchCancelOrders(LibOrder.Order[] memory orders) | ||||
|         public | ||||
|         nonReentrant | ||||
|     { | ||||
|         uint256 ordersLength = orders.length; | ||||
|         for (uint256 i = 0; i != ordersLength; i++) { | ||||
|             cancelOrder(orders[i]); | ||||
|             cancelOrderInternal(orders[i]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -400,4 +399,28 @@ contract MixinWrapperFunctions is | ||||
|         } | ||||
|         return ordersInfo; | ||||
|     } | ||||
|  | ||||
|     /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. | ||||
|     /// @param order Order struct containing order specifications. | ||||
|     /// @param takerAssetFillAmount Desired amount of takerAsset to sell. | ||||
|     /// @param signature Proof that order has been created by maker. | ||||
|     function fillOrKillOrderInternal( | ||||
|         LibOrder.Order memory order, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
|         returns (FillResults memory fillResults) | ||||
|     { | ||||
|         fillResults = fillOrderInternal( | ||||
|             order, | ||||
|             takerAssetFillAmount, | ||||
|             signature | ||||
|         ); | ||||
|         require( | ||||
|             fillResults.takerAssetFilledAmount == takerAssetFillAmount, | ||||
|             "COMPLETE_FILL_FAILED" | ||||
|         ); | ||||
|         return fillResults; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,6 +20,7 @@ pragma solidity 0.4.24; | ||||
|  | ||||
|  | ||||
| contract LibEIP712 { | ||||
|  | ||||
|     // EIP191 header for EIP712 prefix | ||||
|     string constant internal EIP191_HEADER = "\x19\x01"; | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../../../utils/SafeMath/SafeMath.sol"; | ||||
| contract LibFillResults is | ||||
|     SafeMath | ||||
| { | ||||
|  | ||||
|     struct FillResults { | ||||
|         uint256 makerAssetFilledAmount;  // Total amount of makerAsset(s) filled. | ||||
|         uint256 takerAssetFilledAmount;  // Total amount of takerAsset(s) filled. | ||||
|   | ||||
| @@ -24,13 +24,13 @@ import "../../../utils/SafeMath/SafeMath.sol"; | ||||
| contract LibMath is | ||||
|     SafeMath | ||||
| { | ||||
|  | ||||
|     /// @dev Calculates partial value given a numerator and denominator. | ||||
|     /// @dev Calculates partial value given a numerator and denominator rounded down. | ||||
|     ///      Reverts if rounding error is >= 0.1% | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target. | ||||
|     function getPartialAmount( | ||||
|     /// @return Partial value of target rounded down. | ||||
|     function safeGetPartialAmountFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -39,6 +39,20 @@ contract LibMath is | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|  | ||||
|         require( | ||||
|             !isRoundingErrorFloor( | ||||
|                 numerator, | ||||
|                 denominator, | ||||
|                 target | ||||
|             ), | ||||
|             "ROUNDING_ERROR" | ||||
|         ); | ||||
|          | ||||
|         partialAmount = safeDiv( | ||||
|             safeMul(numerator, target), | ||||
|             denominator | ||||
| @@ -46,12 +60,112 @@ contract LibMath is | ||||
|         return partialAmount; | ||||
|     } | ||||
|  | ||||
|     /// @dev Checks if rounding error > 0.1%. | ||||
|     /// @dev Calculates partial value given a numerator and denominator rounded down. | ||||
|     ///      Reverts if rounding error is >= 0.1% | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target rounded up. | ||||
|     function safeGetPartialAmountCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|  | ||||
|         require( | ||||
|             !isRoundingErrorCeil( | ||||
|                 numerator, | ||||
|                 denominator, | ||||
|                 target | ||||
|             ), | ||||
|             "ROUNDING_ERROR" | ||||
|         ); | ||||
|          | ||||
|         // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): | ||||
|         //       ceil(a / b) = floor((a + b - 1) / b) | ||||
|         // To implement `ceil(a / b)` using safeDiv. | ||||
|         partialAmount = safeDiv( | ||||
|             safeAdd( | ||||
|                 safeMul(numerator, target), | ||||
|                 safeSub(denominator, 1) | ||||
|             ), | ||||
|             denominator | ||||
|         ); | ||||
|         return partialAmount; | ||||
|     } | ||||
|  | ||||
|     /// @dev Calculates partial value given a numerator and denominator rounded down. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target rounded down. | ||||
|     function getPartialAmountFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|  | ||||
|         partialAmount = safeDiv( | ||||
|             safeMul(numerator, target), | ||||
|             denominator | ||||
|         ); | ||||
|         return partialAmount; | ||||
|     } | ||||
|      | ||||
|     /// @dev Calculates partial value given a numerator and denominator rounded down. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target rounded up. | ||||
|     function getPartialAmountCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|  | ||||
|         // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): | ||||
|         //       ceil(a / b) = floor((a + b - 1) / b) | ||||
|         // To implement `ceil(a / b)` using safeDiv. | ||||
|         partialAmount = safeDiv( | ||||
|             safeAdd( | ||||
|                 safeMul(numerator, target), | ||||
|                 safeSub(denominator, 1) | ||||
|             ), | ||||
|             denominator | ||||
|         ); | ||||
|         return partialAmount; | ||||
|     } | ||||
|      | ||||
|     /// @dev Checks if rounding error >= 0.1% when rounding down. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to multiply with numerator/denominator. | ||||
|     /// @return Rounding error is present. | ||||
|     function isRoundingError( | ||||
|     function isRoundingErrorFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -60,16 +174,80 @@ contract LibMath is | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         uint256 remainder = mulmod(target, numerator, denominator); | ||||
|         if (remainder == 0) { | ||||
|             return false; // No rounding error. | ||||
|         } | ||||
|  | ||||
|         uint256 errPercentageTimes1000000 = safeDiv( | ||||
|             safeMul(remainder, 1000000), | ||||
|             safeMul(numerator, target) | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|         isError = errPercentageTimes1000000 > 1000; | ||||
|          | ||||
|         // The absolute rounding error is the difference between the rounded | ||||
|         // value and the ideal value. The relative rounding error is the | ||||
|         // absolute rounding error divided by the absolute value of the | ||||
|         // ideal value. This is undefined when the ideal value is zero. | ||||
|         // | ||||
|         // The ideal value is `numerator * target / denominator`. | ||||
|         // Let's call `numerator * target % denominator` the remainder. | ||||
|         // The absolute error is `remainder / denominator`. | ||||
|         // | ||||
|         // When the ideal value is zero, we require the absolute error to | ||||
|         // be zero. Fortunately, this is always the case. The ideal value is | ||||
|         // zero iff `numerator == 0` and/or `target == 0`. In this case the | ||||
|         // remainder and absolute error are also zero.  | ||||
|         if (target == 0 || numerator == 0) { | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|         // Otherwise, we want the relative rounding error to be strictly | ||||
|         // less than 0.1%. | ||||
|         // The relative error is `remainder / (numerator * target)`. | ||||
|         // We want the relative error less than 1 / 1000: | ||||
|         //        remainder / (numerator * denominator)  <  1 / 1000 | ||||
|         // or equivalently: | ||||
|         //        1000 * remainder  <  numerator * target | ||||
|         // so we have a rounding error iff: | ||||
|         //        1000 * remainder  >=  numerator * target | ||||
|         uint256 remainder = mulmod( | ||||
|             target, | ||||
|             numerator, | ||||
|             denominator | ||||
|         ); | ||||
|         isError = safeMul(1000, remainder) >= safeMul(numerator, target); | ||||
|         return isError; | ||||
|     } | ||||
|      | ||||
|     /// @dev Checks if rounding error >= 0.1% when rounding up. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to multiply with numerator/denominator. | ||||
|     /// @return Rounding error is present. | ||||
|     function isRoundingErrorCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         require( | ||||
|             denominator > 0, | ||||
|             "DIVISION_BY_ZERO" | ||||
|         ); | ||||
|          | ||||
|         // See the comments in `isRoundingError`. | ||||
|         if (target == 0 || numerator == 0) { | ||||
|             // When either is zero, the ideal value and rounded value are zero | ||||
|             // and there is no rounding error. (Although the relative error | ||||
|             // is undefined.) | ||||
|             return false; | ||||
|         } | ||||
|         // Compute remainder as before | ||||
|         uint256 remainder = mulmod( | ||||
|             target, | ||||
|             numerator, | ||||
|             denominator | ||||
|         ); | ||||
|         remainder = safeSub(denominator, remainder) % denominator; | ||||
|         isError = safeMul(1000, remainder) >= safeMul(numerator, target); | ||||
|         return isError; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "./LibEIP712.sol"; | ||||
| contract LibOrder is | ||||
|     LibEIP712 | ||||
| { | ||||
|  | ||||
|     // Hash for the EIP712 Order Schema | ||||
|     bytes32 constant internal EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( | ||||
|         "Order(", | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../interfaces/IAssetProxyDispatcher.sol"; | ||||
| contract MAssetProxyDispatcher is | ||||
|     IAssetProxyDispatcher | ||||
| { | ||||
|  | ||||
|     // Logs registration of new asset proxy | ||||
|     event AssetProxyRegistered( | ||||
|         bytes4 id,              // Id of new registered AssetProxy. | ||||
|   | ||||
| @@ -59,6 +59,24 @@ contract MExchangeCore is | ||||
|         uint256 orderEpoch                    // Orders with specified makerAddress and senderAddress with a salt less than this value are considered cancelled. | ||||
|     ); | ||||
|  | ||||
|     /// @dev Fills the input order. | ||||
|     /// @param order Order struct containing order specifications. | ||||
|     /// @param takerAssetFillAmount Desired amount of takerAsset to sell. | ||||
|     /// @param signature Proof that order has been created by maker. | ||||
|     /// @return Amounts filled and fees paid by maker and taker. | ||||
|     function fillOrderInternal( | ||||
|         LibOrder.Order memory order, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
|         returns (LibFillResults.FillResults memory fillResults); | ||||
|  | ||||
|     /// @dev After calling, the order can not be filled anymore. | ||||
|     /// @param order Order struct containing order specifications. | ||||
|     function cancelOrderInternal(LibOrder.Order memory order) | ||||
|         internal; | ||||
|  | ||||
|     /// @dev Updates state with results of a fill order. | ||||
|     /// @param order that was filled. | ||||
|     /// @param takerAddress Address of taker who filled the order. | ||||
| @@ -83,21 +101,33 @@ contract MExchangeCore is | ||||
|         bytes32 orderHash | ||||
|     ) | ||||
|         internal; | ||||
|  | ||||
|      | ||||
|     /// @dev Validates context for fillOrder. Succeeds or throws. | ||||
|     /// @param order to be filled. | ||||
|     /// @param orderInfo Status, orderHash, and amount already filled of order. | ||||
|     /// @param orderInfo OrderStatus, orderHash, and amount already filled of order. | ||||
|     /// @param takerAddress Address of order taker. | ||||
|     /// @param takerAssetFillAmount Desired amount of order to fill by taker. | ||||
|     /// @param takerAssetFilledAmount Amount of takerAsset that will be filled. | ||||
|     /// @param signature Proof that the orders was created by its maker. | ||||
|     function assertValidFill( | ||||
|     function assertFillableOrder( | ||||
|         LibOrder.Order memory order, | ||||
|         LibOrder.OrderInfo memory orderInfo, | ||||
|         address takerAddress, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
|         view; | ||||
|      | ||||
|     /// @dev Validates context for fillOrder. Succeeds or throws. | ||||
|     /// @param order to be filled. | ||||
|     /// @param orderInfo Status, orderHash, and amount already filled of order. | ||||
|     /// @param takerAssetFillAmount Desired amount of order to fill by taker. | ||||
|     /// @param takerAssetFilledAmount Amount of takerAsset that will be filled. | ||||
|     /// @param makerAssetFilledAmount Amount of makerAsset that will be transfered. | ||||
|     function assertValidFill( | ||||
|         LibOrder.Order memory order, | ||||
|         LibOrder.OrderInfo memory orderInfo, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         uint256 takerAssetFilledAmount, | ||||
|         bytes memory signature | ||||
|         uint256 makerAssetFilledAmount | ||||
|     ) | ||||
|         internal | ||||
|         view; | ||||
|   | ||||
| @@ -26,7 +26,6 @@ import "../interfaces/IMatchOrders.sol"; | ||||
| contract MMatchOrders is | ||||
|     IMatchOrders | ||||
| { | ||||
|  | ||||
|     /// @dev Validates context for matchOrders. Succeeds or throws. | ||||
|     /// @param leftOrder First order to match. | ||||
|     /// @param rightOrder Second order to match. | ||||
|   | ||||
| @@ -36,11 +36,40 @@ contract MSignatureValidator is | ||||
|         Invalid,         // 0x01 | ||||
|         EIP712,          // 0x02 | ||||
|         EthSign,         // 0x03 | ||||
|         Caller,          // 0x04 | ||||
|         Wallet,          // 0x05 | ||||
|         Validator,       // 0x06 | ||||
|         PreSigned,       // 0x07 | ||||
|         Trezor,          // 0x08 | ||||
|         NSignatureTypes  // 0x09, number of signature types. Always leave at end. | ||||
|         Wallet,          // 0x04 | ||||
|         Validator,       // 0x05 | ||||
|         PreSigned,       // 0x06 | ||||
|         NSignatureTypes  // 0x07, number of signature types. Always leave at end. | ||||
|     } | ||||
|  | ||||
|     /// @dev Verifies signature using logic defined by Wallet contract. | ||||
|     /// @param hash Any 32 byte hash. | ||||
|     /// @param walletAddress Address that should have signed the given hash | ||||
|     ///                      and defines its own signature verification method. | ||||
|     /// @param signature Proof that the hash has been signed by signer. | ||||
|     /// @return True if the address recovered from the provided signature matches the input signer address. | ||||
|     function isValidWalletSignature( | ||||
|         bytes32 hash, | ||||
|         address walletAddress, | ||||
|         bytes signature | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|         returns (bool isValid); | ||||
|  | ||||
|     /// @dev Verifies signature using logic defined by Validator contract. | ||||
|     /// @param validatorAddress Address of validator contract. | ||||
|     /// @param hash Any 32 byte hash. | ||||
|     /// @param signerAddress Address that should have signed the given hash. | ||||
|     /// @param signature Proof that the hash has been signed by signer. | ||||
|     /// @return True if the address recovered from the provided signature matches the input signer address. | ||||
|     function isValidValidatorSignature( | ||||
|         address validatorAddress, | ||||
|         bytes32 hash, | ||||
|         address signerAddress, | ||||
|         bytes signature | ||||
|     ) | ||||
|         internal | ||||
|         view | ||||
|         returns (bool isValid); | ||||
| } | ||||
|   | ||||
| @@ -23,6 +23,28 @@ import "../interfaces/ITransactions.sol"; | ||||
| contract MTransactions is | ||||
|     ITransactions | ||||
| { | ||||
|     // Hash for the EIP712 ZeroEx Transaction Schema | ||||
|     bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked( | ||||
|         "ZeroExTransaction(", | ||||
|         "uint256 salt,", | ||||
|         "address signerAddress,", | ||||
|         "bytes data", | ||||
|         ")" | ||||
|     )); | ||||
|  | ||||
|     /// @dev Calculates EIP712 hash of the Transaction. | ||||
|     /// @param salt Arbitrary number to ensure uniqueness of transaction hash. | ||||
|     /// @param signerAddress Address of transaction signer. | ||||
|     /// @param data AbiV2 encoded calldata. | ||||
|     /// @return EIP712 hash of the Transaction. | ||||
|     function hashZeroExTransaction( | ||||
|         uint256 salt, | ||||
|         address signerAddress, | ||||
|         bytes memory data | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (bytes32 result); | ||||
|  | ||||
|     /// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`). | ||||
|     ///      If calling a fill function, this address will represent the taker. | ||||
|   | ||||
							
								
								
									
										41
									
								
								packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol
									
									
									
									
										vendored
									
									
										Normal 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.4.24; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../libs/LibOrder.sol"; | ||||
| import "../libs/LibFillResults.sol"; | ||||
| import "../interfaces/IWrapperFunctions.sol"; | ||||
|  | ||||
|  | ||||
| contract MWrapperFunctions is  | ||||
|     IWrapperFunctions | ||||
| { | ||||
|     /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. | ||||
|     /// @param order LibOrder.Order struct containing order specifications. | ||||
|     /// @param takerAssetFillAmount Desired amount of takerAsset to sell. | ||||
|     /// @param signature Proof that order has been created by maker. | ||||
|     function fillOrKillOrderInternal( | ||||
|         LibOrder.Order memory order, | ||||
|         uint256 takerAssetFillAmount, | ||||
|         bytes memory signature | ||||
|     ) | ||||
|         internal | ||||
|         returns (LibFillResults.FillResults memory fillResults); | ||||
| } | ||||
							
								
								
									
										69
									
								
								packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|  | ||||
|   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.4.24; | ||||
|  | ||||
| import "./DummyERC20Token.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable no-empty-blocks | ||||
| contract DummyMultipleReturnERC20Token is | ||||
|     DummyERC20Token | ||||
| { | ||||
|     constructor ( | ||||
|         string _name, | ||||
|         string _symbol, | ||||
|         uint256 _decimals, | ||||
|         uint256 _totalSupply | ||||
|     ) | ||||
|         public | ||||
|         DummyERC20Token( | ||||
|             _name, | ||||
|             _symbol, | ||||
|             _decimals, | ||||
|             _totalSupply | ||||
|         ) | ||||
|     {} | ||||
|  | ||||
|     /// @dev send `value` token to `to` from `from` on the condition it is approved by `from` | ||||
|     /// @param _from The address of the sender | ||||
|     /// @param _to The address of the recipient | ||||
|     /// @param _value The amount of token to be transferred | ||||
|     function transferFrom( | ||||
|         address _from, | ||||
|         address _to, | ||||
|         uint256 _value | ||||
|     ) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         emit Transfer( | ||||
|             _from, | ||||
|             _to, | ||||
|             _value | ||||
|         ); | ||||
|  | ||||
|         // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes (equiavalent to true, true) | ||||
|         assembly { | ||||
|             mstore(0, 1) | ||||
|             mstore(32, 1) | ||||
|             return(0, 64) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -25,7 +25,6 @@ import "./DummyERC20Token.sol"; | ||||
| contract DummyNoReturnERC20Token is | ||||
|     DummyERC20Token | ||||
| { | ||||
|  | ||||
|     constructor ( | ||||
|         string _name, | ||||
|         string _symbol, | ||||
|   | ||||
| @@ -24,7 +24,6 @@ import "../../tokens/ERC721Token/IERC721Receiver.sol"; | ||||
| contract DummyERC721Receiver is | ||||
|     IERC721Receiver | ||||
| { | ||||
|  | ||||
|     // Function selector for ERC721Receiver.onERC721Received | ||||
|     // 0x150b7a02 | ||||
|     bytes4 constant internal ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); | ||||
|   | ||||
							
								
								
									
										188
									
								
								packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| /* | ||||
|  | ||||
|   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.4.24; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../../utils/LibBytes/LibBytes.sol"; | ||||
| import "../../tokens/ERC20Token/ERC20Token.sol"; | ||||
| import "../../protocol/Exchange/interfaces/IExchange.sol"; | ||||
| import "../../protocol/Exchange/libs/LibOrder.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable no-unused-vars | ||||
| contract ReentrantERC20Token is | ||||
|     ERC20Token | ||||
| { | ||||
|     using LibBytes for bytes; | ||||
|  | ||||
|     // solhint-disable-next-line var-name-mixedcase | ||||
|     IExchange internal EXCHANGE; | ||||
|  | ||||
|     bytes internal constant REENTRANCY_ILLEGAL_REVERT_REASON = abi.encodeWithSelector( | ||||
|         bytes4(keccak256("Error(string)")), | ||||
|         "REENTRANCY_ILLEGAL" | ||||
|     ); | ||||
|  | ||||
|     // All of these functions are potentially vulnerable to reentrancy | ||||
|     // We do not test any "noThrow" functions because `fillOrderNoThrow` makes a delegatecall to `fillOrder` | ||||
|     enum ExchangeFunction { | ||||
|         FILL_ORDER, | ||||
|         FILL_OR_KILL_ORDER, | ||||
|         BATCH_FILL_ORDERS, | ||||
|         BATCH_FILL_OR_KILL_ORDERS, | ||||
|         MARKET_BUY_ORDERS, | ||||
|         MARKET_SELL_ORDERS, | ||||
|         MATCH_ORDERS, | ||||
|         CANCEL_ORDER, | ||||
|         BATCH_CANCEL_ORDERS, | ||||
|         CANCEL_ORDERS_UP_TO, | ||||
|         SET_SIGNATURE_VALIDATOR_APPROVAL | ||||
|     } | ||||
|  | ||||
|     uint8 internal currentFunctionId = 0; | ||||
|  | ||||
|     constructor (address _exchange) | ||||
|         public | ||||
|     { | ||||
|         EXCHANGE = IExchange(_exchange); | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the current function that will be called when `transferFrom` is called. | ||||
|     /// @param _currentFunctionId Id that corresponds to function name. | ||||
|     function setCurrentFunction(uint8 _currentFunctionId) | ||||
|         external | ||||
|     { | ||||
|         currentFunctionId = _currentFunctionId; | ||||
|     } | ||||
|  | ||||
|     /// @dev A version of `transferFrom` that attempts to reenter the Exchange contract. | ||||
|     /// @param _from The address of the sender | ||||
|     /// @param _to The address of the recipient | ||||
|     /// @param _value The amount of token to be transferred | ||||
|     function transferFrom( | ||||
|         address _from, | ||||
|         address _to, | ||||
|         uint256 _value | ||||
|     ) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         // This order would normally be invalid, but it will be used strictly for testing reentrnacy. | ||||
|         // Any reentrancy checks will happen before any other checks that invalidate the order. | ||||
|         LibOrder.Order memory order; | ||||
|  | ||||
|         // Initialize remaining null parameters | ||||
|         bytes memory signature; | ||||
|         LibOrder.Order[] memory orders; | ||||
|         uint256[] memory takerAssetFillAmounts; | ||||
|         bytes[] memory signatures; | ||||
|         bytes memory calldata; | ||||
|  | ||||
|         // Create calldata for function that corresponds to currentFunctionId | ||||
|         if (currentFunctionId == uint8(ExchangeFunction.FILL_ORDER)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.fillOrder.selector, | ||||
|                 order, | ||||
|                 0, | ||||
|                 signature | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.FILL_OR_KILL_ORDER)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.fillOrKillOrder.selector, | ||||
|                 order, | ||||
|                 0, | ||||
|                 signature | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.BATCH_FILL_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.batchFillOrders.selector, | ||||
|                 orders, | ||||
|                 takerAssetFillAmounts, | ||||
|                 signatures | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.BATCH_FILL_OR_KILL_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.batchFillOrKillOrders.selector, | ||||
|                 orders, | ||||
|                 takerAssetFillAmounts, | ||||
|                 signatures | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.MARKET_BUY_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.marketBuyOrders.selector, | ||||
|                 orders, | ||||
|                 0, | ||||
|                 signatures | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.MARKET_SELL_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.marketSellOrders.selector, | ||||
|                 orders, | ||||
|                 0, | ||||
|                 signatures | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.MATCH_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.matchOrders.selector, | ||||
|                 order, | ||||
|                 order, | ||||
|                 signature, | ||||
|                 signature | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDER)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.cancelOrder.selector, | ||||
|                 order | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.BATCH_CANCEL_ORDERS)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.batchCancelOrders.selector, | ||||
|                 orders | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDERS_UP_TO)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.cancelOrdersUpTo.selector, | ||||
|                 0 | ||||
|             ); | ||||
|         } else if (currentFunctionId == uint8(ExchangeFunction.SET_SIGNATURE_VALIDATOR_APPROVAL)) { | ||||
|             calldata = abi.encodeWithSelector( | ||||
|                 EXCHANGE.setSignatureValidatorApproval.selector, | ||||
|                 address(0), | ||||
|                 false | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         // Call Exchange function, swallow error | ||||
|         address(EXCHANGE).call(calldata); | ||||
|  | ||||
|         // Revert reason is 100 bytes | ||||
|         bytes memory returnData = new bytes(100); | ||||
|  | ||||
|         // Copy return data | ||||
|         assembly { | ||||
|             returndatacopy(add(returnData, 32), 0, 100) | ||||
|         } | ||||
|  | ||||
|         // Revert if function reverted with REENTRANCY_ILLEGAL error | ||||
|         require(!REENTRANCY_ILLEGAL_REVERT_REASON.equals(returnData)); | ||||
|  | ||||
|         // Transfer will return true if function failed for any other reason | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @@ -16,7 +16,7 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity 0.4.10; | ||||
| pragma solidity 0.4.24; | ||||
|  | ||||
| import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol"; | ||||
|  | ||||
| @@ -25,8 +25,7 @@ import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol"; | ||||
| contract TestAssetProxyOwner is | ||||
|     AssetProxyOwner | ||||
| { | ||||
|  | ||||
|     function TestAssetProxyOwner( | ||||
|     constructor ( | ||||
|         address[] memory _owners, | ||||
|         address[] memory _assetProxyContracts, | ||||
|         uint256 _required, | ||||
| @@ -38,6 +37,7 @@ contract TestAssetProxyOwner is | ||||
|      | ||||
|     function testValidRemoveAuthorizedAddressAtIndexTx(uint256 id) | ||||
|         public | ||||
|         view | ||||
|         validRemoveAuthorizedAddressAtIndexTx(id) | ||||
|         returns (bool) | ||||
|     { | ||||
| @@ -50,23 +50,9 @@ contract TestAssetProxyOwner is | ||||
|     /// @return Successful if data is a call to `removeAuthorizedAddressAtIndex`. | ||||
|     function isFunctionRemoveAuthorizedAddressAtIndex(bytes memory data) | ||||
|         public | ||||
|         pure | ||||
|         returns (bool) | ||||
|     { | ||||
|         return readBytes4(data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR; | ||||
|     } | ||||
|  | ||||
|     /// @dev Reads an unpadded bytes4 value from a position in a byte array. | ||||
|     /// @param b Byte array containing a bytes4 value. | ||||
|     /// @param index Index in byte array of bytes4 value. | ||||
|     /// @return bytes4 value from byte array. | ||||
|     function publicReadBytes4( | ||||
|         bytes memory b, | ||||
|         uint256 index | ||||
|     ) | ||||
|         public | ||||
|         returns (bytes4 result) | ||||
|     { | ||||
|         result = readBytes4(b, index); | ||||
|         return result; | ||||
|         return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -63,11 +63,12 @@ contract TestExchangeInternals is | ||||
|     } | ||||
|  | ||||
|     /// @dev Calculates partial value given a numerator and denominator. | ||||
|     ///      Reverts if rounding error is >= 0.1% | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target. | ||||
|     function publicGetPartialAmount( | ||||
|     function publicSafeGetPartialAmountFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -76,15 +77,67 @@ contract TestExchangeInternals is | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         return getPartialAmount(numerator, denominator, target); | ||||
|         return safeGetPartialAmountFloor(numerator, denominator, target); | ||||
|     } | ||||
|  | ||||
|     /// @dev Checks if rounding error > 0.1%. | ||||
|     /// @dev Calculates partial value given a numerator and denominator. | ||||
|     ///      Reverts if rounding error is >= 0.1% | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target. | ||||
|     function publicSafeGetPartialAmountCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         return safeGetPartialAmountCeil(numerator, denominator, target); | ||||
|     } | ||||
|  | ||||
|     /// @dev Calculates partial value given a numerator and denominator. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target. | ||||
|     function publicGetPartialAmountFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         return getPartialAmountFloor(numerator, denominator, target); | ||||
|     } | ||||
|  | ||||
|     /// @dev Calculates partial value given a numerator and denominator. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to calculate partial of. | ||||
|     /// @return Partial value of target. | ||||
|     function publicGetPartialAmountCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         return getPartialAmountCeil(numerator, denominator, target); | ||||
|     } | ||||
|  | ||||
|     /// @dev Checks if rounding error >= 0.1%. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to multiply with numerator/denominator. | ||||
|     /// @return Rounding error is present. | ||||
|     function publicIsRoundingError( | ||||
|     function publicIsRoundingErrorFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -93,7 +146,24 @@ contract TestExchangeInternals is | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         return isRoundingError(numerator, denominator, target); | ||||
|         return isRoundingErrorFloor(numerator, denominator, target); | ||||
|     } | ||||
|  | ||||
|     /// @dev Checks if rounding error >= 0.1%. | ||||
|     /// @param numerator Numerator. | ||||
|     /// @param denominator Denominator. | ||||
|     /// @param target Value to multiply with numerator/denominator. | ||||
|     /// @return Rounding error is present. | ||||
|     function publicIsRoundingErrorCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         return isRoundingErrorCeil(numerator, denominator, target); | ||||
|     } | ||||
|   | ||||
|     /// @dev Updates state with results of a fill order. | ||||
|   | ||||
| @@ -31,7 +31,6 @@ contract TestLibs is | ||||
|     LibFillResults, | ||||
|     LibAbiEncoder | ||||
| { | ||||
|  | ||||
|     function publicAbiEncodeFillOrder( | ||||
|         Order memory order, | ||||
|         uint256 takerAssetFillAmount, | ||||
| @@ -49,7 +48,7 @@ contract TestLibs is | ||||
|         return fillOrderCalldata; | ||||
|     } | ||||
|  | ||||
|     function publicGetPartialAmount( | ||||
|     function publicGetPartialAmountFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -58,7 +57,7 @@ contract TestLibs is | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         partialAmount = getPartialAmount( | ||||
|         partialAmount = getPartialAmountFloor( | ||||
|             numerator, | ||||
|             denominator, | ||||
|             target | ||||
| @@ -66,7 +65,24 @@ contract TestLibs is | ||||
|         return partialAmount; | ||||
|     } | ||||
|  | ||||
|     function publicIsRoundingError( | ||||
|     function publicGetPartialAmountCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (uint256 partialAmount) | ||||
|     { | ||||
|         partialAmount = getPartialAmountCeil( | ||||
|             numerator, | ||||
|             denominator, | ||||
|             target | ||||
|         ); | ||||
|         return partialAmount; | ||||
|     } | ||||
|  | ||||
|     function publicIsRoundingErrorFloor( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
| @@ -75,7 +91,24 @@ contract TestLibs is | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         isError = isRoundingError( | ||||
|         isError = isRoundingErrorFloor( | ||||
|             numerator, | ||||
|             denominator, | ||||
|             target | ||||
|         ); | ||||
|         return isError; | ||||
|     } | ||||
|  | ||||
|     function publicIsRoundingErrorCeil( | ||||
|         uint256 numerator, | ||||
|         uint256 denominator, | ||||
|         uint256 target | ||||
|     ) | ||||
|         public | ||||
|         pure | ||||
|         returns (bool isError) | ||||
|     { | ||||
|         isError = isRoundingErrorCeil( | ||||
|             numerator, | ||||
|             denominator, | ||||
|             target | ||||
|   | ||||
| @@ -26,7 +26,6 @@ contract TestSignatureValidator is | ||||
|     MixinSignatureValidator, | ||||
|     MixinTransactions | ||||
| { | ||||
|  | ||||
|     function publicIsValidSignature( | ||||
|         bytes32 hash, | ||||
|         address signer, | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user