Compare commits
	
		
			329 Commits
		
	
	
		
			@0x/monore
			...
			monorepo@e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e853555165 | ||
| 
						 | 
					2ce09d73ac | ||
| 
						 | 
					14f48a5f4f | ||
| 
						 | 
					8da4e4a830 | ||
| 
						 | 
					88ae8311c8 | ||
| 
						 | 
					eabf6a466a | ||
| 
						 | 
					989f691d06 | ||
| 
						 | 
					52a3dae7cb | ||
| 
						 | 
					8a6dfacf71 | ||
| 
						 | 
					19ca6c13ad | ||
| 
						 | 
					9196f122dd | ||
| 
						 | 
					55e3d81c58 | ||
| 
						 | 
					80caa16718 | ||
| 
						 | 
					ddc5aaacdb | ||
| 
						 | 
					38825865cc | ||
| 
						 | 
					157b2efa1d | ||
| 
						 | 
					212a2d229a | ||
| 
						 | 
					ccb89fb26a | ||
| 
						 | 
					3a0b0c0973 | ||
| 
						 | 
					c159ed9ebb | ||
| 
						 | 
					e37dbcc273 | ||
| 
						 | 
					841e660b1f | ||
| 
						 | 
					391aba5f37 | ||
| 
						 | 
					f5d30f4a07 | ||
| 
						 | 
					230cf7dfb7 | ||
| 
						 | 
					8734b70f83 | ||
| 
						 | 
					ff9a2b2d9a | ||
| 
						 | 
					a41dab2922 | ||
| 
						 | 
					f4504106a1 | ||
| 
						 | 
					1a5b8041c7 | ||
| 
						 | 
					1e2170f8bb | ||
| 
						 | 
					0a4a973a7f | ||
| 
						 | 
					67137cadac | ||
| 
						 | 
					ead4afa06b | ||
| 
						 | 
					e39ef95191 | ||
| 
						 | 
					3d7585671f | ||
| 
						 | 
					44806106db | ||
| 
						 | 
					6a8197a4e8 | ||
| 
						 | 
					4d4b4e0f2b | ||
| 
						 | 
					82da33d742 | ||
| 
						 | 
					1c6130a492 | ||
| 
						 | 
					dabe5e939f | ||
| 
						 | 
					b4ac6d3439 | ||
| 
						 | 
					d0ea74e180 | ||
| 
						 | 
					a5f77f3964 | ||
| 
						 | 
					9401bb53e8 | ||
| 
						 | 
					347c6d02cf | ||
| 
						 | 
					64a0080616 | ||
| 
						 | 
					288a7d4cea | ||
| 
						 | 
					1207b68f57 | ||
| 
						 | 
					2b82187fe0 | ||
| 
						 | 
					3e2dbfc83c | ||
| 
						 | 
					6691f490bc | ||
| 
						 | 
					a7db900e51 | ||
| 
						 | 
					cfa2a90dae | ||
| 
						 | 
					feebb45e9d | ||
| 
						 | 
					13a2f3a330 | ||
| 
						 | 
					1da8801084 | ||
| 
						 | 
					7a7b17c4f3 | ||
| 
						 | 
					2afb06de13 | ||
| 
						 | 
					ac771e2865 | ||
| 
						 | 
					4b09204936 | ||
| 
						 | 
					e4a5518a7c | ||
| 
						 | 
					e83507ba98 | ||
| 
						 | 
					6e5b77edb2 | ||
| 
						 | 
					98167da8fa | ||
| 
						 | 
					11d5fec59b | ||
| 
						 | 
					ed02f4ca88 | ||
| 
						 | 
					e7c612971d | ||
| 
						 | 
					242a2e21b5 | ||
| 
						 | 
					92a1e5413b | ||
| 
						 | 
					e1ab9aa690 | ||
| 
						 | 
					222f7e6fd4 | ||
| 
						 | 
					59001f827b | ||
| 
						 | 
					549bfe98f1 | ||
| 
						 | 
					64e3b6f5ee | ||
| 
						 | 
					2fdc0426ff | ||
| 
						 | 
					e6c70fda66 | ||
| 
						 | 
					50da1354f3 | ||
| 
						 | 
					e503cacf57 | ||
| 
						 | 
					6a1e0edc78 | ||
| 
						 | 
					048f5c2771 | ||
| 
						 | 
					d9378e9a8f | ||
| 
						 | 
					f77aaaf2e0 | ||
| 
						 | 
					380835b151 | ||
| 
						 | 
					857d91df85 | ||
| 
						 | 
					cd9a6b0de7 | ||
| 
						 | 
					86333f4928 | ||
| 
						 | 
					d1975bd5dd | ||
| 
						 | 
					08b9f27eac | ||
| 
						 | 
					5b2cf8a776 | ||
| 
						 | 
					7394106880 | ||
| 
						 | 
					9134a7ae1e | ||
| 
						 | 
					c617e9f483 | ||
| 
						 | 
					545fcef716 | ||
| 
						 | 
					e20fa3a1bf | ||
| 
						 | 
					9d01b47d5b | ||
| 
						 | 
					fa4c34df41 | ||
| 
						 | 
					9f8ab4d626 | ||
| 
						 | 
					1971c9cecd | ||
| 
						 | 
					82f730831d | ||
| 
						 | 
					035167e5b7 | ||
| 
						 | 
					323fb0a965 | ||
| 
						 | 
					45aacf122f | ||
| 
						 | 
					5dcf7919fc | ||
| 
						 | 
					f15560bd89 | ||
| 
						 | 
					bf3ae730d6 | ||
| 
						 | 
					92ce258bb4 | ||
| 
						 | 
					5810e7df82 | ||
| 
						 | 
					f2cbf4a561 | ||
| 
						 | 
					0c8bb2e675 | ||
| 
						 | 
					f51c4f9617 | ||
| 
						 | 
					5345f7c983 | ||
| 
						 | 
					7d9e43b2e1 | ||
| 
						 | 
					570c1e1809 | ||
| 
						 | 
					720d335b09 | ||
| 
						 | 
					f0ecda1a48 | ||
| 
						 | 
					4ed111a7d4 | ||
| 
						 | 
					fc257523c7 | ||
| 
						 | 
					9775f8d83c | ||
| 
						 | 
					01a1b19556 | ||
| 
						 | 
					bd228034fd | ||
| 
						 | 
					2672a5c59f | ||
| 
						 | 
					5f383430eb | ||
| 
						 | 
					66ec3e9f4d | ||
| 
						 | 
					c269c427a6 | ||
| 
						 | 
					212855ebd8 | ||
| 
						 | 
					8f78945a73 | ||
| 
						 | 
					86d50cf597 | ||
| 
						 | 
					8986d506a5 | ||
| 
						 | 
					3d2c945c35 | ||
| 
						 | 
					8206a3969f | ||
| 
						 | 
					43afe67593 | ||
| 
						 | 
					ecf939f8c8 | ||
| 
						 | 
					f0c4ccfa1e | ||
| 
						 | 
					718d48b7d5 | ||
| 
						 | 
					d5e88677ae | ||
| 
						 | 
					b1cfdc7a6a | ||
| 
						 | 
					5c5f815b20 | ||
| 
						 | 
					d9edb9675f | ||
| 
						 | 
					be6fce5a89 | ||
| 
						 | 
					12afeb30ae | ||
| 
						 | 
					23df406ff0 | ||
| 
						 | 
					c9ecef4fc3 | ||
| 
						 | 
					62f0a867a8 | ||
| 
						 | 
					f68b8d82e0 | ||
| 
						 | 
					6b7cb13e9a | ||
| 
						 | 
					613af6013a | ||
| 
						 | 
					0db56a781e | ||
| 
						 | 
					fe7674b184 | ||
| 
						 | 
					44a6fe7310 | ||
| 
						 | 
					46690f0c35 | ||
| 
						 | 
					cfc4e345cc | ||
| 
						 | 
					c68278d824 | ||
| 
						 | 
					09600a71cd | ||
| 
						 | 
					d66ba70f5e | ||
| 
						 | 
					e7c4120d24 | ||
| 
						 | 
					1212e534a8 | ||
| 
						 | 
					899d0f1e42 | ||
| 
						 | 
					dde4ed3754 | ||
| 
						 | 
					b596e02752 | ||
| 
						 | 
					d5afe696da | ||
| 
						 | 
					976be66dee | ||
| 
						 | 
					98c8a6387a | ||
| 
						 | 
					be1b636e30 | ||
| 
						 | 
					8bae0b81aa | ||
| 
						 | 
					7ee19e1306 | ||
| 
						 | 
					626d0dfa93 | ||
| 
						 | 
					8453c616a5 | ||
| 
						 | 
					56bc2944d0 | ||
| 
						 | 
					b2cf701e30 | ||
| 
						 | 
					9a3b29acb7 | ||
| 
						 | 
					85b217f167 | ||
| 
						 | 
					a7700d6c22 | ||
| 
						 | 
					1e274518dd | ||
| 
						 | 
					f4f8927c79 | ||
| 
						 | 
					60b7890f16 | ||
| 
						 | 
					4d46290ef6 | ||
| 
						 | 
					00f7e2cfc3 | ||
| 
						 | 
					e742708261 | ||
| 
						 | 
					8c9de31c5c | ||
| 
						 | 
					2bf992f0ac | ||
| 
						 | 
					52a01bcc11 | ||
| 
						 | 
					f250e03c40 | ||
| 
						 | 
					75acbfb042 | ||
| 
						 | 
					740fd6f5d9 | ||
| 
						 | 
					c58306cd49 | ||
| 
						 | 
					985696631c | ||
| 
						 | 
					d8a3d7f920 | ||
| 
						 | 
					b6b96f0eee | ||
| 
						 | 
					3f037ef3cc | ||
| 
						 | 
					5c2d3fb3da | ||
| 
						 | 
					84d38ea878 | ||
| 
						 | 
					6226aa0b23 | ||
| 
						 | 
					72af35834b | ||
| 
						 | 
					3019e3817f | ||
| 
						 | 
					da9e90faf0 | ||
| 
						 | 
					e737395c2b | ||
| 
						 | 
					5a33167594 | ||
| 
						 | 
					dfb7e50948 | ||
| 
						 | 
					b43c9f075c | ||
| 
						 | 
					f42ce6adb5 | ||
| 
						 | 
					bf533bbdbb | ||
| 
						 | 
					9328729c4c | ||
| 
						 | 
					2e23a044ca | ||
| 
						 | 
					691a3a1e72 | ||
| 
						 | 
					fc40f9634b | ||
| 
						 | 
					4969441f21 | ||
| 
						 | 
					d04d50794e | ||
| 
						 | 
					5e1fbe34a9 | ||
| 
						 | 
					2b75829a0c | ||
| 
						 | 
					3b3fd0a3a2 | ||
| 
						 | 
					1e4b61008a | ||
| 
						 | 
					ffb71e9fd5 | ||
| 
						 | 
					c1aeb4bde6 | ||
| 
						 | 
					66bca5cd81 | ||
| 
						 | 
					b68df3a067 | ||
| 
						 | 
					066f3bb646 | ||
| 
						 | 
					661c334928 | ||
| 
						 | 
					a1895d4157 | ||
| 
						 | 
					1e7efe026a | ||
| 
						 | 
					02e7da979a | ||
| 
						 | 
					bd2839110b | ||
| 
						 | 
					1bcb2697e7 | ||
| 
						 | 
					fdb9a664f5 | ||
| 
						 | 
					8099c334c7 | ||
| 
						 | 
					344d28ab78 | ||
| 
						 | 
					5e41168305 | ||
| 
						 | 
					dd97669cdd | ||
| 
						 | 
					af75581659 | ||
| 
						 | 
					3c08f5b86a | ||
| 
						 | 
					7809cad6cb | ||
| 
						 | 
					3e59029966 | ||
| 
						 | 
					24249bcb4d | ||
| 
						 | 
					543011c3de | ||
| 
						 | 
					4d9f2586d9 | ||
| 
						 | 
					7f94ebe362 | ||
| 
						 | 
					c9bf1eda54 | ||
| 
						 | 
					2cd4d9004c | ||
| 
						 | 
					35cd0319d4 | ||
| 
						 | 
					899030e966 | ||
| 
						 | 
					15e3944d23 | ||
| 
						 | 
					f1fbaedb0f | ||
| 
						 | 
					cf04062a19 | ||
| 
						 | 
					2e922bf7db | ||
| 
						 | 
					741a731ecb | ||
| 
						 | 
					91bff1976c | ||
| 
						 | 
					fad500042a | ||
| 
						 | 
					bdb2a01385 | ||
| 
						 | 
					f372cd2d13 | ||
| 
						 | 
					a435da910f | ||
| 
						 | 
					f1d96d9673 | ||
| 
						 | 
					45226ee1f6 | ||
| 
						 | 
					03b8d29740 | ||
| 
						 | 
					80a4af249f | ||
| 
						 | 
					900d444946 | ||
| 
						 | 
					7ca9393d2d | ||
| 
						 | 
					b22d7bb310 | ||
| 
						 | 
					c742cdfe5c | ||
| 
						 | 
					2d3fe02cd7 | ||
| 
						 | 
					7d61cb6bac | ||
| 
						 | 
					a804433a7a | ||
| 
						 | 
					11082320c2 | ||
| 
						 | 
					9f9797b123 | ||
| 
						 | 
					05d34616b7 | ||
| 
						 | 
					c7f474ada1 | ||
| 
						 | 
					c7328a63d0 | ||
| 
						 | 
					db818794d5 | ||
| 
						 | 
					b4b34e4890 | ||
| 
						 | 
					eec016380d | ||
| 
						 | 
					dcab272be0 | ||
| 
						 | 
					418d033a5c | ||
| 
						 | 
					e7a7713b80 | ||
| 
						 | 
					52a580d845 | ||
| 
						 | 
					ea42a0b5f5 | ||
| 
						 | 
					a0b63da9a6 | ||
| 
						 | 
					8d9932fc42 | ||
| 
						 | 
					54be45bedc | ||
| 
						 | 
					3c9d2a562b | ||
| 
						 | 
					654bd5175c | ||
| 
						 | 
					9db660cd3f | ||
| 
						 | 
					9aeadff9bd | ||
| 
						 | 
					cd631b789b | ||
| 
						 | 
					4d98408aaf | ||
| 
						 | 
					9dd4ea1584 | ||
| 
						 | 
					9d085cdb61 | ||
| 
						 | 
					f00a2dbc59 | ||
| 
						 | 
					20862d47ab | ||
| 
						 | 
					1bff790628 | ||
| 
						 | 
					0010ca3e03 | ||
| 
						 | 
					9edb5dae88 | ||
| 
						 | 
					85b49096dc | ||
| 
						 | 
					a7eaa10220 | ||
| 
						 | 
					5a46ce55b6 | ||
| 
						 | 
					dbebbecab1 | ||
| 
						 | 
					c7593e66bf | ||
| 
						 | 
					d52dc69279 | ||
| 
						 | 
					1c65fa212d | ||
| 
						 | 
					be88eb00f8 | ||
| 
						 | 
					65c60f5386 | ||
| 
						 | 
					83a043e639 | ||
| 
						 | 
					8175192f60 | ||
| 
						 | 
					7d2c975d73 | ||
| 
						 | 
					e5153737d8 | ||
| 
						 | 
					88766a02c7 | ||
| 
						 | 
					8162394797 | ||
| 
						 | 
					fd001186dd | ||
| 
						 | 
					128fef8838 | ||
| 
						 | 
					1e25a0654a | ||
| 
						 | 
					82b0ff6008 | ||
| 
						 | 
					ca7c3630f9 | ||
| 
						 | 
					260bb8218f | ||
| 
						 | 
					a691de7d55 | ||
| 
						 | 
					5674c484e2 | ||
| 
						 | 
					9286dc284c | ||
| 
						 | 
					624b71bd39 | ||
| 
						 | 
					b7ea605a3b | ||
| 
						 | 
					489a787de8 | ||
| 
						 | 
					84150036ed | ||
| 
						 | 
					619123720c | ||
| 
						 | 
					cc98ff9fe6 | ||
| 
						 | 
					39d159f38c | ||
| 
						 | 
					ca8eb90cec | ||
| 
						 | 
					f8e3e28d85 | ||
| 
						 | 
					4d868489bd | ||
| 
						 | 
					b06f09f6af | ||
| 
						 | 
					bf00f5f945 | ||
| 
						 | 
					6ceb6cc301 | ||
| 
						 | 
					00a6afaa8e | 
@@ -29,6 +29,10 @@ jobs:
 | 
			
		||||
                  key: repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/python-contract-wrappers/generated
 | 
			
		||||
    build-website:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
@@ -47,17 +51,7 @@ jobs:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-multisig
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange-libs
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-erc20
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-erc721
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-erc1155
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-extensions
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-asset-proxy
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange-forwarder
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-coordinator
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils
 | 
			
		||||
    test-contracts-geth:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: circleci/node:9-browsers
 | 
			
		||||
@@ -69,17 +63,7 @@ jobs:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            # HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
 | 
			
		||||
            # initialized
 | 
			
		||||
            - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test @0x/contracts-multisig
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-utils
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-libs
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc20
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc721
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc1155
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-extensions
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-asset-proxy
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-forwarder
 | 
			
		||||
            - run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-coordinator
 | 
			
		||||
            - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils
 | 
			
		||||
    test-publish:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
@@ -100,20 +84,6 @@ jobs:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn test:generate_docs:circleci
 | 
			
		||||
    test-pipeline:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: circleci/node:9
 | 
			
		||||
            - image: postgres:11-alpine
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: ZEROEX_DATA_PIPELINE_TEST_DB_URL='postgresql://postgres@localhost/postgres' yarn wsrun test:circleci @0x/pipeline
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-pipeline-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/pipeline/coverage/lcov.info
 | 
			
		||||
    test-rest:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: circleci/node:9-browsers
 | 
			
		||||
@@ -124,6 +94,7 @@ jobs:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-test-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/abi-gen
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/asset-buyer
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contract-artifacts
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/assert
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/base-contract
 | 
			
		||||
@@ -149,6 +120,10 @@ jobs:
 | 
			
		||||
                  key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/assert/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-asset-buyer-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/asset-buyer/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
@@ -217,14 +192,17 @@ jobs:
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/bin
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      ./pre_install
 | 
			
		||||
                      ./install
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - '/usr/local/bin'
 | 
			
		||||
                      - '/usr/local/lib/python3.7/site-packages'
 | 
			
		||||
@@ -265,14 +243,14 @@ jobs:
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/bin
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages/order_utils
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      python -m pip install .
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - '/usr/local/bin'
 | 
			
		||||
                      - '/usr/local/lib/python3.7/site-packages'
 | 
			
		||||
@@ -293,11 +271,14 @@ jobs:
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/bin
 | 
			
		||||
            - run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      ./pre_install
 | 
			
		||||
                      ./install
 | 
			
		||||
                      ./lint
 | 
			
		||||
    static-tests:
 | 
			
		||||
@@ -327,6 +308,9 @@ jobs:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-asset-buyer-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
@@ -404,9 +388,6 @@ workflows:
 | 
			
		||||
            # - test-contracts-geth:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            - test-pipeline:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-rest:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
@@ -426,6 +407,8 @@ workflows:
 | 
			
		||||
            - static-tests-python:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - test-python
 | 
			
		||||
            - test-python
 | 
			
		||||
            - test-python:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            # skip python tox run for now, as we don't yet have multiple test environments to support.
 | 
			
		||||
            #- test-rest-python
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
*.sol linguist-language=Solidity
 | 
			
		||||
 | 
			
		||||
# Automatically collapse generated files in GitHub.
 | 
			
		||||
*.svg linguist-generated
 | 
			
		||||
packages/contract-artifacts/artifacts/*json linguist-generated
 | 
			
		||||
packages/abi-gen-wrappers/wrappers/*.ts liguist-generated
 | 
			
		||||
*.svg linguist-generated=true
 | 
			
		||||
packages/contract-artifacts/artifacts/*json linguist-generated=true
 | 
			
		||||
packages/abi-gen-wrappers/src/generated-wrappers/*.ts liguist-generated=true
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										80
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,43 +1,43 @@
 | 
			
		||||
python: ['python-packages']
 | 
			
		||||
contracts: ['contracts']
 | 
			
		||||
sol-doc: ['packages/sol-doc']
 | 
			
		||||
sol-resolver: ['packages/sol-resolver']
 | 
			
		||||
contracts-gen: ['packages/contracts-gen']
 | 
			
		||||
sra-spec: ['packages/sra-spec']
 | 
			
		||||
subproviders: ['packages/subproviders']
 | 
			
		||||
contract-addresses: ['packages/contract-addresses']
 | 
			
		||||
migrations: ['packages/migrations']
 | 
			
		||||
web3-wrapper: ['packages/web3-wrapper']
 | 
			
		||||
sol-compiler: ['packages/sol-compiler']
 | 
			
		||||
types: ['packages/types']
 | 
			
		||||
instant: ['packages/instant']
 | 
			
		||||
abi-gen-templates: ['packages/abi-gen-templates']
 | 
			
		||||
abi-gen: ['packages/abi-gen']
 | 
			
		||||
website: ['packages/website']
 | 
			
		||||
sol-coverage: ['packages/sol-coverage']
 | 
			
		||||
sol-profiler: ['packages/sol-profiler']
 | 
			
		||||
sol-trace: ['packages/sol-trace']
 | 
			
		||||
sol-tracing-utils: ['packages/sol-tracing-utils']
 | 
			
		||||
utils: ['packages/utils']
 | 
			
		||||
tslint-config: ['packages/tslint-config']
 | 
			
		||||
asset-buyer: ['packages/asset-buyer']
 | 
			
		||||
order-watcher: ['packages/order-watcher']
 | 
			
		||||
react-docs: ['packages/react-docs']
 | 
			
		||||
order-utils: ['packages/order-utils']
 | 
			
		||||
react-shared: ['packages/react-shared']
 | 
			
		||||
assert: ['packages/assert']
 | 
			
		||||
base-contract: ['packages/base-contract']
 | 
			
		||||
typescript-typings: ['packages/typescript-typings']
 | 
			
		||||
@0x/sol-doc: ['packages/sol-doc']
 | 
			
		||||
@0x/sol-resolver: ['packages/sol-resolver']
 | 
			
		||||
@0x/contracts-gen: ['packages/contracts-gen']
 | 
			
		||||
@0x/sra-spec: ['packages/sra-spec']
 | 
			
		||||
@0x/subproviders: ['packages/subproviders']
 | 
			
		||||
@0x/contract-addresses: ['packages/contract-addresses']
 | 
			
		||||
@0x/migrations: ['packages/migrations']
 | 
			
		||||
@0x/web3-wrapper: ['packages/web3-wrapper']
 | 
			
		||||
@0x/sol-compiler: ['packages/sol-compiler']
 | 
			
		||||
@0x/types: ['packages/types']
 | 
			
		||||
@0x/instant: ['packages/instant']
 | 
			
		||||
@0x/abi-gen-templates: ['packages/abi-gen-templates']
 | 
			
		||||
@0x/abi-gen: ['packages/abi-gen']
 | 
			
		||||
@0x/website: ['packages/website']
 | 
			
		||||
@0x/sol-coverage: ['packages/sol-coverage']
 | 
			
		||||
@0x/sol-profiler: ['packages/sol-profiler']
 | 
			
		||||
@0x/sol-trace: ['packages/sol-trace']
 | 
			
		||||
@0x/sol-tracing-utils: ['packages/sol-tracing-utils']
 | 
			
		||||
@0x/utils: ['packages/utils']
 | 
			
		||||
@0x/tslint-config: ['packages/tslint-config']
 | 
			
		||||
@0x/asset-buyer: ['packages/asset-buyer']
 | 
			
		||||
@0x/order-watcher: ['packages/order-watcher']
 | 
			
		||||
@0x/react-docs: ['packages/react-docs']
 | 
			
		||||
@0x/order-utils: ['packages/order-utils']
 | 
			
		||||
@0x/react-shared: ['packages/react-shared']
 | 
			
		||||
@0x/assert: ['packages/assert']
 | 
			
		||||
@0x/base-contract: ['packages/base-contract']
 | 
			
		||||
@0x/typescript-typings: ['packages/typescript-typings']
 | 
			
		||||
0x.js: ['packages/0x.js']
 | 
			
		||||
abi-gen-wrappers: ['packages/abi-gen-wrappers']
 | 
			
		||||
metacoin: ['packages/metacoin']
 | 
			
		||||
contract-artifacts: ['packages/contract-artifacts']
 | 
			
		||||
dev-utils: ['packages/dev-utils']
 | 
			
		||||
contract-wrappers: ['packages/contract-wrappers']
 | 
			
		||||
json-schemas: ['packages/json-schemas']
 | 
			
		||||
ethereum-types: ['ethereum-types']
 | 
			
		||||
connect: ['packages/connect']
 | 
			
		||||
fill-scenarios: ['packages/fill-scenarios']
 | 
			
		||||
dev-tools-pages: ['packages/dev-tools-pages']
 | 
			
		||||
testnet-faucets: ['packages/testnet-faucets']
 | 
			
		||||
monorepo-scripts: ['packages/monorepo-scripts']
 | 
			
		||||
@0x/abi-gen-wrappers: ['packages/abi-gen-wrappers']
 | 
			
		||||
@0x/metacoin: ['packages/metacoin']
 | 
			
		||||
@0x/contract-artifacts: ['packages/contract-artifacts']
 | 
			
		||||
@0x/dev-utils: ['packages/dev-utils']
 | 
			
		||||
@0x/contract-wrappers: ['packages/contract-wrappers']
 | 
			
		||||
@0x/json-schemas: ['packages/json-schemas']
 | 
			
		||||
@0x/ethereum-types: ['ethereum-types']
 | 
			
		||||
@0x/connect: ['packages/connect']
 | 
			
		||||
@0x/fill-scenarios: ['packages/fill-scenarios']
 | 
			
		||||
@0x/dev-tools-pages: ['packages/dev-tools-pages']
 | 
			
		||||
@0x/testnet-faucets: ['packages/testnet-faucets']
 | 
			
		||||
@0x/monorepo-scripts: ['packages/monorepo-scripts']
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -94,11 +94,14 @@ contracts/erc721/generated-artifacts/
 | 
			
		||||
contracts/erc1155/generated-artifacts/
 | 
			
		||||
contracts/extensions/generated-artifacts/
 | 
			
		||||
contracts/exchange-forwarder/generated-artifacts/
 | 
			
		||||
contracts/dev-utils/generated-artifacts/
 | 
			
		||||
packages/sol-tracing-utils/test/fixtures/artifacts/
 | 
			
		||||
packages/metacoin/artifacts/
 | 
			
		||||
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
 | 
			
		||||
 | 
			
		||||
# generated contract wrappers
 | 
			
		||||
packages/abi-gen-wrappers/wrappers
 | 
			
		||||
packages/abi-gen-wrappers/src/generated-wrappers/
 | 
			
		||||
packages/python-contract-wrappers/generated/
 | 
			
		||||
contracts/coordinator/generated-wrappers/
 | 
			
		||||
contracts/exchange/generated-wrappers/
 | 
			
		||||
contracts/asset-proxy/generated-wrappers/
 | 
			
		||||
@@ -110,8 +113,12 @@ contracts/erc721/generated-wrappers/
 | 
			
		||||
contracts/erc1155/generated-wrappers/
 | 
			
		||||
contracts/extensions/generated-wrappers/
 | 
			
		||||
contracts/exchange-forwarder/generated-wrappers/
 | 
			
		||||
contracts/dev-utils/generated-wrappers/
 | 
			
		||||
packages/metacoin/src/contract_wrappers
 | 
			
		||||
 | 
			
		||||
# cli test output
 | 
			
		||||
packages/abi-gen/test-cli/output
 | 
			
		||||
 | 
			
		||||
# solc-bin in sol-compiler
 | 
			
		||||
packages/sol-compiler/solc_bin/
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,9 @@ lib
 | 
			
		||||
/contracts/extensions/generated-artifacts
 | 
			
		||||
/contracts/exchange-forwarder/generated-wrappers
 | 
			
		||||
/contracts/exchange-forwarder/generated-artifacts
 | 
			
		||||
/packages/abi-gen-wrappers/src/generated-wrappers
 | 
			
		||||
/packages/contract-artifacts/artifacts
 | 
			
		||||
/python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts
 | 
			
		||||
/contracts/dev-utils/generated-wrappers
 | 
			
		||||
/contracts/dev-utils/generated-artifacts
 | 
			
		||||
/packages/abi-gen/test-cli/output
 | 
			
		||||
/packages/json-schemas/schemas
 | 
			
		||||
/python-packages/json_schemas/src/zero_ex/json_schemas/schemas
 | 
			
		||||
/packages/metacoin/src/contract_wrappers
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,10 @@ packages/website/  @BMillman19 @fragosti @fabioberger @steveklebanoff
 | 
			
		||||
 | 
			
		||||
# Dev tools & setup
 | 
			
		||||
.circleci/ @LogvinovLeon
 | 
			
		||||
packages/abi-gen/ @LogvinovLeon
 | 
			
		||||
packages/base-contract/ @LogvinovLeon
 | 
			
		||||
packages/abi-gen/ @feuGeneA
 | 
			
		||||
packages/base-contract/ @xianny
 | 
			
		||||
packages/connect/ @fragosti 
 | 
			
		||||
packages/abi-gen-templates/ @LogvinovLeon
 | 
			
		||||
packages/abi-gen-templates/ @feuGeneA @xianny
 | 
			
		||||
packages/contract-addresses/ @albrow
 | 
			
		||||
packages/contract-artifacts/ @albrow
 | 
			
		||||
packages/dev-utils/ @LogvinovLeon @fabioberger
 | 
			
		||||
@@ -23,6 +23,7 @@ packages/ethereum-types/ @LogvinovLeon
 | 
			
		||||
packages/metacoin/ @LogvinovLeon
 | 
			
		||||
packages/monorepo-scripts/ @fabioberger
 | 
			
		||||
packages/order-utils/ @fabioberger @LogvinovLeon 
 | 
			
		||||
packages/python-contract-wrappers/ @feuGeneA
 | 
			
		||||
packages/sol-compiler/ @LogvinovLeon
 | 
			
		||||
packages/sol-coverage/ @LogvinovLeon
 | 
			
		||||
packages/sol-profiler/ @LogvinovLeon
 | 
			
		||||
@@ -36,5 +37,4 @@ python-packages/ @feuGeneA
 | 
			
		||||
packages/utils/ @hysz
 | 
			
		||||
 | 
			
		||||
# Protocol/smart contracts
 | 
			
		||||
contracts/core/test/ @albrow
 | 
			
		||||
contracts/ @abandeali1 @hysz
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
<!--- Before submitting please check to see if this issue was already reported -->
 | 
			
		||||
 | 
			
		||||
<!--- Provide a general summary of the issue in the Title above -->
 | 
			
		||||
<!--- Prefix your issue title with the package name it relates to (e.g., `0x.js: ` or `general:`) -->
 | 
			
		||||
 | 
			
		||||
## Expected Behavior
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ These packages are all under development. See [/contracts/README.md](/contracts/
 | 
			
		||||
| [`@0x/contracts-test-utils`](/contracts/test-utils)                 | [](https://www.npmjs.com/package/@0x/contracts-test-utils)                 | Typescript/Javascript shared utilities used for testing contracts                                                                                                                                                                                     |
 | 
			
		||||
| [`@0x/contracts-utils`](/contracts/utils)                           | [](https://www.npmjs.com/package/@0x/contracts-utils)                           | Generic libraries and utilities used throughout all of the contracts                                                                                                                                                                                  |
 | 
			
		||||
| [`@0x/contracts-coordinator`](/contracts/coordinator)               | [](https://www.npmjs.com/package/@0x/contracts-coordinator)               | A contract that allows users to execute 0x transactions with permission from a Coordinator                                                                                                                                                            |
 | 
			
		||||
| [`@0x/contracts-dev-utils`](/contracts/dev-utils)                   | [](https://www.npmjs.com/package/@0x/contracts-dev-utils)                   | A contract contains utility functions for developers (such as validating many orders using a single eth_call)                                                                                                                                         |
 | 
			
		||||
 | 
			
		||||
### Typescript/Javascript Packages
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,3 +10,7 @@
 | 
			
		||||
| Forwarder       | [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder/v/1.0.1) | [@0x/contracts-exchange-forwarder@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange-forwarder@1.0.1) |
 | 
			
		||||
| MultiAssetProxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy)               | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1)        | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1)               |
 | 
			
		||||
| ZRXToken        | [`@0x/contracts-erc20`](/contracts/erc20)                           | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-erc20/v/1.0.1)              | [@0x/contracts-erc20@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-erc20@1.0.1)                           |
 | 
			
		||||
 | 
			
		||||
#### Development
 | 
			
		||||
 | 
			
		||||
Building solidity files will update the contract artifact in `{package-name}/generated-artifacts/{contract}.json`, but does not automatically update the `abi-gen-wrappers` package, which are generated from the artifact JSON. To ensure consistency, clean and rebuild `abi-gen-wrappers` after any changes to the artifact JSON.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,49 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.2.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `LibAssetProxyIds` contract",
 | 
			
		||||
                "pr": 1835
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases.",
 | 
			
		||||
                "pr": 1852
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Implement StaticCallProxy",
 | 
			
		||||
                "pr": 1863
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1563006338
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "2.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,24 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.2.0 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Add `LibAssetProxyIds` contract (#1835)
 | 
			
		||||
    * Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases. (#1852)
 | 
			
		||||
    * Implement StaticCallProxy (#1863)
 | 
			
		||||
 | 
			
		||||
## v2.1.5 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.4 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.3 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Update tests to use contract-built-in `awaitTransactionSuccessAsync` (#1797)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
@@ -28,9 +29,10 @@
 | 
			
		||||
        "src/ERC721Proxy.sol",
 | 
			
		||||
        "src/MixinAuthorizable.sol",
 | 
			
		||||
        "src/MultiAssetProxy.sol",
 | 
			
		||||
        "src/StaticCallProxy.sol",
 | 
			
		||||
        "src/interfaces/IAssetData.sol",
 | 
			
		||||
        "src/interfaces/IAssetProxy.sol",
 | 
			
		||||
        "src/interfaces/IAuthorizable.sol",
 | 
			
		||||
        "src/libs/LibAssetData.sol"
 | 
			
		||||
        "test/TestStaticCallTarget.sol"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "./MixinAuthorizable.sol";
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +28,7 @@ contract ERC1155Proxy is
 | 
			
		||||
    // Id of this proxy.
 | 
			
		||||
    bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
 | 
			
		||||
 | 
			
		||||
    // solhint-disable-next-line payable-fallback
 | 
			
		||||
    function () 
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
@@ -58,11 +59,11 @@ contract ERC1155Proxy is
 | 
			
		||||
        // |          | 100         |         |   4. offset to data (*)             |
 | 
			
		||||
        // | Data     |             |         | ids:                                |
 | 
			
		||||
        // |          | 132         | 32      |   1. ids Length                     |
 | 
			
		||||
        // |          | 164         | a       |   2. ids Contents                   | 
 | 
			
		||||
        // |          | 164         | a       |   2. ids Contents                   |
 | 
			
		||||
        // |          |             |         | values:                             |
 | 
			
		||||
        // |          | 164 + a     | 32      |   1. values Length                  |
 | 
			
		||||
        // |          | 196 + a     | b       |   2. values Contents                |
 | 
			
		||||
        // |          |             |         | data                                |
 | 
			
		||||
        // |          |             |         | data:                               |
 | 
			
		||||
        // |          | 196 + a + b | 32      |   1. data Length                    |
 | 
			
		||||
        // |          | 228 + a + b | c       |   2. data Contents                  |
 | 
			
		||||
        //
 | 
			
		||||
@@ -80,18 +81,18 @@ contract ERC1155Proxy is
 | 
			
		||||
        // |          | 132         |         |   5. offset to data (*)             |
 | 
			
		||||
        // | Data     |             |         | ids:                                |
 | 
			
		||||
        // |          | 164         | 32      |   1. ids Length                     |
 | 
			
		||||
        // |          | 196         | a       |   2. ids Contents                   | 
 | 
			
		||||
        // |          | 196         | a       |   2. ids Contents                   |
 | 
			
		||||
        // |          |             |         | values:                             |
 | 
			
		||||
        // |          | 196 + a     | 32      |   1. values Length                  |
 | 
			
		||||
        // |          | 228 + a     | b       |   2. values Contents                |
 | 
			
		||||
        // |          |             |         | data                                |
 | 
			
		||||
        // |          |             |         | data:                               |
 | 
			
		||||
        // |          | 228 + a + b | 32      |   1. data Length                    |
 | 
			
		||||
        // |          | 260 + a + b | c       |   2. data Contents                  |
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // (*): offset is computed from start of function parameters, so offset
 | 
			
		||||
        //      by an additional 4 bytes in the calldata.
 | 
			
		||||
        // 
 | 
			
		||||
        //
 | 
			
		||||
        // (**): the `Offset` column is computed assuming no calldata compression;
 | 
			
		||||
        //       offsets in the Data Area are dynamic and should be evaluated in
 | 
			
		||||
        //       real-time.
 | 
			
		||||
@@ -100,7 +101,7 @@ contract ERC1155Proxy is
 | 
			
		||||
        //          the Params and Data section. This will result in a larger
 | 
			
		||||
        //          offset to assetData.
 | 
			
		||||
        //
 | 
			
		||||
        // Note: Table #1 and Table #2 exists in Calldata. We construct Table #3 in memory. 
 | 
			
		||||
        // Note: Table #1 and Table #2 exist in Calldata. We construct Table #3 in memory.
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        assembly {
 | 
			
		||||
@@ -114,7 +115,7 @@ contract ERC1155Proxy is
 | 
			
		||||
            // amount Amount of asset to transfer.
 | 
			
		||||
            // bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
 | 
			
		||||
            if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                // To lookup a value in a mapping, we load from the storage location keccak256(k, p),
 | 
			
		||||
                // where k is the key left padded to 32 bytes and p is the storage slot
 | 
			
		||||
                mstore(0, caller)
 | 
			
		||||
@@ -131,71 +132,154 @@ contract ERC1155Proxy is
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Construct Table #3 in memory, starting at memory offset 0.
 | 
			
		||||
                // The algorithm below maps asset data from Table #1 and Table #2 to Table #3, while
 | 
			
		||||
                // scaling the `values` (Table #2) by `amount` (Table #1). Once Table #3 has
 | 
			
		||||
                // been constructed in memory, the destination erc1155 contract is called using this 
 | 
			
		||||
                // as its calldata. This process is divided into four steps, below.
 | 
			
		||||
                // The algorithm below maps calldata (Table #1) and assetData (Table #2) to memory (Table #3).
 | 
			
		||||
                // Once Table #3 ha been constructed in memory, the destination erc1155 contract is called using this
 | 
			
		||||
                // as its calldata. This process is divided into three steps, below.
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 1/3 - Map calldata to memory (Table #1 -> Table #3) //////////
 | 
			
		||||
 | 
			
		||||
                // Store the safeBatchTransferFrom function selector, which is computed using:
 | 
			
		||||
                // bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))
 | 
			
		||||
                mstore(0, 0x2eb2c2d600000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
 | 
			
		||||
                // Copy `from` and `to` fields from calldata (Table #1) into memory (Table #3)
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    4,          // aligned such that `from` and `to` are at the correct location for Table #3
 | 
			
		||||
                    36,         // beginning of `from` field from Table #1
 | 
			
		||||
                    64          // 32 bytes for `from` + 32 bytes for `to` field
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 2/3 - Map assetData to memory (Table #2 -> Table #3) //////////
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 1/4 //////////
 | 
			
		||||
                // Map relevant fields from assetData (Table #2) into memory (Table #3)
 | 
			
		||||
                // The Contents column of Table #2 is the same as Table #3,
 | 
			
		||||
                // beginning from parameter 3 - `offset to ids (*)`
 | 
			
		||||
                // The offsets in these rows are offset by 32 bytes in Table #3.
 | 
			
		||||
                // Strategy:
 | 
			
		||||
                // 1. Copy the assetData into memory at offset 32
 | 
			
		||||
                // 2. Increment by 32 the offsets to `ids`, `values`, and `data`
 | 
			
		||||
                // The `values` from assetData (Table #2) are multiplied by `amount` (Table #1)
 | 
			
		||||
                // when they are copied into memory.
 | 
			
		||||
 | 
			
		||||
                // Load offset to `assetData`
 | 
			
		||||
                let assetDataOffset := calldataload(4)
 | 
			
		||||
                let assetDataOffset := add(calldataload(4), 4)
 | 
			
		||||
 | 
			
		||||
                // Load length in bytes of `assetData`, computed by:
 | 
			
		||||
                // 4 (function selector)
 | 
			
		||||
                // + assetDataOffset
 | 
			
		||||
                let assetDataLength := calldataload(add(4, assetDataOffset))
 | 
			
		||||
                // Load length in bytes of `assetData`
 | 
			
		||||
                let assetDataLength := calldataload(assetDataOffset)
 | 
			
		||||
 | 
			
		||||
                // This corresponds to the beginning of the Data Area for Table #3.
 | 
			
		||||
                // Computed by:
 | 
			
		||||
                // 4 (function selector)
 | 
			
		||||
                // + assetDataOffset
 | 
			
		||||
                // + 32 (length of assetData)
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    32,                         // aligned such that "offset to ids" is at the correct location for Table #3
 | 
			
		||||
                    add(36, assetDataOffset),   // beginning of asset data contents
 | 
			
		||||
                    assetDataLength             // length of asset data
 | 
			
		||||
                )
 | 
			
		||||
                // Assert that the length of asset data:
 | 
			
		||||
                // 1. Must be at least 132 bytes (Table #2)
 | 
			
		||||
                // 2. Must be a multiple of 32 (excluding the 4-byte selector)
 | 
			
		||||
                if or(lt(assetDataLength, 132), mod(sub(assetDataLength, 4), 32)) {
 | 
			
		||||
                    // Revert with `Error("INVALID_ASSET_DATA_LENGTH")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000019494e56414c49445f41535345545f444154415f4c454e475448000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Increment by 32 the offsets to `ids`, `values`, and `data`
 | 
			
		||||
                mstore(68, add(mload(68), 32))
 | 
			
		||||
                mstore(100, add(mload(100), 32))
 | 
			
		||||
                mstore(132, add(mload(132), 32))
 | 
			
		||||
                // End of asset data in calldata
 | 
			
		||||
                // +32 for length field
 | 
			
		||||
                let assetDataEnd := add(assetDataOffset, add(assetDataLength, 32))
 | 
			
		||||
                if gt(assetDataEnd, calldatasize()) {
 | 
			
		||||
                    // Revert with `Error("INVALID_ASSET_DATA_END")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000016494e56414c49445f41535345545f444154415f454e44000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Record the address of the destination erc1155 asset for later.
 | 
			
		||||
                let assetAddress := and(
 | 
			
		||||
                    mload(36),
 | 
			
		||||
                    0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
 | 
			
		||||
                )
 | 
			
		||||
                // Load offset to parameters section in asset data
 | 
			
		||||
                let paramsInAssetDataOffset := add(assetDataOffset, 36)
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 2/4 //////////
 | 
			
		||||
                // Offset of end of Data Area in memory.
 | 
			
		||||
                // This value will grow as we construct Table #3.
 | 
			
		||||
                let dataAreaEndOffset := 164
 | 
			
		||||
 | 
			
		||||
                // Load amount by which to scale values
 | 
			
		||||
                let amount := calldataload(100)
 | 
			
		||||
                let valuesOffset := add(mload(100), 4) // add 4 for calldata offset
 | 
			
		||||
                let valuesLengthInBytes := mul(
 | 
			
		||||
                    mload(valuesOffset),
 | 
			
		||||
                    32
 | 
			
		||||
 | 
			
		||||
                // Store pointer to `ids` (Table #3)
 | 
			
		||||
                // Subtract 4 for `safeBatchTransferFrom` selector
 | 
			
		||||
                mstore(68, sub(dataAreaEndOffset, 4))
 | 
			
		||||
 | 
			
		||||
                // Ensure length of `ids` does not overflow
 | 
			
		||||
                let idsOffset := add(paramsInAssetDataOffset, calldataload(add(assetDataOffset, 68)))
 | 
			
		||||
                let idsLength := calldataload(idsOffset)
 | 
			
		||||
                let idsLengthInBytes := mul(idsLength, 32)
 | 
			
		||||
                if sub(div(idsLengthInBytes, 32), idsLength) {
 | 
			
		||||
                    // Revert with `Error("UINT256_OVERFLOW")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Ensure `ids` does not resolve to outside of `assetData`
 | 
			
		||||
                let idsBegin := add(idsOffset, 32)
 | 
			
		||||
                let idsEnd := add(idsBegin, idsLengthInBytes)
 | 
			
		||||
                if gt(idsEnd, assetDataEnd) {
 | 
			
		||||
                    // Revert with `Error("INVALID_IDS_OFFSET")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000012494e56414c49445f4944535f4f464653455400000000000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Copy `ids` from `assetData` (Table #2) to memory (Table #3)
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    dataAreaEndOffset,
 | 
			
		||||
                    idsOffset,
 | 
			
		||||
                    add(idsLengthInBytes, 32)
 | 
			
		||||
                )
 | 
			
		||||
                dataAreaEndOffset := add(dataAreaEndOffset, add(idsLengthInBytes, 32))
 | 
			
		||||
 | 
			
		||||
                // Store pointer to `values` (Table #3)
 | 
			
		||||
                // Subtract 4 for `safeBatchTrasferFrom` selector
 | 
			
		||||
                mstore(100, sub(dataAreaEndOffset, 4))
 | 
			
		||||
 | 
			
		||||
                // Ensure length of `values` does not overflow
 | 
			
		||||
                let valuesOffset := add(paramsInAssetDataOffset, calldataload(add(assetDataOffset, 100)))
 | 
			
		||||
                let valuesLength := calldataload(valuesOffset)
 | 
			
		||||
                let valuesLengthInBytes := mul(valuesLength, 32)
 | 
			
		||||
                if sub(div(valuesLengthInBytes, 32), valuesLength) {
 | 
			
		||||
                    // Revert with `Error("UINT256_OVERFLOW")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Ensure `values` does not resolve to outside of `assetData`
 | 
			
		||||
                let valuesBegin := add(valuesOffset, 32)
 | 
			
		||||
                let valuesEnd := add(valuesBegin, valuesLengthInBytes)
 | 
			
		||||
                for { let tokenValueOffset := valuesBegin }
 | 
			
		||||
                    lt(tokenValueOffset, valuesEnd)
 | 
			
		||||
                    { tokenValueOffset := add(tokenValueOffset, 32) }
 | 
			
		||||
                if gt(valuesEnd, assetDataEnd) {
 | 
			
		||||
                    // Revert with `Error("INVALID_VALUES_OFFSET")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000015494e56414c49445f56414c5545535f4f464653455400000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Store length of `values`
 | 
			
		||||
                mstore(dataAreaEndOffset, valuesLength)
 | 
			
		||||
                dataAreaEndOffset := add(dataAreaEndOffset, 32)
 | 
			
		||||
 | 
			
		||||
                // Scale and store elements of `values`
 | 
			
		||||
                for { let currentValueOffset := valuesBegin }
 | 
			
		||||
                    lt(currentValueOffset, valuesEnd)
 | 
			
		||||
                    { currentValueOffset := add(currentValueOffset, 32) }
 | 
			
		||||
                {
 | 
			
		||||
                    // Load token value and generate scaled value
 | 
			
		||||
                    let tokenValue := mload(tokenValueOffset)
 | 
			
		||||
                    let scaledTokenValue := mul(tokenValue, amount)
 | 
			
		||||
                    // Load value and generate scaled value
 | 
			
		||||
                    let currentValue := calldataload(currentValueOffset)
 | 
			
		||||
                    let currentValueScaled := mul(currentValue, amount)
 | 
			
		||||
 | 
			
		||||
                    // Revert if `amount` != 0 and multiplication resulted in an overflow
 | 
			
		||||
                    if iszero(or(
 | 
			
		||||
                        iszero(amount),
 | 
			
		||||
                        eq(div(scaledTokenValue, amount), tokenValue)
 | 
			
		||||
                        eq(div(currentValueScaled, amount), currentValue)
 | 
			
		||||
                    )) {
 | 
			
		||||
                        // Revert with `Error("UINT256_OVERFLOW")`
 | 
			
		||||
                        mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
@@ -205,33 +289,57 @@ contract ERC1155Proxy is
 | 
			
		||||
                        revert(0, 100)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // There was no overflow, update `tokenValue` with its scaled counterpart
 | 
			
		||||
                    mstore(tokenValueOffset, scaledTokenValue)
 | 
			
		||||
                    // There was no overflow, store the scaled token value
 | 
			
		||||
                    mstore(dataAreaEndOffset, currentValueScaled)
 | 
			
		||||
                    dataAreaEndOffset := add(dataAreaEndOffset, 32)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 3/4 //////////
 | 
			
		||||
                // Store the safeBatchTransferFrom function selector,
 | 
			
		||||
                // and copy `from`/`to` fields from Table #1 to Table #3.
 | 
			
		||||
                // Store pointer to `data` (Table #3)
 | 
			
		||||
                // Subtract 4 for `safeBatchTrasferFrom` selector
 | 
			
		||||
                mstore(132, sub(dataAreaEndOffset, 4))
 | 
			
		||||
 | 
			
		||||
                // The function selector is computed using:
 | 
			
		||||
                // bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))
 | 
			
		||||
                mstore(0, 0x2eb2c2d600000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                // Ensure `data` does not resolve to outside of `assetData`
 | 
			
		||||
                let dataOffset := add(paramsInAssetDataOffset, calldataload(add(assetDataOffset, 132)))
 | 
			
		||||
                let dataLengthInBytes := calldataload(dataOffset)
 | 
			
		||||
                let dataBegin := add(dataOffset, 32)
 | 
			
		||||
                let dataEnd := add(dataBegin, dataLengthInBytes)
 | 
			
		||||
                if gt(dataEnd, assetDataEnd) {
 | 
			
		||||
                    // Revert with `Error("INVALID_DATA_OFFSET")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000013494e56414c49445f444154415f4f4646534554000000000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Copy `from` and `to` fields from Table #1 to Table #3
 | 
			
		||||
                // Copy `data` from `assetData` (Table #2) to memory (Table #3)
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    4,          // aligned such that `from` and `to` are at the correct location for Table #3
 | 
			
		||||
                    36,         // beginning of `from` field from Table #1
 | 
			
		||||
                    64          // 32 bytes for `from` + 32 bytes for `to` field
 | 
			
		||||
                    dataAreaEndOffset,
 | 
			
		||||
                    dataOffset,
 | 
			
		||||
                    add(dataLengthInBytes, 32)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Update the end of data offset to be word-aligned
 | 
			
		||||
                let dataLengthInWords := div(add(dataLengthInBytes, 31), 32)
 | 
			
		||||
                let dataLengthInBytesWordAligned := mul(dataLengthInWords, 32)
 | 
			
		||||
                dataAreaEndOffset := add(dataAreaEndOffset, add(dataLengthInBytesWordAligned, 32))
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 3/3 - Execute Transfer //////////
 | 
			
		||||
                // Load the address of the destination erc1155 contract from asset data (Table #2)
 | 
			
		||||
                // +32 bytes for assetData Length
 | 
			
		||||
                // +4 bytes for assetProxyId
 | 
			
		||||
                let assetAddress := and(
 | 
			
		||||
                    calldataload(add(assetDataOffset, 36)),
 | 
			
		||||
                    0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 4/4 //////////
 | 
			
		||||
                // Call into the destination erc1155 contract using as calldata Table #3 (constructed in-memory above)
 | 
			
		||||
                let success := call(
 | 
			
		||||
                    gas,                                    // forward all gas
 | 
			
		||||
                    assetAddress,                           // call address of erc1155 asset
 | 
			
		||||
                    0,                                      // don't send any ETH
 | 
			
		||||
                    0,                                      // pointer to start of input
 | 
			
		||||
                    add(assetDataLength, 32),               // length of input (Table #3) is 32 bytes longer than `assetData` (Table #2)
 | 
			
		||||
                    dataAreaEndOffset,                      // length of input is the end of the Data Area (Table #3)
 | 
			
		||||
                    0,                                      // write output over memory that won't be reused
 | 
			
		||||
                    0                                       // don't copy output to memory
 | 
			
		||||
                )
 | 
			
		||||
@@ -245,7 +353,7 @@ contract ERC1155Proxy is
 | 
			
		||||
                    )
 | 
			
		||||
                    revert(0, returndatasize())
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                // Return if call was successful
 | 
			
		||||
                return(0, 0)
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										207
									
								
								contracts/asset-proxy/contracts/src/StaticCallProxy.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								contracts/asset-proxy/contracts/src/StaticCallProxy.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract StaticCallProxy {
 | 
			
		||||
 | 
			
		||||
    // Id of this proxy.
 | 
			
		||||
    bytes4 constant internal PROXY_ID = bytes4(keccak256("StaticCall(address,bytes,bytes32)"));
 | 
			
		||||
 | 
			
		||||
    // solhint-disable-next-line payable-fallback
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // The first 4 bytes of calldata holds the function selector
 | 
			
		||||
            let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
 | 
			
		||||
            // `transferFrom` will be called with the following parameters:
 | 
			
		||||
            // assetData Encoded byte array.
 | 
			
		||||
            // from Address to transfer asset from.
 | 
			
		||||
            // to Address to transfer asset to.
 | 
			
		||||
            // amount Amount of asset to transfer.
 | 
			
		||||
            // bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
 | 
			
		||||
            if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
 | 
			
		||||
 | 
			
		||||
                // `transferFrom`.
 | 
			
		||||
                // The function is marked `external`, so no abi decoding 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
 | 
			
		||||
                // (***): Note that the `from`, `to`, and `amount` params in calldata are ignored in this function.
 | 
			
		||||
                //
 | 
			
		||||
                // WARNING: The ABIv2 specification allows additional padding between
 | 
			
		||||
                //          the Params and Data section. This will result in a larger
 | 
			
		||||
                //          offset to assetData.
 | 
			
		||||
 | 
			
		||||
                // Load offset to `assetData`
 | 
			
		||||
                let assetDataOffset := add(calldataload(4), 4)
 | 
			
		||||
 | 
			
		||||
                // Validate length of `assetData`
 | 
			
		||||
                let assetDataLen := calldataload(assetDataOffset)
 | 
			
		||||
                if or(lt(assetDataLen, 100), mod(sub(assetDataLen, 4), 32)) {
 | 
			
		||||
                    // Revert with `Error("INVALID_ASSET_DATA_LENGTH")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000019494e56414c49445f41535345545f444154415f4c454e475448000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Ensure that `assetData` ends inside of calldata
 | 
			
		||||
                let assetDataEnd := add(assetDataOffset, add(assetDataLen, 32))
 | 
			
		||||
                if gt(assetDataEnd, calldatasize()) {
 | 
			
		||||
                    // Revert with `Error("INVALID_ASSET_DATA_END")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x00000016494e56414c49445f41535345545f444154415f454e44000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Asset data is encoded as follows:
 | 
			
		||||
                // | Area     | Offset      | Length  | Contents                             |
 | 
			
		||||
                // |----------|-------------|---------|--------------------------------------|
 | 
			
		||||
                // | Header   | 0           | 4       | assetProxyId                         |
 | 
			
		||||
                // | Params   |             | 4 * 32  | function parameters:                 |
 | 
			
		||||
                // |          | 4           |         |   1. address of callTarget           |
 | 
			
		||||
                // |          | 36          |         |   2. offset to staticCallData (*)    |
 | 
			
		||||
                // |          | 68          |         |   3. expected 32 byte hash of output |
 | 
			
		||||
                // | Data     |             |         | staticCallData:                      |
 | 
			
		||||
                // |          | 100         | 32      |   1. staticCallData Length           |
 | 
			
		||||
                // |          | 132         | a       |   2. staticCallData Contents         | 
 | 
			
		||||
 | 
			
		||||
                // In order to find the offset to `staticCallData`, we must add:
 | 
			
		||||
                // assetDataOffset
 | 
			
		||||
                // + 32 (assetData len)
 | 
			
		||||
                // + 4 (proxyId)
 | 
			
		||||
                // + 32 (callTarget)
 | 
			
		||||
                let paramsInAssetDataOffset := add(assetDataOffset, 36)
 | 
			
		||||
                let staticCallDataOffset := add(paramsInAssetDataOffset, calldataload(add(assetDataOffset, 68)))
 | 
			
		||||
 | 
			
		||||
                // Load length of `staticCallData`
 | 
			
		||||
                let staticCallDataLen := calldataload(staticCallDataOffset)
 | 
			
		||||
 | 
			
		||||
                // Ensure `staticCallData` does not begin to outside of `assetData`
 | 
			
		||||
                let staticCallDataBegin := add(staticCallDataOffset, 32)
 | 
			
		||||
                let staticCallDataEnd := add(staticCallDataBegin, staticCallDataLen)
 | 
			
		||||
                if gt(staticCallDataEnd, assetDataEnd) {
 | 
			
		||||
                    // Revert with `Error("INVALID_STATIC_CALL_DATA_OFFSET")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x0000001f494e56414c49445f5354415449435f43414c4c5f444154415f4f4646)
 | 
			
		||||
                    mstore(96, 0x5345540000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Copy `staticCallData` into memory
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    0,                              // memory can be safely overwritten from beginning
 | 
			
		||||
                    staticCallDataBegin,            // start of `staticCallData`
 | 
			
		||||
                    staticCallDataLen               // copy the entire `staticCallData`
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // In order to find the offset to `callTarget`, we must add:
 | 
			
		||||
                // assetDataOffset
 | 
			
		||||
                // + 32 (assetData len)
 | 
			
		||||
                // + 4 (proxyId)
 | 
			
		||||
                let callTarget := and(
 | 
			
		||||
                    calldataload(add(assetDataOffset, 36)),
 | 
			
		||||
                    0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Perform `callTarget.staticcall(staticCallData)`
 | 
			
		||||
                let success := staticcall(
 | 
			
		||||
                    gas,                         // forward all gas
 | 
			
		||||
                    callTarget,                  // call address `callTarget`
 | 
			
		||||
                    0,                           // pointer to start of input
 | 
			
		||||
                    staticCallDataLen,           // length of input
 | 
			
		||||
                    0,                           // start of memory can be safely overwritten
 | 
			
		||||
                    0                            // don't copy output to memory
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Copy entire output to start of memory
 | 
			
		||||
                let outputLen := returndatasize()
 | 
			
		||||
                returndatacopy(
 | 
			
		||||
                    0,                // copy to memory at 0
 | 
			
		||||
                    0,                // copy from return data at 0
 | 
			
		||||
                    outputLen         // copy all return data
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Revert with reason given by `callTarget` if staticcall is unsuccessful
 | 
			
		||||
                if iszero(success) {
 | 
			
		||||
                    revert(0, outputLen)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Calculate hash of output
 | 
			
		||||
                let callResultHash := keccak256(0, outputLen)
 | 
			
		||||
 | 
			
		||||
                // In order to find the offset to `expectedCallResultHash`, we must add:
 | 
			
		||||
                // assetDataOffset
 | 
			
		||||
                // + 32 (assetData len)
 | 
			
		||||
                // + 4 (proxyId)
 | 
			
		||||
                // + 32 (callTarget)
 | 
			
		||||
                // + 32 (staticCallDataOffset)
 | 
			
		||||
                let expectedResultHash := calldataload(add(assetDataOffset, 100))
 | 
			
		||||
 | 
			
		||||
                if sub(callResultHash, expectedResultHash) {
 | 
			
		||||
                    // Revert with `Error("UNEXPECTED_STATIC_CALL_RESULT")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x0000001d554e45585045435445445f5354415449435f43414c4c5f524553554c)
 | 
			
		||||
                    mstore(96, 0x5400000000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Return if output matched expected output
 | 
			
		||||
                return(0, 0)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Revert if undefined function is called
 | 
			
		||||
            revert(0, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets the proxy id associated with the proxy address.
 | 
			
		||||
    /// @return Proxy id.
 | 
			
		||||
    function getProxyId()
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes4)
 | 
			
		||||
    {
 | 
			
		||||
        return PROXY_ID;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,19 +26,33 @@ pragma experimental ABIEncoderV2;
 | 
			
		||||
// This argument is ABI encoded as one of the methods of this interface.
 | 
			
		||||
interface IAssetData {
 | 
			
		||||
 | 
			
		||||
    function ERC20Token(address tokenContract)
 | 
			
		||||
    function ERC20Token(address tokenAddress)
 | 
			
		||||
        external;
 | 
			
		||||
    
 | 
			
		||||
    function ERC721Token(
 | 
			
		||||
        address tokenContract,
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256 tokenId
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    function ERC1155Assets(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256[] calldata tokenIds,
 | 
			
		||||
        uint256[] calldata tokenValues,
 | 
			
		||||
        bytes calldata callbackData
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    function MultiAsset(
 | 
			
		||||
        uint256[] calldata amounts,
 | 
			
		||||
        bytes[] calldata nestedAssetData
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    function StaticCall(
 | 
			
		||||
        address callTarget,
 | 
			
		||||
        bytes calldata staticCallData,
 | 
			
		||||
        bytes32 callResultHash
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,420 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
library LibAssetData {
 | 
			
		||||
    bytes4 constant public ERC20_PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
 | 
			
		||||
    bytes4 constant public ERC721_PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
 | 
			
		||||
    bytes4 constant public ERC1155_PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
 | 
			
		||||
    bytes4 constant public MULTI_ASSET_PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the owner's balance of the token(s) specified in
 | 
			
		||||
    ///     assetData.  When the asset data contains multiple tokens (eg in
 | 
			
		||||
    ///     ERC1155 or Multi-Asset), the return value indicates how many
 | 
			
		||||
    ///     complete "baskets" of those tokens are owned by owner.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @return Number of tokens (or token baskets) held by owner.
 | 
			
		||||
    function getBalance(address owner, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance)
 | 
			
		||||
    {
 | 
			
		||||
        bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
        if (proxyId == ERC20_PROXY_ID) {
 | 
			
		||||
            address tokenAddress = LibBytes.readAddress(assetData, 16);
 | 
			
		||||
            return IERC20Token(tokenAddress).balanceOf(owner);
 | 
			
		||||
        } else if (proxyId == ERC721_PROXY_ID) {
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
            return getERC721TokenOwner(tokenAddress, tokenId) == owner ? 1 : 0;
 | 
			
		||||
        } else if (proxyId == ERC1155_PROXY_ID) {
 | 
			
		||||
            uint256 lowestTokenBalance = 0;
 | 
			
		||||
            (
 | 
			
		||||
                ,
 | 
			
		||||
                address tokenAddress,
 | 
			
		||||
                uint256[] memory tokenIds,
 | 
			
		||||
                uint256[] memory tokenValues,
 | 
			
		||||
            ) = decodeERC1155AssetData(assetData);
 | 
			
		||||
            for (uint256 i = 0; i < tokenIds.length; i++) {
 | 
			
		||||
                uint256 tokenBalance = IERC1155(tokenAddress).balanceOf(owner, tokenIds[i]) / tokenValues[i];
 | 
			
		||||
                if (tokenBalance < lowestTokenBalance || lowestTokenBalance == 0) {
 | 
			
		||||
                    lowestTokenBalance = tokenBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return lowestTokenBalance;
 | 
			
		||||
        } else if (proxyId == MULTI_ASSET_PROXY_ID) {
 | 
			
		||||
            uint256 lowestAssetBalance = 0;
 | 
			
		||||
            (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
            for (uint256 i = 0; i < nestedAssetData.length; i++) {
 | 
			
		||||
                uint256 assetBalance = getBalance(owner, nestedAssetData[i]) / assetAmounts[i];
 | 
			
		||||
                if (assetBalance < lowestAssetBalance || lowestAssetBalance == 0) {
 | 
			
		||||
                    lowestAssetBalance = assetBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return lowestAssetBalance;
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("UNSUPPORTED_PROXY_IDENTIFIER");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() for each element of assetData.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param assetData Array of token descriptors, each encoded per the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @return Array of token balances from getBalance(), with each element
 | 
			
		||||
    ///     corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalances(address owner, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory balances)
 | 
			
		||||
    {
 | 
			
		||||
        balances = new uint256[](assetData.length);
 | 
			
		||||
        for (uint256 i = 0; i < assetData.length; i++) {
 | 
			
		||||
            balances[i] = getBalance(owner, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the number of token(s) (described by assetData) that
 | 
			
		||||
    ///     spender is authorized to spend.  When the asset data contains
 | 
			
		||||
    ///     multiple tokens (eg for Multi-Asset), the return value indicates
 | 
			
		||||
    ///     how many complete "baskets" of those tokens may be spent by spender.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param spender Address whose authority to spend is in question.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @return Number of tokens (or token baskets) that the spender is
 | 
			
		||||
    ///     authorized to spend.
 | 
			
		||||
    function getAllowance(address owner, address spender, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
 | 
			
		||||
        if (proxyId == ERC20_PROXY_ID) {
 | 
			
		||||
            address tokenAddress = LibBytes.readAddress(assetData, 16);
 | 
			
		||||
            return IERC20Token(tokenAddress).allowance(owner, spender);
 | 
			
		||||
        } else if (proxyId == ERC721_PROXY_ID) {
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
            IERC721Token token = IERC721Token(tokenAddress);
 | 
			
		||||
            if (spender == token.getApproved(tokenId) || token.isApprovedForAll(owner, spender)) {
 | 
			
		||||
                return 1;
 | 
			
		||||
            } else {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (proxyId == ERC1155_PROXY_ID) {
 | 
			
		||||
            (, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
 | 
			
		||||
            if (IERC1155(tokenAddress).isApprovedForAll(owner, spender)) {
 | 
			
		||||
                return 1;
 | 
			
		||||
            } else {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (proxyId == MULTI_ASSET_PROXY_ID) {
 | 
			
		||||
            uint256 lowestAssetAllowance = 0;
 | 
			
		||||
            // solhint-disable-next-line indent
 | 
			
		||||
            (, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
            for (uint256 i = 0; i < nestedAssetData.length; i++) {
 | 
			
		||||
                uint256 assetAllowance = getAllowance(owner, spender, nestedAssetData[i]) / amounts[i];
 | 
			
		||||
                if (assetAllowance < lowestAssetAllowance || lowestAssetAllowance == 0) {
 | 
			
		||||
                    lowestAssetAllowance = assetAllowance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return lowestAssetAllowance;
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("UNSUPPORTED_PROXY_IDENTIFIER");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getAllowance() for each element of assetData.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param spender Address whose authority to spend is in question.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @return An array of token allowances from getAllowance(), with each
 | 
			
		||||
    ///     element corresponding to the same-indexed element in the assetData
 | 
			
		||||
    ///     input.
 | 
			
		||||
    function getBatchAllowances(address owner, address spender, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        allowances = new uint256[](assetData.length);
 | 
			
		||||
        for (uint256 i = 0; i < assetData.length; i++) {
 | 
			
		||||
            allowances[i] = getAllowance(owner, spender, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() and getAllowance() for assetData.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param spender Address whose authority to spend is in question.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @return Number of tokens (or token baskets) held by owner, and number
 | 
			
		||||
    ///     of tokens (or token baskets) that the spender is authorized to
 | 
			
		||||
    ///     spend.
 | 
			
		||||
    function getBalanceAndAllowance(address owner, address spender, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        balance = getBalance(owner, assetData);
 | 
			
		||||
        allowance = getAllowance(owner, spender, assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBatchBalances() and getBatchAllowances() for each element
 | 
			
		||||
    ///     of assetData.
 | 
			
		||||
    /// @param owner Owner of the tokens specified by assetData.
 | 
			
		||||
    /// @param spender Address whose authority to spend is in question.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @return An array of token balances from getBalance(), and an array of
 | 
			
		||||
    ///     token allowances from getAllowance(), with each element
 | 
			
		||||
    ///     corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalancesAndAllowances(address owner, address spender, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory balances, uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        balances = getBatchBalances(owner, assetData);
 | 
			
		||||
        allowances = getBatchAllowances(owner, spender, assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-20 asset data into the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-20 contract hosting the
 | 
			
		||||
    ///     token to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the asset.
 | 
			
		||||
    function encodeERC20AssetData(address tokenAddress)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(ERC20_PROXY_ID, tokenAddress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-20 asset data from the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-20
 | 
			
		||||
    ///     asset.
 | 
			
		||||
    /// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20
 | 
			
		||||
    ///     contract hosting this asset.
 | 
			
		||||
    function decodeERC20AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 proxyId,
 | 
			
		||||
            address tokenAddress
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
 | 
			
		||||
        require(proxyId == ERC20_PROXY_ID, "WRONG_PROXY_ID");
 | 
			
		||||
 | 
			
		||||
        tokenAddress = LibBytes.readAddress(assetData, 16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-721 asset data into the format described in the
 | 
			
		||||
    ///     AssetProxy specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-721 contract hosting the
 | 
			
		||||
    ///     token to be traded.
 | 
			
		||||
    /// @param tokenId The identifier of the specific token to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the asset.
 | 
			
		||||
    function encodeERC721AssetData(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256 tokenId
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(ERC721_PROXY_ID, tokenAddress, tokenId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-721 asset data from the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-721
 | 
			
		||||
    ///     asset.
 | 
			
		||||
    /// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
 | 
			
		||||
    ///     contract hosting this asset, and the identifier of the specific
 | 
			
		||||
    ///     token to be traded.
 | 
			
		||||
    function decodeERC721AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 proxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256 tokenId
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
 | 
			
		||||
        require(proxyId == ERC721_PROXY_ID, "WRONG_PROXY_ID");
 | 
			
		||||
 | 
			
		||||
        tokenAddress = LibBytes.readAddress(assetData, 16);
 | 
			
		||||
        tokenId = LibBytes.readUint256(assetData, 36);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-1155 asset data into the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-1155 contract hosting the
 | 
			
		||||
    ///     token(s) to be traded.
 | 
			
		||||
    /// @param tokenIds The identifiers of the specific tokens to be traded.
 | 
			
		||||
    /// @param tokenValues The amounts of each token to be traded.
 | 
			
		||||
    /// @param callbackData ...
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the set of assets.
 | 
			
		||||
    function encodeERC1155AssetData(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256[] memory tokenIds,
 | 
			
		||||
        uint256[] memory tokenValues,
 | 
			
		||||
        bytes memory callbackData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(ERC1155_PROXY_ID, tokenAddress, tokenIds, tokenValues, callbackData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-1155 asset data from the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-1155
 | 
			
		||||
    ///     set of assets.
 | 
			
		||||
    /// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
 | 
			
		||||
    ///     contract hosting the assets, an array of the identifiers of the
 | 
			
		||||
    ///     tokens to be traded, an array of token amounts to be traded, and
 | 
			
		||||
    ///     callback data.  Each element of the arrays corresponds to the
 | 
			
		||||
    ///     same-indexed element of the other array.  Return values specified as
 | 
			
		||||
    ///     `memory` are returned as pointers to locations within the memory of
 | 
			
		||||
    ///     the input parameter `assetData`.
 | 
			
		||||
    function decodeERC1155AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 proxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256[] memory tokenIds,
 | 
			
		||||
            uint256[] memory tokenValues,
 | 
			
		||||
            bytes memory callbackData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
 | 
			
		||||
        require(proxyId == ERC1155_PROXY_ID, "WRONG_PROXY_ID");
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Skip selector and length to get to the first parameter:
 | 
			
		||||
            assetData := add(assetData, 36)
 | 
			
		||||
            // Read the value of the first parameter:
 | 
			
		||||
            tokenAddress := mload(assetData)
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            tokenIds := add(assetData, mload(add(assetData, 32)))
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            tokenValues := add(assetData, mload(add(assetData, 64)))
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            callbackData := add(assetData, mload(add(assetData, 96)))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode data for multiple assets, per the AssetProxy contract
 | 
			
		||||
    ///     specification.
 | 
			
		||||
    /// @param amounts The amounts of each asset to be traded.
 | 
			
		||||
    /// @param nestedAssetData AssetProxy-compliant data describing each asset
 | 
			
		||||
    ///     to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the set of assets.
 | 
			
		||||
    function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(MULTI_ASSET_PROXY_ID, amounts, nestedAssetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode multi-asset data from the format described in the
 | 
			
		||||
    ///     AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant data describing a multi-asset
 | 
			
		||||
    ///     basket.
 | 
			
		||||
    /// @return The Multi-Asset AssetProxy identifier, an array of the amounts
 | 
			
		||||
    ///     of the assets to be traded, and an array of the
 | 
			
		||||
    ///     AssetProxy-compliant data describing each asset to be traded.  Each
 | 
			
		||||
    ///     element of the arrays corresponds to the same-indexed element of
 | 
			
		||||
    ///     the other array.
 | 
			
		||||
    function decodeMultiAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 proxyId,
 | 
			
		||||
            uint256[] memory amounts,
 | 
			
		||||
            bytes[] memory nestedAssetData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        proxyId = LibBytes.readBytes4(assetData, 0);
 | 
			
		||||
 | 
			
		||||
        require(proxyId == MULTI_ASSET_PROXY_ID, "WRONG_PROXY_ID");
 | 
			
		||||
 | 
			
		||||
        // solhint-disable-next-line indent
 | 
			
		||||
        (amounts, nestedAssetData) = abi.decode(LibBytes.slice(assetData, 4, assetData.length), (uint256[], bytes[]));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
 | 
			
		||||
    /// @param token Address of ERC721 token.
 | 
			
		||||
    /// @param tokenId The identifier for the specific NFT.
 | 
			
		||||
    /// @return Owner of tokenId or null address if unowned.
 | 
			
		||||
    function getERC721TokenOwner(address token, uint256 tokenId)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (address owner)
 | 
			
		||||
    {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // load free memory pointer
 | 
			
		||||
            let cdStart := mload(64)
 | 
			
		||||
 | 
			
		||||
            // bytes4(keccak256(ownerOf(uint256))) = 0x6352211e
 | 
			
		||||
            mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
            mstore(add(cdStart, 4), tokenId)
 | 
			
		||||
 | 
			
		||||
            // staticcall `ownerOf(tokenId)`
 | 
			
		||||
            // `ownerOf` will revert if tokenId is not owned
 | 
			
		||||
            let success := staticcall(
 | 
			
		||||
                gas,      // forward all gas
 | 
			
		||||
                token,    // call token contract
 | 
			
		||||
                cdStart,  // start of calldata
 | 
			
		||||
                36,       // length of input is 36 bytes
 | 
			
		||||
                cdStart,  // write output over input
 | 
			
		||||
                32        // size of output is 32 bytes
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            // Success implies that tokenId is owned
 | 
			
		||||
            // Copy owner from return data if successful
 | 
			
		||||
            if success {
 | 
			
		||||
                owner := mload(cdStart)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Owner initialized to address(0), no need to modify if call is unsuccessful
 | 
			
		||||
        return owner;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LibAssetProxyIds {
 | 
			
		||||
 | 
			
		||||
    // AssetProxy Ids are equiavalent the first 4 bytes of the keccak256 hash of the function signature assigned to each AssetProxy.
 | 
			
		||||
 | 
			
		||||
    // ERC20Token(address)
 | 
			
		||||
    bytes4 constant public ERC20_PROXY_ID = 0xf47261b0;
 | 
			
		||||
 | 
			
		||||
    // ERC721Token(address,uint256)
 | 
			
		||||
    bytes4 constant public ERC721_PROXY_ID = 0x02571792;
 | 
			
		||||
 | 
			
		||||
    // ERC1155Assets(address,uint256[],uint256[],bytes)
 | 
			
		||||
    bytes4 constant public ERC1155_PROXY_ID = 0xa7cb5fb7;
 | 
			
		||||
 | 
			
		||||
    // MultiAsset(uint256[],bytes[])
 | 
			
		||||
    bytes4 constant public MULTI_ASSET_PROXY_ID = 0x94cfcdd7;
 | 
			
		||||
 | 
			
		||||
    // StaticCall(address,bytes,bytes32)
 | 
			
		||||
    bytes4 constant public STATIC_CALL_PROXY_ID = 0xc339d10a;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,82 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestStaticCallTarget {
 | 
			
		||||
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    uint256 internal _state;
 | 
			
		||||
 
 | 
			
		||||
    function updateState()
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _state++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function assertEvenNumber(uint256 target)
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            target % 2 == 0,
 | 
			
		||||
            "TARGET_NOT_EVEN"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function isOddNumber(uint256 target)
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bool isOdd)
 | 
			
		||||
    {
 | 
			
		||||
        isOdd = target % 2 == 1;
 | 
			
		||||
        return isOdd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function noInputFunction()
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
    {
 | 
			
		||||
        assert(msg.data.length == 4 && msg.data.readBytes4(0) == bytes4(keccak256("noInputFunction()")));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function dynamicInputFunction(bytes calldata a)
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
    {
 | 
			
		||||
        bytes memory abiEncodedData = abi.encodeWithSignature("dynamicInputFunction(bytes)", a);
 | 
			
		||||
        assert(msg.data.equals(abiEncodedData));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function returnComplexType(uint256 a, uint256 b)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes memory result)
 | 
			
		||||
    {
 | 
			
		||||
        result = abi.encodePacked(
 | 
			
		||||
            address(this),
 | 
			
		||||
            a,
 | 
			
		||||
            b
 | 
			
		||||
        );
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-asset-proxy",
 | 
			
		||||
    "version": "2.1.2",
 | 
			
		||||
    "version": "2.2.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|LibAssetData|MixinAuthorizable|MultiAssetProxy).json",
 | 
			
		||||
        "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy|StaticCallProxy|TestStaticCallTarget).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,17 +68,18 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.1.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.7",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,17 +11,19 @@ import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
 | 
			
		||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
 | 
			
		||||
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
 | 
			
		||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
 | 
			
		||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
 | 
			
		||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
 | 
			
		||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
 | 
			
		||||
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    LibAssetData: LibAssetData as ContractArtifact,
 | 
			
		||||
    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
			
		||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ export * from '../generated-wrappers/erc721_proxy';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_data';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_proxy';
 | 
			
		||||
export * from '../generated-wrappers/i_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/lib_asset_data';
 | 
			
		||||
export * from '../generated-wrappers/mixin_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/multi_asset_proxy';
 | 
			
		||||
export * from '../generated-wrappers/static_call_proxy';
 | 
			
		||||
export * from '../generated-wrappers/test_static_call_target';
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,426 +0,0 @@
 | 
			
		||||
// TODO: change test titles to say "... from asset data"
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc1155Artifacts,
 | 
			
		||||
    ERC1155MintableContract,
 | 
			
		||||
    ERC1155TransferSingleEventArgs,
 | 
			
		||||
    IERC1155MintableContract,
 | 
			
		||||
} from '@0x/contracts-erc1155';
 | 
			
		||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract, IERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import { artifacts as erc721Artifacts, DummyERC721TokenContract, IERC721TokenContract } from '@0x/contracts-erc721';
 | 
			
		||||
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { artifacts, LibAssetDataContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
const KNOWN_ERC20_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC721_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenId: new BigNumber(1),
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC1155_ENCODING = {
 | 
			
		||||
    tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
 | 
			
		||||
    tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
 | 
			
		||||
    callbackData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_MULTI_ASSET_ENCODING = {
 | 
			
		||||
    amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
 | 
			
		||||
    nestedAssetData: [
 | 
			
		||||
        KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC721_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC1155_ENCODING.assetData,
 | 
			
		||||
    ],
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('LibAssetData', () => {
 | 
			
		||||
    let libAssetData: LibAssetDataContract;
 | 
			
		||||
 | 
			
		||||
    let tokenOwnerAddress: string;
 | 
			
		||||
    let approvedSpenderAddress: string;
 | 
			
		||||
    let anotherApprovedSpenderAddress: string;
 | 
			
		||||
 | 
			
		||||
    let erc20TokenAddress: string;
 | 
			
		||||
    const erc20TokenTotalSupply = new BigNumber(1);
 | 
			
		||||
 | 
			
		||||
    let erc721TokenAddress: string;
 | 
			
		||||
    const firstERC721TokenId = new BigNumber(1);
 | 
			
		||||
    const numberOfERC721Tokens = 10;
 | 
			
		||||
 | 
			
		||||
    let erc1155MintableAddress: string;
 | 
			
		||||
    let erc1155TokenId: BigNumber;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
 | 
			
		||||
        libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.LibAssetData,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        [
 | 
			
		||||
            tokenOwnerAddress,
 | 
			
		||||
            approvedSpenderAddress,
 | 
			
		||||
            anotherApprovedSpenderAddress,
 | 
			
		||||
        ] = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
 | 
			
		||||
        erc20TokenAddress = (await DummyERC20TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc20Artifacts.DummyERC20Token,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            'Dummy',
 | 
			
		||||
            'DUM',
 | 
			
		||||
            new BigNumber(1),
 | 
			
		||||
            erc20TokenTotalSupply,
 | 
			
		||||
        )).address;
 | 
			
		||||
 | 
			
		||||
        const erc721TokenContract = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc721Artifacts.DummyERC721Token,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            'Dummy',
 | 
			
		||||
            'DUM',
 | 
			
		||||
        );
 | 
			
		||||
        erc721TokenAddress = erc721TokenContract.address;
 | 
			
		||||
        // mint `numberOfERC721Tokens` tokens
 | 
			
		||||
        const transactionMinedPromises = [];
 | 
			
		||||
        for (let i = 0; i < numberOfERC721Tokens; i++) {
 | 
			
		||||
            transactionMinedPromises.push(
 | 
			
		||||
                web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721TokenContract.mint.sendTransactionAsync(
 | 
			
		||||
                        tokenOwnerAddress,
 | 
			
		||||
                        firstERC721TokenId.plus(i - 1),
 | 
			
		||||
                    ),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        await Promise.all(transactionMinedPromises);
 | 
			
		||||
 | 
			
		||||
        const erc1155MintableContract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc1155Artifacts.ERC1155Mintable,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        erc1155MintableAddress = erc1155MintableContract.address;
 | 
			
		||||
        // Somewhat re-inventing the wheel here, but the prior art currently
 | 
			
		||||
        // exists only as an unexported test util in the erc1155 package
 | 
			
		||||
        // (Erc1155Wrapper.mintFungibleTokensAsync() in erc1155/test/utils/).
 | 
			
		||||
        // This is concise enough to justify duplication, but it sure is ugly.
 | 
			
		||||
        // tslint:disable-next-line no-unnecessary-type-assertion
 | 
			
		||||
        erc1155TokenId = ((await new LogDecoder(web3Wrapper, erc1155Artifacts).getTxWithDecodedLogsAsync(
 | 
			
		||||
            await erc1155MintableContract.create.sendTransactionAsync('uri:Dummy', /*isNonFungible:*/ false),
 | 
			
		||||
        )).logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc1155MintableContract.mintFungible.sendTransactionAsync(
 | 
			
		||||
                erc1155TokenId,
 | 
			
		||||
                [tokenOwnerAddress],
 | 
			
		||||
                [new BigNumber(1)],
 | 
			
		||||
            ),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    async function setERC20AllowanceAsync(): Promise<any> {
 | 
			
		||||
        return web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await new IERC20TokenContract(
 | 
			
		||||
                erc20Artifacts.IERC20Token.compilerOutput.abi,
 | 
			
		||||
                erc20TokenAddress,
 | 
			
		||||
                provider,
 | 
			
		||||
            ).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async function setERC721AllowanceAsync(): Promise<any> {
 | 
			
		||||
        return web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await new IERC721TokenContract(
 | 
			
		||||
                erc721Artifacts.IERC721Token.compilerOutput.abi,
 | 
			
		||||
                erc721TokenAddress,
 | 
			
		||||
                provider,
 | 
			
		||||
            ).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should have a deployed-to address', () => {
 | 
			
		||||
        expect(libAssetData.address.slice(0, 2)).to.equal('0x');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should encode ERC20 asset data', async () => {
 | 
			
		||||
        expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
 | 
			
		||||
            KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should decode ERC20 asset data', async () => {
 | 
			
		||||
        expect(await libAssetData.decodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
            AssetProxyId.ERC20,
 | 
			
		||||
            KNOWN_ERC20_ENCODING.address,
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should encode ERC721 asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.encodeERC721AssetData.callAsync(
 | 
			
		||||
                KNOWN_ERC721_ENCODING.address,
 | 
			
		||||
                KNOWN_ERC721_ENCODING.tokenId,
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.equal(KNOWN_ERC721_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should decode ERC721 asset data', async () => {
 | 
			
		||||
        expect(await libAssetData.decodeERC721AssetData.callAsync(KNOWN_ERC721_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
            AssetProxyId.ERC721,
 | 
			
		||||
            KNOWN_ERC721_ENCODING.address,
 | 
			
		||||
            KNOWN_ERC721_ENCODING.tokenId,
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should encode ERC1155 asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.encodeERC1155AssetData.callAsync(
 | 
			
		||||
                KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
                KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
                KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
                KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.equal(KNOWN_ERC1155_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should decode ERC1155 asset data', async () => {
 | 
			
		||||
        expect(await libAssetData.decodeERC1155AssetData.callAsync(KNOWN_ERC1155_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
            AssetProxyId.ERC1155,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should encode multiasset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.encodeMultiAssetData.callAsync(
 | 
			
		||||
                KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
                KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should decode multiasset data', async () => {
 | 
			
		||||
        expect(await libAssetData.decodeMultiAssetData.callAsync(KNOWN_MULTI_ASSET_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
            AssetProxyId.MultiAsset,
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC20 balance by asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBalance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(erc20TokenTotalSupply);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC721 balance by asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBalance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC1155 balances by asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBalance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                await libAssetData.encodeERC1155AssetData.callAsync(
 | 
			
		||||
                    erc1155MintableAddress,
 | 
			
		||||
                    [erc1155TokenId],
 | 
			
		||||
                    [new BigNumber(1)], // token values
 | 
			
		||||
                    '0x', // callback data
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query multi-asset batch balance by asset data', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBalance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                await libAssetData.encodeMultiAssetData.callAsync(
 | 
			
		||||
                    [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                    [
 | 
			
		||||
                        await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
                        await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
                    ],
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC20 allowances by asset data', async () => {
 | 
			
		||||
        await setERC20AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                approvedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC721 approval by asset data', async () => {
 | 
			
		||||
        await setERC721AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                approvedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC721 approvalForAll by assetData', async () => {
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await new IERC721TokenContract(
 | 
			
		||||
                erc721Artifacts.IERC721Token.compilerOutput.abi,
 | 
			
		||||
                erc721TokenAddress,
 | 
			
		||||
                provider,
 | 
			
		||||
            ).setApprovalForAll.sendTransactionAsync(anotherApprovedSpenderAddress, true, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                anotherApprovedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query ERC1155 allowances by asset data', async () => {
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await new IERC1155MintableContract(
 | 
			
		||||
                erc1155Artifacts.IERC1155Mintable.compilerOutput.abi,
 | 
			
		||||
                erc1155MintableAddress,
 | 
			
		||||
                provider,
 | 
			
		||||
            ).setApprovalForAll.sendTransactionAsync(approvedSpenderAddress, true, { from: tokenOwnerAddress }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                approvedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeERC1155AssetData.callAsync(
 | 
			
		||||
                    erc1155MintableAddress,
 | 
			
		||||
                    [erc1155TokenId],
 | 
			
		||||
                    [new BigNumber(1)],
 | 
			
		||||
                    '0x',
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query multi-asset allowances by asset data', async () => {
 | 
			
		||||
        await setERC20AllowanceAsync();
 | 
			
		||||
        await setERC721AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                approvedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeMultiAssetData.callAsync(
 | 
			
		||||
                    [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                    [
 | 
			
		||||
                        await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
                        await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
                    ],
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.bignumber.equal(1);
 | 
			
		||||
        return;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query balances for a batch of asset data strings', async () => {
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ]),
 | 
			
		||||
        ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query allowances for a batch of asset data strings', async () => {
 | 
			
		||||
        await setERC20AllowanceAsync();
 | 
			
		||||
        await setERC721AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBatchAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ]),
 | 
			
		||||
        ).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getERC721TokenOwner', async () => {
 | 
			
		||||
        it('should return the null address when tokenId is not owned', async () => {
 | 
			
		||||
            const nonexistentTokenId = new BigNumber(1234567890);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, nonexistentTokenId),
 | 
			
		||||
            ).to.be.equal(constants.NULL_ADDRESS);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the owner address when tokenId is owned', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, firstERC721TokenId),
 | 
			
		||||
            ).to.be.equal(tokenOwnerAddress);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query balance and allowance together, from asset data', async () => {
 | 
			
		||||
        await setERC20AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                tokenOwnerAddress,
 | 
			
		||||
                approvedSpenderAddress,
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
            ),
 | 
			
		||||
        ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should query balances and allowances together, from an asset data array', async () => {
 | 
			
		||||
        await setERC20AllowanceAsync();
 | 
			
		||||
        expect(
 | 
			
		||||
            await libAssetData.getBatchBalancesAndAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
 | 
			
		||||
                await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
 | 
			
		||||
            ]),
 | 
			
		||||
        ).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [new BigNumber(1)]]);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -44,16 +44,8 @@ import {
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
const assetProxyInterface = new IAssetProxyContract(
 | 
			
		||||
    artifacts.IAssetProxy.compilerOutput.abi,
 | 
			
		||||
    constants.NULL_ADDRESS,
 | 
			
		||||
    provider,
 | 
			
		||||
);
 | 
			
		||||
const assetDataInterface = new IAssetDataContract(
 | 
			
		||||
    artifacts.IAssetData.compilerOutput.abi,
 | 
			
		||||
    constants.NULL_ADDRESS,
 | 
			
		||||
    provider,
 | 
			
		||||
);
 | 
			
		||||
const assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
const assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
 | 
			
		||||
// tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
describe('Asset Transfer Proxies', () => {
 | 
			
		||||
@@ -199,6 +191,9 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
        await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
            fromAddress,
 | 
			
		||||
            constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
            {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await noReturnErc20Token.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
@@ -210,6 +205,9 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
        await multipleReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
            fromAddress,
 | 
			
		||||
            constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
            {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await multipleReturnErc20Token.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										250
									
								
								contracts/asset-proxy/test/static_call_proxy.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								contracts/asset-proxy/test/static_call_proxy.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectTransactionFailedAsync,
 | 
			
		||||
    expectTransactionFailedWithoutReasonAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { AssetProxyId, RevertReason } from '@0x/types';
 | 
			
		||||
import { AbiEncoder, BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
 | 
			
		||||
import { artifacts, IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('StaticCallProxy', () => {
 | 
			
		||||
    const amount = constants.ZERO_AMOUNT;
 | 
			
		||||
    let fromAddress: string;
 | 
			
		||||
    let toAddress: string;
 | 
			
		||||
 | 
			
		||||
    let staticCallProxy: IAssetProxyContract;
 | 
			
		||||
    let staticCallTarget: TestStaticCallTargetContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        [fromAddress, toAddress] = accounts.slice(0, 2);
 | 
			
		||||
        const staticCallProxyWithoutTransferFrom = await StaticCallProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.StaticCallProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        staticCallProxy = new IAssetProxyContract(staticCallProxyWithoutTransferFrom.address, provider, txDefaults);
 | 
			
		||||
        staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestStaticCallTarget,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('general', () => {
 | 
			
		||||
        it('should revert if undefined function is called', async () => {
 | 
			
		||||
            const undefinedSelector = '0x01020304';
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                    from: fromAddress,
 | 
			
		||||
                    to: staticCallProxy.address,
 | 
			
		||||
                    value: constants.ZERO_AMOUNT,
 | 
			
		||||
                    data: undefinedSelector,
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should have an id of 0xc339d10a', async () => {
 | 
			
		||||
            const proxyId = await staticCallProxy.getProxyId.callAsync();
 | 
			
		||||
            const expectedProxyId = AssetProxyId.StaticCall;
 | 
			
		||||
            expect(proxyId).to.equal(expectedProxyId);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('transferFrom', () => {
 | 
			
		||||
        it('should revert if assetData lies outside the bounds of calldata', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const txData = staticCallProxy.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
                assetData,
 | 
			
		||||
                fromAddress,
 | 
			
		||||
                toAddress,
 | 
			
		||||
                amount,
 | 
			
		||||
            );
 | 
			
		||||
            const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080';
 | 
			
		||||
            const txDataEndBuffer = ethUtil.toBuffer((txData.length - 2) / 2 - 4);
 | 
			
		||||
            const paddedTxDataEndBuffer = ethUtil.setLengthLeft(txDataEndBuffer, 32);
 | 
			
		||||
            const invalidOffsetToAssetData = ethUtil.bufferToHex(paddedTxDataEndBuffer).slice(2);
 | 
			
		||||
            const newAssetData = '0000000000000000000000000000000000000000000000000000000000000304';
 | 
			
		||||
            const badTxData = `${txData.replace(offsetToAssetData, invalidOffsetToAssetData)}${newAssetData}`;
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                    to: staticCallProxy.address,
 | 
			
		||||
                    from: fromAddress,
 | 
			
		||||
                    data: badTxData,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.InvalidAssetDataEnd,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the length of assetData, excluding the proxyId, is not a multiple of 32', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = `${assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            )}01`;
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                RevertReason.InvalidAssetDataLength,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the length of assetData is less than 100 bytes', async () => {
 | 
			
		||||
            const staticCallData = constants.NULL_BYTES;
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .slice(0, -128);
 | 
			
		||||
            const assetDataByteLen = (assetData.length - 2) / 2;
 | 
			
		||||
            expect((assetDataByteLen - 4) % 32).to.equal(0);
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                RevertReason.InvalidAssetDataLength,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
 | 
			
		||||
            const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
 | 
			
		||||
            const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
 | 
			
		||||
            const invalidOffsetToStaticCallData = ethUtil.bufferToHex(paddedAssetDataEndBuffer).slice(2);
 | 
			
		||||
            const newStaticCallData = '0000000000000000000000000000000000000000000000000000000000000304';
 | 
			
		||||
            const badAssetData = `${assetData.replace(
 | 
			
		||||
                offsetToStaticCallData,
 | 
			
		||||
                invalidOffsetToStaticCallData,
 | 
			
		||||
            )}${newStaticCallData}`;
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(badAssetData, fromAddress, toAddress, amount),
 | 
			
		||||
                RevertReason.InvalidStaticCallDataOffset,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the callTarget attempts to write to state', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                RevertReason.TargetNotEven,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the hash of the output is different than expected expected', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                RevertReason.UnexpectedStaticCallResult,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function call with no inputs is successful', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function call with one static input returns the correct value', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function with one dynamic input is successful', async () => {
 | 
			
		||||
            const dynamicInput = '0x0102030405060708';
 | 
			
		||||
            const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput);
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function call returns a complex type', async () => {
 | 
			
		||||
            const a = new BigNumber(1);
 | 
			
		||||
            const b = new BigNumber(2);
 | 
			
		||||
            const staticCallData = staticCallTarget.returnComplexType.getABIEncodedTransactionData(a, b);
 | 
			
		||||
            const abiEncoder = new AbiEncoder.DynamicBytes({
 | 
			
		||||
                name: '',
 | 
			
		||||
                type: 'bytes',
 | 
			
		||||
            });
 | 
			
		||||
            const aHex = '0000000000000000000000000000000000000000000000000000000000000001';
 | 
			
		||||
            const bHex = '0000000000000000000000000000000000000000000000000000000000000002';
 | 
			
		||||
            const expectedResults = `${staticCallTarget.address}${aHex}${bHex}`;
 | 
			
		||||
            const offset = '0000000000000000000000000000000000000000000000000000000000000020';
 | 
			
		||||
            const encodedExpectedResultWithOffset = `0x${offset}${abiEncoder.encode(expectedResults).slice(2)}`;
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(
 | 
			
		||||
                ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -36,11 +36,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        const allArtifacts = _.merge(artifacts, erc1155Artifacts);
 | 
			
		||||
        this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
 | 
			
		||||
        this._dummyTokenWrappers = [];
 | 
			
		||||
        this._assetProxyInterface = new IAssetProxyContract(
 | 
			
		||||
            artifacts.IAssetProxy.compilerOutput.abi,
 | 
			
		||||
            constants.NULL_ADDRESS,
 | 
			
		||||
            provider,
 | 
			
		||||
        );
 | 
			
		||||
        this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._fungibleTokenIds = [];
 | 
			
		||||
@@ -84,6 +80,66 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        return this._proxyIdIfExists as string;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev generates abi-encoded tx data for transferring erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param from source address
 | 
			
		||||
     * @param to destination address
 | 
			
		||||
     * @param contractAddress address of erc155 contract
 | 
			
		||||
     * @param tokensToTransfer array of erc1155 tokens to transfer
 | 
			
		||||
     * @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
 | 
			
		||||
     * @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
 | 
			
		||||
     * @param receiverCallbackData callback data if `to` is a contract
 | 
			
		||||
     * @param authorizedSender sender of `transferFrom` transaction
 | 
			
		||||
     * @param extraData extra data to append to `transferFrom` transaction. Optional.
 | 
			
		||||
     * @return abi encoded tx data.
 | 
			
		||||
     */
 | 
			
		||||
    public getTransferFromAbiEncodedTxData(
 | 
			
		||||
        from: string,
 | 
			
		||||
        to: string,
 | 
			
		||||
        contractAddress: string,
 | 
			
		||||
        tokensToTransfer: BigNumber[],
 | 
			
		||||
        valuesToTransfer: BigNumber[],
 | 
			
		||||
        valueMultiplier: BigNumber,
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        assetData_?: string,
 | 
			
		||||
    ): string {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                      contractAddress,
 | 
			
		||||
                      tokensToTransfer,
 | 
			
		||||
                      valuesToTransfer,
 | 
			
		||||
                      receiverCallbackData,
 | 
			
		||||
                  )
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
            assetData,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            valueMultiplier,
 | 
			
		||||
        );
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev transfers erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param txData: abi-encoded tx data
 | 
			
		||||
     * @param authorizedSender sender of `transferFrom` transaction
 | 
			
		||||
     */
 | 
			
		||||
    public async transferFromRawAsync(
 | 
			
		||||
        txData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const txHash = await this._web3Wrapper.sendTransactionAsync({
 | 
			
		||||
            to: (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
            data: txData,
 | 
			
		||||
            from: authorizedSender,
 | 
			
		||||
            gas: 300000,
 | 
			
		||||
        });
 | 
			
		||||
        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev transfers erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param from source address
 | 
			
		||||
@@ -106,20 +162,20 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        valueMultiplier: BigNumber,
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        extraData?: string,
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        assetData_?: string,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        let encodedAssetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
            contractAddress,
 | 
			
		||||
            tokensToTransfer,
 | 
			
		||||
            valuesToTransfer,
 | 
			
		||||
            receiverCallbackData,
 | 
			
		||||
        );
 | 
			
		||||
        if (extraData !== undefined) {
 | 
			
		||||
            encodedAssetData = `${encodedAssetData}${extraData}`;
 | 
			
		||||
        }
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                      contractAddress,
 | 
			
		||||
                      tokensToTransfer,
 | 
			
		||||
                      valuesToTransfer,
 | 
			
		||||
                      receiverCallbackData,
 | 
			
		||||
                  )
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
            encodedAssetData,
 | 
			
		||||
            assetData,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            valueMultiplier,
 | 
			
		||||
@@ -128,46 +184,9 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
            to: (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
            data,
 | 
			
		||||
            from: authorizedSender,
 | 
			
		||||
            gas: 300000,
 | 
			
		||||
        });
 | 
			
		||||
        return txHash;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev transfers erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param from source address
 | 
			
		||||
     * @param to destination address
 | 
			
		||||
     * @param contractAddress address of erc155 contract
 | 
			
		||||
     * @param tokensToTransfer array of erc1155 tokens to transfer
 | 
			
		||||
     * @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
 | 
			
		||||
     * @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
 | 
			
		||||
     * @param receiverCallbackData callback data if `to` is a contract
 | 
			
		||||
     * @param authorizedSender sender of `transferFrom` transaction
 | 
			
		||||
     * @param extraData extra data to append to `transferFrom` transaction. Optional.
 | 
			
		||||
     * @return tranasction receipt with decoded logs.
 | 
			
		||||
     */
 | 
			
		||||
    public async transferFromWithLogsAsync(
 | 
			
		||||
        from: string,
 | 
			
		||||
        to: string,
 | 
			
		||||
        contractAddress: string,
 | 
			
		||||
        tokensToTransfer: BigNumber[],
 | 
			
		||||
        valuesToTransfer: BigNumber[],
 | 
			
		||||
        valueMultiplier: BigNumber,
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        extraData?: string,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this.transferFromAsync(
 | 
			
		||||
                from,
 | 
			
		||||
                to,
 | 
			
		||||
                contractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorizedSender,
 | 
			
		||||
                extraData,
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,10 @@
 | 
			
		||||
        "generated-artifacts/IAssetData.json",
 | 
			
		||||
        "generated-artifacts/IAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/LibAssetData.json",
 | 
			
		||||
        "generated-artifacts/MixinAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/MultiAssetProxy.json"
 | 
			
		||||
        "generated-artifacts/MultiAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/StaticCallProxy.json",
 | 
			
		||||
        "generated-artifacts/TestStaticCallTarget.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "2.0.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.0.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.0.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "2.0.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "2.0.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.0.5 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.0.4 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.0.3 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.0.2 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.0.1 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-coordinator",
 | 
			
		||||
    "version": "2.0.1",
 | 
			
		||||
    "version": "2.0.5",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,18 +68,18 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/contracts-exchange": "1.0.2",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.6",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { artifacts, IExchangeContract } from '@0x/contracts-exchange';
 | 
			
		||||
import { IExchangeContract } from '@0x/contracts-exchange';
 | 
			
		||||
import { constants as devConstants, provider } from '@0x/contracts-test-utils';
 | 
			
		||||
import { SignedOrder } from '@0x/types';
 | 
			
		||||
 | 
			
		||||
@@ -6,11 +6,7 @@ import { constants } from './index';
 | 
			
		||||
 | 
			
		||||
export const exchangeDataEncoder = {
 | 
			
		||||
    encodeOrdersToExchangeData(fnName: string, orders: SignedOrder[]): string {
 | 
			
		||||
        const exchangeInstance = new IExchangeContract(
 | 
			
		||||
            artifacts.IExchange.compilerOutput.abi,
 | 
			
		||||
            devConstants.NULL_ADDRESS,
 | 
			
		||||
            provider,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeInstance = new IExchangeContract(devConstants.NULL_ADDRESS, provider);
 | 
			
		||||
        let data;
 | 
			
		||||
        if (constants.SINGLE_FILL_FN_NAMES.indexOf(fnName) !== -1) {
 | 
			
		||||
            data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								contracts/dev-utils/CHANGELOG.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								contracts/dev-utils/CHANGELOG.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "0.0.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.0.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Create dev-utils package",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `LibAssetData` and `LibTransactionDecoder` contracts",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Refactor `LibAssetData` to only check 0x-specific allowances",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Refactor `LibAssetData` balance/allowance checks to never revert",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Refactor `OrderValidationUtils` to calculate `fillableTakerAssetAmount`",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add support for StaticCallProxy",
 | 
			
		||||
                "pr": 1863
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										19
									
								
								contracts/dev-utils/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								contracts/dev-utils/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
<!--
 | 
			
		||||
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
 | 
			
		||||
Edit the package's CHANGELOG.json file only.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.0.2 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v0.0.1 - _Invalid date_
 | 
			
		||||
 | 
			
		||||
    * Create dev-utils package (#1848)
 | 
			
		||||
    * Add `LibAssetData` and `LibTransactionDecoder` contracts (#1848)
 | 
			
		||||
    * Refactor `LibAssetData` to only check 0x-specific allowances (#1848)
 | 
			
		||||
    * Refactor `LibAssetData` balance/allowance checks to never revert (#1848)
 | 
			
		||||
    * Refactor `OrderValidationUtils` to calculate `fillableTakerAssetAmount` (#1848)
 | 
			
		||||
    * Add support for StaticCallProxy (#1863)
 | 
			
		||||
							
								
								
									
										1
									
								
								contracts/dev-utils/DEPLOYS.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								contracts/dev-utils/DEPLOYS.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
[]
 | 
			
		||||
							
								
								
									
										73
									
								
								contracts/dev-utils/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								contracts/dev-utils/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
## Dev-Utils
 | 
			
		||||
 | 
			
		||||
This package implements various utilities for developers. For example, the `DevUtils` contract can query batches of balances or allowances given some `assetData`, can validate batches of orders, and can decode 0x-specific calldata. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
**Install**
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npm install @0x/contracts-dev-utils --save
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Bug bounty
 | 
			
		||||
 | 
			
		||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
 | 
			
		||||
 | 
			
		||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
 | 
			
		||||
 | 
			
		||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
 | 
			
		||||
 | 
			
		||||
### Install Dependencies
 | 
			
		||||
 | 
			
		||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn config set workspaces-experimental true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then install dependencies
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Build
 | 
			
		||||
 | 
			
		||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=@0x/contracts-extensions yarn build
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or continuously rebuild on change:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=@0x/contracts-extensions yarn watch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Clean
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn clean
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Lint
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn lint
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Run Tests
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn test
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Testing options
 | 
			
		||||
 | 
			
		||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
 | 
			
		||||
							
								
								
									
										32
									
								
								contracts/dev-utils/compiler.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								contracts/dev-utils/compiler.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "constantinople",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "runs": 1000000,
 | 
			
		||||
            "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
 | 
			
		||||
        },
 | 
			
		||||
        "outputSelection": {
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
                    "evm.deployedBytecode.sourceMap"
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "contracts": [
 | 
			
		||||
        "src/DevUtils.sol",
 | 
			
		||||
        "src/LibAssetData.sol",
 | 
			
		||||
        "src/LibTransactionDecoder.sol",
 | 
			
		||||
        "src/EthBalanceChecker.sol"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								contracts/dev-utils/contracts/src/DevUtils.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								contracts/dev-utils/contracts/src/DevUtils.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "./OrderValidationUtils.sol";
 | 
			
		||||
import "./LibTransactionDecoder.sol";
 | 
			
		||||
import "./EthBalanceChecker.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-empty-blocks
 | 
			
		||||
contract DevUtils is
 | 
			
		||||
    OrderValidationUtils,
 | 
			
		||||
    LibTransactionDecoder,
 | 
			
		||||
    EthBalanceChecker
 | 
			
		||||
{
 | 
			
		||||
    constructor (address _exchange, bytes memory _zrxAssetData)
 | 
			
		||||
        public
 | 
			
		||||
        OrderValidationUtils(_exchange, _zrxAssetData)
 | 
			
		||||
    {}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								contracts/dev-utils/contracts/src/EthBalanceChecker.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								contracts/dev-utils/contracts/src/EthBalanceChecker.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract EthBalanceChecker {
 | 
			
		||||
 | 
			
		||||
    /// @dev Batch fetches ETH balances
 | 
			
		||||
    /// @param addresses Array of addresses.
 | 
			
		||||
    /// @return Array of ETH balances.
 | 
			
		||||
    function getEthBalances(address[] memory addresses)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory)
 | 
			
		||||
    {
 | 
			
		||||
        uint256[] memory balances = new uint256[](addresses.length);
 | 
			
		||||
        for (uint256 i = 0; i != addresses.length; i++) {
 | 
			
		||||
            balances[i] = addresses[i].balance;
 | 
			
		||||
        }
 | 
			
		||||
        return balances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										541
									
								
								contracts/dev-utils/contracts/src/LibAssetData.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										541
									
								
								contracts/dev-utils/contracts/src/LibAssetData.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,541 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/libs/LibAssetProxyIds.sol";
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LibAssetData is
 | 
			
		||||
    LibAssetProxyIds
 | 
			
		||||
{
 | 
			
		||||
    // 2^256 - 1
 | 
			
		||||
    uint256 constant internal _MAX_UINT256 = uint256(-1);
 | 
			
		||||
 | 
			
		||||
    // ERC20 selectors
 | 
			
		||||
    bytes4 constant internal _ERC20_BALANCE_OF_SELECTOR = 0x70a08231;
 | 
			
		||||
    bytes4 constant internal _ERC20_ALLOWANCE_SELECTOR = 0xdd62ed3e;
 | 
			
		||||
 | 
			
		||||
    // ERC721 selectors
 | 
			
		||||
    bytes4 constant internal _ERC721_OWNER_OF_SELECTOR = 0x6352211e;
 | 
			
		||||
    bytes4 constant internal _ERC721_IS_APPROVED_FOR_ALL_SELECTOR = 0xe985e9c5;
 | 
			
		||||
    bytes4 constant internal _ERC721_GET_APPROVED_SELECTOR = 0x081812fc;
 | 
			
		||||
 | 
			
		||||
    // ERC1155 selectors
 | 
			
		||||
    bytes4 constant internal _ERC1155_BALANCE_OF_SELECTOR = 0x00fdd58e;
 | 
			
		||||
    bytes4 constant internal _ERC1155_IS_APPROVED_FOR_ALL_SELECTOR = 0xe985e9c5;
 | 
			
		||||
 | 
			
		||||
    // `transferFrom` selector for all AssetProxy contracts
 | 
			
		||||
    bytes4 constant internal _ASSET_PROXY_TRANSFER_FROM_SELECTOR = 0xa85e59e4;
 | 
			
		||||
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable var-name-mixedcase
 | 
			
		||||
    IExchange internal _EXCHANGE;
 | 
			
		||||
    address internal _ERC20_PROXY_ADDRESS;
 | 
			
		||||
    address internal _ERC721_PROXY_ADDRESS;
 | 
			
		||||
    address internal _ERC1155_PROXY_ADDRESS;
 | 
			
		||||
    address internal _STATIC_CALL_PROXY_ADDRESS;
 | 
			
		||||
    // solhint-enable var-name-mixedcase
 | 
			
		||||
 | 
			
		||||
    constructor (address _exchange)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        _EXCHANGE = IExchange(_exchange);
 | 
			
		||||
        _ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC20_PROXY_ID);
 | 
			
		||||
        _ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC721_PROXY_ID);
 | 
			
		||||
        _ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC1155_PROXY_ID);
 | 
			
		||||
        _STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(STATIC_CALL_PROXY_ID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the owner's balance of the assets(s) specified in
 | 
			
		||||
    /// assetData.  When the asset data contains multiple assets (eg in
 | 
			
		||||
    /// ERC1155 or Multi-Asset), the return value indicates how many
 | 
			
		||||
    /// complete "baskets" of those assets are owned by owner.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner.
 | 
			
		||||
    function getBalance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == ERC20_PROXY_ID) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `balanceOf(ownerAddress)`
 | 
			
		||||
            bytes memory balanceOfData = abi.encodeWithSelector(_ERC20_BALANCE_OF_SELECTOR, ownerAddress);
 | 
			
		||||
 | 
			
		||||
            // Query balance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
 | 
			
		||||
            balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
        } else if (assetProxyId == ERC721_PROXY_ID) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Check if id is owned by ownerAddress
 | 
			
		||||
            balance = getERC721TokenOwner(tokenAddress, tokenId) == ownerAddress ? 1 : 0;
 | 
			
		||||
        } else if (assetProxyId == ERC1155_PROXY_ID) {
 | 
			
		||||
            // Get ERC1155 token address, array of ids, and array of values
 | 
			
		||||
            (, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = tokenIds.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Encode data for `balanceOf(ownerAddress, tokenIds[i])
 | 
			
		||||
                bytes memory balanceOfData = abi.encodeWithSelector(
 | 
			
		||||
                    _ERC1155_BALANCE_OF_SELECTOR,
 | 
			
		||||
                    ownerAddress,
 | 
			
		||||
                    tokenIds[i]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                // Query balance
 | 
			
		||||
                (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
 | 
			
		||||
                uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / tokenValues[i];
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (assetProxyId == STATIC_CALL_PROXY_ID) {
 | 
			
		||||
            // Encode data for `staticCallProxy.transferFrom(assetData,...)`
 | 
			
		||||
            bytes memory transferFromData = abi.encodeWithSelector(
 | 
			
		||||
                _ASSET_PROXY_TRANSFER_FROM_SELECTOR,
 | 
			
		||||
                assetData,
 | 
			
		||||
                address(0),  // `from` address is not used
 | 
			
		||||
                address(0),  // `to` address is not used
 | 
			
		||||
                0            // `amount` is not used
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Check if staticcall would be successful
 | 
			
		||||
            (bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
 | 
			
		||||
 | 
			
		||||
            // Success means that the staticcall can be made an unlimited amount of times
 | 
			
		||||
            balance = success ? _MAX_UINT256 : 0;
 | 
			
		||||
        } else if (assetProxyId == MULTI_ASSET_PROXY_ID) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Query balance of individual assetData
 | 
			
		||||
                uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / assetAmounts[i];
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        // Balance will be 0 if assetProxyId is unknown
 | 
			
		||||
        return balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Array of asset balances from getBalance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory balances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        balances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            balances[i] = getBalance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return balances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the number of asset(s) (described by assetData) that
 | 
			
		||||
    /// the corresponding AssetProxy contract is authorized to spend.  When the asset data contains
 | 
			
		||||
    /// multiple assets (eg for Multi-Asset), the return value indicates
 | 
			
		||||
    /// how many complete "baskets" of those assets may be spent by all of the corresponding
 | 
			
		||||
    /// AssetProxy contracts.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == MULTI_ASSET_PROXY_ID) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Query allowance of individual assetData
 | 
			
		||||
                uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total allowance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledAllowance = totalAllowance / amounts[i];
 | 
			
		||||
                if (scaledAllowance < allowance || allowance == 0) {
 | 
			
		||||
                    allowance = scaledAllowance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return allowance;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == ERC20_PROXY_ID) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory allowanceData = abi.encodeWithSelector(
 | 
			
		||||
                _ERC20_ALLOWANCE_SELECTOR,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC20_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
 | 
			
		||||
            allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
        } else if (assetProxyId == ERC721_PROXY_ID) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                _ERC721_IS_APPROVED_FOR_ALL_SELECTOR,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC721_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
 | 
			
		||||
            // If not approved for all, call `getApproved(tokenId)`
 | 
			
		||||
            if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
 | 
			
		||||
                // Encode data for `getApproved(tokenId)`
 | 
			
		||||
                bytes memory getApprovedData = abi.encodeWithSelector(_ERC721_GET_APPROVED_SELECTOR, tokenId);
 | 
			
		||||
                (success, returnData) = tokenAddress.staticcall(getApprovedData);
 | 
			
		||||
 | 
			
		||||
                // Allowance is 1 if successful and the approved address is the ERC721Proxy
 | 
			
		||||
                allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                // Allowance is 2^256 - 1 if `isApprovedForAll` returned true
 | 
			
		||||
                allowance = _MAX_UINT256;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (assetProxyId == ERC1155_PROXY_ID) {
 | 
			
		||||
            // Get ERC1155 token address
 | 
			
		||||
            (, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                _ERC1155_IS_APPROVED_FOR_ALL_SELECTOR,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC1155_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
            allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
 | 
			
		||||
        } else if (assetProxyId == STATIC_CALL_PROXY_ID) {
 | 
			
		||||
            // The StaticCallProxy does not require any approvals
 | 
			
		||||
            allowance = _MAX_UINT256;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Allowance will be 0 if the assetProxyId is unknown
 | 
			
		||||
        return allowance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getAssetProxyAllowance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset allowances from getAllowance(), with each
 | 
			
		||||
    /// element corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        allowances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return allowances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() and getAllowance() for assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner, and number
 | 
			
		||||
    /// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        balance = getBalance(ownerAddress, assetData);
 | 
			
		||||
        allowance = getAssetProxyAllowance(ownerAddress, assetData);
 | 
			
		||||
        return (balance, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset balances from getBalance(), and an array of
 | 
			
		||||
    /// asset allowances from getAllowance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory balances, uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        balances = getBatchBalances(ownerAddress, assetData);
 | 
			
		||||
        allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
 | 
			
		||||
        return (balances, allowances);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the asset.
 | 
			
		||||
    function encodeERC20AssetData(address tokenAddress)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(ERC20_PROXY_ID, tokenAddress);
 | 
			
		||||
        return assetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
 | 
			
		||||
    /// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20 
 | 
			
		||||
    /// contract hosting this asset.
 | 
			
		||||
    function decodeERC20AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == ERC20_PROXY_ID,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        tokenAddress = assetData.readAddress(16);
 | 
			
		||||
        return (assetProxyId, tokenAddress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded.
 | 
			
		||||
    /// @param tokenId The identifier of the specific asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the asset.
 | 
			
		||||
    function encodeERC721AssetData(address tokenAddress, uint256 tokenId)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(
 | 
			
		||||
            ERC721_PROXY_ID,
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            tokenId
 | 
			
		||||
        );
 | 
			
		||||
        return assetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset.
 | 
			
		||||
    /// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
 | 
			
		||||
    /// contract hosting this asset, and the identifier of the specific
 | 
			
		||||
    /// asset to be traded.
 | 
			
		||||
    function decodeERC721AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256 tokenId
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == ERC721_PROXY_ID,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        tokenAddress = assetData.readAddress(16);
 | 
			
		||||
        tokenId = assetData.readUint256(36);
 | 
			
		||||
        return (assetProxyId, tokenAddress, tokenId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded.
 | 
			
		||||
    /// @param tokenIds The identifiers of the specific assets to be traded.
 | 
			
		||||
    /// @param tokenValues The amounts of each asset to be traded.
 | 
			
		||||
    /// @param callbackData Data to be passed to receiving contracts when a transfer is performed.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the set of assets.
 | 
			
		||||
    function encodeERC1155AssetData(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256[] memory tokenIds,
 | 
			
		||||
        uint256[] memory tokenValues,
 | 
			
		||||
        bytes memory callbackData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(
 | 
			
		||||
            ERC1155_PROXY_ID,
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            tokenIds,
 | 
			
		||||
            tokenValues,
 | 
			
		||||
            callbackData
 | 
			
		||||
        );
 | 
			
		||||
        return assetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets.
 | 
			
		||||
    /// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
 | 
			
		||||
    /// contract hosting the assets, an array of the identifiers of the
 | 
			
		||||
    /// assets to be traded, an array of asset amounts to be traded, and
 | 
			
		||||
    /// callback data.  Each element of the arrays corresponds to the
 | 
			
		||||
    /// same-indexed element of the other array.  Return values specified as
 | 
			
		||||
    /// `memory` are returned as pointers to locations within the memory of
 | 
			
		||||
    /// the input parameter `assetData`.
 | 
			
		||||
    function decodeERC1155AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256[] memory tokenIds,
 | 
			
		||||
            uint256[] memory tokenValues,
 | 
			
		||||
            bytes memory callbackData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == ERC1155_PROXY_ID,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Skip selector and length to get to the first parameter:
 | 
			
		||||
            assetData := add(assetData, 36)
 | 
			
		||||
            // Read the value of the first parameter:
 | 
			
		||||
            tokenAddress := mload(assetData)
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            tokenIds := add(assetData, mload(add(assetData, 32)))
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            tokenValues := add(assetData, mload(add(assetData, 64)))
 | 
			
		||||
            // Point to the next parameter's data:
 | 
			
		||||
            callbackData := add(assetData, mload(add(assetData, 96)))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            assetProxyId,
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            tokenIds,
 | 
			
		||||
            tokenValues,
 | 
			
		||||
            callbackData
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode data for multiple assets, per the AssetProxy contract specification.
 | 
			
		||||
    /// @param amounts The amounts of each asset to be traded.
 | 
			
		||||
    /// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the set of assets.
 | 
			
		||||
    function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(
 | 
			
		||||
            MULTI_ASSET_PROXY_ID,
 | 
			
		||||
            amounts,
 | 
			
		||||
            nestedAssetData
 | 
			
		||||
        );
 | 
			
		||||
        return assetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode multi-asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant data describing a multi-asset basket.
 | 
			
		||||
    /// @return The Multi-Asset AssetProxy identifier, an array of the amounts
 | 
			
		||||
    /// of the assets to be traded, and an array of the
 | 
			
		||||
    /// AssetProxy-compliant data describing each asset to be traded.  Each
 | 
			
		||||
    /// element of the arrays corresponds to the same-indexed element of the other array.
 | 
			
		||||
    function decodeMultiAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            uint256[] memory amounts,
 | 
			
		||||
            bytes[] memory nestedAssetData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == MULTI_ASSET_PROXY_ID,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // solhint-disable indent
 | 
			
		||||
        (amounts, nestedAssetData) = abi.decode(
 | 
			
		||||
            assetData.slice(4, assetData.length),
 | 
			
		||||
            (uint256[], bytes[])
 | 
			
		||||
        );
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `asset.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned asset.
 | 
			
		||||
    /// @param tokenAddress Address of ERC721 asset.
 | 
			
		||||
    /// @param tokenId The identifier for the specific NFT.
 | 
			
		||||
    /// @return Owner of tokenId or null address if unowned.
 | 
			
		||||
    function getERC721TokenOwner(address tokenAddress, uint256 tokenId)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (address ownerAddress)
 | 
			
		||||
    {
 | 
			
		||||
        bytes memory ownerOfCalldata = abi.encodeWithSelector(
 | 
			
		||||
            _ERC721_OWNER_OF_SELECTOR,
 | 
			
		||||
            tokenId
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        (bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
 | 
			
		||||
 | 
			
		||||
        ownerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
 | 
			
		||||
        return ownerAddress;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										193
									
								
								contracts/dev-utils/contracts/src/LibTransactionDecoder.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								contracts/dev-utils/contracts/src/LibTransactionDecoder.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibExchangeSelectors.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LibTransactionDecoder is
 | 
			
		||||
    LibExchangeSelectors
 | 
			
		||||
{
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Decodes the call data for an Exchange contract method call.
 | 
			
		||||
    /// @param transactionData ABI-encoded calldata for an Exchange
 | 
			
		||||
    ///     contract method call.
 | 
			
		||||
    /// @return The name of the function called, and the parameters it was
 | 
			
		||||
    ///     given.  For single-order fills and cancels, the arrays will have
 | 
			
		||||
    ///     just one element.
 | 
			
		||||
    function decodeZeroExTransactionData(bytes memory transactionData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns(
 | 
			
		||||
            string memory functionName,
 | 
			
		||||
            LibOrder.Order[] memory orders,
 | 
			
		||||
            uint256[] memory takerAssetFillAmounts,
 | 
			
		||||
            bytes[] memory signatures
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        bytes4 functionSelector = transactionData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (functionSelector == BATCH_CANCEL_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "batchCancelOrders";
 | 
			
		||||
        } else if (functionSelector == BATCH_FILL_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "batchFillOrders";
 | 
			
		||||
        } else if (functionSelector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR) {
 | 
			
		||||
            functionName = "batchFillOrdersNoThrow";
 | 
			
		||||
        } else if (functionSelector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "batchFillOrKillOrders";
 | 
			
		||||
        } else if (functionSelector == CANCEL_ORDER_SELECTOR) {
 | 
			
		||||
            functionName = "cancelOrder";
 | 
			
		||||
        } else if (functionSelector == FILL_ORDER_SELECTOR) {
 | 
			
		||||
            functionName = "fillOrder";
 | 
			
		||||
        } else if (functionSelector == FILL_ORDER_NO_THROW_SELECTOR) {
 | 
			
		||||
            functionName = "fillOrderNoThrow";
 | 
			
		||||
        } else if (functionSelector == FILL_OR_KILL_ORDER_SELECTOR) {
 | 
			
		||||
            functionName = "fillOrKillOrder";
 | 
			
		||||
        } else if (functionSelector == MARKET_BUY_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "marketBuyOrders";
 | 
			
		||||
        } else if (functionSelector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR) {
 | 
			
		||||
            functionName = "marketBuyOrdersNoThrow";
 | 
			
		||||
        } else if (functionSelector == MARKET_SELL_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "marketSellOrders";
 | 
			
		||||
        } else if (functionSelector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR) {
 | 
			
		||||
            functionName = "marketSellOrdersNoThrow";
 | 
			
		||||
        } else if (functionSelector == MATCH_ORDERS_SELECTOR) {
 | 
			
		||||
            functionName = "matchOrders";
 | 
			
		||||
        } else if (
 | 
			
		||||
            functionSelector == CANCEL_ORDERS_UP_TO_SELECTOR ||
 | 
			
		||||
            functionSelector == EXECUTE_TRANSACTION_SELECTOR
 | 
			
		||||
            // TODO: add new noThrow cancel functions when https://github.com/0xProject/ZEIPs/issues/35 is merged.
 | 
			
		||||
        ) {
 | 
			
		||||
            revert("UNIMPLEMENTED");
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("UNKNOWN_FUNCTION_SELECTOR");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (functionSelector == BATCH_CANCEL_ORDERS_SELECTOR) {
 | 
			
		||||
            // solhint-disable-next-line indent
 | 
			
		||||
            orders = abi.decode(transactionData.slice(4, transactionData.length), (LibOrder.Order[]));
 | 
			
		||||
            takerAssetFillAmounts = new uint256[](0);
 | 
			
		||||
            signatures = new bytes[](0);
 | 
			
		||||
        } else if (
 | 
			
		||||
            functionSelector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR ||
 | 
			
		||||
            functionSelector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR ||
 | 
			
		||||
            functionSelector == BATCH_FILL_ORDERS_SELECTOR
 | 
			
		||||
        ) {
 | 
			
		||||
            (orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForBatchFill(transactionData);
 | 
			
		||||
        } else if (functionSelector == CANCEL_ORDER_SELECTOR) {
 | 
			
		||||
            orders = new LibOrder.Order[](1);
 | 
			
		||||
            orders[0] = abi.decode(transactionData.slice(4, transactionData.length), (LibOrder.Order));
 | 
			
		||||
            takerAssetFillAmounts = new uint256[](0);
 | 
			
		||||
            signatures = new bytes[](0);
 | 
			
		||||
        } else if (
 | 
			
		||||
            functionSelector == FILL_OR_KILL_ORDER_SELECTOR ||
 | 
			
		||||
            functionSelector == FILL_ORDER_SELECTOR ||
 | 
			
		||||
            functionSelector == FILL_ORDER_NO_THROW_SELECTOR
 | 
			
		||||
        ) {
 | 
			
		||||
            (orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForSingleOrderFill(transactionData);
 | 
			
		||||
        } else if (
 | 
			
		||||
            functionSelector == MARKET_BUY_ORDERS_SELECTOR ||
 | 
			
		||||
            functionSelector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR ||
 | 
			
		||||
            functionSelector == MARKET_SELL_ORDERS_SELECTOR ||
 | 
			
		||||
            functionSelector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR
 | 
			
		||||
        ) {
 | 
			
		||||
            (orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForMarketFill(transactionData);
 | 
			
		||||
        } else if (functionSelector == MATCH_ORDERS_SELECTOR) {
 | 
			
		||||
            (
 | 
			
		||||
                LibOrder.Order memory leftOrder,
 | 
			
		||||
                LibOrder.Order memory rightOrder,
 | 
			
		||||
                bytes memory leftSignature,
 | 
			
		||||
                bytes memory rightSignature
 | 
			
		||||
            ) = abi.decode(
 | 
			
		||||
                transactionData.slice(4, transactionData.length),
 | 
			
		||||
                (LibOrder.Order, LibOrder.Order, bytes, bytes)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            orders = new LibOrder.Order[](2);
 | 
			
		||||
            orders[0] = leftOrder;
 | 
			
		||||
            orders[1] = rightOrder;
 | 
			
		||||
 | 
			
		||||
            takerAssetFillAmounts = new uint256[](2);
 | 
			
		||||
            takerAssetFillAmounts[0] = leftOrder.takerAssetAmount;
 | 
			
		||||
            takerAssetFillAmounts[1] = rightOrder.takerAssetAmount;
 | 
			
		||||
 | 
			
		||||
            signatures = new bytes[](2);
 | 
			
		||||
            signatures[0] = leftSignature;
 | 
			
		||||
            signatures[1] = rightSignature;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _makeReturnValuesForSingleOrderFill(bytes memory transactionData)
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns(
 | 
			
		||||
            LibOrder.Order[] memory orders,
 | 
			
		||||
            uint256[] memory takerAssetFillAmounts,
 | 
			
		||||
            bytes[] memory signatures
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        orders = new LibOrder.Order[](1);
 | 
			
		||||
        takerAssetFillAmounts = new uint256[](1);
 | 
			
		||||
        signatures = new bytes[](1);
 | 
			
		||||
        // solhint-disable-next-line indent
 | 
			
		||||
        (orders[0], takerAssetFillAmounts[0], signatures[0]) = abi.decode(
 | 
			
		||||
            transactionData.slice(4, transactionData.length),
 | 
			
		||||
            (LibOrder.Order, uint256, bytes)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _makeReturnValuesForBatchFill(bytes memory transactionData)
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns(
 | 
			
		||||
            LibOrder.Order[] memory orders,
 | 
			
		||||
            uint256[] memory takerAssetFillAmounts,
 | 
			
		||||
            bytes[] memory signatures
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable-next-line indent
 | 
			
		||||
        (orders, takerAssetFillAmounts, signatures) = abi.decode(
 | 
			
		||||
            transactionData.slice(4, transactionData.length),
 | 
			
		||||
            // solhint-disable-next-line indent
 | 
			
		||||
            (LibOrder.Order[], uint256[], bytes[])
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _makeReturnValuesForMarketFill(bytes memory transactionData)
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns(
 | 
			
		||||
            LibOrder.Order[] memory orders,
 | 
			
		||||
            uint256[] memory takerAssetFillAmounts,
 | 
			
		||||
            bytes[] memory signatures
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        takerAssetFillAmounts = new uint256[](1);
 | 
			
		||||
        // solhint-disable-next-line indent
 | 
			
		||||
        (orders, takerAssetFillAmounts[0], signatures) = abi.decode(
 | 
			
		||||
            transactionData.slice(4, transactionData.length),
 | 
			
		||||
            // solhint-disable-next-line indent
 | 
			
		||||
            (LibOrder.Order[], uint256, bytes[])
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										184
									
								
								contracts/dev-utils/contracts/src/OrderValidationUtils.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								contracts/dev-utils/contracts/src/OrderValidationUtils.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,184 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "./LibAssetData.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract OrderValidationUtils is
 | 
			
		||||
    LibAssetData,
 | 
			
		||||
    LibMath
 | 
			
		||||
{
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable var-name-mixedcase
 | 
			
		||||
    bytes internal _ZRX_ASSET_DATA;
 | 
			
		||||
    // solhint-enable var-name-mixedcase
 | 
			
		||||
 | 
			
		||||
    constructor (address _exchange, bytes memory _zrxAssetData)
 | 
			
		||||
        public
 | 
			
		||||
        LibAssetData(_exchange)
 | 
			
		||||
    {
 | 
			
		||||
        _ZRX_ASSET_DATA = _zrxAssetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
 | 
			
		||||
    /// @param order The order structure.
 | 
			
		||||
    /// @param signature Signature provided by maker that proves the order's authenticity.
 | 
			
		||||
    /// `0x01` can always be provided if the signature does not need to be validated.
 | 
			
		||||
    /// @return The orderInfo (hash, status, and `takerAssetAmount` already filled for the given order),
 | 
			
		||||
    /// fillableTakerAssetAmount (amount of the order's `takerAssetAmount` that is fillable given all on-chain state),
 | 
			
		||||
    /// and isValidSignature (validity of the provided signature).
 | 
			
		||||
    /// NOTE: If the `takerAssetData` encodes data for multiple assets, `fillableTakerAssetAmount` will represent a "scaled"
 | 
			
		||||
    /// amount, meaning it must be multiplied by all the individual asset amounts within the `takerAssetData` to get the final
 | 
			
		||||
    /// amount of each asset that can be filled.
 | 
			
		||||
    function getOrderRelevantState(LibOrder.Order memory order, bytes memory signature)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibOrder.OrderInfo memory orderInfo,
 | 
			
		||||
            uint256 fillableTakerAssetAmount,
 | 
			
		||||
            bool isValidSignature
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        // Get info specific to order
 | 
			
		||||
        orderInfo = _EXCHANGE.getOrderInfo(order);
 | 
			
		||||
 | 
			
		||||
        // Validate the maker's signature
 | 
			
		||||
        address makerAddress = order.makerAddress;
 | 
			
		||||
        isValidSignature = _EXCHANGE.isValidSignature(
 | 
			
		||||
            orderInfo.orderHash,
 | 
			
		||||
            makerAddress,
 | 
			
		||||
            signature
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Get the transferable amount of the `makerAsset`
 | 
			
		||||
        uint256 transferableMakerAssetAmount = getTransferableAssetAmount(makerAddress, order.makerAssetData);
 | 
			
		||||
 | 
			
		||||
        // Assign to stack variables to reduce redundant mloads/sloads
 | 
			
		||||
        uint256 takerAssetAmount = order.takerAssetAmount;
 | 
			
		||||
        uint256 makerFee = order.makerFee;
 | 
			
		||||
        bytes memory zrxAssetData = _ZRX_ASSET_DATA;
 | 
			
		||||
    
 | 
			
		||||
        // Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`,
 | 
			
		||||
        // and the total amounts specified in the order
 | 
			
		||||
        uint256 transferableTakerAssetAmount;
 | 
			
		||||
        if (order.makerAssetData.equals(zrxAssetData)) {
 | 
			
		||||
            // If `makerAsset` equals `makerFeeAsset`, the % that can be filled is
 | 
			
		||||
            // transferableMakerAssetAmount / (makerAssetAmount + makerFee)
 | 
			
		||||
            transferableTakerAssetAmount = getPartialAmountFloor(
 | 
			
		||||
                transferableMakerAssetAmount,
 | 
			
		||||
                safeAdd(order.makerAssetAmount, makerFee),
 | 
			
		||||
                takerAssetAmount
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            // Get the transferable amount of the `makerFeeAsset`
 | 
			
		||||
            uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, zrxAssetData);
 | 
			
		||||
 | 
			
		||||
            // If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
 | 
			
		||||
            if (makerFee == 0) {
 | 
			
		||||
                transferableTakerAssetAmount = getPartialAmountFloor(
 | 
			
		||||
                    transferableMakerAssetAmount,
 | 
			
		||||
                    order.makerAssetAmount,
 | 
			
		||||
                    takerAssetAmount
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            // If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
 | 
			
		||||
            // (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
 | 
			
		||||
            } else {
 | 
			
		||||
                uint256 transferableMakerToTakerAmount = getPartialAmountFloor(
 | 
			
		||||
                    transferableMakerAssetAmount,
 | 
			
		||||
                    order.makerAssetAmount,
 | 
			
		||||
                    takerAssetAmount
 | 
			
		||||
                );
 | 
			
		||||
                uint256 transferableMakerFeeToTakerAmount = getPartialAmountFloor(
 | 
			
		||||
                    transferableMakerFeeAssetAmount,
 | 
			
		||||
                    makerFee,
 | 
			
		||||
                    takerAssetAmount
 | 
			
		||||
                );
 | 
			
		||||
                transferableTakerAssetAmount = min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
 | 
			
		||||
        fillableTakerAssetAmount = min256(
 | 
			
		||||
            safeSub(takerAssetAmount, orderInfo.orderTakerAssetFilledAmount),
 | 
			
		||||
            transferableTakerAssetAmount
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return (orderInfo, fillableTakerAssetAmount, isValidSignature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches all order-relevant information needed to validate if the supplied orders are fillable.
 | 
			
		||||
    /// @param orders Array of order structures.
 | 
			
		||||
    /// @param signatures Array of signatures provided by makers that prove the authenticity of the orders.
 | 
			
		||||
    /// `0x01` can always be provided if a signature does not need to be validated.
 | 
			
		||||
    /// @return The ordersInfo (array of the hash, status, and `takerAssetAmount` already filled for each order),
 | 
			
		||||
    /// fillableTakerAssetAmounts (array of amounts for each order's `takerAssetAmount` that is fillable given all on-chain state),
 | 
			
		||||
    /// and isValidSignature (array containing the validity of each provided signature).
 | 
			
		||||
    /// NOTE: If the `takerAssetData` encodes data for multiple assets, each element of `fillableTakerAssetAmounts`
 | 
			
		||||
    /// will represent a "scaled" amount, meaning it must be multiplied by all the individual asset amounts within
 | 
			
		||||
    /// the `takerAssetData` to get the final amount of each asset that can be filled.
 | 
			
		||||
    function getOrderRelevantStates(LibOrder.Order[] memory orders, bytes[] memory signatures)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibOrder.OrderInfo[] memory ordersInfo,
 | 
			
		||||
            uint256[] memory fillableTakerAssetAmounts,
 | 
			
		||||
            bool[] memory isValidSignature
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = orders.length;
 | 
			
		||||
        ordersInfo = new LibOrder.OrderInfo[](length);
 | 
			
		||||
        fillableTakerAssetAmounts = new uint256[](length);
 | 
			
		||||
        isValidSignature = new bool[](length);
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            (ordersInfo[i], fillableTakerAssetAmounts[i], isValidSignature[i]) = getOrderRelevantState(
 | 
			
		||||
                orders[i],
 | 
			
		||||
                signatures[i]
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return (ordersInfo, fillableTakerAssetAmounts, isValidSignature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets the amount of an asset transferable by the owner.
 | 
			
		||||
    /// @param ownerAddress Address of the owner of the asset.
 | 
			
		||||
    /// @param assetData Description of tokens, per the AssetProxy contract specification.
 | 
			
		||||
    /// @return The amount of the asset tranferable by the owner.
 | 
			
		||||
    /// NOTE: If the `assetData` encodes data for multiple assets, the `transferableAssetAmount`
 | 
			
		||||
    /// will represent the amount of times the entire `assetData` can be transferred. To calculate
 | 
			
		||||
    /// the total individual transferable amounts, this scaled `transferableAmount` must be multiplied by 
 | 
			
		||||
    /// the individual asset amounts located within the `assetData`.
 | 
			
		||||
    function getTransferableAssetAmount(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 transferableAssetAmount)
 | 
			
		||||
    {
 | 
			
		||||
        (uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
 | 
			
		||||
        transferableAssetAmount = min256(balance, allowance);
 | 
			
		||||
        return transferableAssetAmount;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								contracts/dev-utils/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								contracts/dev-utils/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-dev-utils",
 | 
			
		||||
    "version": "0.0.2",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
    "description": "0x protocol specific utility contracts",
 | 
			
		||||
    "main": "lib/src/index.js",
 | 
			
		||||
    "directories": {
 | 
			
		||||
        "test": "test"
 | 
			
		||||
    },
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "build": "yarn pre_build && tsc -b",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile generate_contract_wrappers",
 | 
			
		||||
        "test": "yarn run_mocha",
 | 
			
		||||
        "rebuild_and_test": "run-s build test",
 | 
			
		||||
        "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
 | 
			
		||||
        "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
 | 
			
		||||
        "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
 | 
			
		||||
        "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
 | 
			
		||||
        "compile": "sol-compiler",
 | 
			
		||||
        "watch": "sol-compiler -w",
 | 
			
		||||
        "clean": "shx rm -rf lib generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --abis  ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "coverage:report:text": "istanbul report text",
 | 
			
		||||
        "coverage:report:html": "istanbul report html && open coverage/index.html",
 | 
			
		||||
        "profiler:report:html": "istanbul report html && open coverage/index.html",
 | 
			
		||||
        "coverage:report:lcov": "istanbul report lcov",
 | 
			
		||||
        "test:circleci": "yarn test",
 | 
			
		||||
        "contracts:gen": "contracts-gen",
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(DevUtils|LibAssetData|LibTransactionDecoder|EthBalanceChecker).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo.git"
 | 
			
		||||
    },
 | 
			
		||||
    "license": "Apache-2.0",
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^9.1.5",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
        "chai": "^4.0.1",
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
        "dirty-chai": "^2.0.1",
 | 
			
		||||
        "make-promises-safe": "^1.1.0",
 | 
			
		||||
        "mocha": "^4.1.0",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
        "solhint": "^1.4.1",
 | 
			
		||||
        "tslint": "5.11.0",
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.1.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.7",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.6",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								contracts/dev-utils/src/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								contracts/dev-utils/src/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DevUtils from '../generated-artifacts/DevUtils.json';
 | 
			
		||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
 | 
			
		||||
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    DevUtils: DevUtils as ContractArtifact,
 | 
			
		||||
    LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
 | 
			
		||||
    LibAssetData: LibAssetData as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										2
									
								
								contracts/dev-utils/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								contracts/dev-utils/src/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
export * from './artifacts';
 | 
			
		||||
export * from './wrappers';
 | 
			
		||||
							
								
								
									
										8
									
								
								contracts/dev-utils/src/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								contracts/dev-utils/src/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/dev_utils';
 | 
			
		||||
export * from '../generated-wrappers/lib_asset_data';
 | 
			
		||||
export * from '../generated-wrappers/lib_transaction_decoder';
 | 
			
		||||
							
								
								
									
										19
									
								
								contracts/dev-utils/test/global_hooks.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								contracts/dev-utils/test/global_hooks.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
import { env, EnvVars } from '@0x/dev-utils';
 | 
			
		||||
 | 
			
		||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
 | 
			
		||||
import { providerUtils } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
before('start web3 provider', () => {
 | 
			
		||||
    providerUtils.startProviderEngine(provider);
 | 
			
		||||
});
 | 
			
		||||
after('generate coverage report', async () => {
 | 
			
		||||
    if (env.parseBoolean(EnvVars.SolidityCoverage)) {
 | 
			
		||||
        const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
 | 
			
		||||
        await coverageSubprovider.writeCoverageAsync();
 | 
			
		||||
    }
 | 
			
		||||
    if (env.parseBoolean(EnvVars.SolidityProfiler)) {
 | 
			
		||||
        const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
 | 
			
		||||
        await profilerSubprovider.writeProfilerOutputAsync();
 | 
			
		||||
    }
 | 
			
		||||
    provider.stop();
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										527
									
								
								contracts/dev-utils/test/lib_asset_data.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								contracts/dev-utils/test/lib_asset_data.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,527 @@
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as proxyArtifacts,
 | 
			
		||||
    ERC1155ProxyContract,
 | 
			
		||||
    ERC20ProxyContract,
 | 
			
		||||
    ERC721ProxyContract,
 | 
			
		||||
    MultiAssetProxyContract,
 | 
			
		||||
    StaticCallProxyContract,
 | 
			
		||||
    TestStaticCallTargetContract,
 | 
			
		||||
} from '@0x/contracts-asset-proxy';
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc1155Artifacts,
 | 
			
		||||
    ERC1155MintableContract,
 | 
			
		||||
    ERC1155TransferSingleEventArgs,
 | 
			
		||||
} from '@0x/contracts-erc1155';
 | 
			
		||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
 | 
			
		||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
 | 
			
		||||
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
 | 
			
		||||
import { artifacts, LibAssetDataContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
const KNOWN_ERC20_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC721_ENCODING = {
 | 
			
		||||
    address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenId: new BigNumber(1),
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC1155_ENCODING = {
 | 
			
		||||
    tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
 | 
			
		||||
    tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
 | 
			
		||||
    callbackData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_MULTI_ASSET_ENCODING = {
 | 
			
		||||
    amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
 | 
			
		||||
    nestedAssetData: [
 | 
			
		||||
        KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC721_ENCODING.assetData,
 | 
			
		||||
        KNOWN_ERC1155_ENCODING.assetData,
 | 
			
		||||
    ],
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('LibAssetData', () => {
 | 
			
		||||
    let exchange: ExchangeContract;
 | 
			
		||||
    let erc20Proxy: ERC20ProxyContract;
 | 
			
		||||
    let erc721Proxy: ERC721ProxyContract;
 | 
			
		||||
    let erc1155Proxy: ERC1155ProxyContract;
 | 
			
		||||
    let multiAssetProxy: MultiAssetProxyContract;
 | 
			
		||||
    let staticCallProxy: StaticCallProxyContract;
 | 
			
		||||
    let staticCallTarget: TestStaticCallTargetContract;
 | 
			
		||||
    let libAssetData: LibAssetDataContract;
 | 
			
		||||
 | 
			
		||||
    let tokenOwnerAddress: string;
 | 
			
		||||
 | 
			
		||||
    let erc20Token: DummyERC20TokenContract;
 | 
			
		||||
    let erc721Token: DummyERC721TokenContract;
 | 
			
		||||
    let erc1155Token: ERC1155MintableContract;
 | 
			
		||||
 | 
			
		||||
    const erc20TokenTotalSupply = new BigNumber(1);
 | 
			
		||||
 | 
			
		||||
    const firstERC721TokenId = new BigNumber(1);
 | 
			
		||||
    const numberOfERC721Tokens = 10;
 | 
			
		||||
 | 
			
		||||
    let erc1155TokenId: BigNumber;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            exchangeArtifacts.Exchange,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            constants.NULL_BYTES,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.ERC20Proxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.ERC721Proxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.ERC1155Proxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.MultiAssetProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.StaticCallProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address);
 | 
			
		||||
        await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address);
 | 
			
		||||
        await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address);
 | 
			
		||||
        await exchange.registerAssetProxy.awaitTransactionSuccessAsync(multiAssetProxy.address);
 | 
			
		||||
        await exchange.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address);
 | 
			
		||||
 | 
			
		||||
        libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.LibAssetData,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.TestStaticCallTarget,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        [tokenOwnerAddress] = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
 | 
			
		||||
        erc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc20Artifacts.DummyERC20Token,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            'Dummy',
 | 
			
		||||
            'DUM',
 | 
			
		||||
            new BigNumber(1),
 | 
			
		||||
            erc20TokenTotalSupply,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc721Artifacts.DummyERC721Token,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            'Dummy',
 | 
			
		||||
            'DUM',
 | 
			
		||||
        );
 | 
			
		||||
        // mint `numberOfERC721Tokens` tokens
 | 
			
		||||
        const transactionMinedPromises = [];
 | 
			
		||||
        for (let i = 0; i < numberOfERC721Tokens; i++) {
 | 
			
		||||
            transactionMinedPromises.push(
 | 
			
		||||
                erc721Token.mint.awaitTransactionSuccessAsync(tokenOwnerAddress, firstERC721TokenId.plus(i - 1)),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        await Promise.all(transactionMinedPromises);
 | 
			
		||||
 | 
			
		||||
        erc1155Token = await ERC1155MintableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc1155Artifacts.ERC1155Mintable,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const logDecoder = new LogDecoder(web3Wrapper, erc1155Artifacts);
 | 
			
		||||
        const transactionReceipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await erc1155Token.create.sendTransactionAsync('uri:Dummy', /*isNonFungible:*/ false),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // tslint:disable-next-line no-unnecessary-type-assertion
 | 
			
		||||
        erc1155TokenId = (transactionReceipt.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
 | 
			
		||||
        await erc1155Token.mintFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
            erc1155TokenId,
 | 
			
		||||
            [tokenOwnerAddress],
 | 
			
		||||
            [new BigNumber(1)],
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should have a deployed-to address', () => {
 | 
			
		||||
        expect(libAssetData.address.slice(0, 2)).to.equal('0x');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('encoding and decoding', () => {
 | 
			
		||||
        it('should encode ERC20 asset data', async () => {
 | 
			
		||||
            expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
 | 
			
		||||
                KNOWN_ERC20_ENCODING.assetData,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should decode ERC20 asset data', async () => {
 | 
			
		||||
            expect(await libAssetData.decodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
                AssetProxyId.ERC20,
 | 
			
		||||
                KNOWN_ERC20_ENCODING.address,
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should encode ERC721 asset data', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.encodeERC721AssetData.callAsync(
 | 
			
		||||
                    KNOWN_ERC721_ENCODING.address,
 | 
			
		||||
                    KNOWN_ERC721_ENCODING.tokenId,
 | 
			
		||||
                ),
 | 
			
		||||
            ).to.equal(KNOWN_ERC721_ENCODING.assetData);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should decode ERC721 asset data', async () => {
 | 
			
		||||
            expect(await libAssetData.decodeERC721AssetData.callAsync(KNOWN_ERC721_ENCODING.assetData)).to.deep.equal([
 | 
			
		||||
                AssetProxyId.ERC721,
 | 
			
		||||
                KNOWN_ERC721_ENCODING.address,
 | 
			
		||||
                KNOWN_ERC721_ENCODING.tokenId,
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should encode ERC1155 asset data', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.encodeERC1155AssetData.callAsync(
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
                ),
 | 
			
		||||
            ).to.equal(KNOWN_ERC1155_ENCODING.assetData);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should decode ERC1155 asset data', async () => {
 | 
			
		||||
            expect(await libAssetData.decodeERC1155AssetData.callAsync(KNOWN_ERC1155_ENCODING.assetData)).to.deep.equal(
 | 
			
		||||
                [
 | 
			
		||||
                    AssetProxyId.ERC1155,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
                    KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
                ],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should encode multiasset data', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.encodeMultiAssetData.callAsync(
 | 
			
		||||
                    KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
                    KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
 | 
			
		||||
                ),
 | 
			
		||||
            ).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should decode multiasset data', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.decodeMultiAssetData.callAsync(KNOWN_MULTI_ASSET_ENCODING.assetData),
 | 
			
		||||
            ).to.deep.equal([
 | 
			
		||||
                AssetProxyId.MultiAsset,
 | 
			
		||||
                KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
                KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getBalance', () => {
 | 
			
		||||
        it('should query ERC20 balance by asset data', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
 | 
			
		||||
                erc20TokenTotalSupply,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return 0 if ERC20 token does not exist', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC20AssetData(constants.NULL_ADDRESS);
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query ERC721 balance by asset data', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
 | 
			
		||||
            expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return 0 if ERC721 token does not exist', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC721AssetData(constants.NULL_ADDRESS, firstERC721TokenId);
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query ERC1155 balances by asset data', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155Token.address,
 | 
			
		||||
                [erc1155TokenId],
 | 
			
		||||
                [new BigNumber(1)],
 | 
			
		||||
                constants.NULL_BYTES,
 | 
			
		||||
            );
 | 
			
		||||
            expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return 0 if ERC1155 token does not exist', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                constants.NULL_ADDRESS,
 | 
			
		||||
                [erc1155TokenId],
 | 
			
		||||
                [new BigNumber(1)],
 | 
			
		||||
                constants.NULL_BYTES,
 | 
			
		||||
            );
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query multi-asset batch balance by asset data', async () => {
 | 
			
		||||
            const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [
 | 
			
		||||
                    assetDataUtils.encodeERC20AssetData(erc20Token.address),
 | 
			
		||||
                    assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
 | 
			
		||||
                ],
 | 
			
		||||
            );
 | 
			
		||||
            expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
 | 
			
		||||
                Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
 | 
			
		||||
            const fakeAssetData = '0x01020304';
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, fakeAssetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getAssetProxyAllowance', () => {
 | 
			
		||||
        it('should query ERC20 allowances by asset data', async () => {
 | 
			
		||||
            const allowance = new BigNumber(1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.bignumber.equal(allowance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query ERC721 approval by asset data', async () => {
 | 
			
		||||
            await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.bignumber.equal(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query ERC721 approvalForAll by assetData', async () => {
 | 
			
		||||
            await erc721Token.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, true, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query ERC1155 allowances by asset data', async () => {
 | 
			
		||||
            await erc1155Token.setApprovalForAll.awaitTransactionSuccessAsync(erc1155Proxy.address, true, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155Token.address,
 | 
			
		||||
                [erc1155TokenId],
 | 
			
		||||
                [new BigNumber(1)],
 | 
			
		||||
                constants.NULL_BYTES,
 | 
			
		||||
            );
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should query multi-asset allowances by asset data', async () => {
 | 
			
		||||
            const allowance = new BigNumber(1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [
 | 
			
		||||
                    assetDataUtils.encodeERC20AssetData(erc20Token.address),
 | 
			
		||||
                    assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
 | 
			
		||||
                ],
 | 
			
		||||
            );
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.bignumber.equal(1);
 | 
			
		||||
            return;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
 | 
			
		||||
            const fakeAssetData = '0x01020304';
 | 
			
		||||
            const allowance = await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, fakeAssetData);
 | 
			
		||||
            expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
 | 
			
		||||
            const staticCallData = AssetProxyId.StaticCall;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                constants.KECCAK256_NULL,
 | 
			
		||||
            );
 | 
			
		||||
            const allowance = await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData);
 | 
			
		||||
            expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getBatchBalances', () => {
 | 
			
		||||
        it('should query balances for a batch of asset data strings', async () => {
 | 
			
		||||
            const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [erc20AssetData, erc721AssetData]),
 | 
			
		||||
            ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getERC721TokenOwner', async () => {
 | 
			
		||||
        it('should return the null address when tokenId is not owned', async () => {
 | 
			
		||||
            const nonexistentTokenId = new BigNumber(1234567890);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getERC721TokenOwner.callAsync(erc721Token.address, nonexistentTokenId),
 | 
			
		||||
            ).to.be.equal(constants.NULL_ADDRESS);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the owner address when tokenId is owned', async () => {
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getERC721TokenOwner.callAsync(erc721Token.address, firstERC721TokenId),
 | 
			
		||||
            ).to.be.equal(tokenOwnerAddress);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getBalanceAndAllowance', () => {
 | 
			
		||||
        it('should query balance and allowance together, from asset data', async () => {
 | 
			
		||||
            const allowance = new BigNumber(1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getBalanceAndAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
 | 
			
		||||
            ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getBatchBalancesAndAllowances', () => {
 | 
			
		||||
        it('should query balances and allowances together, from an asset data array', async () => {
 | 
			
		||||
            const allowance = new BigNumber(1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getBatchBalancesAndAssetProxyAllowances.callAsync(tokenOwnerAddress, [assetData]),
 | 
			
		||||
            ).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getBatchAssetProxyAllowances', () => {
 | 
			
		||||
        it('should query allowances for a batch of asset data strings', async () => {
 | 
			
		||||
            const allowance = new BigNumber(1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
 | 
			
		||||
                from: tokenOwnerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
            const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
 | 
			
		||||
            expect(
 | 
			
		||||
                await libAssetData.getBatchAssetProxyAllowances.callAsync(tokenOwnerAddress, [
 | 
			
		||||
                    erc20AssetData,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                ]),
 | 
			
		||||
            ).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
							
								
								
									
										139
									
								
								contracts/dev-utils/test/lib_transaction_decoder.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								contracts/dev-utils/test/lib_transaction_decoder.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
import { IExchangeContract } from '@0x/contracts-exchange';
 | 
			
		||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { artifacts, LibTransactionDecoderContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
const order = {
 | 
			
		||||
    makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
 | 
			
		||||
    takerAddress: '0x0000000000000000000000000000000000000000',
 | 
			
		||||
    feeRecipientAddress: '0x78dc5d2d739606d31509c31d654056a45185ecb6',
 | 
			
		||||
    senderAddress: '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb',
 | 
			
		||||
    makerAssetAmount: new BigNumber('100000000000000000000'),
 | 
			
		||||
    takerAssetAmount: new BigNumber('200000000000000000000'),
 | 
			
		||||
    makerFee: new BigNumber('1000000000000000000'),
 | 
			
		||||
    takerFee: new BigNumber('1000000000000000000'),
 | 
			
		||||
    expirationTimeSeconds: new BigNumber('1552396423'),
 | 
			
		||||
    salt: new BigNumber('66097384406870180066678463045003379626790660770396923976862707230261946348951'),
 | 
			
		||||
    makerAssetData: '0xf47261b000000000000000000000000034d402f14d58e001d8efbe6585051bf9706aa064',
 | 
			
		||||
    takerAssetData: '0xf47261b000000000000000000000000025b8fe1de9daf8ba351890744ff28cf7dfa8f5e3',
 | 
			
		||||
};
 | 
			
		||||
const takerAssetFillAmount = new BigNumber('100000000000000000000');
 | 
			
		||||
const signature =
 | 
			
		||||
    '0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
 | 
			
		||||
 | 
			
		||||
describe('LibTransactionDecoder', () => {
 | 
			
		||||
    let libTxDecoder: LibTransactionDecoderContract;
 | 
			
		||||
    const exchangeInterface = new IExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
        libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.LibTransactionDecoder,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should decode an Exchange.batchCancelOrders() transaction', async () => {
 | 
			
		||||
        const input = exchangeInterface.batchCancelOrders.getABIEncodedTransactionData([order, order]);
 | 
			
		||||
        expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
            'batchCancelOrders',
 | 
			
		||||
            [order, order],
 | 
			
		||||
            [],
 | 
			
		||||
            [],
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    for (const func of ['batchFillOrders', 'batchFillOrdersNoThrow', 'batchFillOrKillOrders']) {
 | 
			
		||||
        const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
 | 
			
		||||
            [order, order],
 | 
			
		||||
            [takerAssetFillAmount, takerAssetFillAmount],
 | 
			
		||||
            [signature, signature],
 | 
			
		||||
        );
 | 
			
		||||
        it(`should decode an Exchange.${func}() transaction`, async () => {
 | 
			
		||||
            expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
                func,
 | 
			
		||||
                [order, order],
 | 
			
		||||
                [takerAssetFillAmount, takerAssetFillAmount],
 | 
			
		||||
                [signature, signature],
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    it('should decode an Exchange.cancelOrder() transaction', async () => {
 | 
			
		||||
        const input = exchangeInterface.cancelOrder.getABIEncodedTransactionData(order);
 | 
			
		||||
        expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
            'cancelOrder',
 | 
			
		||||
            [order],
 | 
			
		||||
            [],
 | 
			
		||||
            [],
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    for (const func of ['fillOrder', 'fillOrderNoThrow', 'fillOrKillOrder']) {
 | 
			
		||||
        const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
 | 
			
		||||
            order,
 | 
			
		||||
            takerAssetFillAmount,
 | 
			
		||||
            signature,
 | 
			
		||||
        );
 | 
			
		||||
        it(`should decode an Exchange.${func}() transaction`, async () => {
 | 
			
		||||
            expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
                func,
 | 
			
		||||
                [order],
 | 
			
		||||
                [takerAssetFillAmount],
 | 
			
		||||
                [signature],
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const func of ['marketBuyOrders', 'marketBuyOrdersNoThrow', 'marketSellOrders', 'marketSellOrdersNoThrow']) {
 | 
			
		||||
        const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
 | 
			
		||||
            [order, order],
 | 
			
		||||
            takerAssetFillAmount,
 | 
			
		||||
            [signature, signature],
 | 
			
		||||
        );
 | 
			
		||||
        it(`should decode an Exchange.${func}() transaction`, async () => {
 | 
			
		||||
            expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
                func,
 | 
			
		||||
                [order, order],
 | 
			
		||||
                [takerAssetFillAmount],
 | 
			
		||||
                [signature, signature],
 | 
			
		||||
            ]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    it('should decode an Exchange.matchOrders() transaction', async () => {
 | 
			
		||||
        const complementaryOrder = {
 | 
			
		||||
            ...order,
 | 
			
		||||
            makerAddress: order.takerAddress,
 | 
			
		||||
            takerAddress: order.makerAddress,
 | 
			
		||||
            makerAssetData: order.takerAssetData,
 | 
			
		||||
            takerAssetData: order.makerAssetData,
 | 
			
		||||
            makerAssetAmount: order.takerAssetAmount,
 | 
			
		||||
            takerAssetAmount: order.makerAssetAmount,
 | 
			
		||||
            makerFee: order.takerFee,
 | 
			
		||||
            takerFee: order.makerFee,
 | 
			
		||||
        };
 | 
			
		||||
        const input = exchangeInterface.matchOrders.getABIEncodedTransactionData(
 | 
			
		||||
            order,
 | 
			
		||||
            complementaryOrder,
 | 
			
		||||
            signature,
 | 
			
		||||
            signature,
 | 
			
		||||
        );
 | 
			
		||||
        expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
 | 
			
		||||
            'matchOrders',
 | 
			
		||||
            [order, complementaryOrder],
 | 
			
		||||
            [order.takerAssetAmount, complementaryOrder.takerAssetAmount],
 | 
			
		||||
            [signature, signature],
 | 
			
		||||
        ]);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										442
									
								
								contracts/dev-utils/test/order_validation_utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								contracts/dev-utils/test/order_validation_utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,442 @@
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as proxyArtifacts,
 | 
			
		||||
    ERC20ProxyContract,
 | 
			
		||||
    ERC20Wrapper,
 | 
			
		||||
    ERC721ProxyContract,
 | 
			
		||||
    ERC721Wrapper,
 | 
			
		||||
    MultiAssetProxyContract,
 | 
			
		||||
} from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
 | 
			
		||||
import { artifacts as exchangeArtifacts, ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    OrderFactory,
 | 
			
		||||
    OrderStatus,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { artifacts, DevUtilsContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('OrderValidationUtils', () => {
 | 
			
		||||
    let makerAddress: string;
 | 
			
		||||
    let takerAddress: string;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let erc20AssetData: string;
 | 
			
		||||
    let erc20AssetData2: string;
 | 
			
		||||
    let erc721AssetData: string;
 | 
			
		||||
    let zrxAssetData: string;
 | 
			
		||||
 | 
			
		||||
    let erc20Token: DummyERC20TokenContract;
 | 
			
		||||
    let erc20Token2: DummyERC20TokenContract;
 | 
			
		||||
    let zrxToken: DummyERC20TokenContract;
 | 
			
		||||
    let erc721Token: DummyERC721TokenContract;
 | 
			
		||||
    let exchange: ExchangeContract;
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    let erc20Proxy: ERC20ProxyContract;
 | 
			
		||||
    let erc721Proxy: ERC721ProxyContract;
 | 
			
		||||
    let multiAssetProxy: MultiAssetProxyContract;
 | 
			
		||||
 | 
			
		||||
    let signedOrder: SignedOrder;
 | 
			
		||||
    let orderFactory: OrderFactory;
 | 
			
		||||
 | 
			
		||||
    const tokenId = new BigNumber(123456789);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const usedAddresses = ([owner, makerAddress, takerAddress] = accounts.slice(0, 3));
 | 
			
		||||
 | 
			
		||||
        const erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
        const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
 | 
			
		||||
        const numDummyErc20ToDeploy = 3;
 | 
			
		||||
        [erc20Token, zrxToken, erc20Token2] = await erc20Wrapper.deployDummyTokensAsync(
 | 
			
		||||
            numDummyErc20ToDeploy,
 | 
			
		||||
            constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
        );
 | 
			
		||||
        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
 | 
			
		||||
        erc721Proxy = await erc721Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            exchangeArtifacts.Exchange,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            zrxAssetData,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.MultiAssetProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeWrapper = new ExchangeWrapper(exchange, provider);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
 | 
			
		||||
        await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
        await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
 | 
			
		||||
        devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.DevUtils,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
            zrxAssetData,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
        erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address);
 | 
			
		||||
        erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
 | 
			
		||||
        const defaultOrderParams = {
 | 
			
		||||
            ...constants.STATIC_ORDER_PARAMS,
 | 
			
		||||
            exchangeAddress: exchange.address,
 | 
			
		||||
            makerAddress,
 | 
			
		||||
            feeRecipientAddress: constants.NULL_ADDRESS,
 | 
			
		||||
            makerAssetData: erc20AssetData,
 | 
			
		||||
            takerAssetData: erc20AssetData2,
 | 
			
		||||
        };
 | 
			
		||||
        const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
 | 
			
		||||
        orderFactory = new OrderFactory(privateKey, defaultOrderParams);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getTransferableAssetAmount', () => {
 | 
			
		||||
        it('should return the balance when balance < allowance', async () => {
 | 
			
		||||
            const balance = new BigNumber(123);
 | 
			
		||||
            const allowance = new BigNumber(456);
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, balance);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                erc20AssetData,
 | 
			
		||||
            );
 | 
			
		||||
            expect(transferableAmount).to.bignumber.equal(balance);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the allowance when allowance < balance', async () => {
 | 
			
		||||
            const balance = new BigNumber(456);
 | 
			
		||||
            const allowance = new BigNumber(123);
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, balance);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                erc20AssetData,
 | 
			
		||||
            );
 | 
			
		||||
            expect(transferableAmount).to.bignumber.equal(allowance);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct transferable amount for multiAssetData', async () => {
 | 
			
		||||
            const multiAssetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [erc20AssetData, erc20AssetData2],
 | 
			
		||||
            );
 | 
			
		||||
            const transferableAmount1 = new BigNumber(10);
 | 
			
		||||
            const transferableAmount2 = new BigNumber(5);
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableAmount1);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableAmount1, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableAmount2);
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableAmount2, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                multiAssetData,
 | 
			
		||||
            );
 | 
			
		||||
            expect(transferableAmount).to.bignumber.equal(transferableAmount2);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getOrderRelevantState', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct orderInfo when the order is valid', async () => {
 | 
			
		||||
            const [orderInfo] = await devUtils.getOrderRelevantState.callAsync(signedOrder, signedOrder.signature);
 | 
			
		||||
            expect(orderInfo.orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
 | 
			
		||||
            expect(orderInfo.orderStatus).to.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return isValidSignature=true when the signature is valid', async () => {
 | 
			
		||||
            const [, , isValidSignature] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(isValidSignature).to.equal(true);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return isValidSignature=false when the signature is invalid', async () => {
 | 
			
		||||
            const invalidSignature = '0x01';
 | 
			
		||||
            const [, , isValidSignature] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                invalidSignature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(isValidSignature).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount of 0 when balances or allowances are insufficient', async () => {
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount of 0 when fee balances/allowances are insufficient', async () => {
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount of 0 when balances/allowances of one asset within a multiAssetData are insufficient', async () => {
 | 
			
		||||
            const multiAssetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [erc20AssetData, erc20AssetData2],
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: multiAssetData });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct fillableTakerAssetAmount when fee balances/allowances are partially sufficient', async () => {
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const divisor = 4;
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                signedOrder.makerFee.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(
 | 
			
		||||
                signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct fillableTakerAssetAmount when non-fee balances/allowances are partially sufficient', async () => {
 | 
			
		||||
            const divisor = 4;
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(
 | 
			
		||||
                signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct fillableTakerAssetAmount when balances/allowances of one asset within a multiAssetData are partially sufficient', async () => {
 | 
			
		||||
            const multiAssetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [erc20AssetData, erc20AssetData2],
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: multiAssetData });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const divisor = 4;
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
                erc20Proxy.address,
 | 
			
		||||
                signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
                {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(
 | 
			
		||||
                signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount of 0 when non-fee balances/allowances are insufficient', async () => {
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount equal to the takerAssetAmount when the order is unfilled and balances/allowances are sufficient', async () => {
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct fillableTakerAssetAmount when balances/allowances are partially sufficient and makerAsset=makerFeeAsset', async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                makerAssetData: zrxAssetData,
 | 
			
		||||
                makerAssetAmount: new BigNumber(10),
 | 
			
		||||
                takerAssetAmount: new BigNumber(20),
 | 
			
		||||
                makerFee: new BigNumber(40),
 | 
			
		||||
            });
 | 
			
		||||
            const transferableMakerAssetAmount = new BigNumber(10);
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableMakerAssetAmount);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableMakerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const expectedFillableTakerAssetAmount = transferableMakerAssetAmount
 | 
			
		||||
                .times(signedOrder.takerAssetAmount)
 | 
			
		||||
                .dividedToIntegerBy(signedOrder.makerAssetAmount.plus(signedOrder.makerFee));
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(expectedFillableTakerAssetAmount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct fillabeTakerassetAmount when makerAsset balances/allowances are sufficient and there are no maker fees', async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerFee: constants.ZERO_AMOUNT });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return a fillableTakerAssetAmount when the remaining takerAssetAmount is less than the transferable amount', async () => {
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount);
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee);
 | 
			
		||||
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const takerAssetFillAmount = signedOrder.takerAssetAmount.dividedToIntegerBy(4);
 | 
			
		||||
            await exchange.fillOrder.awaitTransactionSuccessAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAssetFillAmount,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
                { from: takerAddress },
 | 
			
		||||
            );
 | 
			
		||||
            const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                signedOrder.signature,
 | 
			
		||||
            );
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(
 | 
			
		||||
                signedOrder.takerAssetAmount.minus(takerAssetFillAmount),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getOrderRelevantStates', async () => {
 | 
			
		||||
        it('should return the correct information for multiple orders', async () => {
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const signedOrder2 = await orderFactory.newSignedOrderAsync({ makerAssetData: erc721AssetData });
 | 
			
		||||
            const invalidSignature = '0x01';
 | 
			
		||||
            await exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder2, { from: makerAddress });
 | 
			
		||||
            const [
 | 
			
		||||
                ordersInfo,
 | 
			
		||||
                fillableTakerAssetAmounts,
 | 
			
		||||
                isValidSignature,
 | 
			
		||||
            ] = await devUtils.getOrderRelevantStates.callAsync(
 | 
			
		||||
                [signedOrder, signedOrder2],
 | 
			
		||||
                [signedOrder.signature, invalidSignature],
 | 
			
		||||
            );
 | 
			
		||||
            expect(ordersInfo[0].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
 | 
			
		||||
            expect(ordersInfo[1].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder2));
 | 
			
		||||
            expect(ordersInfo[0].orderStatus).to.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(ordersInfo[1].orderStatus).to.equal(OrderStatus.Cancelled);
 | 
			
		||||
            expect(ordersInfo[0].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(ordersInfo[1].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(fillableTakerAssetAmounts[0]).to.bignumber.equal(signedOrder.takerAssetAmount);
 | 
			
		||||
            expect(fillableTakerAssetAmounts[1]).to.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(isValidSignature[0]).to.equal(true);
 | 
			
		||||
            expect(isValidSignature[1]).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
							
								
								
									
										12
									
								
								contracts/dev-utils/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								contracts/dev-utils/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": "../../tsconfig",
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/DevUtils.json",
 | 
			
		||||
        "generated-artifacts/LibAssetData.json",
 | 
			
		||||
        "generated-artifacts/LibTransactionDecoder.json",
 | 
			
		||||
        "generated-artifacts/EthBalanceChecker.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								contracts/dev-utils/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								contracts/dev-utils/tslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": ["@0x/tslint-config"],
 | 
			
		||||
    "rules": {
 | 
			
		||||
        "custom-no-magic-numbers": false
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "1.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "1.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "1.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.1.7 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.6 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.5 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.4 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,32 @@ contract ERC1155Mintable is
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev creates a new token
 | 
			
		||||
    /// @param type_ of token
 | 
			
		||||
    /// @param uri URI of token
 | 
			
		||||
    function createWithType(
 | 
			
		||||
        uint256 type_,
 | 
			
		||||
        string calldata uri
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        // This will allow restricted access to creators.
 | 
			
		||||
        creators[type_] = msg.sender;
 | 
			
		||||
 | 
			
		||||
        // emit a Transfer event with Create semantic to help with discovery.
 | 
			
		||||
        emit TransferSingle(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            address(0x0),
 | 
			
		||||
            address(0x0),
 | 
			
		||||
            type_,
 | 
			
		||||
            0
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (bytes(uri).length > 0) {
 | 
			
		||||
            emit URI(uri, type_);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev mints fungible tokens
 | 
			
		||||
    /// @param id token type
 | 
			
		||||
    /// @param to beneficiaries of minted tokens
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc1155",
 | 
			
		||||
    "version": "1.1.2",
 | 
			
		||||
    "version": "1.1.7",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,10 +47,10 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -67,14 +67,14 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "2.2.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.2.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.2.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.2.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "2.2.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.2.6 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.2.5 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.2.4 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.2.3 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.2.1 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,10 +14,12 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
                    "evm.deployedBytecode.sourceMap"
 | 
			
		||||
                    "evm.deployedBytecode.sourceMap",
 | 
			
		||||
                    "devdoc"
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc20",
 | 
			
		||||
    "version": "2.2.1",
 | 
			
		||||
    "version": "2.2.6",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,14 +68,13 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "2.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "2.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.1.7 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.6 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.5 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.4 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc721",
 | 
			
		||||
    "version": "2.1.2",
 | 
			
		||||
    "version": "2.1.7",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,13 +68,13 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "3.0.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "3.0.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "3.0.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "3.0.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.0.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.0.4 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.0.3 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.0.2 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.0.1 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.0.0 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Update contracts to solidity ^0.5.5 and unpin dependencies (#1796)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange-forwarder",
 | 
			
		||||
    "version": "3.0.0",
 | 
			
		||||
    "version": "3.0.4",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -46,12 +46,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contract-wrappers": "^9.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^9.1.5",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,19 +68,19 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.1",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.7",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.6",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ describe(ContractName.Forwarder, () => {
 | 
			
		||||
        erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
 | 
			
		||||
 | 
			
		||||
        wethContract = await WETH9Contract.deployFrom0xArtifactAsync(erc20Artifacts.WETH9, provider, txDefaults);
 | 
			
		||||
        weth = new DummyERC20TokenContract(wethContract.abi, wethContract.address, provider);
 | 
			
		||||
        weth = new DummyERC20TokenContract(wethContract.address, provider);
 | 
			
		||||
        erc20Wrapper.addDummyTokenContract(weth);
 | 
			
		||||
 | 
			
		||||
        wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
 | 
			
		||||
@@ -135,7 +135,7 @@ describe(ContractName.Forwarder, () => {
 | 
			
		||||
            zrxAssetData,
 | 
			
		||||
            wethAssetData,
 | 
			
		||||
        );
 | 
			
		||||
        forwarderContract = new ForwarderContract(forwarderInstance.abi, forwarderInstance.address, provider);
 | 
			
		||||
        forwarderContract = new ForwarderContract(forwarderInstance.address, provider);
 | 
			
		||||
        forwarderWrapper = new ForwarderWrapper(forwarderContract, provider);
 | 
			
		||||
        const zrxDepositAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18);
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,41 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.0.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Move `LibTransactionDecoder` to contracts/dev-utils package",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1563006338
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "2.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.0.0 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Move `LibTransactionDecoder` to contracts/dev-utils package (#1848)
 | 
			
		||||
 | 
			
		||||
## v2.1.6 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.5 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.4 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange-libs",
 | 
			
		||||
    "version": "2.1.2",
 | 
			
		||||
    "version": "3.0.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/libs/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,14 +68,14 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "2.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "2.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "2.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "2.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "2.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.1.6 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.5 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.4 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.3 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange",
 | 
			
		||||
    "version": "2.1.2",
 | 
			
		||||
    "version": "2.1.6",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,19 +68,19 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.1.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.7",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ import {
 | 
			
		||||
    ERC721ProxyContract,
 | 
			
		||||
    ERC721Wrapper,
 | 
			
		||||
    MultiAssetProxyContract,
 | 
			
		||||
    StaticCallProxyContract,
 | 
			
		||||
    TestStaticCallTargetContract,
 | 
			
		||||
} from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
@@ -69,6 +71,8 @@ describe('Exchange core', () => {
 | 
			
		||||
    let erc721Proxy: ERC721ProxyContract;
 | 
			
		||||
    let erc1155Proxy: ERC721ProxyContract;
 | 
			
		||||
    let multiAssetProxy: MultiAssetProxyContract;
 | 
			
		||||
    let staticCallProxy: StaticCallProxyContract;
 | 
			
		||||
    let staticCallTarget: TestStaticCallTargetContract;
 | 
			
		||||
    let maliciousWallet: TestStaticCallReceiverContract;
 | 
			
		||||
    let maliciousValidator: TestStaticCallReceiverContract;
 | 
			
		||||
    let erc1155Contract: ERC1155MintableContract;
 | 
			
		||||
@@ -113,6 +117,11 @@ describe('Exchange core', () => {
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.StaticCallProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        const numDummyErc20ToDeploy = 3;
 | 
			
		||||
        [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
 | 
			
		||||
            numDummyErc20ToDeploy,
 | 
			
		||||
@@ -141,66 +150,22 @@ describe('Exchange core', () => {
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Configure ERC20Proxy
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
        await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner });
 | 
			
		||||
 | 
			
		||||
        // Configure ERC721Proxy
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
        await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner });
 | 
			
		||||
 | 
			
		||||
        // Configure ERC1155Proxy
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner });
 | 
			
		||||
 | 
			
		||||
        // Configure MultiAssetProxy
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
 | 
			
		||||
        await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: owner });
 | 
			
		||||
        await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address, { from: owner });
 | 
			
		||||
        await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address, { from: owner });
 | 
			
		||||
 | 
			
		||||
        // Configure Exchange
 | 
			
		||||
        exchangeWrapper = new ExchangeWrapper(exchange, provider);
 | 
			
		||||
@@ -208,6 +173,7 @@ describe('Exchange core', () => {
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(staticCallProxy.address, owner);
 | 
			
		||||
 | 
			
		||||
        // Configure ERC20 tokens
 | 
			
		||||
        await erc20Wrapper.setBalancesAndAllowancesAsync();
 | 
			
		||||
@@ -268,10 +234,7 @@ describe('Exchange core', () => {
 | 
			
		||||
                    signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                        makerAssetData: assetDataUtils.encodeERC20AssetData(reentrantErc20Token.address),
 | 
			
		||||
                    });
 | 
			
		||||
                    await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                        await reentrantErc20Token.setCurrentFunction.sendTransactionAsync(functionId),
 | 
			
		||||
                        constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                    );
 | 
			
		||||
                    await reentrantErc20Token.setCurrentFunction.awaitTransactionSuccessAsync(functionId);
 | 
			
		||||
                    await expectTransactionFailedAsync(
 | 
			
		||||
                        exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
 | 
			
		||||
                        RevertReason.TransferFailed,
 | 
			
		||||
@@ -310,20 +273,14 @@ describe('Exchange core', () => {
 | 
			
		||||
 | 
			
		||||
        it('should revert if `isValidSignature` tries to update state when SignatureType=Wallet', async () => {
 | 
			
		||||
            const maliciousMakerAddress = maliciousWallet.address;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20TokenA.setBalance.sendTransactionAsync(
 | 
			
		||||
                    maliciousMakerAddress,
 | 
			
		||||
                    constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
                ),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            await erc20TokenA.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                maliciousMakerAddress,
 | 
			
		||||
                constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await maliciousWallet.approveERC20.sendTransactionAsync(
 | 
			
		||||
                    erc20TokenA.address,
 | 
			
		||||
                    erc20Proxy.address,
 | 
			
		||||
                    constants.INITIAL_ERC20_ALLOWANCE,
 | 
			
		||||
                ),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            await maliciousWallet.approveERC20.awaitTransactionSuccessAsync(
 | 
			
		||||
                erc20TokenA.address,
 | 
			
		||||
                erc20Proxy.address,
 | 
			
		||||
                constants.INITIAL_ERC20_ALLOWANCE,
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                makerAddress: maliciousMakerAddress,
 | 
			
		||||
@@ -338,13 +295,10 @@ describe('Exchange core', () => {
 | 
			
		||||
 | 
			
		||||
        it('should revert if `isValidSignature` tries to update state when SignatureType=Validator', async () => {
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await exchange.setSignatureValidatorApproval.sendTransactionAsync(
 | 
			
		||||
                    maliciousValidator.address,
 | 
			
		||||
                    isApproved,
 | 
			
		||||
                    { from: makerAddress },
 | 
			
		||||
                ),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            await exchange.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
 | 
			
		||||
                maliciousValidator.address,
 | 
			
		||||
                isApproved,
 | 
			
		||||
                { from: makerAddress },
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder.signature = `${maliciousValidator.address}0${SignatureType.Validator}`;
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
@@ -399,17 +353,14 @@ describe('Exchange core', () => {
 | 
			
		||||
                constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
                constants.DUMMY_TOKEN_TOTAL_SUPPLY,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await noReturnErc20Token.setBalance.sendTransactionAsync(makerAddress, constants.INITIAL_ERC20_BALANCE),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await noReturnErc20Token.approve.sendTransactionAsync(
 | 
			
		||||
                    erc20Proxy.address,
 | 
			
		||||
                    constants.INITIAL_ERC20_ALLOWANCE,
 | 
			
		||||
                    { from: makerAddress },
 | 
			
		||||
                ),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            await noReturnErc20Token.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
                erc20Proxy.address,
 | 
			
		||||
                constants.INITIAL_ERC20_ALLOWANCE,
 | 
			
		||||
                { from: makerAddress },
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => {
 | 
			
		||||
@@ -1516,6 +1467,122 @@ describe('Exchange core', () => {
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('Testing orders that utilize StaticCallProxy', () => {
 | 
			
		||||
        before(async () => {
 | 
			
		||||
            staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
 | 
			
		||||
                proxyArtifacts.TestStaticCallTarget,
 | 
			
		||||
                provider,
 | 
			
		||||
                txDefaults,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the staticcall is unsuccessful', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                constants.KECCAK256_NULL,
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
 | 
			
		||||
                RevertReason.TargetNotEven,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should fill the order if the staticcall is successful', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(
 | 
			
		||||
                constants.ZERO_AMOUNT,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                constants.KECCAK256_NULL,
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
 | 
			
		||||
 | 
			
		||||
            const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const initialFeeRecipientZrxBalance = await zrxToken.balanceOf.callAsync(feeRecipientAddress);
 | 
			
		||||
            const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
 | 
			
		||||
 | 
			
		||||
            await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
 | 
			
		||||
 | 
			
		||||
            const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const finalFeeRecipientZrxBalance = await zrxToken.balanceOf.callAsync(feeRecipientAddress);
 | 
			
		||||
            const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
 | 
			
		||||
 | 
			
		||||
            expect(finalMakerZrxBalance).to.bignumber.equal(initialMakerZrxBalance.minus(signedOrder.makerFee));
 | 
			
		||||
            expect(finalTakerZrxBalance).to.bignumber.equal(initialTakerZrxBalance.minus(signedOrder.takerFee));
 | 
			
		||||
            expect(finalFeeRecipientZrxBalance).to.bignumber.equal(
 | 
			
		||||
                initialFeeRecipientZrxBalance.plus(signedOrder.makerFee).plus(signedOrder.takerFee),
 | 
			
		||||
            );
 | 
			
		||||
            expect(finalMakerBalanceB).to.bignumber.equal(initialMakerBalanceB.plus(signedOrder.takerAssetAmount));
 | 
			
		||||
            expect(finalTakerBalanceB).to.bignumber.equal(initialTakerBalanceB.minus(signedOrder.takerAssetAmount));
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the staticcall is unsuccessful using the MultiAssetProxy', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const staticCallAssetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                constants.KECCAK256_NULL,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), staticCallAssetData],
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
 | 
			
		||||
                RevertReason.TargetNotEven,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should fill the order is the staticcall is successful using the MultiAssetProxy', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(
 | 
			
		||||
                constants.ZERO_AMOUNT,
 | 
			
		||||
            );
 | 
			
		||||
            const staticCallAssetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                constants.KECCAK256_NULL,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
                [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
                [assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), staticCallAssetData],
 | 
			
		||||
            );
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
 | 
			
		||||
 | 
			
		||||
            const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const initialFeeRecipientZrxBalance = await zrxToken.balanceOf.callAsync(feeRecipientAddress);
 | 
			
		||||
            const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
 | 
			
		||||
 | 
			
		||||
            await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
 | 
			
		||||
 | 
			
		||||
            const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const finalFeeRecipientZrxBalance = await zrxToken.balanceOf.callAsync(feeRecipientAddress);
 | 
			
		||||
            const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
 | 
			
		||||
            const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
 | 
			
		||||
            const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
 | 
			
		||||
 | 
			
		||||
            expect(finalMakerZrxBalance).to.bignumber.equal(initialMakerZrxBalance.minus(signedOrder.makerFee));
 | 
			
		||||
            expect(finalTakerZrxBalance).to.bignumber.equal(initialTakerZrxBalance.minus(signedOrder.takerFee));
 | 
			
		||||
            expect(finalFeeRecipientZrxBalance).to.bignumber.equal(
 | 
			
		||||
                initialFeeRecipientZrxBalance.plus(signedOrder.makerFee).plus(signedOrder.takerFee),
 | 
			
		||||
            );
 | 
			
		||||
            expect(finalMakerBalanceA).to.bignumber.equal(initialMakerBalanceA.minus(signedOrder.makerAssetAmount));
 | 
			
		||||
            expect(finalTakerBalanceA).to.bignumber.equal(initialTakerBalanceA.plus(signedOrder.makerAssetAmount));
 | 
			
		||||
            expect(finalMakerBalanceB).to.bignumber.equal(initialMakerBalanceB.plus(signedOrder.takerAssetAmount));
 | 
			
		||||
            expect(finalTakerBalanceB).to.bignumber.equal(initialTakerBalanceB.minus(signedOrder.takerAssetAmount));
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getOrderInfo', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,41 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "4.0.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Move `OrderValidator` to contracts/dev-utils package as `OrderValidationUtils`",
 | 
			
		||||
                "pr": 1848
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1563006338
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "3.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "3.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "3.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "3.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.0.0 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Move `OrderValidator` to contracts/dev-utils package as `OrderValidationUtils` (#1848)
 | 
			
		||||
 | 
			
		||||
## v3.1.5 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.4 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.3 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
@@ -28,7 +29,6 @@
 | 
			
		||||
        "@0x/contracts-exchange/contracts/src/Exchange.sol",
 | 
			
		||||
        "src/BalanceThresholdFilter/BalanceThresholdFilter.sol",
 | 
			
		||||
        "src/DutchAuction/DutchAuction.sol",
 | 
			
		||||
        "src/OrderMatcher/OrderMatcher.sol",
 | 
			
		||||
        "src/OrderValidator/OrderValidator.sol"
 | 
			
		||||
        "src/OrderMatcher/OrderMatcher.sol"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,218 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/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)"));
 | 
			
		||||
 | 
			
		||||
    struct TraderInfo {
 | 
			
		||||
        uint256 makerBalance;       // Maker's balance of makerAsset
 | 
			
		||||
        uint256 makerAllowance;     // Maker's allowance to corresponding AssetProxy
 | 
			
		||||
        uint256 takerBalance;       // Taker's balance of takerAsset
 | 
			
		||||
        uint256 takerAllowance;     // Taker's allowance to corresponding AssetProxy
 | 
			
		||||
        uint256 makerZrxBalance;    // Maker's balance of ZRX
 | 
			
		||||
        uint256 makerZrxAllowance;  // Maker's allowance of ZRX to ERC20Proxy
 | 
			
		||||
        uint256 takerZrxBalance;    // Taker's balance of ZRX
 | 
			
		||||
        uint256 takerZrxAllowance;  // Taker's allowance of ZRX to ERC20Proxy
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // solhint-disable var-name-mixedcase
 | 
			
		||||
    IExchange internal EXCHANGE;
 | 
			
		||||
    bytes internal ZRX_ASSET_DATA;
 | 
			
		||||
    // solhint-enable var-name-mixedcase
 | 
			
		||||
 | 
			
		||||
    constructor (address _exchange, bytes memory _zrxAssetData)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        EXCHANGE = IExchange(_exchange);
 | 
			
		||||
        ZRX_ASSET_DATA = _zrxAssetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches information for order and maker/taker of order.
 | 
			
		||||
    /// @param order The order structure.
 | 
			
		||||
    /// @param takerAddress Address that will be filling the order.
 | 
			
		||||
    /// @return OrderInfo and TraderInfo instances for given order.
 | 
			
		||||
    function getOrderAndTraderInfo(LibOrder.Order memory order, address takerAddress)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibOrder.OrderInfo memory orderInfo, TraderInfo memory traderInfo)
 | 
			
		||||
    {
 | 
			
		||||
        orderInfo = EXCHANGE.getOrderInfo(order);
 | 
			
		||||
        traderInfo = getTraderInfo(order, takerAddress);
 | 
			
		||||
        return (orderInfo, traderInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches information for all passed in orders and the makers/takers of each order.
 | 
			
		||||
    /// @param orders Array of order specifications.
 | 
			
		||||
    /// @param takerAddresses Array of taker addresses corresponding to each order.
 | 
			
		||||
    /// @return Arrays of OrderInfo and TraderInfo instances that correspond to each order.
 | 
			
		||||
    function getOrdersAndTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibOrder.OrderInfo[] memory ordersInfo, TraderInfo[] memory tradersInfo)
 | 
			
		||||
    {
 | 
			
		||||
        ordersInfo = EXCHANGE.getOrdersInfo(orders);
 | 
			
		||||
        tradersInfo = getTradersInfo(orders, takerAddresses);
 | 
			
		||||
        return (ordersInfo, tradersInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches balance and allowances for maker and taker of order.
 | 
			
		||||
    /// @param order The order structure.
 | 
			
		||||
    /// @param takerAddress Address that will be filling the order.
 | 
			
		||||
    /// @return Balances and allowances of maker and taker of order.
 | 
			
		||||
    function getTraderInfo(LibOrder.Order memory order, address takerAddress)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (TraderInfo memory traderInfo)
 | 
			
		||||
    {
 | 
			
		||||
        (traderInfo.makerBalance, traderInfo.makerAllowance) = getBalanceAndAllowance(order.makerAddress, order.makerAssetData);
 | 
			
		||||
        (traderInfo.takerBalance, traderInfo.takerAllowance) = getBalanceAndAllowance(takerAddress, order.takerAssetData);
 | 
			
		||||
        bytes memory zrxAssetData = ZRX_ASSET_DATA;
 | 
			
		||||
        (traderInfo.makerZrxBalance, traderInfo.makerZrxAllowance) = getBalanceAndAllowance(order.makerAddress, zrxAssetData);
 | 
			
		||||
        (traderInfo.takerZrxBalance, traderInfo.takerZrxAllowance) = getBalanceAndAllowance(takerAddress, zrxAssetData);
 | 
			
		||||
        return traderInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches balances and allowances of maker and taker for each provided order.
 | 
			
		||||
    /// @param orders Array of order specifications.
 | 
			
		||||
    /// @param takerAddresses Array of taker addresses corresponding to each order.
 | 
			
		||||
    /// @return Array of balances and allowances for maker and taker of each order.
 | 
			
		||||
    function getTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (TraderInfo[] memory)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 ordersLength = orders.length;
 | 
			
		||||
        TraderInfo[] memory tradersInfo = new TraderInfo[](ordersLength);
 | 
			
		||||
        for (uint256 i = 0; i != ordersLength; i++) {
 | 
			
		||||
            tradersInfo[i] = getTraderInfo(orders[i], takerAddresses[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return tradersInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches token balances and allowances of an address to given assetProxy. Supports ERC20 and ERC721.
 | 
			
		||||
    /// @param target Address to fetch balances and allowances of.
 | 
			
		||||
    /// @param assetData Encoded data that can be decoded by a specified proxy contract when transferring asset.
 | 
			
		||||
    /// @return Balance of asset and allowance set to given proxy of asset.
 | 
			
		||||
    ///         For ERC721 tokens, these values will always be 1 or 0.
 | 
			
		||||
    function getBalanceAndAllowance(address target, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
        address token = assetData.readAddress(16);
 | 
			
		||||
        address assetProxy = EXCHANGE.getAssetProxy(assetProxyId);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == ERC20_DATA_ID) {
 | 
			
		||||
            // Query balance
 | 
			
		||||
            balance = IERC20Token(token).balanceOf(target);
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            allowance = IERC20Token(token).allowance(target, assetProxy);
 | 
			
		||||
        } else if (assetProxyId == ERC721_DATA_ID) {
 | 
			
		||||
            uint256 tokenId = assetData.readUint256(36);
 | 
			
		||||
 | 
			
		||||
            // Query owner of tokenId
 | 
			
		||||
            address owner = getERC721TokenOwner(token, tokenId);
 | 
			
		||||
 | 
			
		||||
            // Set balance to 1 if tokenId is owned by target
 | 
			
		||||
            balance = target == owner ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
            // Check if ERC721Proxy is approved to spend tokenId
 | 
			
		||||
            bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy);
 | 
			
		||||
            
 | 
			
		||||
            // Set alowance to 1 if ERC721Proxy is approved to spend tokenId
 | 
			
		||||
            allowance = isApproved ? 1 : 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("UNSUPPORTED_ASSET_PROXY");
 | 
			
		||||
        }
 | 
			
		||||
        return (balance, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches token balances and allowances of an address for each given assetProxy. Supports ERC20 and ERC721.
 | 
			
		||||
    /// @param target Address to fetch balances and allowances of.
 | 
			
		||||
    /// @param assetData Array of encoded byte arrays that can be decoded by a specified proxy contract when transferring asset.
 | 
			
		||||
    /// @return Balances and allowances of assets.
 | 
			
		||||
    ///         For ERC721 tokens, these values will always be 1 or 0.
 | 
			
		||||
    function getBalancesAndAllowances(address target, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory, uint256[] memory)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        uint256[] memory balances = new uint256[](length);
 | 
			
		||||
        uint256[] memory allowances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            (balances[i], allowances[i]) = getBalanceAndAllowance(target, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return (balances, allowances);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
 | 
			
		||||
    /// @param token Address of ERC721 token.
 | 
			
		||||
    /// @param tokenId The identifier for the specific NFT.
 | 
			
		||||
    /// @return Owner of tokenId or null address if unowned.
 | 
			
		||||
    function getERC721TokenOwner(address token, uint256 tokenId)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (address owner)
 | 
			
		||||
    {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // load free memory pointer
 | 
			
		||||
            let cdStart := mload(64)
 | 
			
		||||
 | 
			
		||||
            // bytes4(keccak256(ownerOf(uint256))) = 0x6352211e
 | 
			
		||||
            mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
            mstore(add(cdStart, 4), tokenId)
 | 
			
		||||
 | 
			
		||||
            // staticcall `ownerOf(tokenId)`
 | 
			
		||||
            // `ownerOf` will revert if tokenId is not owned
 | 
			
		||||
            let success := staticcall(
 | 
			
		||||
                gas,      // forward all gas
 | 
			
		||||
                token,    // call token contract
 | 
			
		||||
                cdStart,  // start of calldata
 | 
			
		||||
                36,       // length of input is 36 bytes
 | 
			
		||||
                cdStart,  // write output over input
 | 
			
		||||
                32        // size of output is 32 bytes
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            // Success implies that tokenId is owned
 | 
			
		||||
            // Copy owner from return data if successful
 | 
			
		||||
            if success {
 | 
			
		||||
                owner := mload(cdStart)
 | 
			
		||||
            }    
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Owner initialized to address(0), no need to modify if call is unsuccessful
 | 
			
		||||
        return owner;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-extensions",
 | 
			
		||||
    "version": "3.1.2",
 | 
			
		||||
    "version": "4.0.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(BalanceThresholdFilter|DutchAuction|Exchange|ExchangeWrapper|OrderMatcher|OrderValidator|WETH9).json",
 | 
			
		||||
        "abis": "./generated-artifacts/@(BalanceThresholdFilter|DutchAuction|Exchange|ExchangeWrapper|OrderMatcher|WETH9).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -47,12 +47,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contract-wrappers": "^9.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^9.1.5",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -69,19 +69,19 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.1.7",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.1.6",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.1.7",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@ import * as DutchAuction from '../generated-artifacts/DutchAuction.json';
 | 
			
		||||
import * as Exchange from '../generated-artifacts/Exchange.json';
 | 
			
		||||
import * as ExchangeWrapper from '../generated-artifacts/ExchangeWrapper.json';
 | 
			
		||||
import * as OrderMatcher from '../generated-artifacts/OrderMatcher.json';
 | 
			
		||||
import * as OrderValidator from '../generated-artifacts/OrderValidator.json';
 | 
			
		||||
import * as WETH9 from '../generated-artifacts/WETH9.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    WETH9: WETH9 as ContractArtifact,
 | 
			
		||||
@@ -19,5 +18,4 @@ export const artifacts = {
 | 
			
		||||
    BalanceThresholdFilter: BalanceThresholdFilter as ContractArtifact,
 | 
			
		||||
    DutchAuction: DutchAuction as ContractArtifact,
 | 
			
		||||
    OrderMatcher: OrderMatcher as ContractArtifact,
 | 
			
		||||
    OrderValidator: OrderValidator as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,5 +8,4 @@ export * from '../generated-wrappers/dutch_auction';
 | 
			
		||||
export * from '../generated-wrappers/exchange';
 | 
			
		||||
export * from '../generated-wrappers/exchange_wrapper';
 | 
			
		||||
export * from '../generated-wrappers/order_matcher';
 | 
			
		||||
export * from '../generated-wrappers/order_validator';
 | 
			
		||||
export * from '../generated-wrappers/weth9';
 | 
			
		||||
 
 | 
			
		||||
@@ -109,11 +109,7 @@ describe(ContractName.DutchAuction, () => {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            exchangeInstance.address,
 | 
			
		||||
        );
 | 
			
		||||
        dutchAuctionContract = new DutchAuctionContract(
 | 
			
		||||
            dutchAuctionInstance.abi,
 | 
			
		||||
            dutchAuctionInstance.address,
 | 
			
		||||
            provider,
 | 
			
		||||
        );
 | 
			
		||||
        dutchAuctionContract = new DutchAuctionContract(dutchAuctionInstance.address, provider);
 | 
			
		||||
        dutchAuctionTestWrapper = new DutchAuctionTestWrapper(dutchAuctionInstance, provider);
 | 
			
		||||
 | 
			
		||||
        defaultMakerAssetAddress = erc20TokenA.address;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,602 +0,0 @@
 | 
			
		||||
import { ERC20ProxyContract, ERC20Wrapper, ERC721ProxyContract, ERC721Wrapper } from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
 | 
			
		||||
import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    OrderFactory,
 | 
			
		||||
    OrderStatus,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, OrderValidatorContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('OrderValidator', () => {
 | 
			
		||||
    let makerAddress: string;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let takerAddress: string;
 | 
			
		||||
    let erc20AssetData: string;
 | 
			
		||||
    let erc721AssetData: string;
 | 
			
		||||
 | 
			
		||||
    let erc20Token: DummyERC20TokenContract;
 | 
			
		||||
    let zrxToken: DummyERC20TokenContract;
 | 
			
		||||
    let erc721Token: DummyERC721TokenContract;
 | 
			
		||||
    let exchange: ExchangeContract;
 | 
			
		||||
    let orderValidator: OrderValidatorContract;
 | 
			
		||||
    let erc20Proxy: ERC20ProxyContract;
 | 
			
		||||
    let erc721Proxy: ERC721ProxyContract;
 | 
			
		||||
 | 
			
		||||
    let signedOrder: SignedOrder;
 | 
			
		||||
    let signedOrder2: SignedOrder;
 | 
			
		||||
    let orderFactory: OrderFactory;
 | 
			
		||||
 | 
			
		||||
    const tokenId = new BigNumber(123456789);
 | 
			
		||||
    const tokenId2 = new BigNumber(987654321);
 | 
			
		||||
    const ERC721_BALANCE = new BigNumber(1);
 | 
			
		||||
    const ERC721_ALLOWANCE = new BigNumber(1);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const usedAddresses = ([owner, makerAddress, takerAddress] = _.slice(accounts, 0, 3));
 | 
			
		||||
 | 
			
		||||
        const erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
        const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
 | 
			
		||||
        const numDummyErc20ToDeploy = 2;
 | 
			
		||||
        [erc20Token, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
 | 
			
		||||
            numDummyErc20ToDeploy,
 | 
			
		||||
            constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
        );
 | 
			
		||||
        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
 | 
			
		||||
        erc721Proxy = await erc721Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Exchange,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            zrxAssetData,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeWrapper = new ExchangeWrapper(exchange, provider);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
 | 
			
		||||
 | 
			
		||||
        orderValidator = await OrderValidatorContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.OrderValidator,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
            zrxAssetData,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
        erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
 | 
			
		||||
        const defaultOrderParams = {
 | 
			
		||||
            ...constants.STATIC_ORDER_PARAMS,
 | 
			
		||||
            exchangeAddress: exchange.address,
 | 
			
		||||
            makerAddress,
 | 
			
		||||
            feeRecipientAddress: constants.NULL_ADDRESS,
 | 
			
		||||
            makerAssetData: erc20AssetData,
 | 
			
		||||
            takerAssetData: erc721AssetData,
 | 
			
		||||
        };
 | 
			
		||||
        const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
 | 
			
		||||
        orderFactory = new OrderFactory(privateKey, defaultOrderParams);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getBalanceAndAllowance', () => {
 | 
			
		||||
        describe('getERC721TokenOwner', async () => {
 | 
			
		||||
            it('should return the null address when tokenId is not owned', async () => {
 | 
			
		||||
                const tokenOwner = await orderValidator.getERC721TokenOwner.callAsync(makerAddress, tokenId);
 | 
			
		||||
                expect(tokenOwner).to.be.equal(constants.NULL_ADDRESS);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return the owner address when tokenId is owned', async () => {
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const tokenOwner = await orderValidator.getERC721TokenOwner.callAsync(erc721Token.address, tokenId);
 | 
			
		||||
                expect(tokenOwner).to.be.equal(makerAddress);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        describe('ERC20 assetData', () => {
 | 
			
		||||
            it('should return the correct balances and allowances when both values are 0', async () => {
 | 
			
		||||
                const [newBalance, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc20AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(constants.ZERO_AMOUNT).to.be.bignumber.equal(newBalance);
 | 
			
		||||
                expect(constants.ZERO_AMOUNT).to.be.bignumber.equal(newAllowance);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return the correct balance and allowance when both values are non-zero', async () => {
 | 
			
		||||
                const balance = new BigNumber(123);
 | 
			
		||||
                const allowance = new BigNumber(456);
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc20Token.setBalance.sendTransactionAsync(makerAddress, balance),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    }),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const [newBalance, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc20AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(balance).to.be.bignumber.equal(newBalance);
 | 
			
		||||
                expect(allowance).to.be.bignumber.equal(newAllowance);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        describe('ERC721 assetData', () => {
 | 
			
		||||
            it('should return a balance of 0 when the tokenId is not owned by target', async () => {
 | 
			
		||||
                const [newBalance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(newBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return an allowance of 0 when no approval is set', async () => {
 | 
			
		||||
                const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(newAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return a balance of 1 when the tokenId is owned by target', async () => {
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const [newBalance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(newBalance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return an allowance of 1 when ERC721Proxy is approved for all', async () => {
 | 
			
		||||
                const isApproved = true;
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    }),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(newAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            });
 | 
			
		||||
            it('should return an allowance of 0 when ERC721Proxy is approved for specific tokenId', async () => {
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await erc721Token.approve.sendTransactionAsync(erc721Proxy.address, tokenId, {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    }),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const [, newAllowance] = await orderValidator.getBalanceAndAllowance.callAsync(
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    erc721AssetData,
 | 
			
		||||
                );
 | 
			
		||||
                expect(newAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getBalancesAndAllowances', () => {
 | 
			
		||||
        it('should return the correct balances and allowances when all values are 0', async () => {
 | 
			
		||||
            const [
 | 
			
		||||
                [erc20Balance, erc721Balance],
 | 
			
		||||
                [erc20Allowance, erc721Allowance],
 | 
			
		||||
            ] = await orderValidator.getBalancesAndAllowances.callAsync(makerAddress, [
 | 
			
		||||
                erc20AssetData,
 | 
			
		||||
                erc721AssetData,
 | 
			
		||||
            ]);
 | 
			
		||||
            expect(erc20Balance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(erc721Balance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(erc20Allowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(erc721Allowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct balances and allowances when balances and allowances are non-zero', async () => {
 | 
			
		||||
            const balance = new BigNumber(123);
 | 
			
		||||
            const allowance = new BigNumber(456);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.setBalance.sendTransactionAsync(makerAddress, balance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.mint.sendTransactionAsync(makerAddress, tokenId),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const [
 | 
			
		||||
                [erc20Balance, erc721Balance],
 | 
			
		||||
                [erc20Allowance, erc721Allowance],
 | 
			
		||||
            ] = await orderValidator.getBalancesAndAllowances.callAsync(makerAddress, [
 | 
			
		||||
                erc20AssetData,
 | 
			
		||||
                erc721AssetData,
 | 
			
		||||
            ]);
 | 
			
		||||
            expect(erc20Balance).to.be.bignumber.equal(balance);
 | 
			
		||||
            expect(erc721Balance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            expect(erc20Allowance).to.be.bignumber.equal(allowance);
 | 
			
		||||
            expect(erc721Allowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getTraderInfo', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when no balances or allowances are set', async () => {
 | 
			
		||||
            const traderInfo = await orderValidator.getTraderInfo.callAsync(signedOrder, takerAddress);
 | 
			
		||||
            expect(traderInfo.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when balances and allowances are set', async () => {
 | 
			
		||||
            const makerBalance = new BigNumber(123);
 | 
			
		||||
            const makerAllowance = new BigNumber(456);
 | 
			
		||||
            const makerZrxBalance = new BigNumber(789);
 | 
			
		||||
            const takerZrxAllowance = new BigNumber(987);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const traderInfo = await orderValidator.getTraderInfo.callAsync(signedOrder, takerAddress);
 | 
			
		||||
            expect(traderInfo.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            expect(traderInfo.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getTradersInfo', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
            signedOrder2 = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId2),
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when no balances or allowances have been set', async () => {
 | 
			
		||||
            const orders = [signedOrder, signedOrder2];
 | 
			
		||||
            const takers = [takerAddress, takerAddress];
 | 
			
		||||
            const [traderInfo1, traderInfo2] = await orderValidator.getTradersInfo.callAsync(orders, takers);
 | 
			
		||||
            expect(traderInfo1.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when balances and allowances are set', async () => {
 | 
			
		||||
            const makerBalance = new BigNumber(123);
 | 
			
		||||
            const makerAllowance = new BigNumber(456);
 | 
			
		||||
            const makerZrxBalance = new BigNumber(789);
 | 
			
		||||
            const takerZrxAllowance = new BigNumber(987);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId2),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const orders = [signedOrder, signedOrder2];
 | 
			
		||||
            const takers = [takerAddress, takerAddress];
 | 
			
		||||
            const [traderInfo1, traderInfo2] = await orderValidator.getTradersInfo.callAsync(orders, takers);
 | 
			
		||||
 | 
			
		||||
            expect(traderInfo1.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo1.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
            expect(traderInfo2.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo2.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo2.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            expect(traderInfo2.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getOrderAndTraderInfo', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when no balances or allowances are set', async () => {
 | 
			
		||||
            const [orderInfo, traderInfo] = await orderValidator.getOrderAndTraderInfo.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
            );
 | 
			
		||||
            const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
            expect(orderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
            expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when balances and allowances are set', async () => {
 | 
			
		||||
            const makerBalance = new BigNumber(123);
 | 
			
		||||
            const makerAllowance = new BigNumber(456);
 | 
			
		||||
            const makerZrxBalance = new BigNumber(789);
 | 
			
		||||
            const takerZrxAllowance = new BigNumber(987);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const [orderInfo, traderInfo] = await orderValidator.getOrderAndTraderInfo.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
            );
 | 
			
		||||
            const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
            expect(orderInfo.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
            expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            expect(traderInfo.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getOrdersAndTradersInfo', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
            signedOrder2 = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId2),
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when no balances or allowances have been set', async () => {
 | 
			
		||||
            const orders = [signedOrder, signedOrder2];
 | 
			
		||||
            const takers = [takerAddress, takerAddress];
 | 
			
		||||
            const [
 | 
			
		||||
                [orderInfo1, orderInfo2],
 | 
			
		||||
                [traderInfo1, traderInfo2],
 | 
			
		||||
            ] = await orderValidator.getOrdersAndTradersInfo.callAsync(orders, takers);
 | 
			
		||||
            const expectedOrderHash1 = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
            const expectedOrderHash2 = orderHashUtils.getOrderHashHex(signedOrder2);
 | 
			
		||||
            expect(orderInfo1.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo1.orderHash).to.be.equal(expectedOrderHash1);
 | 
			
		||||
            expect(orderInfo1.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(orderInfo2.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo2.orderHash).to.be.equal(expectedOrderHash2);
 | 
			
		||||
            expect(orderInfo2.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct info when balances and allowances are set', async () => {
 | 
			
		||||
            const makerBalance = new BigNumber(123);
 | 
			
		||||
            const makerAllowance = new BigNumber(456);
 | 
			
		||||
            const makerZrxBalance = new BigNumber(789);
 | 
			
		||||
            const takerZrxAllowance = new BigNumber(987);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.setBalance.sendTransactionAsync(makerAddress, makerBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc20Token.approve.sendTransactionAsync(erc20Proxy.address, makerAllowance, {
 | 
			
		||||
                    from: makerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.setBalance.sendTransactionAsync(makerAddress, makerZrxBalance),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, takerZrxAllowance, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isApproved = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, isApproved, {
 | 
			
		||||
                    from: takerAddress,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc721Token.mint.sendTransactionAsync(takerAddress, tokenId2),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const orders = [signedOrder, signedOrder2];
 | 
			
		||||
            const takers = [takerAddress, takerAddress];
 | 
			
		||||
            const [
 | 
			
		||||
                [orderInfo1, orderInfo2],
 | 
			
		||||
                [traderInfo1, traderInfo2],
 | 
			
		||||
            ] = await orderValidator.getOrdersAndTradersInfo.callAsync(orders, takers);
 | 
			
		||||
            const expectedOrderHash1 = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
            const expectedOrderHash2 = orderHashUtils.getOrderHashHex(signedOrder2);
 | 
			
		||||
            expect(orderInfo1.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo1.orderHash).to.be.equal(expectedOrderHash1);
 | 
			
		||||
            expect(orderInfo1.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(orderInfo2.orderStatus).to.be.equal(OrderStatus.Fillable);
 | 
			
		||||
            expect(orderInfo2.orderHash).to.be.equal(expectedOrderHash2);
 | 
			
		||||
            expect(orderInfo2.orderTakerAssetFilledAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo1.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo1.takerBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo1.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo1.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo1.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
            expect(traderInfo2.makerBalance).to.be.bignumber.equal(makerBalance);
 | 
			
		||||
            expect(traderInfo2.makerAllowance).to.be.bignumber.equal(makerAllowance);
 | 
			
		||||
            expect(traderInfo2.takerBalance).to.be.bignumber.equal(ERC721_BALANCE);
 | 
			
		||||
            expect(traderInfo2.takerAllowance).to.be.bignumber.equal(ERC721_ALLOWANCE);
 | 
			
		||||
            expect(traderInfo2.makerZrxBalance).to.be.bignumber.equal(makerZrxBalance);
 | 
			
		||||
            expect(traderInfo2.makerZrxAllowance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(traderInfo2.takerZrxAllowance).to.be.bignumber.equal(takerZrxAllowance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
        "generated-artifacts/Exchange.json",
 | 
			
		||||
        "generated-artifacts/ExchangeWrapper.json",
 | 
			
		||||
        "generated-artifacts/OrderMatcher.json",
 | 
			
		||||
        "generated-artifacts/OrderValidator.json",
 | 
			
		||||
        "generated-artifacts/WETH9.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "3.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "3.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "3.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557799313,
 | 
			
		||||
        "version": "3.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "3.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.6 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.5 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.4 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.3 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-multisig",
 | 
			
		||||
    "version": "3.1.2",
 | 
			
		||||
    "version": "3.1.6",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,11 +47,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/multisig/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/abi-gen": "^2.1.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.0.10",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.1.8",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -68,15 +68,15 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.1.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.1.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.1",
 | 
			
		||||
        "@0x/base-contract": "^5.1.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.2.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.2.6",
 | 
			
		||||
        "@0x/contracts-utils": "2.0.1",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,41 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.1.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fixed false positives in `expectTransactionFailedAsync` and `expectContractCallFailedAsync`",
 | 
			
		||||
                "pr": 1852
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1563006338
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "3.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "3.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "3.1.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.8 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Fixed false positives in `expectTransactionFailedAsync` and `expectContractCallFailedAsync` (#1852)
 | 
			
		||||
 | 
			
		||||
## v3.1.7 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.6 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.5 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.3 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-test-utils",
 | 
			
		||||
    "version": "3.1.3",
 | 
			
		||||
    "version": "3.1.8",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -41,19 +41,18 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^2.0.10",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.2",
 | 
			
		||||
        "@0x/order-utils": "^8.0.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.7",
 | 
			
		||||
        "@0x/sol-coverage": "^3.0.4",
 | 
			
		||||
        "@0x/sol-profiler": "^3.1.6",
 | 
			
		||||
        "@0x/sol-trace": "^2.0.12",
 | 
			
		||||
        "@0x/subproviders": "^4.0.6",
 | 
			
		||||
        "@0x/dev-utils": "^2.2.4",
 | 
			
		||||
        "@0x/order-utils": "^8.2.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.1.9",
 | 
			
		||||
        "@0x/sol-coverage": "^3.0.6",
 | 
			
		||||
        "@0x/sol-profiler": "^3.1.8",
 | 
			
		||||
        "@0x/sol-trace": "^2.0.14",
 | 
			
		||||
        "@0x/subproviders": "^4.1.1",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@0x/types": "^2.2.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.2",
 | 
			
		||||
        "@0x/utils": "^4.3.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.6",
 | 
			
		||||
        "@0x/types": "^2.4.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.2.3",
 | 
			
		||||
        "@0x/utils": "^4.4.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.0.7",
 | 
			
		||||
        "@types/bn.js": "^4.11.0",
 | 
			
		||||
        "@types/js-combinatorics": "^0.5.29",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
@@ -63,7 +62,7 @@
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
        "dirty-chai": "^2.0.1",
 | 
			
		||||
        "ethereum-types": "^2.1.2",
 | 
			
		||||
        "ethereum-types": "^2.1.3",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "ethers": "~4.0.4",
 | 
			
		||||
        "js-combinatorics": "^0.5.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,8 @@ export async function expectTransactionFailedAsync(p: sendTransactionResult, rea
 | 
			
		||||
    }
 | 
			
		||||
    switch (nodeType) {
 | 
			
		||||
        case NodeType.Ganache:
 | 
			
		||||
            return expect(p).to.be.rejectedWith(reason);
 | 
			
		||||
            const rejectionMessageRegex = new RegExp(`^VM Exception while processing transaction: revert ${reason}$`);
 | 
			
		||||
            return expect(p).to.be.rejectedWith(rejectionMessageRegex);
 | 
			
		||||
        case NodeType.Geth:
 | 
			
		||||
            logUtils.warn(
 | 
			
		||||
                'WARNING: Geth does not support revert reasons for sendTransaction. This test will pass if the transaction fails for any reason.',
 | 
			
		||||
@@ -160,7 +161,8 @@ export async function expectTransactionFailedWithoutReasonAsync(p: sendTransacti
 | 
			
		||||
 * otherwise resolve with no value.
 | 
			
		||||
 */
 | 
			
		||||
export async function expectContractCallFailedAsync<T>(p: Promise<T>, reason: RevertReason): Promise<void> {
 | 
			
		||||
    return expect(p).to.be.rejectedWith(reason);
 | 
			
		||||
    const rejectionMessageRegex = new RegExp(`^VM Exception while processing transaction: revert ${reason}$`);
 | 
			
		||||
    return expect(p).to.be.rejectedWith(rejectionMessageRegex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -70,4 +70,5 @@ export const constants = {
 | 
			
		||||
        'CANCEL_ORDERS_UP_TO',
 | 
			
		||||
        'SET_SIGNATURE_VALIDATOR_APPROVAL',
 | 
			
		||||
    ],
 | 
			
		||||
    KECCAK256_NULL: ethUtil.addHexPrefix(ethUtil.bufferToHex(ethUtil.SHA3_NULL)),
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,40 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1563006338,
 | 
			
		||||
        "version": "3.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1558712885,
 | 
			
		||||
        "version": "3.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557961111,
 | 
			
		||||
        "version": "3.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1557799313
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1557507213,
 | 
			
		||||
        "version": "3.1.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.7 - _July 13, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.6 - _May 24, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.5 - _May 15, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.4 - _May 14, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.2 - _May 10, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user