Compare commits
	
		
			455 Commits
		
	
	
		
			@0x/types@
			...
			monorepo@9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9e9e0d6592 | ||
| 
						 | 
					cb5f9ba97d | ||
| 
						 | 
					34538f2ced | ||
| 
						 | 
					2575644920 | ||
| 
						 | 
					b4b43a9e9e | ||
| 
						 | 
					df97b20913 | ||
| 
						 | 
					9e3cc379ed | ||
| 
						 | 
					c1d78a94a2 | ||
| 
						 | 
					7f4cbba076 | ||
| 
						 | 
					bdca84fe72 | ||
| 
						 | 
					cf8fd7103b | ||
| 
						 | 
					8e8cdbd413 | ||
| 
						 | 
					30f01681d4 | ||
| 
						 | 
					ecf1ad8da1 | ||
| 
						 | 
					42dc112a13 | ||
| 
						 | 
					58276cefce | ||
| 
						 | 
					4b6501a739 | ||
| 
						 | 
					724085e068 | ||
| 
						 | 
					21fab3ef9f | ||
| 
						 | 
					db8837f4ce | ||
| 
						 | 
					5781cdf6da | ||
| 
						 | 
					874eb1602f | ||
| 
						 | 
					82149917b7 | ||
| 
						 | 
					f11d8a5bd8 | ||
| 
						 | 
					f0d7d10fe7 | ||
| 
						 | 
					9d4d9ce978 | ||
| 
						 | 
					96a38602b8 | ||
| 
						 | 
					90d3558d31 | ||
| 
						 | 
					e491a56dd0 | ||
| 
						 | 
					4d8eb61924 | ||
| 
						 | 
					17fab541c6 | ||
| 
						 | 
					91de35e8e9 | ||
| 
						 | 
					f61964676a | ||
| 
						 | 
					41a34c19bb | ||
| 
						 | 
					d90810d127 | ||
| 
						 | 
					7f3d281faa | ||
| 
						 | 
					812c306805 | ||
| 
						 | 
					fc1c59f374 | ||
| 
						 | 
					35eac1e3ff | ||
| 
						 | 
					e16041d7fa | ||
| 
						 | 
					b8fc84ecc8 | ||
| 
						 | 
					572c576e15 | ||
| 
						 | 
					9df7f80fbb | ||
| 
						 | 
					f003400135 | ||
| 
						 | 
					ca7616c1d2 | ||
| 
						 | 
					a4a2bfdf35 | ||
| 
						 | 
					eb6bbb6e78 | ||
| 
						 | 
					4d0172f634 | ||
| 
						 | 
					3b61e0e126 | ||
| 
						 | 
					1540a91835 | ||
| 
						 | 
					2bcce9eed0 | ||
| 
						 | 
					1e53564386 | ||
| 
						 | 
					d1c72706ef | ||
| 
						 | 
					bd9e531257 | ||
| 
						 | 
					48436424db | ||
| 
						 | 
					4f10d7f859 | ||
| 
						 | 
					80e5a29444 | ||
| 
						 | 
					0ec8a4a160 | ||
| 
						 | 
					810bf7af0c | ||
| 
						 | 
					e7825206bf | ||
| 
						 | 
					2b887c336a | ||
| 
						 | 
					48ecd32d5d | ||
| 
						 | 
					1f5a0987cb | ||
| 
						 | 
					f33a9d162a | ||
| 
						 | 
					c2919bcdb0 | ||
| 
						 | 
					120d554a6b | ||
| 
						 | 
					44f268a7ee | ||
| 
						 | 
					3c7a0bcd85 | ||
| 
						 | 
					8e2e9e9331 | ||
| 
						 | 
					91c26fc046 | ||
| 
						 | 
					afcfe58add | ||
| 
						 | 
					8d423be223 | ||
| 
						 | 
					03b7314550 | ||
| 
						 | 
					1a7e425780 | ||
| 
						 | 
					8bc5faff3c | ||
| 
						 | 
					2676278a66 | ||
| 
						 | 
					6376b3baf3 | ||
| 
						 | 
					e569abe740 | ||
| 
						 | 
					71be9ef92a | ||
| 
						 | 
					4990c4903d | ||
| 
						 | 
					9d468e2383 | ||
| 
						 | 
					109cac013c | ||
| 
						 | 
					0d8a9921cd | ||
| 
						 | 
					2a5f5f7312 | ||
| 
						 | 
					fe54fbefbb | ||
| 
						 | 
					fc824b8d06 | ||
| 
						 | 
					d91a7b6d0e | ||
| 
						 | 
					aa4b3f93fa | ||
| 
						 | 
					efe8225d18 | ||
| 
						 | 
					b2c0f8c158 | ||
| 
						 | 
					66dce8794d | ||
| 
						 | 
					30d54407e6 | ||
| 
						 | 
					6324a92ec5 | ||
| 
						 | 
					67e7b5c124 | ||
| 
						 | 
					35099d9b2f | ||
| 
						 | 
					e07f7b54e0 | ||
| 
						 | 
					5c409929b4 | ||
| 
						 | 
					1a504fdde9 | ||
| 
						 | 
					4b06fd511b | ||
| 
						 | 
					def6727286 | ||
| 
						 | 
					bedaa0db16 | ||
| 
						 | 
					90640a4fcf | ||
| 
						 | 
					0142d07f10 | ||
| 
						 | 
					c9d85cfc7d | ||
| 
						 | 
					64304c1991 | ||
| 
						 | 
					993adc3578 | ||
| 
						 | 
					8813bd26f6 | ||
| 
						 | 
					35925de320 | ||
| 
						 | 
					3b426a3f07 | ||
| 
						 | 
					5104fd5dcf | ||
| 
						 | 
					a5a9ca9e46 | ||
| 
						 | 
					ba0f07e3b2 | ||
| 
						 | 
					8614475324 | ||
| 
						 | 
					744dda144b | ||
| 
						 | 
					13d47915f4 | ||
| 
						 | 
					3059b85e41 | ||
| 
						 | 
					184ea4a67f | ||
| 
						 | 
					8032f536ed | ||
| 
						 | 
					fba3870ef1 | ||
| 
						 | 
					2915ee08ea | ||
| 
						 | 
					86b76a3e75 | ||
| 
						 | 
					bc1dca3f6f | ||
| 
						 | 
					5db1820123 | ||
| 
						 | 
					657c35fb86 | ||
| 
						 | 
					9432a84468 | ||
| 
						 | 
					15a5bc02ef | ||
| 
						 | 
					f011be9347 | ||
| 
						 | 
					b6094fdb34 | ||
| 
						 | 
					9e6ab9f585 | ||
| 
						 | 
					869d2c02fa | ||
| 
						 | 
					3b1dca0e70 | ||
| 
						 | 
					595358fa69 | ||
| 
						 | 
					8a8ec79c6c | ||
| 
						 | 
					6252446bd3 | ||
| 
						 | 
					403ceebff9 | ||
| 
						 | 
					4767882ed3 | ||
| 
						 | 
					3b9d84fa58 | ||
| 
						 | 
					6fd96a6fd7 | ||
| 
						 | 
					c93b02d55e | ||
| 
						 | 
					568f87d5eb | ||
| 
						 | 
					49ad0f0d54 | ||
| 
						 | 
					0e642f59e1 | ||
| 
						 | 
					7c5730fb03 | ||
| 
						 | 
					45f0f755ab | ||
| 
						 | 
					1ef2913c5b | ||
| 
						 | 
					fecbf220b6 | ||
| 
						 | 
					17a5f05cf3 | ||
| 
						 | 
					6a852ab0ed | ||
| 
						 | 
					ec26cff656 | ||
| 
						 | 
					cdd34a1214 | ||
| 
						 | 
					857a4042ef | ||
| 
						 | 
					f51c80adb2 | ||
| 
						 | 
					e61f23d001 | ||
| 
						 | 
					cbe4c4fbf9 | ||
| 
						 | 
					deffdabc30 | ||
| 
						 | 
					8811a5387a | ||
| 
						 | 
					9336d4e545 | ||
| 
						 | 
					f65d8cc325 | ||
| 
						 | 
					68656c4083 | ||
| 
						 | 
					44793a9cf9 | ||
| 
						 | 
					2d0ad6f181 | ||
| 
						 | 
					a7f0717afb | ||
| 
						 | 
					a9022352e7 | ||
| 
						 | 
					9b2231ed24 | ||
| 
						 | 
					c123200f38 | ||
| 
						 | 
					3c6c4128a6 | ||
| 
						 | 
					47e050cbaf | ||
| 
						 | 
					62d15117c5 | ||
| 
						 | 
					fb8360edfd | ||
| 
						 | 
					e557f2fb48 | ||
| 
						 | 
					c957b48281 | ||
| 
						 | 
					c15c5e12b0 | ||
| 
						 | 
					15c3c8074c | ||
| 
						 | 
					cba72c811d | ||
| 
						 | 
					28a2e56003 | ||
| 
						 | 
					8c4c3d56c6 | ||
| 
						 | 
					911fcc0bed | ||
| 
						 | 
					55fd16ccf1 | ||
| 
						 | 
					4e05e41f7f | ||
| 
						 | 
					ebab80cff7 | ||
| 
						 | 
					91cb162662 | ||
| 
						 | 
					fa26f8de51 | ||
| 
						 | 
					26602ac2db | ||
| 
						 | 
					0b8af181d8 | ||
| 
						 | 
					19d661d324 | ||
| 
						 | 
					7d29b36246 | ||
| 
						 | 
					8ba7b95e86 | ||
| 
						 | 
					30c72daed5 | ||
| 
						 | 
					575cb99839 | ||
| 
						 | 
					0c064bf85b | ||
| 
						 | 
					0f3610c92a | ||
| 
						 | 
					c8ef10baaf | ||
| 
						 | 
					16dc73bd1e | ||
| 
						 | 
					4f56d68689 | ||
| 
						 | 
					8e6d92cad5 | ||
| 
						 | 
					3a1c464543 | ||
| 
						 | 
					a0c2f6b7b4 | ||
| 
						 | 
					7bfbf0ad3a | ||
| 
						 | 
					82ee6750c7 | ||
| 
						 | 
					c37fc30c55 | ||
| 
						 | 
					09d13b2bfa | ||
| 
						 | 
					af0de72bc3 | ||
| 
						 | 
					43e32f6a1a | ||
| 
						 | 
					e9e6452890 | ||
| 
						 | 
					5f699b0c47 | ||
| 
						 | 
					bf18b86f9f | ||
| 
						 | 
					56f7dd7538 | ||
| 
						 | 
					7aa88307f6 | ||
| 
						 | 
					8aa69233e0 | ||
| 
						 | 
					e843333918 | ||
| 
						 | 
					133a4dc4e1 | ||
| 
						 | 
					c7945a542e | ||
| 
						 | 
					b4e00baa07 | ||
| 
						 | 
					dde570706a | ||
| 
						 | 
					0b3e3ab990 | ||
| 
						 | 
					205c895d75 | ||
| 
						 | 
					6402d29dd4 | ||
| 
						 | 
					dc18999931 | ||
| 
						 | 
					43f8101d0b | ||
| 
						 | 
					3d56c06ff3 | ||
| 
						 | 
					db9be73fec | ||
| 
						 | 
					a02892cbc8 | ||
| 
						 | 
					49c67fbb18 | ||
| 
						 | 
					6f2e79208a | ||
| 
						 | 
					ceb3ba4116 | ||
| 
						 | 
					08d4f1402f | ||
| 
						 | 
					77fa97f259 | ||
| 
						 | 
					3ac5d9add5 | ||
| 
						 | 
					cab89f312a | ||
| 
						 | 
					8972475389 | ||
| 
						 | 
					330f2d54e2 | ||
| 
						 | 
					9c181f09ba | ||
| 
						 | 
					011ecb8f4b | ||
| 
						 | 
					bc2a9beb14 | ||
| 
						 | 
					091f5ed8b8 | ||
| 
						 | 
					ea9f535a7c | ||
| 
						 | 
					f246314b1d | ||
| 
						 | 
					cdfd62a296 | ||
| 
						 | 
					dcff7d511b | ||
| 
						 | 
					16a5475d24 | ||
| 
						 | 
					42468c3fa2 | ||
| 
						 | 
					9312d5d9f7 | ||
| 
						 | 
					33a0c22021 | ||
| 
						 | 
					58e9c70203 | ||
| 
						 | 
					0067f10a6a | ||
| 
						 | 
					59210f5e5e | ||
| 
						 | 
					1c695b2759 | ||
| 
						 | 
					c7222c17ae | ||
| 
						 | 
					0f237d22f9 | ||
| 
						 | 
					b1b1162b60 | ||
| 
						 | 
					6ee1605a77 | ||
| 
						 | 
					a22b2e7a9f | ||
| 
						 | 
					86ed32a007 | ||
| 
						 | 
					8e8ea6a3ab | ||
| 
						 | 
					cc7452da8f | ||
| 
						 | 
					06715201a7 | ||
| 
						 | 
					281658ba34 | ||
| 
						 | 
					f192648c76 | ||
| 
						 | 
					07e1d502e7 | ||
| 
						 | 
					703e890918 | ||
| 
						 | 
					096950729e | ||
| 
						 | 
					8869d79c68 | ||
| 
						 | 
					752dd04546 | ||
| 
						 | 
					3e5d166ec4 | ||
| 
						 | 
					64bc1b0990 | ||
| 
						 | 
					548b0db6ea | ||
| 
						 | 
					c9607e8b2c | ||
| 
						 | 
					c676ecb8cf | ||
| 
						 | 
					39804fdc83 | ||
| 
						 | 
					1a1dc89454 | ||
| 
						 | 
					e427698956 | ||
| 
						 | 
					575af6b6e8 | ||
| 
						 | 
					3a1fc9ee5f | ||
| 
						 | 
					1237c7d479 | ||
| 
						 | 
					c44e16a88f | ||
| 
						 | 
					06c180475e | ||
| 
						 | 
					74a2c3a199 | ||
| 
						 | 
					9ac715f99d | ||
| 
						 | 
					22e39f782f | ||
| 
						 | 
					f5a6b84fa3 | ||
| 
						 | 
					718407ba6f | ||
| 
						 | 
					e603a81a46 | ||
| 
						 | 
					03e35846fb | ||
| 
						 | 
					c87364f86b | ||
| 
						 | 
					a794a33551 | ||
| 
						 | 
					494b437f1a | ||
| 
						 | 
					92b80fc436 | ||
| 
						 | 
					d66101cd9d | ||
| 
						 | 
					89ae04803f | ||
| 
						 | 
					be95bce4cd | ||
| 
						 | 
					01aee08c02 | ||
| 
						 | 
					6cba9fd77f | ||
| 
						 | 
					673d45361f | ||
| 
						 | 
					d91a7fc663 | ||
| 
						 | 
					ce8fd44234 | ||
| 
						 | 
					6617ad9531 | ||
| 
						 | 
					10f8051835 | ||
| 
						 | 
					e7dc7167d0 | ||
| 
						 | 
					359b804001 | ||
| 
						 | 
					fd9084b345 | ||
| 
						 | 
					44dac2cd80 | ||
| 
						 | 
					a66ea2bf74 | ||
| 
						 | 
					a362e9d2d8 | ||
| 
						 | 
					1885957bd3 | ||
| 
						 | 
					1a409c3731 | ||
| 
						 | 
					7b7c64fc6a | ||
| 
						 | 
					102fcd3fb8 | ||
| 
						 | 
					566e05aea4 | ||
| 
						 | 
					f014370531 | ||
| 
						 | 
					dfbbe9daa2 | ||
| 
						 | 
					6b653fb00d | ||
| 
						 | 
					21cf2319d5 | ||
| 
						 | 
					4210477e71 | ||
| 
						 | 
					93b02e93b9 | ||
| 
						 | 
					f4cb8cfb7e | ||
| 
						 | 
					ce9f051d42 | ||
| 
						 | 
					083216a0c6 | ||
| 
						 | 
					820b40e227 | ||
| 
						 | 
					59a38a8db0 | ||
| 
						 | 
					d0884dcb4d | ||
| 
						 | 
					c7ca625408 | ||
| 
						 | 
					e46f51339a | ||
| 
						 | 
					b45ec47eee | ||
| 
						 | 
					c50cbd7a75 | ||
| 
						 | 
					5ddc35fdf2 | ||
| 
						 | 
					d6c064b9c3 | ||
| 
						 | 
					caf6329bb3 | ||
| 
						 | 
					008938cf5b | ||
| 
						 | 
					3fd29656cb | ||
| 
						 | 
					ffac52f42e | ||
| 
						 | 
					9114510c00 | ||
| 
						 | 
					2dbda6fc42 | ||
| 
						 | 
					eae4001622 | ||
| 
						 | 
					727d0498b6 | ||
| 
						 | 
					e43f2d39bf | ||
| 
						 | 
					cde0169733 | ||
| 
						 | 
					0e90b0e7d0 | ||
| 
						 | 
					b793a31cdd | ||
| 
						 | 
					23198174f3 | ||
| 
						 | 
					523bc3f951 | ||
| 
						 | 
					41d99e77c7 | ||
| 
						 | 
					90193c8197 | ||
| 
						 | 
					6f5c62914e | ||
| 
						 | 
					17faeae47d | ||
| 
						 | 
					7283a16710 | ||
| 
						 | 
					52c3dc4ad8 | ||
| 
						 | 
					1cf8ae5909 | ||
| 
						 | 
					51282953bd | ||
| 
						 | 
					a6603d6bd6 | ||
| 
						 | 
					54a03eacd6 | ||
| 
						 | 
					43fa753a13 | ||
| 
						 | 
					9d9fe882b6 | ||
| 
						 | 
					4f6958b7b5 | ||
| 
						 | 
					9a5752fff9 | ||
| 
						 | 
					c21932d149 | ||
| 
						 | 
					ce6c05637f | ||
| 
						 | 
					b0699fc238 | ||
| 
						 | 
					8bf7c4cf48 | ||
| 
						 | 
					9f6d113fe8 | ||
| 
						 | 
					646507c41a | ||
| 
						 | 
					65f2626544 | ||
| 
						 | 
					7155d878b3 | ||
| 
						 | 
					361576814c | ||
| 
						 | 
					aa541d0cad | ||
| 
						 | 
					7e58385a78 | ||
| 
						 | 
					b5545255d0 | ||
| 
						 | 
					a22ba8647c | ||
| 
						 | 
					22fc0b4337 | ||
| 
						 | 
					063d6ff24e | ||
| 
						 | 
					09c0b83fe3 | ||
| 
						 | 
					a42f3d189c | ||
| 
						 | 
					7815da7257 | ||
| 
						 | 
					8e2b971f5a | ||
| 
						 | 
					3fd7132a0d | ||
| 
						 | 
					93edb083fa | ||
| 
						 | 
					9e41c648dc | ||
| 
						 | 
					a7ef54dbff | ||
| 
						 | 
					414084a7ad | ||
| 
						 | 
					681e6eab7a | ||
| 
						 | 
					701b203c58 | ||
| 
						 | 
					cbd0ca4b60 | ||
| 
						 | 
					1626566f93 | ||
| 
						 | 
					ac75053f69 | ||
| 
						 | 
					13afc65b54 | ||
| 
						 | 
					aa0a1bb54d | ||
| 
						 | 
					2e36c7ef83 | ||
| 
						 | 
					43399a9ad9 | ||
| 
						 | 
					2ef546210d | ||
| 
						 | 
					7b379f3933 | ||
| 
						 | 
					f8ac986a0f | ||
| 
						 | 
					dc0a78434d | ||
| 
						 | 
					d1b0384aef | ||
| 
						 | 
					7ac7f45c4a | ||
| 
						 | 
					b3c7ccec57 | ||
| 
						 | 
					93725ecec0 | ||
| 
						 | 
					3c31ef188a | ||
| 
						 | 
					53df2130ea | ||
| 
						 | 
					8b695f9b98 | ||
| 
						 | 
					d914f6fce9 | ||
| 
						 | 
					e2e5152648 | ||
| 
						 | 
					d3dcf7fb0c | ||
| 
						 | 
					a0f5a8b64b | ||
| 
						 | 
					ee508f70bc | ||
| 
						 | 
					200b3d450f | ||
| 
						 | 
					52fc7517f9 | ||
| 
						 | 
					cf517b1459 | ||
| 
						 | 
					c17984b74f | ||
| 
						 | 
					589d2212ee | ||
| 
						 | 
					9b922f746b | ||
| 
						 | 
					0e7387550c | ||
| 
						 | 
					dbf22583b5 | ||
| 
						 | 
					6825eb442b | ||
| 
						 | 
					45f284973a | ||
| 
						 | 
					ef6e691646 | ||
| 
						 | 
					e67888d65f | ||
| 
						 | 
					584f8b13fe | ||
| 
						 | 
					f993b6d1ed | ||
| 
						 | 
					035dc607db | ||
| 
						 | 
					cf2053ec77 | ||
| 
						 | 
					3840ebf538 | ||
| 
						 | 
					80cb6b654b | ||
| 
						 | 
					ab70c4df74 | ||
| 
						 | 
					95e461072f | ||
| 
						 | 
					2593f1ff30 | ||
| 
						 | 
					c2261a6bbe | ||
| 
						 | 
					b383781870 | ||
| 
						 | 
					7d121bafd0 | ||
| 
						 | 
					6a2911d10f | ||
| 
						 | 
					17362bcf44 | ||
| 
						 | 
					87906a3af1 | ||
| 
						 | 
					c0c27ed637 | ||
| 
						 | 
					6be5552944 | ||
| 
						 | 
					b4ae42cc9a | ||
| 
						 | 
					3c6957095d | ||
| 
						 | 
					2020d87824 | ||
| 
						 | 
					ac1063dd68 | ||
| 
						 | 
					b8e01d7be5 | ||
| 
						 | 
					24e4567b25 | ||
| 
						 | 
					ccf40fd65e | ||
| 
						 | 
					d4729e2669 | ||
| 
						 | 
					52d38c63de | ||
| 
						 | 
					086c30831d | ||
| 
						 | 
					4be83de7e5 | ||
| 
						 | 
					650efb95e2 | ||
| 
						 | 
					3948f8b66b | ||
| 
						 | 
					ffcd297e5b | ||
| 
						 | 
					cfb099c65c | ||
| 
						 | 
					ba5c702a9e | ||
| 
						 | 
					9d4010299a | ||
| 
						 | 
					b5492bb023 | ||
| 
						 | 
					76724a6c73 | ||
| 
						 | 
					57ec0858fe | ||
| 
						 | 
					b281b9aac8 | ||
| 
						 | 
					f4453c0966 | ||
| 
						 | 
					ebd328db06 | 
@@ -47,7 +47,7 @@ jobs:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - 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 @0x/contracts-staking
 | 
			
		||||
            - 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-tests @0x/contracts-staking
 | 
			
		||||
    test-exchange-ganache-3.0:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
@@ -58,6 +58,16 @@ jobs:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange
 | 
			
		||||
    test-integrations-ganache-3.0:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-integrations
 | 
			
		||||
    test-contracts-rest-ganache-3.0:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
@@ -67,11 +77,11 @@ jobs:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - 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-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-dev-utils @0x/contracts-staking
 | 
			
		||||
            # TODO(dorothy-zbornak): Re-enable after updating this package for 3.0.
 | 
			
		||||
            - 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-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-tests @0x/contracts-staking @0x/contracts-coordinator
 | 
			
		||||
            # TODO(dorothy-zbornak): Re-enable after updating this package for
 | 
			
		||||
            # 3.0. At that time, also remove exclusion from monorepo
 | 
			
		||||
            # package.json's test script.
 | 
			
		||||
            # - run: yarn wsrun test:circleci @0x/contracts-extensions
 | 
			
		||||
            # TODO(abandeali): Re-enable after this package is complete.
 | 
			
		||||
            # - run: yarn wsrun test:circleci @0x/contracts-coordinator
 | 
			
		||||
    test-publish:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
@@ -82,7 +92,7 @@ jobs:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: 
 | 
			
		||||
            - run:
 | 
			
		||||
                command: yarn test:publish:circleci
 | 
			
		||||
                no_output_timeout: 1800
 | 
			
		||||
    test-doc-generation:
 | 
			
		||||
@@ -108,6 +118,9 @@ jobs:
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/abi-gen
 | 
			
		||||
            # TODO (xianny): Needs to be updated for 3.0
 | 
			
		||||
            # - run: yarn wsrun test:circleci @0x/asset-buyer
 | 
			
		||||
            # TODO: Needs to be updated for 3.0.  At that time, also remove
 | 
			
		||||
            # exclusion from monorepo package.json's test script.
 | 
			
		||||
            # - run: yarn wsrun test:circleci @0x/asset-swapper
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contract-artifacts
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/assert
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/base-contract
 | 
			
		||||
@@ -117,6 +130,9 @@ jobs:
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/dev-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/json-schemas
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/order-utils
 | 
			
		||||
            # TODO: Needs to be updated for 3.0. At that time, also remove
 | 
			
		||||
            # exclusion from monorepo package.json's test script.
 | 
			
		||||
            # - run: yarn wsrun test:circleci @0x/orderbook
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/sol-compiler
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/sol-tracing-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/sol-doc
 | 
			
		||||
@@ -184,14 +200,33 @@ jobs:
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: 0xorg/ganache-cli:2.2.2
 | 
			
		||||
            - image: 0xorg/launch-kit-backend:74bcc39
 | 
			
		||||
            - image: 0xorg/ganache-cli:4.4.0-beta.1
 | 
			
		||||
              environment:
 | 
			
		||||
                  RPC_URL: http://localhost:8545
 | 
			
		||||
                  NETWORK_ID: 50
 | 
			
		||||
                  WHITELIST_ALL_TOKENS: True
 | 
			
		||||
                  VERSION: 4.4.0-beta.1
 | 
			
		||||
                  SNAPSHOT_NAME: 0x_ganache_snapshot-v3-beta
 | 
			
		||||
            - image: 0xorg/mesh:6.0.0-beta-0xv3
 | 
			
		||||
              environment:
 | 
			
		||||
                  ETHEREUM_RPC_URL: 'http://localhost:8545'
 | 
			
		||||
                  ETHEREUM_NETWORK_ID: '50'
 | 
			
		||||
                  ETHEREUM_CHAIN_ID: '1337'
 | 
			
		||||
                  USE_BOOTSTRAP_LIST: 'true'
 | 
			
		||||
                  VERBOSITY: 3
 | 
			
		||||
                  PRIVATE_KEY_PATH: ''
 | 
			
		||||
                  BLOCK_POLLING_INTERVAL: '5s'
 | 
			
		||||
                  P2P_LISTEN_PORT: '60557'
 | 
			
		||||
              command: |
 | 
			
		||||
                  sh -c "until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done; node_modules/.bin/forever ts/lib/index.js"
 | 
			
		||||
                  sh -c "waitForGanache () { until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done }; waitForGanache && ./mesh"
 | 
			
		||||
            - image: 0xorg/launch-kit-backend:v3
 | 
			
		||||
              environment:
 | 
			
		||||
                  RPC_URL: 'http://localhost:8545'
 | 
			
		||||
                  CHAIN_ID: 1337
 | 
			
		||||
                  WHITELIST_ALL_TOKENS: True
 | 
			
		||||
                  FEE_RECIPIENT: '0x0000000000000000000000000000000000000001'
 | 
			
		||||
                  MAKER_FEE_UNIT_AMOUNT: 0
 | 
			
		||||
                  TAKER_FEE_UNIT_AMOUNT: 0
 | 
			
		||||
                  MESH_ENDPOINT: 'ws://localhost:60557'
 | 
			
		||||
              command: |
 | 
			
		||||
                  sh -c "waitForMesh () { sleep 5; }; waitForMesh && node_modules/.bin/forever ts/lib/index.js"
 | 
			
		||||
        steps:
 | 
			
		||||
            - checkout
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
@@ -213,8 +248,14 @@ jobs:
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      ./parallel_without_sra_client coverage run setup.py test
 | 
			
		||||
                      ./parallel coverage run setup.py test
 | 
			
		||||
                      ./build_docs
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      # copy generated wrappers into contract_wrappers/build,
 | 
			
		||||
                      # JUST so CircleCI will persist them as build artifacts.
 | 
			
		||||
                      cd python-packages/contract_wrappers/src/zero_ex
 | 
			
		||||
                      for i in contract_wrappers/[^__]*/; do mkdir -p ../../build/$i; cp $i/__init__.py ../../build/$i; done
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
@@ -239,8 +280,6 @@ jobs:
 | 
			
		||||
                  key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/sra_client/.coverage
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/*/__init__.py
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/contract_addresses/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
@@ -394,6 +433,9 @@ workflows:
 | 
			
		||||
            - test-exchange-ganache-3.0:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-integrations-ganache-3.0:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-contracts-rest-ganache-3.0:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
@@ -415,12 +457,11 @@ workflows:
 | 
			
		||||
                      - test-exchange-ganache-3.0
 | 
			
		||||
                      - test-rest
 | 
			
		||||
                      - static-tests
 | 
			
		||||
            # - test-python:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            #           - test-rest
 | 
			
		||||
            # - static-tests-python:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - test-python
 | 
			
		||||
            - test-python:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - static-tests-python:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            # skip python tox run for now, as we don't yet have multiple test environments to support.
 | 
			
		||||
            # - test-rest-python
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							@@ -32,5 +32,3 @@ contracts: ['contracts']
 | 
			
		||||
@0x/json-schemas: ['packages/json-schemas']
 | 
			
		||||
@0x/ethereum-types: ['ethereum-types']
 | 
			
		||||
@0x/connect: ['packages/connect']
 | 
			
		||||
@0x/testnet-faucets: ['packages/testnet-faucets']
 | 
			
		||||
@0x/monorepo-scripts: ['packages/monorepo-scripts']
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -78,23 +78,35 @@ TODO.md
 | 
			
		||||
# VSCode file
 | 
			
		||||
.vscode
 | 
			
		||||
 | 
			
		||||
# server cli
 | 
			
		||||
packages/testnet-faucets/server/
 | 
			
		||||
 | 
			
		||||
# generated contract artifacts/
 | 
			
		||||
contracts/integrations/generated-artifacts/
 | 
			
		||||
contracts/integrations/test/generated-artifacts/
 | 
			
		||||
contracts/staking/generated-artifacts/
 | 
			
		||||
contracts/staking/test/generated-artifacts/
 | 
			
		||||
contracts/coordinator/generated-artifacts/
 | 
			
		||||
contracts/coordinator/test/generated-artifacts/
 | 
			
		||||
contracts/exchange/generated-artifacts/
 | 
			
		||||
contracts/exchange/test/generated-artifacts/
 | 
			
		||||
contracts/asset-proxy/generated-artifacts/
 | 
			
		||||
contracts/asset-proxy/test/generated-artifacts/
 | 
			
		||||
contracts/multisig/generated-artifacts/
 | 
			
		||||
contracts/multisig/test/generated-artifacts/
 | 
			
		||||
contracts/utils/generated-artifacts/
 | 
			
		||||
contracts/utils/test/generated-artifacts/
 | 
			
		||||
contracts/exchange-libs/generated-artifacts/
 | 
			
		||||
contracts/exchange-libs/test/generated-artifacts/
 | 
			
		||||
contracts/erc20/generated-artifacts/
 | 
			
		||||
contracts/erc20/test/generated-artifacts/
 | 
			
		||||
contracts/erc721/generated-artifacts/
 | 
			
		||||
contracts/erc721/test/generated-artifacts/
 | 
			
		||||
contracts/erc1155/generated-artifacts/
 | 
			
		||||
contracts/erc1155/test/generated-artifacts/
 | 
			
		||||
contracts/extensions/generated-artifacts/
 | 
			
		||||
contracts/extensions/test/generated-artifacts/
 | 
			
		||||
contracts/exchange-forwarder/generated-artifacts/
 | 
			
		||||
contracts/exchange-forwarder/test/generated-artifacts/
 | 
			
		||||
contracts/dev-utils/generated-artifacts/
 | 
			
		||||
contracts/dev-utils/test/generated-artifacts/
 | 
			
		||||
packages/sol-tracing-utils/test/fixtures/artifacts/
 | 
			
		||||
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
 | 
			
		||||
 | 
			
		||||
@@ -115,19 +127,35 @@ contracts/dev-utils/build/
 | 
			
		||||
 | 
			
		||||
# generated contract wrappers
 | 
			
		||||
packages/python-contract-wrappers/generated/
 | 
			
		||||
contracts/integrations/generated-wrappers/
 | 
			
		||||
contracts/integrations/test/generated-wrappers/
 | 
			
		||||
contracts/staking/generated-wrappers/
 | 
			
		||||
contracts/staking/test/generated-wrappers/
 | 
			
		||||
contracts/coordinator/generated-wrappers/
 | 
			
		||||
contracts/coordinator/test/generated-wrappers/
 | 
			
		||||
contracts/exchange/generated-wrappers/
 | 
			
		||||
contracts/exchange/test/generated-wrappers/
 | 
			
		||||
contracts/asset-proxy/generated-wrappers/
 | 
			
		||||
contracts/asset-proxy/test/generated-wrappers/
 | 
			
		||||
contracts/multisig/generated-wrappers/
 | 
			
		||||
contracts/multisig/test/generated-wrappers/
 | 
			
		||||
contracts/utils/generated-wrappers/
 | 
			
		||||
contracts/utils/test/generated-wrappers/
 | 
			
		||||
contracts/exchange-libs/generated-wrappers/
 | 
			
		||||
contracts/exchange-libs/test/generated-wrappers/
 | 
			
		||||
contracts/erc20/generated-wrappers/
 | 
			
		||||
contracts/erc20/test/generated-wrappers/
 | 
			
		||||
contracts/erc721/generated-wrappers/
 | 
			
		||||
contracts/erc721/test/generated-wrappers/
 | 
			
		||||
contracts/erc1155/generated-wrappers/
 | 
			
		||||
contracts/erc1155/test/generated-wrappers/
 | 
			
		||||
contracts/extensions/generated-wrappers/
 | 
			
		||||
contracts/extensions/test/generated-wrappers/
 | 
			
		||||
contracts/exchange-forwarder/generated-wrappers/
 | 
			
		||||
contracts/exchange-forwarder/test/generated-wrappers/
 | 
			
		||||
contracts/dev-utils/generated-wrappers/
 | 
			
		||||
contracts/dev-utils/test/generated-wrappers/
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dev_utils/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/asset_proxy_owner/__init__.py
 | 
			
		||||
@@ -136,16 +164,20 @@ python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator_regi
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc20_token/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc721_token/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dutch_auction/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_mintable/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/eth_balance_checker/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/forwarder/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_asset_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_validator/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_wallet/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/multi_asset_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/order_validator/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/staking/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/staking_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/static_call_proxy/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/weth9/__init__.py
 | 
			
		||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_token/__init__.py
 | 
			
		||||
 | 
			
		||||
@@ -162,10 +194,14 @@ __pycache__
 | 
			
		||||
python-packages/*/src/*.egg-info
 | 
			
		||||
python-packages/*/.coverage
 | 
			
		||||
 | 
			
		||||
# python keeps package-local copies of json schemas
 | 
			
		||||
# python keeps package-local copies of json schemas and contract addresses
 | 
			
		||||
python-packages/json_schemas/src/zero_ex/json_schemas/schemas
 | 
			
		||||
python-packages/contract_addresses/src/zero_ex/contract_addresses/addresses.json
 | 
			
		||||
 | 
			
		||||
# Doc README copy
 | 
			
		||||
packages/*/docs/README.md
 | 
			
		||||
 | 
			
		||||
.DS_Store
 | 
			
		||||
 | 
			
		||||
# the snapshot that gets built for migrations sure does have a ton of files
 | 
			
		||||
packages/migrations/0x_ganache_snapshot*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,61 @@
 | 
			
		||||
lib
 | 
			
		||||
.nyc_output
 | 
			
		||||
/contracts/integrations/generated-wrappers
 | 
			
		||||
/contracts/integrations/test/generated-wrappers
 | 
			
		||||
/contracts/integrations/generated-artifacts
 | 
			
		||||
/contracts/integrations/test/generated-artifacts
 | 
			
		||||
/contracts/staking/generated-wrappers
 | 
			
		||||
/contracts/staking/test/generated-wrappers
 | 
			
		||||
/contracts/staking/generated-artifacts
 | 
			
		||||
/contracts/staking/test/generated-artifacts
 | 
			
		||||
/contracts/coordinator/generated-wrappers
 | 
			
		||||
/contracts/coordinator/test/generated-wrappers
 | 
			
		||||
/contracts/coordinator/generated-artifacts
 | 
			
		||||
/contracts/coordinator/test/generated-artifacts
 | 
			
		||||
/contracts/exchange/generated-wrappers
 | 
			
		||||
/contracts/exchange/test/generated-wrappers
 | 
			
		||||
/contracts/exchange/generated-artifacts
 | 
			
		||||
/contracts/exchange/test/generated-artifacts
 | 
			
		||||
/contracts/asset-proxy/generated-wrappers
 | 
			
		||||
/contracts/asset-proxy/test/generated-wrappers
 | 
			
		||||
/contracts/asset-proxy/generated-artifacts
 | 
			
		||||
/contracts/asset-proxy/test/generated-artifacts
 | 
			
		||||
/contracts/multisig/generated-wrappers
 | 
			
		||||
/contracts/multisig/test/generated-wrappers
 | 
			
		||||
/contracts/multisig/generated-artifacts
 | 
			
		||||
/contracts/multisig/test/generated-artifacts
 | 
			
		||||
/contracts/utils/generated-wrappers
 | 
			
		||||
/contracts/utils/test/generated-wrappers
 | 
			
		||||
/contracts/utils/generated-artifacts
 | 
			
		||||
/contracts/utils/test/generated-artifacts
 | 
			
		||||
/contracts/exchange-libs/generated-wrappers
 | 
			
		||||
/contracts/exchange-libs/test/generated-wrappers
 | 
			
		||||
/contracts/exchange-libs/generated-artifacts
 | 
			
		||||
/contracts/exchange-libs/test/generated-artifacts
 | 
			
		||||
/contracts/erc20/generated-wrappers
 | 
			
		||||
/contracts/erc20/test/generated-wrappers
 | 
			
		||||
/contracts/erc20/generated-artifacts
 | 
			
		||||
/contracts/erc20/test/generated-artifacts
 | 
			
		||||
/contracts/erc721/generated-wrappers
 | 
			
		||||
/contracts/erc721/test/generated-wrappers
 | 
			
		||||
/contracts/erc721/generated-artifacts
 | 
			
		||||
/contracts/erc721/test/generated-artifacts
 | 
			
		||||
/contracts/erc1155/generated-wrappers
 | 
			
		||||
/contracts/erc1155/test/generated-wrappers
 | 
			
		||||
/contracts/erc1155/generated-artifacts
 | 
			
		||||
/contracts/erc1155/test/generated-artifacts
 | 
			
		||||
/contracts/extensions/generated-wrappers
 | 
			
		||||
/contracts/extensions/test/generated-wrappers
 | 
			
		||||
/contracts/extensions/generated-artifacts
 | 
			
		||||
/contracts/extensions/test/generated-artifacts
 | 
			
		||||
/contracts/exchange-forwarder/generated-wrappers
 | 
			
		||||
/contracts/exchange-forwarder/test/generated-wrappers
 | 
			
		||||
/contracts/exchange-forwarder/generated-artifacts
 | 
			
		||||
/contracts/exchange-forwarder/test/generated-artifacts
 | 
			
		||||
/contracts/dev-utils/generated-wrappers
 | 
			
		||||
/contracts/dev-utils/test/generated-wrappers
 | 
			
		||||
/contracts/dev-utils/generated-artifacts
 | 
			
		||||
/contracts/dev-utils/test/generated-artifacts
 | 
			
		||||
/contracts/staking/build/
 | 
			
		||||
/contracts/coordinator/build/
 | 
			
		||||
/contracts/exchange/build/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "tabWidth": 4,
 | 
			
		||||
    "printWidth": 120,
 | 
			
		||||
    "trailingComma": all,
 | 
			
		||||
    "singleQuote": true
 | 
			
		||||
    "tabWidth": 4,
 | 
			
		||||
    "singleQuote": true,
 | 
			
		||||
    "trailingComma": "all"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -96,10 +96,9 @@ These packages are all under development. See [/contracts/README.md](/contracts/
 | 
			
		||||
 | 
			
		||||
#### Private Packages
 | 
			
		||||
 | 
			
		||||
| Package                                            | Description                                                                      |
 | 
			
		||||
| -------------------------------------------------- | -------------------------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/instant`](/packages/instant)                 | A free and flexible way to offer simple crypto purchasing in any app or website. |
 | 
			
		||||
| [`@0x/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether                 |
 | 
			
		||||
| Package                            | Description                                                                      |
 | 
			
		||||
| ---------------------------------- | -------------------------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/instant`](/packages/instant) | A free and flexible way to offer simple crypto purchasing in any app or website. |
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								contracts/asset-proxy/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/asset-proxy/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Blacklist all files
 | 
			
		||||
.*
 | 
			
		||||
*
 | 
			
		||||
# Whitelist lib
 | 
			
		||||
!lib/**/*
 | 
			
		||||
# Whitelist Solidity contracts
 | 
			
		||||
!contracts/src/**/*
 | 
			
		||||
# Blacklist tests in lib
 | 
			
		||||
/lib/test/*
 | 
			
		||||
# Package specific ignore
 | 
			
		||||
@@ -1,4 +1,24 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
			
		||||
                "pr": 2330
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1574030254
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract",
 | 
			
		||||
                "pr": 2034
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1573159180
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
@@ -25,6 +45,14 @@
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `Eth2DaiBridge`",
 | 
			
		||||
                "pr": 2221
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `UniswapBridge`",
 | 
			
		||||
                "pr": 2233
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Replaced `SafeMath` with `LibSafeMath`",
 | 
			
		||||
                "pr": 2254
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1570135330
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.2 - _November 17, 2019_
 | 
			
		||||
 | 
			
		||||
    * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.1 - _November 7, 2019_
 | 
			
		||||
 | 
			
		||||
    * ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract (#2034)
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.0 - _October 3, 2019_
 | 
			
		||||
 | 
			
		||||
    * Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable (#2019)
 | 
			
		||||
@@ -13,6 +21,8 @@ CHANGELOG
 | 
			
		||||
    * Remove unused dependency on IAuthorizable in IAssetProxy (#1910)
 | 
			
		||||
    * Add `ERC20BridgeProxy` (#2220)
 | 
			
		||||
    * Add `Eth2DaiBridge` (#2221)
 | 
			
		||||
    * Add `UniswapBridge` (#2233)
 | 
			
		||||
    * Replaced `SafeMath` with `LibSafeMath` (#2254)
 | 
			
		||||
 | 
			
		||||
## v2.2.8 - _September 17, 2019_
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./generated-artifacts",
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
 | 
			
		||||
import "../archive/MixinAuthorizable.sol";
 | 
			
		||||
import "./interfaces/IAssetProxy.sol";
 | 
			
		||||
@@ -27,10 +27,10 @@ import "./interfaces/IAssetProxy.sol";
 | 
			
		||||
 | 
			
		||||
contract ERC1155Proxy is
 | 
			
		||||
    MixinAuthorizable,
 | 
			
		||||
    SafeMath,
 | 
			
		||||
    IAssetProxy
 | 
			
		||||
{
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    // Id of this proxy.
 | 
			
		||||
    bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
 | 
			
		||||
@@ -71,7 +71,7 @@ contract ERC1155Proxy is
 | 
			
		||||
            // to avoid copying over `ids` or `data`. This is possible if they are
 | 
			
		||||
            // identical to `values` and the offsets for each are pointing to the
 | 
			
		||||
            // same location in the ABI encoded calldata.
 | 
			
		||||
            scaledValues[i] = _safeMul(values[i], amount);
 | 
			
		||||
            scaledValues[i] = values[i].safeMul(amount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Execute `safeBatchTransferFrom` call
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ contract ERC20BridgeProxy is
 | 
			
		||||
        uint256 balanceBefore = balanceOf(tokenAddress, to);
 | 
			
		||||
        // Call the bridge, who should transfer `amount` of `tokenAddress` to
 | 
			
		||||
        // `to`.
 | 
			
		||||
        bytes4 success = IERC20Bridge(bridgeAddress).withdrawTo(
 | 
			
		||||
        bytes4 success = IERC20Bridge(bridgeAddress).bridgeTransferFrom(
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,10 @@ pragma solidity ^0.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IEth2Dai.sol";
 | 
			
		||||
import "../interfaces/IWallet.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
@@ -42,7 +43,7 @@ contract Eth2DaiBridge is
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoeded "from" token address.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function withdrawTo(
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address /* from */,
 | 
			
		||||
        address to,
 | 
			
		||||
@@ -57,7 +58,7 @@ contract Eth2DaiBridge is
 | 
			
		||||
 | 
			
		||||
        IEth2Dai exchange = _getEth2DaiContract();
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        IERC20Token(fromTokenAddress).approve(address(exchange), uint256(-1));
 | 
			
		||||
        LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        uint256 boughtAmount = _getEth2DaiContract().sellAllAmount(
 | 
			
		||||
@@ -67,7 +68,7 @@ contract Eth2DaiBridge is
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        _transferERC20Token(toTokenAddress, to, boughtAmount);
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -94,49 +95,4 @@ contract Eth2DaiBridge is
 | 
			
		||||
    {
 | 
			
		||||
        return IEth2Dai(ETH2DAI_ADDRESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Permissively transfers an ERC20 token that may not adhere to
 | 
			
		||||
    ///      specs.
 | 
			
		||||
    /// @param tokenAddress The token contract address.
 | 
			
		||||
    /// @param to The token recipient.
 | 
			
		||||
    /// @param amount The amount of tokens to transfer.
 | 
			
		||||
    function _transferERC20Token(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
    {
 | 
			
		||||
        // Transfer tokens.
 | 
			
		||||
        // We do a raw call so we can check the success separate
 | 
			
		||||
        // from the return data.
 | 
			
		||||
        (bool didSucceed, bytes memory returnData) = tokenAddress.call(
 | 
			
		||||
            abi.encodeWithSelector(
 | 
			
		||||
                IERC20Token(0).transfer.selector,
 | 
			
		||||
                to,
 | 
			
		||||
                amount
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        if (!didSucceed) {
 | 
			
		||||
            assembly { revert(add(returnData, 0x20), mload(returnData)) }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check return data.
 | 
			
		||||
        // If there is no return data, we assume the token incorrectly
 | 
			
		||||
        // does not return a bool. In this case we expect it to revert
 | 
			
		||||
        // on failure, which was handled above.
 | 
			
		||||
        // If the token does return data, we require that it is a single
 | 
			
		||||
        // value that evaluates to true.
 | 
			
		||||
        assembly {
 | 
			
		||||
            if returndatasize {
 | 
			
		||||
                didSucceed := 0
 | 
			
		||||
                if eq(returndatasize, 32) {
 | 
			
		||||
                    // First 64 bytes of memory are reserved scratch space
 | 
			
		||||
                    returndatacopy(0, 0, 32)
 | 
			
		||||
                    didSucceed := mload(0)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        require(didSucceed, "ERC20_TRANSFER_FAILED");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										219
									
								
								contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,219 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "../interfaces/IUniswapExchangeFactory.sol";
 | 
			
		||||
import "../interfaces/IUniswapExchange.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
contract UniswapBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet
 | 
			
		||||
{
 | 
			
		||||
    /* Mainnet addresses */
 | 
			
		||||
    address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
 | 
			
		||||
    address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
 | 
			
		||||
 | 
			
		||||
    // Struct to hold `bridgeTransferFrom()` local variables in memory and to avoid
 | 
			
		||||
    // stack overflows.
 | 
			
		||||
    struct WithdrawToState {
 | 
			
		||||
        IUniswapExchange exchange;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        IEtherToken weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // solhint-disable no-empty-blocks
 | 
			
		||||
    /// @dev Payable fallback to receive ETH from uniswap.
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
 | 
			
		||||
    ///      token encoded in the bridge data.
 | 
			
		||||
    /// @param toTokenAddress The token to buy and transfer to `to`.
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded "from" token address.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address /* from */,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // State memory object to avoid stack overflows.
 | 
			
		||||
        WithdrawToState memory state;
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        (address fromTokenAddress) = abi.decode(bridgeData, (address));
 | 
			
		||||
 | 
			
		||||
        // Just transfer the tokens if they're the same.
 | 
			
		||||
        if (fromTokenAddress == toTokenAddress) {
 | 
			
		||||
            LibERC20Token.transfer(fromTokenAddress, to, amount);
 | 
			
		||||
            return BRIDGE_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get the exchange for the token pair.
 | 
			
		||||
        state.exchange = _getUniswapExchangeForTokenPair(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress
 | 
			
		||||
        );
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Get the weth contract.
 | 
			
		||||
        state.weth = getWethContract();
 | 
			
		||||
 | 
			
		||||
        // Convert from WETH to a token.
 | 
			
		||||
        if (fromTokenAddress == address(state.weth)) {
 | 
			
		||||
            // Unwrap the WETH.
 | 
			
		||||
            state.weth.withdraw(state.fromTokenBalance);
 | 
			
		||||
            // Buy as much of `toTokenAddress` token with ETH as possible and
 | 
			
		||||
            // transfer it to `to`.
 | 
			
		||||
            state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)(
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
                amount,
 | 
			
		||||
                // Expires after this block.
 | 
			
		||||
                block.timestamp,
 | 
			
		||||
                // Recipient is `to`.
 | 
			
		||||
                to
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        // Convert from a token to WETH.
 | 
			
		||||
        } else if (toTokenAddress == address(state.weth)) {
 | 
			
		||||
            // Grant the exchange an allowance.
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress);
 | 
			
		||||
            // Buy as much ETH with `fromTokenAddress` token as possible.
 | 
			
		||||
            uint256 ethBought = state.exchange.tokenToEthSwapInput(
 | 
			
		||||
                // Sell all tokens we hold.
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
                amount,
 | 
			
		||||
                // Expires after this block.
 | 
			
		||||
                block.timestamp
 | 
			
		||||
            );
 | 
			
		||||
            // Wrap the ETH.
 | 
			
		||||
            state.weth.deposit.value(ethBought)();
 | 
			
		||||
            // Transfer the WETH to `to`.
 | 
			
		||||
            IEtherToken(toTokenAddress).transfer(to, ethBought);
 | 
			
		||||
 | 
			
		||||
        // Convert from one token to another.
 | 
			
		||||
        } else {
 | 
			
		||||
            // Grant the exchange an allowance.
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress);
 | 
			
		||||
            // Buy as much `toTokenAddress` token with `fromTokenAddress` token
 | 
			
		||||
            // and transfer it to `to`.
 | 
			
		||||
            state.exchange.tokenToTokenTransferInput(
 | 
			
		||||
                // Sell all tokens we hold.
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
                amount,
 | 
			
		||||
                // No minimum intermediate ETH buy amount.
 | 
			
		||||
                0,
 | 
			
		||||
                // Expires after this block.
 | 
			
		||||
                block.timestamp,
 | 
			
		||||
                // Recipient is `to`.
 | 
			
		||||
                to,
 | 
			
		||||
                // Convert to `toTokenAddress`.
 | 
			
		||||
                toTokenAddress
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
 | 
			
		||||
    ///      and sign for itself in orders. Always succeeds.
 | 
			
		||||
    /// @return magicValue Success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the weth contract.
 | 
			
		||||
    /// @return token The WETH contract.
 | 
			
		||||
    function getWethContract()
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (IEtherToken token)
 | 
			
		||||
    {
 | 
			
		||||
        return IEtherToken(WETH_ADDRESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the uniswap exchange factory contract.
 | 
			
		||||
    /// @return factory The exchange factory contract.
 | 
			
		||||
    function getUniswapExchangeFactoryContract()
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (IUniswapExchangeFactory factory)
 | 
			
		||||
    {
 | 
			
		||||
        return IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Grants an unlimited allowance to the exchange for its token
 | 
			
		||||
    ///      on behalf of this contract.
 | 
			
		||||
    /// @param exchange The Uniswap token exchange.
 | 
			
		||||
    /// @param tokenAddress The token address for the exchange.
 | 
			
		||||
    function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress)
 | 
			
		||||
        private
 | 
			
		||||
    {
 | 
			
		||||
        LibERC20Token.approve(tokenAddress, address(exchange), uint256(-1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the uniswap exchange for a given token pair.
 | 
			
		||||
    ///      In the case of a WETH-token exchange, this will be the non-WETH token.
 | 
			
		||||
    ///      In th ecase of a token-token exchange, this will be the first token.
 | 
			
		||||
    /// @param fromTokenAddress The address of the token we are converting from.
 | 
			
		||||
    /// @param toTokenAddress The address of the token we are converting to.
 | 
			
		||||
    /// @return exchange The uniswap exchange.
 | 
			
		||||
    function _getUniswapExchangeForTokenPair(
 | 
			
		||||
        address fromTokenAddress,
 | 
			
		||||
        address toTokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
        returns (IUniswapExchange exchange)
 | 
			
		||||
    {
 | 
			
		||||
        address exchangeTokenAddress = fromTokenAddress;
 | 
			
		||||
        // Whichever isn't WETH is the exchange token.
 | 
			
		||||
        if (fromTokenAddress == address(getWethContract())) {
 | 
			
		||||
            exchangeTokenAddress = toTokenAddress;
 | 
			
		||||
        }
 | 
			
		||||
        exchange = getUniswapExchangeFactoryContract().getExchange(exchangeTokenAddress);
 | 
			
		||||
        require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN");
 | 
			
		||||
        return exchange;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,7 @@ contract IERC20Bridge {
 | 
			
		||||
    /// @param amount Amount of asset to transfer.
 | 
			
		||||
    /// @param bridgeData Arbitrary asset data needed by the bridge contract.
 | 
			
		||||
    /// @return success The magic bytes `0x37708e9b` if successful.
 | 
			
		||||
    function withdrawTo(
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,77 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IUniswapExchange {
 | 
			
		||||
 | 
			
		||||
    /// @dev Buys at least `minTokensBought` tokens with ETH and transfer them
 | 
			
		||||
    ///      to `recipient`.
 | 
			
		||||
    /// @param minTokensBought The minimum number of tokens to buy.
 | 
			
		||||
    /// @param deadline Time when this order expires.
 | 
			
		||||
    /// @param recipient Who to transfer the tokens to.
 | 
			
		||||
    /// @return tokensBought Amount of tokens bought.
 | 
			
		||||
    function ethToTokenTransferInput(
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 tokensBought);
 | 
			
		||||
 | 
			
		||||
    /// @dev Buys at least `minEthBought` ETH with tokens.
 | 
			
		||||
    /// @param tokensSold Amount of tokens to sell.
 | 
			
		||||
    /// @param minEthBought The minimum amount of ETH to buy.
 | 
			
		||||
    /// @param deadline Time when this order expires.
 | 
			
		||||
    /// @return ethBought Amount of tokens bought.
 | 
			
		||||
    function tokenToEthSwapInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 ethBought);
 | 
			
		||||
 | 
			
		||||
    /// @dev Buys at least `minTokensBought` tokens with the exchange token
 | 
			
		||||
    ///      and transfer them to `recipient`.
 | 
			
		||||
    /// @param minTokensBought The minimum number of tokens to buy.
 | 
			
		||||
    /// @param minEthBought The minimum amount of intermediate ETH to buy.
 | 
			
		||||
    /// @param deadline Time when this order expires.
 | 
			
		||||
    /// @param recipient Who to transfer the tokens to.
 | 
			
		||||
    /// @param toTokenAddress The token being bought.
 | 
			
		||||
    /// @return tokensBought Amount of tokens bought.
 | 
			
		||||
    function tokenToTokenTransferInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address toTokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 tokensBought);
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the token that is associated with this exchange.
 | 
			
		||||
    /// @return tokenAddress The token address.
 | 
			
		||||
    function toTokenAddress()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address tokenAddress);
 | 
			
		||||
}
 | 
			
		||||
@@ -16,22 +16,17 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
 | 
			
		||||
import "../src/MixinSignatureValidator.sol";
 | 
			
		||||
import "../src/MixinTransactions.sol";
 | 
			
		||||
import "./IUniswapExchange.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestSignatureValidator is
 | 
			
		||||
    LibEIP712ExchangeDomain,
 | 
			
		||||
    MixinSignatureValidator
 | 
			
		||||
{
 | 
			
		||||
interface IUniswapExchangeFactory {
 | 
			
		||||
 | 
			
		||||
    // solhint-disable no-empty-blocks
 | 
			
		||||
    constructor (uint256 chainId)
 | 
			
		||||
        public
 | 
			
		||||
        LibEIP712ExchangeDomain(chainId, address(0))
 | 
			
		||||
    {}
 | 
			
		||||
    /// @dev Get the exchange for a token.
 | 
			
		||||
    /// @param tokenAddress The address of the token contract.
 | 
			
		||||
    function getExchange(address tokenAddress)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (IUniswapExchange);
 | 
			
		||||
}
 | 
			
		||||
@@ -72,7 +72,7 @@ contract TestERC20Bridge is
 | 
			
		||||
        testToken.setBalance(owner, balance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function withdrawTo(
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										432
									
								
								contracts/asset-proxy/contracts/test/TestUniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								contracts/asset-proxy/contracts/test/TestUniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,432 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "../src/bridges/UniswapBridge.sol";
 | 
			
		||||
import "../src/interfaces/IUniswapExchangeFactory.sol";
 | 
			
		||||
import "../src/interfaces/IUniswapExchange.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-simple-event-func-name
 | 
			
		||||
contract TestEventsRaiser {
 | 
			
		||||
 | 
			
		||||
    event TokenTransfer(
 | 
			
		||||
        address token,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenApprove(
 | 
			
		||||
        address spender,
 | 
			
		||||
        uint256 allowance
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event WethDeposit(
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event WethWithdraw(
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event EthToTokenTransferInput(
 | 
			
		||||
        address exchange,
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenToEthSwapInput(
 | 
			
		||||
        address exchange,
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenToTokenTransferInput(
 | 
			
		||||
        address exchange,
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address toTokenAddress
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    function raiseEthToTokenTransferInput(
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit EthToTokenTransferInput(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            minTokensBought,
 | 
			
		||||
            deadline,
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseTokenToEthSwapInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit TokenToEthSwapInput(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            tokensSold,
 | 
			
		||||
            minEthBought,
 | 
			
		||||
            deadline
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseTokenToTokenTransferInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address toTokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit TokenToTokenTransferInput(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            tokensSold,
 | 
			
		||||
            minTokensBought,
 | 
			
		||||
            minEthBought,
 | 
			
		||||
            deadline,
 | 
			
		||||
            recipient,
 | 
			
		||||
            toTokenAddress
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseTokenTransfer(
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit TokenTransfer(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseTokenApprove(address spender, uint256 allowance)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit TokenApprove(spender, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseWethDeposit(uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit WethDeposit(amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function raiseWethWithdraw(uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        emit WethWithdraw(amount);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev A minimalist ERC20/WETH token.
 | 
			
		||||
contract TestToken {
 | 
			
		||||
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    mapping (address => uint256) public balances;
 | 
			
		||||
    string private _nextRevertReason;
 | 
			
		||||
 | 
			
		||||
    /// @dev Set the balance for `owner`.
 | 
			
		||||
    function setBalance(address owner)
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        balances[owner] = msg.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Set the revert reason for `transfer()`,
 | 
			
		||||
    ///      `deposit()`, and `withdraw()`.
 | 
			
		||||
    function setRevertReason(string calldata reason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _nextRevertReason = reason;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just calls `raiseTokenTransfer()` on the caller.
 | 
			
		||||
    function transfer(address to, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just calls `raiseTokenApprove()` on the caller.
 | 
			
		||||
    function approve(address spender, uint256 allowance)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `IWETH.deposit()` that increases balances and calls
 | 
			
		||||
    ///     `raiseWethDeposit()` on the caller.
 | 
			
		||||
    function deposit()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        balances[msg.sender] += balances[msg.sender].safeAdd(msg.value);
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseWethDeposit(msg.value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `IWETH.withdraw()` that just reduces balances and calls
 | 
			
		||||
    ///       `raiseWethWithdraw()` on the caller.
 | 
			
		||||
    function withdraw(uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        balances[msg.sender] = balances[msg.sender].safeSub(amount);
 | 
			
		||||
        msg.sender.transfer(amount);
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseWethWithdraw(amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieve the balance for `owner`.
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256)
 | 
			
		||||
    {
 | 
			
		||||
        return balances[owner];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _revertIfReasonExists()
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        if (bytes(_nextRevertReason).length != 0) {
 | 
			
		||||
            revert(_nextRevertReason);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestExchange is
 | 
			
		||||
    IUniswapExchange
 | 
			
		||||
{
 | 
			
		||||
    address public tokenAddress;
 | 
			
		||||
    string private _nextRevertReason;
 | 
			
		||||
 | 
			
		||||
    constructor(address _tokenAddress) public {
 | 
			
		||||
        tokenAddress = _tokenAddress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setFillBehavior(
 | 
			
		||||
        string calldata revertReason
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        _nextRevertReason = revertReason;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function ethToTokenTransferInput(
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 tokensBought)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseEthToTokenTransferInput(
 | 
			
		||||
            minTokensBought,
 | 
			
		||||
            deadline,
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        return address(this).balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function tokenToEthSwapInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 ethBought)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenToEthSwapInput(
 | 
			
		||||
            tokensSold,
 | 
			
		||||
            minEthBought,
 | 
			
		||||
            deadline
 | 
			
		||||
        );
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        uint256 fillAmount = address(this).balance;
 | 
			
		||||
        msg.sender.transfer(fillAmount);
 | 
			
		||||
        return fillAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function tokenToTokenTransferInput(
 | 
			
		||||
        uint256 tokensSold,
 | 
			
		||||
        uint256 minTokensBought,
 | 
			
		||||
        uint256 minEthBought,
 | 
			
		||||
        uint256 deadline,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address toTokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 tokensBought)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenToTokenTransferInput(
 | 
			
		||||
            tokensSold,
 | 
			
		||||
            minTokensBought,
 | 
			
		||||
            minEthBought,
 | 
			
		||||
            deadline,
 | 
			
		||||
            recipient,
 | 
			
		||||
            toTokenAddress
 | 
			
		||||
        );
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
        return address(this).balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function toTokenAddress()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address _tokenAddress)
 | 
			
		||||
    {
 | 
			
		||||
        return tokenAddress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _revertIfReasonExists()
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        if (bytes(_nextRevertReason).length != 0) {
 | 
			
		||||
            revert(_nextRevertReason);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev UniswapBridge overridden to mock tokens and implement IUniswapExchangeFactory.
 | 
			
		||||
contract TestUniswapBridge is
 | 
			
		||||
    IUniswapExchangeFactory,
 | 
			
		||||
    TestEventsRaiser,
 | 
			
		||||
    UniswapBridge
 | 
			
		||||
{
 | 
			
		||||
    TestToken public wethToken;
 | 
			
		||||
    // Token address to TestToken instance.
 | 
			
		||||
    mapping (address => TestToken) private _testTokens;
 | 
			
		||||
    // Token address to TestExchange instance.
 | 
			
		||||
    mapping (address => TestExchange) private _testExchanges;
 | 
			
		||||
 | 
			
		||||
    constructor() public {
 | 
			
		||||
        wethToken = new TestToken();
 | 
			
		||||
        _testTokens[address(wethToken)] = wethToken;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sets the balance of this contract for an existing token.
 | 
			
		||||
    ///      The wei attached will be the balance.
 | 
			
		||||
    function setTokenBalance(address tokenAddress)
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        TestToken token = _testTokens[tokenAddress];
 | 
			
		||||
        token.deposit.value(msg.value)();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sets the revert reason for an existing token.
 | 
			
		||||
    function setTokenRevertReason(address tokenAddress, string calldata revertReason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        TestToken token = _testTokens[tokenAddress];
 | 
			
		||||
        token.setRevertReason(revertReason);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Create a token and exchange (if they don't exist) for a new token
 | 
			
		||||
    ///      and sets the exchange revert and fill behavior. The wei attached
 | 
			
		||||
    ///      will be the fill amount for the exchange.
 | 
			
		||||
    /// @param tokenAddress The token address. If zero, one will be created.
 | 
			
		||||
    /// @param revertReason The revert reason for exchange operations.
 | 
			
		||||
    function createTokenAndExchange(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        string calldata revertReason
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (TestToken token, TestExchange exchange)
 | 
			
		||||
    {
 | 
			
		||||
        token = TestToken(tokenAddress);
 | 
			
		||||
        if (tokenAddress == address(0)) {
 | 
			
		||||
            token = new TestToken();
 | 
			
		||||
        }
 | 
			
		||||
        _testTokens[address(token)] = token;
 | 
			
		||||
        exchange = _testExchanges[address(token)];
 | 
			
		||||
        if (address(exchange) == address(0)) {
 | 
			
		||||
            _testExchanges[address(token)] = exchange = new TestExchange(address(token));
 | 
			
		||||
        }
 | 
			
		||||
        exchange.setFillBehavior.value(msg.value)(revertReason);
 | 
			
		||||
        return (token, exchange);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `IUniswapExchangeFactory.getExchange`
 | 
			
		||||
    function getExchange(address tokenAddress)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (IUniswapExchange)
 | 
			
		||||
    {
 | 
			
		||||
        return IUniswapExchange(_testExchanges[tokenAddress]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // @dev Use `wethToken`.
 | 
			
		||||
    function getWethContract()
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (IEtherToken)
 | 
			
		||||
    {
 | 
			
		||||
        return IEtherToken(address(wethToken));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // @dev This contract will double as the Uniswap contract.
 | 
			
		||||
    function getUniswapExchangeFactoryContract()
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (IUniswapExchangeFactory)
 | 
			
		||||
    {
 | 
			
		||||
        return IUniswapExchangeFactory(address(this));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-asset-proxy",
 | 
			
		||||
    "version": "2.3.0-beta.0",
 | 
			
		||||
    "version": "2.3.0-beta.2",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "build": "yarn pre_build && tsc -b",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
 | 
			
		||||
        "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",
 | 
			
		||||
@@ -21,21 +21,23 @@
 | 
			
		||||
        "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} --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",
 | 
			
		||||
        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/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",
 | 
			
		||||
        "contracts:gen": "contracts-gen generate",
 | 
			
		||||
        "contracts:copy": "contracts-gen copy",
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
 | 
			
		||||
        "compile:truffle": "truffle compile"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IERC20Bridge|IEth2Dai|IWallet|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestStaticCallTarget).json",
 | 
			
		||||
        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,TestStaticCallTarget",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IERC20Bridge|IEth2Dai|IUniswapExchange|IUniswapExchangeFactory|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -48,12 +50,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^4.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@0x/abi-gen": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.2",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.2",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/tslint-config": "^3.1.0-beta.2",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.2",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -61,6 +65,7 @@
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
        "dirty-chai": "^2.0.1",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "make-promises-safe": "^1.1.0",
 | 
			
		||||
        "mocha": "^6.2.0",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
@@ -71,18 +76,16 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.0",
 | 
			
		||||
        "@0x/order-utils": "^8.5.0-beta.0",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.0",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.0",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.0",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.2",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^0.1.0-beta.2",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.2.0-beta.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.3.0-beta.2",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.2.0-beta.2",
 | 
			
		||||
        "@0x/order-utils": "^8.5.0-beta.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.2",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.2",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.2",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,38 +12,20 @@ import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
 | 
			
		||||
import * as Eth2DaiBridge from '../generated-artifacts/Eth2DaiBridge.json';
 | 
			
		||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
 | 
			
		||||
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
 | 
			
		||||
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
 | 
			
		||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
 | 
			
		||||
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
 | 
			
		||||
import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json';
 | 
			
		||||
import * as IWallet from '../generated-artifacts/IWallet.json';
 | 
			
		||||
import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json';
 | 
			
		||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
 | 
			
		||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
import * as Ownable from '../generated-artifacts/Ownable.json';
 | 
			
		||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
 | 
			
		||||
import * as TestERC20Bridge from '../generated-artifacts/TestERC20Bridge.json';
 | 
			
		||||
import * as TestEth2DaiBridge from '../generated-artifacts/TestEth2DaiBridge.json';
 | 
			
		||||
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
 | 
			
		||||
import * as UniswapBridge from '../generated-artifacts/UniswapBridge.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
    Ownable: Ownable as ContractArtifact,
 | 
			
		||||
    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
			
		||||
    ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact,
 | 
			
		||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
			
		||||
    ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact,
 | 
			
		||||
    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
			
		||||
    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
			
		||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
			
		||||
    IWallet: IWallet as ContractArtifact,
 | 
			
		||||
    TestERC20Bridge: TestERC20Bridge as ContractArtifact,
 | 
			
		||||
    TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
 | 
			
		||||
    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
			
		||||
    TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
    constants,
 | 
			
		||||
@@ -7,13 +8,14 @@ import {
 | 
			
		||||
    LogDecoder,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC1155ProxyContract, IAssetProxyContract } from '../../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC1155ProxyContract, IAssetProxyContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
export class ERC1155ProxyWrapper {
 | 
			
		||||
    private readonly _tokenOwnerAddresses: string[];
 | 
			
		||||
@@ -26,6 +28,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
    private readonly _logDecoder: LogDecoder;
 | 
			
		||||
    private readonly _dummyTokenWrappers: Erc1155Wrapper[];
 | 
			
		||||
    private readonly _assetProxyInterface: IAssetProxyContract;
 | 
			
		||||
    private readonly _devUtils: DevUtilsContract;
 | 
			
		||||
    private _proxyContract?: ERC1155ProxyContract;
 | 
			
		||||
    private _proxyIdIfExists?: string;
 | 
			
		||||
    private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
 | 
			
		||||
@@ -37,6 +40,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
 | 
			
		||||
        this._dummyTokenWrappers = [];
 | 
			
		||||
        this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._fungibleTokenIds = [];
 | 
			
		||||
@@ -72,7 +76,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId().callAsync();
 | 
			
		||||
        return this._proxyContract;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
@@ -95,7 +99,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
     * @param extraData extra data to append to `transferFrom` transaction. Optional.
 | 
			
		||||
     * @return abi encoded tx data.
 | 
			
		||||
     */
 | 
			
		||||
    public getTransferFromAbiEncodedTxData(
 | 
			
		||||
    public async getTransferFromAbiEncodedTxDataAsync(
 | 
			
		||||
        from: string,
 | 
			
		||||
        to: string,
 | 
			
		||||
        contractAddress: string,
 | 
			
		||||
@@ -105,23 +109,17 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        assetData_?: string,
 | 
			
		||||
    ): string {
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                      contractAddress,
 | 
			
		||||
                      tokensToTransfer,
 | 
			
		||||
                      valuesToTransfer,
 | 
			
		||||
                      receiverCallbackData,
 | 
			
		||||
                  )
 | 
			
		||||
                ? await this._devUtils
 | 
			
		||||
                      .encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .callAsync()
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
            assetData,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            valueMultiplier,
 | 
			
		||||
        );
 | 
			
		||||
        const data = this._assetProxyInterface
 | 
			
		||||
            .transferFrom(assetData, from, to, valueMultiplier)
 | 
			
		||||
            .getABIEncodedTransactionData();
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
@@ -169,19 +167,13 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                      contractAddress,
 | 
			
		||||
                      tokensToTransfer,
 | 
			
		||||
                      valuesToTransfer,
 | 
			
		||||
                      receiverCallbackData,
 | 
			
		||||
                  )
 | 
			
		||||
                ? await this._devUtils
 | 
			
		||||
                      .encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .callAsync()
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
            assetData,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            valueMultiplier,
 | 
			
		||||
        );
 | 
			
		||||
        const data = this._assetProxyInterface
 | 
			
		||||
            .transferFrom(assetData, from, to, valueMultiplier)
 | 
			
		||||
            .getABIEncodedTransactionData();
 | 
			
		||||
        const txHash = await this._web3Wrapper.sendTransactionAsync({
 | 
			
		||||
            to: (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
            data,
 | 
			
		||||
@@ -362,7 +354,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const tokenContract = this._getContractFromAddress(contractAddress);
 | 
			
		||||
        const operator = (this._proxyContract as ERC1155ProxyContract).address;
 | 
			
		||||
        const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
 | 
			
		||||
        const didApproveAll = await tokenContract.isApprovedForAll(userAddress, operator).callAsync();
 | 
			
		||||
        return didApproveAll;
 | 
			
		||||
    }
 | 
			
		||||
    public getFungibleTokenIds(): BigNumber[] {
 | 
			
		||||
@@ -1,17 +1,20 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { ZeroExProvider } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC20ProxyContract } from '../../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC20ProxyContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
export class ERC20Wrapper {
 | 
			
		||||
    private readonly _tokenOwnerAddresses: string[];
 | 
			
		||||
    private readonly _contractOwnerAddress: string;
 | 
			
		||||
    private readonly _provider: ZeroExProvider;
 | 
			
		||||
    private readonly _dummyTokenContracts: DummyERC20TokenContract[];
 | 
			
		||||
    private readonly _devUtils: DevUtilsContract;
 | 
			
		||||
    private _proxyContract?: ERC20ProxyContract;
 | 
			
		||||
    private _proxyIdIfExists?: string;
 | 
			
		||||
    /**
 | 
			
		||||
@@ -26,6 +29,7 @@ export class ERC20Wrapper {
 | 
			
		||||
        this._provider = provider;
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
    }
 | 
			
		||||
    public async deployDummyTokensAsync(
 | 
			
		||||
        numberToDeploy: number,
 | 
			
		||||
@@ -54,7 +58,7 @@ export class ERC20Wrapper {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId().callAsync();
 | 
			
		||||
        return this._proxyContract;
 | 
			
		||||
    }
 | 
			
		||||
    public getProxyId(): string {
 | 
			
		||||
@@ -66,50 +70,39 @@ export class ERC20Wrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        for (const dummyTokenContract of this._dummyTokenContracts) {
 | 
			
		||||
            for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
			
		||||
                await dummyTokenContract.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenOwnerAddress,
 | 
			
		||||
                    constants.INITIAL_ERC20_BALANCE,
 | 
			
		||||
                    { from: this._contractOwnerAddress },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                await dummyTokenContract.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
                    (this._proxyContract as ERC20ProxyContract).address,
 | 
			
		||||
                    constants.INITIAL_ERC20_ALLOWANCE,
 | 
			
		||||
                    { from: tokenOwnerAddress },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                await dummyTokenContract
 | 
			
		||||
                    .setBalance(tokenOwnerAddress, constants.INITIAL_ERC20_BALANCE)
 | 
			
		||||
                    .awaitTransactionSuccessAsync({ from: this._contractOwnerAddress });
 | 
			
		||||
                await dummyTokenContract
 | 
			
		||||
                    .approve((this._proxyContract as ERC20ProxyContract).address, constants.INITIAL_ERC20_ALLOWANCE)
 | 
			
		||||
                    .awaitTransactionSuccessAsync({ from: tokenOwnerAddress });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(assetData);
 | 
			
		||||
        const balance = new BigNumber(await tokenContract.balanceOf.callAsync(userAddress));
 | 
			
		||||
        const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
 | 
			
		||||
        const balance = new BigNumber(await tokenContract.balanceOf(userAddress).callAsync());
 | 
			
		||||
        return balance;
 | 
			
		||||
    }
 | 
			
		||||
    public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(assetData);
 | 
			
		||||
        await tokenContract.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
            userAddress,
 | 
			
		||||
            amount,
 | 
			
		||||
            { from: this._contractOwnerAddress },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
 | 
			
		||||
        await tokenContract
 | 
			
		||||
            .setBalance(userAddress, amount)
 | 
			
		||||
            .awaitTransactionSuccessAsync(
 | 
			
		||||
                { from: this._contractOwnerAddress },
 | 
			
		||||
                { pollingIntervalMs: constants.AWAIT_TRANSACTION_MINED_MS },
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
    public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(assetData);
 | 
			
		||||
        const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
 | 
			
		||||
        const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
 | 
			
		||||
        const allowance = new BigNumber(await tokenContract.allowance.callAsync(userAddress, proxyAddress));
 | 
			
		||||
        const allowance = new BigNumber(await tokenContract.allowance(userAddress, proxyAddress).callAsync());
 | 
			
		||||
        return allowance;
 | 
			
		||||
    }
 | 
			
		||||
    public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(assetData);
 | 
			
		||||
        const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
 | 
			
		||||
        const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
 | 
			
		||||
        await tokenContract.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
            proxyAddress,
 | 
			
		||||
            amount,
 | 
			
		||||
            { from: userAddress },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.approve(proxyAddress, amount).awaitTransactionSuccessAsync({ from: userAddress });
 | 
			
		||||
    }
 | 
			
		||||
    public async getBalancesAsync(): Promise<ERC20BalancesByOwner> {
 | 
			
		||||
        this._validateDummyTokenContractsExistOrThrow();
 | 
			
		||||
@@ -118,7 +111,7 @@ export class ERC20Wrapper {
 | 
			
		||||
        const balanceInfo: Array<{ tokenOwnerAddress: string; tokenAddress: string }> = [];
 | 
			
		||||
        for (const dummyTokenContract of this._dummyTokenContracts) {
 | 
			
		||||
            for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
			
		||||
                balances.push(await dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
 | 
			
		||||
                balances.push(await dummyTokenContract.balanceOf(tokenOwnerAddress).callAsync());
 | 
			
		||||
                balanceInfo.push({
 | 
			
		||||
                    tokenOwnerAddress,
 | 
			
		||||
                    tokenAddress: dummyTokenContract.address,
 | 
			
		||||
@@ -151,9 +144,8 @@ export class ERC20Wrapper {
 | 
			
		||||
        const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
 | 
			
		||||
        return tokenAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    private _getTokenContractFromAssetData(assetData: string): DummyERC20TokenContract {
 | 
			
		||||
        const erc20ProxyData = assetDataUtils.decodeERC20AssetData(assetData);
 | 
			
		||||
        const tokenAddress = erc20ProxyData.tokenAddress;
 | 
			
		||||
    private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
 | 
			
		||||
        const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData(assetData).callAsync(); // tslint:disable-line:no-unused-variable
 | 
			
		||||
        const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
 | 
			
		||||
        if (tokenContractIfExists === undefined) {
 | 
			
		||||
            throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);
 | 
			
		||||
@@ -5,7 +5,9 @@ import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { ZeroExProvider } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC721ProxyContract } from '../../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC721ProxyContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
export class ERC721Wrapper {
 | 
			
		||||
    private readonly _tokenOwnerAddresses: string[];
 | 
			
		||||
@@ -44,7 +46,7 @@ export class ERC721Wrapper {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId().callAsync();
 | 
			
		||||
        return this._proxyContract;
 | 
			
		||||
    }
 | 
			
		||||
    public getProxyId(): string {
 | 
			
		||||
@@ -78,7 +80,7 @@ export class ERC721Wrapper {
 | 
			
		||||
    }
 | 
			
		||||
    public async doesTokenExistAsync(tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const owner = await tokenContract.ownerOf.callAsync(tokenId);
 | 
			
		||||
        const owner = await tokenContract.ownerOf(tokenId).callAsync();
 | 
			
		||||
        const doesExist = owner !== constants.NULL_ADDRESS;
 | 
			
		||||
        return doesExist;
 | 
			
		||||
    }
 | 
			
		||||
@@ -93,22 +95,14 @@ export class ERC721Wrapper {
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
 | 
			
		||||
        await tokenContract.setApprovalForAll.awaitTransactionSuccessAsync(
 | 
			
		||||
            proxyAddress,
 | 
			
		||||
            isApproved,
 | 
			
		||||
            { from: ownerAddress },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.setApprovalForAll(proxyAddress, isApproved).awaitTransactionSuccessAsync({
 | 
			
		||||
            from: ownerAddress,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public async approveAsync(to: string, tokenAddress: string, tokenId: BigNumber): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const tokenOwner = await this.ownerOfAsync(tokenAddress, tokenId);
 | 
			
		||||
        await tokenContract.approve.awaitTransactionSuccessAsync(
 | 
			
		||||
            to,
 | 
			
		||||
            tokenId,
 | 
			
		||||
            { from: tokenOwner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.approve(to, tokenId).awaitTransactionSuccessAsync({ from: tokenOwner });
 | 
			
		||||
    }
 | 
			
		||||
    public async transferFromAsync(
 | 
			
		||||
        tokenAddress: string,
 | 
			
		||||
@@ -117,40 +111,28 @@ export class ERC721Wrapper {
 | 
			
		||||
        userAddress: string,
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        await tokenContract.transferFrom.awaitTransactionSuccessAsync(
 | 
			
		||||
            currentOwner,
 | 
			
		||||
            userAddress,
 | 
			
		||||
            tokenId,
 | 
			
		||||
            { from: currentOwner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.transferFrom(currentOwner, userAddress, tokenId).awaitTransactionSuccessAsync({
 | 
			
		||||
            from: currentOwner,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public async mintAsync(tokenAddress: string, tokenId: BigNumber, userAddress: string): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        await tokenContract.mint.awaitTransactionSuccessAsync(
 | 
			
		||||
            userAddress,
 | 
			
		||||
            tokenId,
 | 
			
		||||
            { from: this._contractOwnerAddress },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.mint(userAddress, tokenId).awaitTransactionSuccessAsync({
 | 
			
		||||
            from: this._contractOwnerAddress,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public async burnAsync(tokenAddress: string, tokenId: BigNumber, owner: string): Promise<void> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        await tokenContract.burn.awaitTransactionSuccessAsync(
 | 
			
		||||
            owner,
 | 
			
		||||
            tokenId,
 | 
			
		||||
            { from: this._contractOwnerAddress },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await tokenContract.burn(owner, tokenId).awaitTransactionSuccessAsync({ from: this._contractOwnerAddress });
 | 
			
		||||
    }
 | 
			
		||||
    public async ownerOfAsync(tokenAddress: string, tokenId: BigNumber): Promise<string> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const owner = await tokenContract.ownerOf.callAsync(tokenId);
 | 
			
		||||
        const owner = await tokenContract.ownerOf(tokenId).callAsync();
 | 
			
		||||
        return owner;
 | 
			
		||||
    }
 | 
			
		||||
    public async isOwnerAsync(userAddress: string, tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId);
 | 
			
		||||
        const tokenOwner = await tokenContract.ownerOf(tokenId).callAsync();
 | 
			
		||||
        const isOwner = tokenOwner === userAddress;
 | 
			
		||||
        return isOwner;
 | 
			
		||||
    }
 | 
			
		||||
@@ -158,13 +140,13 @@ export class ERC721Wrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const operator = (this._proxyContract as ERC721ProxyContract).address;
 | 
			
		||||
        const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
 | 
			
		||||
        const didApproveAll = await tokenContract.isApprovedForAll(userAddress, operator).callAsync();
 | 
			
		||||
        return didApproveAll;
 | 
			
		||||
    }
 | 
			
		||||
    public async isProxyApprovedAsync(tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
			
		||||
        const approvedAddress = await tokenContract.getApproved.callAsync(tokenId);
 | 
			
		||||
        const approvedAddress = await tokenContract.getApproved(tokenId).callAsync();
 | 
			
		||||
        const proxyAddress = (this._proxyContract as ERC721ProxyContract).address;
 | 
			
		||||
        const isProxyAnApprovedOperator = approvedAddress === proxyAddress;
 | 
			
		||||
        return isProxyAnApprovedOperator;
 | 
			
		||||
@@ -181,7 +163,7 @@ export class ERC721Wrapper {
 | 
			
		||||
                    dummyTokenContract.address
 | 
			
		||||
                ];
 | 
			
		||||
                for (const tokenId of initialTokenOwnerIds) {
 | 
			
		||||
                    tokenOwnerAddresses.push(await dummyTokenContract.ownerOf.callAsync(tokenId));
 | 
			
		||||
                    tokenOwnerAddresses.push(await dummyTokenContract.ownerOf(tokenId).callAsync());
 | 
			
		||||
                    tokenInfo.push({
 | 
			
		||||
                        tokenId,
 | 
			
		||||
                        tokenAddress: dummyTokenContract.address,
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
export * from './artifacts';
 | 
			
		||||
export * from './wrappers';
 | 
			
		||||
export * from '../test/utils';
 | 
			
		||||
 | 
			
		||||
export { ERC20Wrapper } from './erc20_wrapper';
 | 
			
		||||
export { ERC721Wrapper } from './erc721_wrapper';
 | 
			
		||||
export { ERC1155ProxyWrapper } from './erc1155_proxy_wrapper';
 | 
			
		||||
 
 | 
			
		||||
@@ -10,16 +10,7 @@ export * from '../generated-wrappers/erc721_proxy';
 | 
			
		||||
export * from '../generated-wrappers/eth2_dai_bridge';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_data';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_proxy';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../generated-wrappers/i_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/i_erc20_bridge';
 | 
			
		||||
export * from '../generated-wrappers/i_eth2_dai';
 | 
			
		||||
export * from '../generated-wrappers/i_wallet';
 | 
			
		||||
export * from '../generated-wrappers/mixin_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../generated-wrappers/mixin_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/multi_asset_proxy';
 | 
			
		||||
export * from '../generated-wrappers/ownable';
 | 
			
		||||
export * from '../generated-wrappers/static_call_proxy';
 | 
			
		||||
export * from '../generated-wrappers/test_erc20_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_eth2_dai_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_static_call_target';
 | 
			
		||||
export * from '../generated-wrappers/uniswap_bridge';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								contracts/asset-proxy/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								contracts/asset-proxy/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
 | 
			
		||||
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
 | 
			
		||||
import * as ERC20Proxy from '../test/generated-artifacts/ERC20Proxy.json';
 | 
			
		||||
import * as ERC721Proxy from '../test/generated-artifacts/ERC721Proxy.json';
 | 
			
		||||
import * as Eth2DaiBridge from '../test/generated-artifacts/Eth2DaiBridge.json';
 | 
			
		||||
import * as IAssetData from '../test/generated-artifacts/IAssetData.json';
 | 
			
		||||
import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
 | 
			
		||||
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
 | 
			
		||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
 | 
			
		||||
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
			
		||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
			
		||||
import * as IUniswapExchange from '../test/generated-artifacts/IUniswapExchange.json';
 | 
			
		||||
import * as IUniswapExchangeFactory from '../test/generated-artifacts/IUniswapExchangeFactory.json';
 | 
			
		||||
import * as MixinAssetProxyDispatcher from '../test/generated-artifacts/MixinAssetProxyDispatcher.json';
 | 
			
		||||
import * as MixinAuthorizable from '../test/generated-artifacts/MixinAuthorizable.json';
 | 
			
		||||
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
import * as Ownable from '../test/generated-artifacts/Ownable.json';
 | 
			
		||||
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
 | 
			
		||||
import * as TestERC20Bridge from '../test/generated-artifacts/TestERC20Bridge.json';
 | 
			
		||||
import * as TestEth2DaiBridge from '../test/generated-artifacts/TestEth2DaiBridge.json';
 | 
			
		||||
import * as TestStaticCallTarget from '../test/generated-artifacts/TestStaticCallTarget.json';
 | 
			
		||||
import * as TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridge.json';
 | 
			
		||||
import * as UniswapBridge from '../test/generated-artifacts/UniswapBridge.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
    Ownable: Ownable as ContractArtifact,
 | 
			
		||||
    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
			
		||||
    ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact,
 | 
			
		||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
			
		||||
    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
			
		||||
    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
			
		||||
    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
			
		||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
			
		||||
    IUniswapExchange: IUniswapExchange as ContractArtifact,
 | 
			
		||||
    IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact,
 | 
			
		||||
    TestERC20Bridge: TestERC20Bridge as ContractArtifact,
 | 
			
		||||
    TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
 | 
			
		||||
    TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
 | 
			
		||||
    TestUniswapBridge: TestUniswapBridge as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,18 +1,13 @@
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectTransactionFailedAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { chaiSetup, expectTransactionFailedAsync, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, MixinAuthorizableContract } from '../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { MixinAuthorizableContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
@@ -54,29 +49,21 @@ describe('Authorizable', () => {
 | 
			
		||||
    describe('addAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner }),
 | 
			
		||||
                authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to add an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isAuthorized = await authorizable.authorized.callAsync(address);
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to authorize a duplicate address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
 | 
			
		||||
                authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                RevertReason.TargetAlreadyAuthorized,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
@@ -84,35 +71,23 @@ describe('Authorizable', () => {
 | 
			
		||||
 | 
			
		||||
    describe('removeAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { from: notOwner }),
 | 
			
		||||
                authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isAuthorized = await authorizable.authorized.callAsync(address);
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
 | 
			
		||||
                authorizable.removeAuthorizedAddress(address).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.TargetNotAuthorized,
 | 
			
		||||
@@ -122,14 +97,10 @@ describe('Authorizable', () => {
 | 
			
		||||
 | 
			
		||||
    describe('removeAuthorizedAddressAtIndex', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: notOwner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
@@ -137,14 +108,10 @@ describe('Authorizable', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if index is >= authorities.length', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(1);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.IndexOutOfBounds,
 | 
			
		||||
@@ -154,7 +121,7 @@ describe('Authorizable', () => {
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.TargetNotAuthorized,
 | 
			
		||||
@@ -164,19 +131,11 @@ describe('Authorizable', () => {
 | 
			
		||||
        it('should revert if address at index does not match target', async () => {
 | 
			
		||||
            const address1 = address;
 | 
			
		||||
            const address2 = notOwner;
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address1,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address2,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const address1Index = new BigNumber(0);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address2, address1Index, {
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address2, address1Index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.AuthorizedAddressMismatch,
 | 
			
		||||
@@ -184,41 +143,26 @@ describe('Authorizable', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                index,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const isAuthorized = await authorizable.authorized.callAsync(address);
 | 
			
		||||
            await authorizable.removeAuthorizedAddressAtIndex(address, index).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getAuthorizedAddresses', () => {
 | 
			
		||||
        it('should return all authorized addresses', async () => {
 | 
			
		||||
            const initial = await authorizable.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            const initial = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(initial).to.have.length(0);
 | 
			
		||||
            await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const afterAdd = await authorizable.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const afterAdd = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(afterAdd).to.have.length(1);
 | 
			
		||||
            expect(afterAdd).to.include(address);
 | 
			
		||||
            await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
                address,
 | 
			
		||||
                { from: owner },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const afterRemove = await authorizable.getAuthorizedAddresses.callAsync();
 | 
			
		||||
            await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const afterRemove = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(afterRemove).to.have.length(0);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc1155Artifacts,
 | 
			
		||||
    DummyERC1155ReceiverBatchTokenReceivedEventArgs,
 | 
			
		||||
@@ -14,16 +15,19 @@ import {
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { SafeMathRevertErrors } from '@0x/contracts-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { AssetProxyId, RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC1155ProxyContract, ERC1155ProxyWrapper } from '../src';
 | 
			
		||||
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
 | 
			
		||||
import { ERC1155ProxyContract, IAssetDataContract } from '../src/wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
@@ -59,6 +63,8 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
    // tokens
 | 
			
		||||
    let fungibleTokens: BigNumber[];
 | 
			
		||||
    let nonFungibleTokensOwnedBySpender: BigNumber[];
 | 
			
		||||
    // devUtils for encoding and decoding assetData
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    // tests
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
@@ -72,16 +78,8 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
        const usedAddresses = ([owner, notAuthorized, authorized, spender, receiver] = _.slice(accounts, 0, 5));
 | 
			
		||||
        erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner);
 | 
			
		||||
        erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync();
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
            authorized,
 | 
			
		||||
            { from: owner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | 
			
		||||
            erc1155Proxy.address,
 | 
			
		||||
            { from: owner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress(authorized).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
        await erc1155Proxy.addAuthorizedAddress(erc1155Proxy.address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
        // deploy & configure ERC1155 tokens and receiver
 | 
			
		||||
        [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync();
 | 
			
		||||
        erc1155Contract = erc1155Wrapper.getContract();
 | 
			
		||||
@@ -103,6 +101,8 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
                tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
 | 
			
		||||
            nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
 | 
			
		||||
        });
 | 
			
		||||
        // set up devUtils
 | 
			
		||||
        devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, { from: owner });
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
@@ -123,7 +123,7 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should have an id of 0xa7cb5fb7', async () => {
 | 
			
		||||
            const proxyId = await erc1155Proxy.getProxyId.callAsync();
 | 
			
		||||
            const proxyId = await erc1155Proxy.getProxyId().callAsync();
 | 
			
		||||
            const expectedProxyId = AssetProxyId.ERC1155;
 | 
			
		||||
            expect(proxyId).to.equal(expectedProxyId);
 | 
			
		||||
        });
 | 
			
		||||
@@ -638,12 +638,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const extraData = '0102030405060708091001020304050607080910010203040506070809100102';
 | 
			
		||||
            const assetDataWithExtraData = `${assetData}${extraData}`;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
@@ -696,25 +698,20 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const tokenUri = '';
 | 
			
		||||
            for (const tokenToCreate of tokensToCreate) {
 | 
			
		||||
                // create token
 | 
			
		||||
                await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    tokenUri,
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .createWithType(tokenToCreate, tokenUri)
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                // mint balance for spender
 | 
			
		||||
                await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    [spender],
 | 
			
		||||
                    [spenderInitialBalance],
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .mintFungible(tokenToCreate, [spender], [spenderInitialBalance])
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
            }
 | 
			
		||||
            ///// Step 2/5 /////
 | 
			
		||||
            // Check balances before transfer
 | 
			
		||||
@@ -747,18 +744,16 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const tokensToTransfer = [new BigNumber(1), new BigNumber(2)];
 | 
			
		||||
            const valuesToTransfer = tokensToTransfer;
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            // remove the function selector and contract address from check, as these change on each test
 | 
			
		||||
            const offsetToTokenIds = 74;
 | 
			
		||||
            const assetDataWithoutContractAddress = assetData.substr(offsetToTokenIds);
 | 
			
		||||
            const expectedAssetDataWithoutContractAddress =
 | 
			
		||||
 | 
			
		||||
            // hand encode optimized assetData because our tooling (based on LibAssetData.sol/encodeERC1155AssetData) does not use optimized encoding
 | 
			
		||||
            const assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
            const selector = assetDataContract.getSelector('ERC1155Assets');
 | 
			
		||||
            const assetDataWithoutContractAddress =
 | 
			
		||||
                '0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000';
 | 
			
		||||
            expect(assetDataWithoutContractAddress).to.be.equal(expectedAssetDataWithoutContractAddress);
 | 
			
		||||
            const assetData = `${selector}000000000000000000000000${erc1155ContractAddress.substr(
 | 
			
		||||
                2,
 | 
			
		||||
            )}${assetDataWithoutContractAddress}`;
 | 
			
		||||
 | 
			
		||||
            ///// Step 4/5 /////
 | 
			
		||||
            // Transfer token IDs [1, 2] and amounts [1, 2] with a multiplier of 2;
 | 
			
		||||
            // the expected trade will be token IDs [1, 2] and amounts [2, 4]
 | 
			
		||||
@@ -805,25 +800,20 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const tokenUri = '';
 | 
			
		||||
            for (const tokenToCreate of tokensToCreate) {
 | 
			
		||||
                // create token
 | 
			
		||||
                await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    tokenUri,
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .createWithType(tokenToCreate, tokenUri)
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                // mint balance for spender
 | 
			
		||||
                await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    [spender],
 | 
			
		||||
                    [spenderInitialBalance],
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .mintFungible(tokenToCreate, [spender], [spenderInitialBalance])
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
            }
 | 
			
		||||
            ///// Step 2/5 /////
 | 
			
		||||
            // Check balances before transfer
 | 
			
		||||
@@ -867,12 +857,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [new BigNumber(2), new BigNumber(2)];
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
            // create callback data that is the encoded version of `valuesToTransfer`
 | 
			
		||||
            const generatedAssetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const generatedAssetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // remove the function selector and contract address from check, as these change on each test
 | 
			
		||||
            const offsetToTokenIds = 74;
 | 
			
		||||
            const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
 | 
			
		||||
@@ -937,25 +929,20 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const tokenUri = '';
 | 
			
		||||
            for (const tokenToCreate of tokensToCreate) {
 | 
			
		||||
                // create token
 | 
			
		||||
                await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    tokenUri,
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .createWithType(tokenToCreate, tokenUri)
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                // mint balance for spender
 | 
			
		||||
                await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
                    tokenToCreate,
 | 
			
		||||
                    [spender],
 | 
			
		||||
                    [spenderInitialBalance],
 | 
			
		||||
                    {
 | 
			
		||||
                await erc1155Wrapper
 | 
			
		||||
                    .getContract()
 | 
			
		||||
                    .mintFungible(tokenToCreate, [spender], [spenderInitialBalance])
 | 
			
		||||
                    .awaitTransactionSuccessAsync({
 | 
			
		||||
                        from: owner,
 | 
			
		||||
                    },
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
            }
 | 
			
		||||
            ///// Step 2/5 /////
 | 
			
		||||
            // Check balances before transfer
 | 
			
		||||
@@ -996,12 +983,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [new BigNumber(1), new BigNumber(2)];
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
            // create callback data that is the encoded version of `valuesToTransfer`
 | 
			
		||||
            const generatedAssetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const generatedAssetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // remove the function selector and contract address from check, as these change on each test
 | 
			
		||||
            const offsetToTokenIds = 74;
 | 
			
		||||
            const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
 | 
			
		||||
@@ -1059,12 +1048,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1106,12 +1097,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1157,12 +1150,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1208,12 +1203,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1259,12 +1256,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1311,12 +1310,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1358,12 +1359,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1409,12 +1412,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1456,12 +1461,14 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1507,13 +1514,15 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData(
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
@@ -1538,13 +1547,15 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
                erc1155ContractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
            );
 | 
			
		||||
            const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData(
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
@@ -1667,13 +1678,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
        it('should propagate revert reason from erc1155 contract failure', async () => {
 | 
			
		||||
            // disable transfers
 | 
			
		||||
            const shouldRejectTransfer = true;
 | 
			
		||||
            await erc1155Receiver.setRejectTransferFlag.awaitTransactionSuccessAsync(
 | 
			
		||||
                shouldRejectTransfer,
 | 
			
		||||
                {
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                },
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await erc1155Receiver.setRejectTransferFlag(shouldRejectTransfer).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiverContract];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,17 +9,15 @@ import {
 | 
			
		||||
    Numberish,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { AuthorizableRevertErrors } from '@0x/contracts-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { AbiEncoder, AuthorizableRevertErrors, BigNumber, StringRevertError } from '@0x/utils';
 | 
			
		||||
import { AbiEncoder, BigNumber, StringRevertError } from '@0x/utils';
 | 
			
		||||
import { DecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts,
 | 
			
		||||
    ERC20BridgeProxyContract,
 | 
			
		||||
    TestERC20BridgeBridgeWithdrawToEventArgs,
 | 
			
		||||
    TestERC20BridgeContract,
 | 
			
		||||
} from '../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC20BridgeProxyContract, TestERC20BridgeContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
    const PROXY_ID = AssetProxyId.ERC20Bridge;
 | 
			
		||||
@@ -44,8 +42,8 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        testTokenAddress = await bridgeContract.testToken.callAsync();
 | 
			
		||||
        await assetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(owner);
 | 
			
		||||
        testTokenAddress = await bridgeContract.testToken().callAsync();
 | 
			
		||||
        await assetProxy.addAuthorizedAddress(owner).awaitTransactionSuccessAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    interface AssetDataOpts {
 | 
			
		||||
@@ -102,7 +100,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async function setTestTokenBalanceAsync(_owner: string, balance: Numberish): Promise<void> {
 | 
			
		||||
        await bridgeContract.setTestTokenBalance.awaitTransactionSuccessAsync(_owner, new BigNumber(balance));
 | 
			
		||||
        await bridgeContract.setTestTokenBalance(_owner, new BigNumber(balance)).awaitTransactionSuccessAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    describe('transferFrom()', () => {
 | 
			
		||||
@@ -132,13 +130,9 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
 | 
			
		||||
        async function transferFromAsync(opts?: Partial<TransferFromOpts>, caller?: string): Promise<DecodedLogs> {
 | 
			
		||||
            const _opts = createTransferFromOpts(opts);
 | 
			
		||||
            const { logs } = await assetProxy.transferFrom.awaitTransactionSuccessAsync(
 | 
			
		||||
                encodeAssetData(_opts.assetData),
 | 
			
		||||
                _opts.from,
 | 
			
		||||
                _opts.to,
 | 
			
		||||
                new BigNumber(_opts.amount),
 | 
			
		||||
                { from: caller },
 | 
			
		||||
            );
 | 
			
		||||
            const { logs } = await assetProxy
 | 
			
		||||
                .transferFrom(encodeAssetData(_opts.assetData), _opts.from, _opts.to, new BigNumber(_opts.amount))
 | 
			
		||||
                .awaitTransactionSuccessAsync({ from: caller });
 | 
			
		||||
            return (logs as any) as DecodedLogs;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -164,7 +158,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
            const opts = createTransferFromOpts();
 | 
			
		||||
            const logs = await transferFromAsync(opts);
 | 
			
		||||
            expect(logs.length).to.eq(1);
 | 
			
		||||
            const args = logs[0].args as TestERC20BridgeBridgeWithdrawToEventArgs;
 | 
			
		||||
            const args = logs[0].args;
 | 
			
		||||
            expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress);
 | 
			
		||||
            expect(args.from).to.eq(opts.from);
 | 
			
		||||
            expect(args.to).to.eq(opts.to);
 | 
			
		||||
@@ -180,12 +174,9 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
        it('fails if asset data is truncated', async () => {
 | 
			
		||||
            const opts = createTransferFromOpts();
 | 
			
		||||
            const truncatedAssetData = hexSlice(encodeAssetData(opts.assetData), 0, -1);
 | 
			
		||||
            const tx = assetProxy.transferFrom.awaitTransactionSuccessAsync(
 | 
			
		||||
                truncatedAssetData,
 | 
			
		||||
                opts.from,
 | 
			
		||||
                opts.to,
 | 
			
		||||
                new BigNumber(opts.amount),
 | 
			
		||||
            );
 | 
			
		||||
            const tx = assetProxy
 | 
			
		||||
                .transferFrom(truncatedAssetData, opts.from, opts.to, new BigNumber(opts.amount))
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.be.rejected();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -281,18 +272,18 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
 | 
			
		||||
        it('retrieves the balance of the encoded token', async () => {
 | 
			
		||||
            const _owner = randomAddress();
 | 
			
		||||
            const balance = getRandomInteger(1, 100e18);
 | 
			
		||||
            await bridgeContract.setTestTokenBalance.awaitTransactionSuccessAsync(_owner, balance);
 | 
			
		||||
            await bridgeContract.setTestTokenBalance(_owner, balance).awaitTransactionSuccessAsync();
 | 
			
		||||
            const assetData = createAssetData({
 | 
			
		||||
                tokenAddress: testTokenAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const actualBalance = await assetProxy.balanceOf.callAsync(encodeAssetData(assetData), _owner);
 | 
			
		||||
            const actualBalance = await assetProxy.balanceOf(encodeAssetData(assetData), _owner).callAsync();
 | 
			
		||||
            expect(actualBalance).to.bignumber.eq(balance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getProxyId()', () => {
 | 
			
		||||
        it('returns the correct proxy ID', async () => {
 | 
			
		||||
            const proxyId = await assetProxy.getProxyId.callAsync();
 | 
			
		||||
            const proxyId = await assetProxy.getProxyId().callAsync();
 | 
			
		||||
            expect(proxyId).to.eq(PROXY_ID);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -8,24 +8,23 @@ import {
 | 
			
		||||
    hexRandom,
 | 
			
		||||
    Numberish,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
    TransactionHelper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { BigNumber, RawRevertError } from '@0x/utils';
 | 
			
		||||
import { DecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts,
 | 
			
		||||
    TestEth2DaiBridgeContract,
 | 
			
		||||
    TestEth2DaiBridgeEvents,
 | 
			
		||||
    TestEth2DaiBridgeSellAllAmountEventArgs,
 | 
			
		||||
    TestEth2DaiBridgeTokenApproveEventArgs,
 | 
			
		||||
    TestEth2DaiBridgeTokenTransferEventArgs,
 | 
			
		||||
} from '../src';
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | 
			
		||||
    const txHelper = new TransactionHelper(env.web3Wrapper, artifacts);
 | 
			
		||||
    let testContract: TestEth2DaiBridgeContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
@@ -40,12 +39,12 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | 
			
		||||
    describe('isValidSignature()', () => {
 | 
			
		||||
        it('returns success bytes', async () => {
 | 
			
		||||
            const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
 | 
			
		||||
            const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32)));
 | 
			
		||||
            const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
 | 
			
		||||
            expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('withdrawTo()', () => {
 | 
			
		||||
    describe('bridgeTransferFrom()', () => {
 | 
			
		||||
        interface WithdrawToOpts {
 | 
			
		||||
            toTokenAddress?: string;
 | 
			
		||||
            fromTokenAddress?: string;
 | 
			
		||||
@@ -80,32 +79,30 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | 
			
		||||
        async function withdrawToAsync(opts?: Partial<WithdrawToOpts>): Promise<WithdrawToResult> {
 | 
			
		||||
            const _opts = createWithdrawToOpts(opts);
 | 
			
		||||
            // Set the fill behavior.
 | 
			
		||||
            await testContract.setFillBehavior.awaitTransactionSuccessAsync(
 | 
			
		||||
                _opts.revertReason,
 | 
			
		||||
                new BigNumber(_opts.fillAmount),
 | 
			
		||||
            );
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setFillBehavior(_opts.revertReason, new BigNumber(_opts.fillAmount))
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            // Create tokens and balances.
 | 
			
		||||
            if (_opts.fromTokenAddress === undefined) {
 | 
			
		||||
                [_opts.fromTokenAddress] = await txHelper.getResultAndReceiptAsync(
 | 
			
		||||
                    testContract.createToken,
 | 
			
		||||
                    new BigNumber(_opts.fromTokenBalance),
 | 
			
		||||
                );
 | 
			
		||||
                const createTokenFn = testContract.createToken(new BigNumber(_opts.fromTokenBalance));
 | 
			
		||||
                _opts.fromTokenAddress = await createTokenFn.callAsync();
 | 
			
		||||
                await createTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            }
 | 
			
		||||
            if (_opts.toTokenAddress === undefined) {
 | 
			
		||||
                [_opts.toTokenAddress] = await txHelper.getResultAndReceiptAsync(
 | 
			
		||||
                    testContract.createToken,
 | 
			
		||||
                    constants.ZERO_AMOUNT,
 | 
			
		||||
                );
 | 
			
		||||
                const createTokenFn = testContract.createToken(constants.ZERO_AMOUNT);
 | 
			
		||||
                _opts.toTokenAddress = await createTokenFn.callAsync();
 | 
			
		||||
                await createTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            }
 | 
			
		||||
            // Set the transfer behavior of `toTokenAddress`.
 | 
			
		||||
            await testContract.setTransferBehavior.awaitTransactionSuccessAsync(
 | 
			
		||||
                _opts.toTokenAddress,
 | 
			
		||||
                _opts.toTokentransferRevertReason,
 | 
			
		||||
                _opts.toTokenTransferReturnData,
 | 
			
		||||
            );
 | 
			
		||||
            // Call withdrawTo().
 | 
			
		||||
            const [result, { logs }] = await txHelper.getResultAndReceiptAsync(
 | 
			
		||||
                testContract.withdrawTo,
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setTransferBehavior(
 | 
			
		||||
                    _opts.toTokenAddress,
 | 
			
		||||
                    _opts.toTokentransferRevertReason,
 | 
			
		||||
                    _opts.toTokenTransferReturnData,
 | 
			
		||||
                )
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            // Call bridgeTransferFrom().
 | 
			
		||||
            const bridgeTransferFromFn = testContract.bridgeTransferFrom(
 | 
			
		||||
                // "to" token address
 | 
			
		||||
                _opts.toTokenAddress,
 | 
			
		||||
                // Random from address.
 | 
			
		||||
@@ -116,6 +113,8 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | 
			
		||||
                // ABI-encode the "from" token address as the bridge data.
 | 
			
		||||
                hexLeftPad(_opts.fromTokenAddress as string),
 | 
			
		||||
            );
 | 
			
		||||
            const result = await bridgeTransferFromFn.callAsync();
 | 
			
		||||
            const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            return {
 | 
			
		||||
                opts: _opts,
 | 
			
		||||
                result,
 | 
			
		||||
@@ -179,14 +178,14 @@ blockchainTests.resets('Eth2DaiBridge unit tests', env => {
 | 
			
		||||
            return expect(tx).to.revertWith(opts.toTokentransferRevertReason);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if `toTokenAddress.transfer()` returns falsey', async () => {
 | 
			
		||||
        it('fails if `toTokenAddress.transfer()` returns false', async () => {
 | 
			
		||||
            const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexLeftPad(0) });
 | 
			
		||||
            const tx = withdrawToAsync(opts);
 | 
			
		||||
            return expect(tx).to.revertWith('ERC20_TRANSFER_FAILED');
 | 
			
		||||
            return expect(tx).to.revertWith(new RawRevertError(hexLeftPad(0)));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if `toTokenAddress.transfer()` returns truthy', async () => {
 | 
			
		||||
            await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(100) });
 | 
			
		||||
        it('succeeds if `toTokenAddress.transfer()` returns true', async () => {
 | 
			
		||||
            await withdrawToAsync({ toTokenTransferReturnData: hexLeftPad(1) });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,3 +1,4 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
@@ -8,13 +9,14 @@ import {
 | 
			
		||||
    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';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
@@ -25,6 +27,7 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
    let fromAddress: string;
 | 
			
		||||
    let toAddress: string;
 | 
			
		||||
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    let staticCallProxy: IAssetProxyContract;
 | 
			
		||||
    let staticCallTarget: TestStaticCallTargetContract;
 | 
			
		||||
 | 
			
		||||
@@ -43,6 +46,7 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        staticCallProxy = new IAssetProxyContract(
 | 
			
		||||
            staticCallProxyWithoutTransferFrom.address,
 | 
			
		||||
            provider,
 | 
			
		||||
@@ -77,26 +81,21 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should have an id of 0xc339d10a', async () => {
 | 
			
		||||
            const proxyId = await staticCallProxy.getProxyId.callAsync();
 | 
			
		||||
            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 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 assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const txData = staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080';
 | 
			
		||||
            const txDataEndBuffer = ethUtil.toBuffer((txData.length - 2) / 2 - 4);
 | 
			
		||||
            const paddedTxDataEndBuffer = ethUtil.setLengthLeft(txDataEndBuffer, 32);
 | 
			
		||||
@@ -114,23 +113,21 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        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
 | 
			
		||||
            const assetData = (await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .slice(0, -128);
 | 
			
		||||
                .callAsync()).slice(0, -128);
 | 
			
		||||
            const assetDataByteLen = (assetData.length - 2) / 2;
 | 
			
		||||
            expect((assetDataByteLen - 4) % 32).to.equal(0);
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
 | 
			
		||||
            const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
 | 
			
		||||
            const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
 | 
			
		||||
@@ -141,90 +138,88 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
                invalidOffsetToStaticCallData,
 | 
			
		||||
            )}${newStaticCallData}`;
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(badAssetData, fromAddress, toAddress, amount),
 | 
			
		||||
                staticCallProxy.transferFrom(badAssetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the callTarget attempts to write to state', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData();
 | 
			
		||||
            const staticCallData = staticCallTarget.updateState().getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber(new BigNumber(1)).getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
                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 staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
                RevertReason.UnexpectedStaticCallResult,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function call with no inputs and no outputs is successful', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
 | 
			
		||||
            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);
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => {
 | 
			
		||||
            const staticCallData = '0x0102030405060708';
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash);
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
        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 staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
 | 
			
		||||
            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);
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should be successful if a function with one dynamic input is successful', async () => {
 | 
			
		||||
            const dynamicInput = '0x0102030405060708';
 | 
			
		||||
            const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput);
 | 
			
		||||
            const staticCallData = staticCallTarget.dynamicInputFunction(dynamicInput).getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = assetDataUtils.encodeStaticCallAssetData(
 | 
			
		||||
                staticCallTarget.address,
 | 
			
		||||
                staticCallData,
 | 
			
		||||
                expectedResultHash,
 | 
			
		||||
            );
 | 
			
		||||
            await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
        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 staticCallData = staticCallTarget.returnComplexType(a, b).getABIEncodedTransactionData();
 | 
			
		||||
            const abiEncoder = new AbiEncoder.DynamicBytes({
 | 
			
		||||
                name: '',
 | 
			
		||||
                type: 'bytes',
 | 
			
		||||
@@ -237,12 +232,12 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            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);
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										370
									
								
								contracts/asset-proxy/test/uniswap_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								contracts/asset-proxy/test/uniswap_bridge.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,370 @@
 | 
			
		||||
import {
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    expect,
 | 
			
		||||
    filterLogs,
 | 
			
		||||
    filterLogsToArguments,
 | 
			
		||||
    getRandomInteger,
 | 
			
		||||
    hexLeftPad,
 | 
			
		||||
    hexRandom,
 | 
			
		||||
    Numberish,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { DecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    TestUniswapBridgeContract,
 | 
			
		||||
    TestUniswapBridgeEthToTokenTransferInputEventArgs as EthToTokenTransferInputArgs,
 | 
			
		||||
    TestUniswapBridgeEvents as ContractEvents,
 | 
			
		||||
    TestUniswapBridgeTokenApproveEventArgs as TokenApproveArgs,
 | 
			
		||||
    TestUniswapBridgeTokenToEthSwapInputEventArgs as TokenToEthSwapInputArgs,
 | 
			
		||||
    TestUniswapBridgeTokenToTokenTransferInputEventArgs as TokenToTokenTransferInputArgs,
 | 
			
		||||
    TestUniswapBridgeTokenTransferEventArgs as TokenTransferArgs,
 | 
			
		||||
    TestUniswapBridgeWethDepositEventArgs as WethDepositArgs,
 | 
			
		||||
    TestUniswapBridgeWethWithdrawEventArgs as WethWithdrawArgs,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('UniswapBridge unit tests', env => {
 | 
			
		||||
    let testContract: TestUniswapBridgeContract;
 | 
			
		||||
    let wethTokenAddress: string;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        testContract = await TestUniswapBridgeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestUniswapBridge,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        wethTokenAddress = await testContract.wethToken().callAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isValidSignature()', () => {
 | 
			
		||||
        it('returns success bytes', async () => {
 | 
			
		||||
            const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
 | 
			
		||||
            const result = await testContract.isValidSignature(hexRandom(), hexRandom(_.random(0, 32))).callAsync();
 | 
			
		||||
            expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('bridgeTransferFrom()', () => {
 | 
			
		||||
        interface WithdrawToOpts {
 | 
			
		||||
            fromTokenAddress: string;
 | 
			
		||||
            toTokenAddress: string;
 | 
			
		||||
            fromTokenBalance: Numberish;
 | 
			
		||||
            toAddress: string;
 | 
			
		||||
            amount: Numberish;
 | 
			
		||||
            exchangeRevertReason: string;
 | 
			
		||||
            exchangeFillAmount: Numberish;
 | 
			
		||||
            toTokenRevertReason: string;
 | 
			
		||||
            fromTokenRevertReason: string;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function createWithdrawToOpts(opts?: Partial<WithdrawToOpts>): WithdrawToOpts {
 | 
			
		||||
            return {
 | 
			
		||||
                fromTokenAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                toTokenAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                fromTokenBalance: getRandomInteger(1, 1e18),
 | 
			
		||||
                toAddress: randomAddress(),
 | 
			
		||||
                amount: getRandomInteger(1, 1e18),
 | 
			
		||||
                exchangeRevertReason: '',
 | 
			
		||||
                exchangeFillAmount: getRandomInteger(1, 1e18),
 | 
			
		||||
                toTokenRevertReason: '',
 | 
			
		||||
                fromTokenRevertReason: '',
 | 
			
		||||
                ...opts,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        interface WithdrawToResult {
 | 
			
		||||
            opts: WithdrawToOpts;
 | 
			
		||||
            result: string;
 | 
			
		||||
            logs: DecodedLogs;
 | 
			
		||||
            blockTime: number;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async function withdrawToAsync(opts?: Partial<WithdrawToOpts>): Promise<WithdrawToResult> {
 | 
			
		||||
            const _opts = createWithdrawToOpts(opts);
 | 
			
		||||
            const callData = { value: new BigNumber(_opts.exchangeFillAmount) };
 | 
			
		||||
            // Create the "from" token and exchange.
 | 
			
		||||
            const createFromTokenFn = testContract.createTokenAndExchange(
 | 
			
		||||
                _opts.fromTokenAddress,
 | 
			
		||||
                _opts.exchangeRevertReason,
 | 
			
		||||
            );
 | 
			
		||||
            [_opts.fromTokenAddress] = await createFromTokenFn.callAsync(callData);
 | 
			
		||||
            await createFromTokenFn.awaitTransactionSuccessAsync(callData);
 | 
			
		||||
 | 
			
		||||
            // Create the "to" token and exchange.
 | 
			
		||||
            const createToTokenFn = testContract.createTokenAndExchange(
 | 
			
		||||
                _opts.toTokenAddress,
 | 
			
		||||
                _opts.exchangeRevertReason,
 | 
			
		||||
            );
 | 
			
		||||
            [_opts.toTokenAddress] = await createToTokenFn.callAsync(callData);
 | 
			
		||||
            await createToTokenFn.awaitTransactionSuccessAsync(callData);
 | 
			
		||||
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setTokenRevertReason(_opts.toTokenAddress, _opts.toTokenRevertReason)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setTokenRevertReason(_opts.fromTokenAddress, _opts.fromTokenRevertReason)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            // Set the token balance for the token we're converting from.
 | 
			
		||||
            await testContract.setTokenBalance(_opts.fromTokenAddress).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: new BigNumber(_opts.fromTokenBalance),
 | 
			
		||||
            });
 | 
			
		||||
            // Call bridgeTransferFrom().
 | 
			
		||||
            const bridgeTransferFromFn = testContract.bridgeTransferFrom(
 | 
			
		||||
                // The "to" token address.
 | 
			
		||||
                _opts.toTokenAddress,
 | 
			
		||||
                // The "from" address.
 | 
			
		||||
                randomAddress(),
 | 
			
		||||
                // The "to" address.
 | 
			
		||||
                _opts.toAddress,
 | 
			
		||||
                // The amount to transfer to "to"
 | 
			
		||||
                new BigNumber(_opts.amount),
 | 
			
		||||
                // ABI-encoded "from" token address.
 | 
			
		||||
                hexLeftPad(_opts.fromTokenAddress),
 | 
			
		||||
            );
 | 
			
		||||
            const result = await bridgeTransferFromFn.callAsync();
 | 
			
		||||
            const receipt = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            return {
 | 
			
		||||
                opts: _opts,
 | 
			
		||||
                result,
 | 
			
		||||
                logs: (receipt.logs as any) as DecodedLogs,
 | 
			
		||||
                blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async function getExchangeForTokenAsync(tokenAddress: string): Promise<string> {
 | 
			
		||||
            return testContract.getExchange(tokenAddress).callAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        it('returns magic bytes on success', async () => {
 | 
			
		||||
            const { result } = await withdrawToAsync();
 | 
			
		||||
            expect(result).to.eq(AssetProxyId.ERC20Bridge);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('just transfers tokens to `to` if the same tokens are in play', async () => {
 | 
			
		||||
            const createTokenFn = await testContract.createTokenAndExchange(constants.NULL_ADDRESS, '');
 | 
			
		||||
            const [tokenAddress] = await createTokenFn.callAsync();
 | 
			
		||||
            await createTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            const { opts, result, logs } = await withdrawToAsync({
 | 
			
		||||
                fromTokenAddress: tokenAddress,
 | 
			
		||||
                toTokenAddress: tokenAddress,
 | 
			
		||||
            });
 | 
			
		||||
            expect(result).to.eq(AssetProxyId.ERC20Bridge);
 | 
			
		||||
            const transfers = filterLogsToArguments<TokenTransferArgs>(logs, ContractEvents.TokenTransfer);
 | 
			
		||||
            expect(transfers.length).to.eq(1);
 | 
			
		||||
            expect(transfers[0].token).to.eq(tokenAddress);
 | 
			
		||||
            expect(transfers[0].from).to.eq(testContract.address);
 | 
			
		||||
            expect(transfers[0].to).to.eq(opts.toAddress);
 | 
			
		||||
            expect(transfers[0].amount).to.bignumber.eq(opts.amount);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('token -> token', () => {
 | 
			
		||||
            it('calls `IUniswapExchange.tokenToTokenTransferInput()', async () => {
 | 
			
		||||
                const { opts, logs, blockTime } = await withdrawToAsync();
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                const calls = filterLogsToArguments<TokenToTokenTransferInputArgs>(
 | 
			
		||||
                    logs,
 | 
			
		||||
                    ContractEvents.TokenToTokenTransferInput,
 | 
			
		||||
                );
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].exchange).to.eq(exchangeAddress);
 | 
			
		||||
                expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance);
 | 
			
		||||
                expect(calls[0].minTokensBought).to.bignumber.eq(opts.amount);
 | 
			
		||||
                expect(calls[0].minEthBought).to.bignumber.eq(0);
 | 
			
		||||
                expect(calls[0].deadline).to.bignumber.eq(blockTime);
 | 
			
		||||
                expect(calls[0].recipient).to.eq(opts.toAddress);
 | 
			
		||||
                expect(calls[0].toTokenAddress).to.eq(opts.toTokenAddress);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token', async () => {
 | 
			
		||||
                const { opts, logs } = await withdrawToAsync();
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(exchangeAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token on subsequent calls', async () => {
 | 
			
		||||
                const { opts } = await withdrawToAsync();
 | 
			
		||||
                const { logs } = await withdrawToAsync(opts);
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(exchangeAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if "from" token does not exist', async () => {
 | 
			
		||||
                const tx = testContract
 | 
			
		||||
                    .bridgeTransferFrom(
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        getRandomInteger(1, 1e18),
 | 
			
		||||
                        hexLeftPad(randomAddress()),
 | 
			
		||||
                    )
 | 
			
		||||
                    .awaitTransactionSuccessAsync();
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the exchange fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = withdrawToAsync({
 | 
			
		||||
                    exchangeRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('token -> ETH', () => {
 | 
			
		||||
            it('calls `IUniswapExchange.tokenToEthSwapInput()`, `WETH.deposit()`, then `transfer()`', async () => {
 | 
			
		||||
                const { opts, logs, blockTime } = await withdrawToAsync({
 | 
			
		||||
                    toTokenAddress: wethTokenAddress,
 | 
			
		||||
                });
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                let calls: any = filterLogs<TokenToEthSwapInputArgs>(logs, ContractEvents.TokenToEthSwapInput);
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].args.exchange).to.eq(exchangeAddress);
 | 
			
		||||
                expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance);
 | 
			
		||||
                expect(calls[0].args.minEthBought).to.bignumber.eq(opts.amount);
 | 
			
		||||
                expect(calls[0].args.deadline).to.bignumber.eq(blockTime);
 | 
			
		||||
                calls = filterLogs<WethDepositArgs>(
 | 
			
		||||
                    logs.slice(calls[0].logIndex as number),
 | 
			
		||||
                    ContractEvents.WethDeposit,
 | 
			
		||||
                );
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].args.amount).to.bignumber.eq(opts.exchangeFillAmount);
 | 
			
		||||
                calls = filterLogs<TokenTransferArgs>(
 | 
			
		||||
                    logs.slice(calls[0].logIndex as number),
 | 
			
		||||
                    ContractEvents.TokenTransfer,
 | 
			
		||||
                );
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].args.token).to.eq(opts.toTokenAddress);
 | 
			
		||||
                expect(calls[0].args.from).to.eq(testContract.address);
 | 
			
		||||
                expect(calls[0].args.to).to.eq(opts.toAddress);
 | 
			
		||||
                expect(calls[0].args.amount).to.bignumber.eq(opts.exchangeFillAmount);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token', async () => {
 | 
			
		||||
                const { opts, logs } = await withdrawToAsync({
 | 
			
		||||
                    toTokenAddress: wethTokenAddress,
 | 
			
		||||
                });
 | 
			
		||||
                const transfers = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                expect(transfers.length).to.eq(1);
 | 
			
		||||
                expect(transfers[0].spender).to.eq(exchangeAddress);
 | 
			
		||||
                expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token on subsequent calls', async () => {
 | 
			
		||||
                const { opts } = await withdrawToAsync({
 | 
			
		||||
                    toTokenAddress: wethTokenAddress,
 | 
			
		||||
                });
 | 
			
		||||
                const { logs } = await withdrawToAsync(opts);
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress);
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(exchangeAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if "from" token does not exist', async () => {
 | 
			
		||||
                const tx = testContract
 | 
			
		||||
                    .bridgeTransferFrom(
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        getRandomInteger(1, 1e18),
 | 
			
		||||
                        hexLeftPad(wethTokenAddress),
 | 
			
		||||
                    )
 | 
			
		||||
                    .awaitTransactionSuccessAsync();
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if `WETH.deposit()` fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = withdrawToAsync({
 | 
			
		||||
                    toTokenAddress: wethTokenAddress,
 | 
			
		||||
                    toTokenRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the exchange fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = withdrawToAsync({
 | 
			
		||||
                    toTokenAddress: wethTokenAddress,
 | 
			
		||||
                    exchangeRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('ETH -> token', () => {
 | 
			
		||||
            it('calls  `WETH.withdraw()`, then `IUniswapExchange.ethToTokenTransferInput()`', async () => {
 | 
			
		||||
                const { opts, logs, blockTime } = await withdrawToAsync({
 | 
			
		||||
                    fromTokenAddress: wethTokenAddress,
 | 
			
		||||
                });
 | 
			
		||||
                const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress);
 | 
			
		||||
                let calls: any = filterLogs<WethWithdrawArgs>(logs, ContractEvents.WethWithdraw);
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance);
 | 
			
		||||
                calls = filterLogs<EthToTokenTransferInputArgs>(
 | 
			
		||||
                    logs.slice(calls[0].logIndex as number),
 | 
			
		||||
                    ContractEvents.EthToTokenTransferInput,
 | 
			
		||||
                );
 | 
			
		||||
                expect(calls.length).to.eq(1);
 | 
			
		||||
                expect(calls[0].args.exchange).to.eq(exchangeAddress);
 | 
			
		||||
                expect(calls[0].args.minTokensBought).to.bignumber.eq(opts.amount);
 | 
			
		||||
                expect(calls[0].args.deadline).to.bignumber.eq(blockTime);
 | 
			
		||||
                expect(calls[0].args.recipient).to.eq(opts.toAddress);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('does not set any allowance', async () => {
 | 
			
		||||
                const { logs } = await withdrawToAsync({
 | 
			
		||||
                    fromTokenAddress: wethTokenAddress,
 | 
			
		||||
                });
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                expect(approvals).to.be.empty('');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if "to" token does not exist', async () => {
 | 
			
		||||
                const tx = testContract
 | 
			
		||||
                    .bridgeTransferFrom(
 | 
			
		||||
                        wethTokenAddress,
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        randomAddress(),
 | 
			
		||||
                        getRandomInteger(1, 1e18),
 | 
			
		||||
                        hexLeftPad(randomAddress()),
 | 
			
		||||
                    )
 | 
			
		||||
                    .awaitTransactionSuccessAsync();
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the `WETH.withdraw()` fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = withdrawToAsync({
 | 
			
		||||
                    fromTokenAddress: wethTokenAddress,
 | 
			
		||||
                    fromTokenRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the exchange fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = withdrawToAsync({
 | 
			
		||||
                    fromTokenAddress: wethTokenAddress,
 | 
			
		||||
                    exchangeRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
export * from './erc20_wrapper';
 | 
			
		||||
export * from './erc721_wrapper';
 | 
			
		||||
export * from './erc1155_proxy_wrapper';
 | 
			
		||||
							
								
								
									
										28
									
								
								contracts/asset-proxy/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								contracts/asset-proxy/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/erc1155_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/erc20_bridge_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/erc20_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/erc721_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/eth2_dai_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/i_asset_data';
 | 
			
		||||
export * from '../test/generated-wrappers/i_asset_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../test/generated-wrappers/i_authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/i_eth2_dai';
 | 
			
		||||
export * from '../test/generated-wrappers/i_uniswap_exchange';
 | 
			
		||||
export * from '../test/generated-wrappers/i_uniswap_exchange_factory';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/multi_asset_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/ownable';
 | 
			
		||||
export * from '../test/generated-wrappers/static_call_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/test_erc20_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_eth2_dai_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_static_call_target';
 | 
			
		||||
export * from '../test/generated-wrappers/test_uniswap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/uniswap_bridge';
 | 
			
		||||
@@ -10,19 +10,33 @@
 | 
			
		||||
        "generated-artifacts/Eth2DaiBridge.json",
 | 
			
		||||
        "generated-artifacts/IAssetData.json",
 | 
			
		||||
        "generated-artifacts/IAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/IAssetProxyDispatcher.json",
 | 
			
		||||
        "generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/IERC20Bridge.json",
 | 
			
		||||
        "generated-artifacts/IEth2Dai.json",
 | 
			
		||||
        "generated-artifacts/IWallet.json",
 | 
			
		||||
        "generated-artifacts/MixinAssetProxyDispatcher.json",
 | 
			
		||||
        "generated-artifacts/MixinAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/MultiAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/Ownable.json",
 | 
			
		||||
        "generated-artifacts/StaticCallProxy.json",
 | 
			
		||||
        "generated-artifacts/TestERC20Bridge.json",
 | 
			
		||||
        "generated-artifacts/TestEth2DaiBridge.json",
 | 
			
		||||
        "generated-artifacts/TestStaticCallTarget.json"
 | 
			
		||||
        "generated-artifacts/TestStaticCallTarget.json",
 | 
			
		||||
        "generated-artifacts/UniswapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/ERC1155Proxy.json",
 | 
			
		||||
        "test/generated-artifacts/ERC20BridgeProxy.json",
 | 
			
		||||
        "test/generated-artifacts/ERC20Proxy.json",
 | 
			
		||||
        "test/generated-artifacts/ERC721Proxy.json",
 | 
			
		||||
        "test/generated-artifacts/Eth2DaiBridge.json",
 | 
			
		||||
        "test/generated-artifacts/IAssetData.json",
 | 
			
		||||
        "test/generated-artifacts/IAssetProxy.json",
 | 
			
		||||
        "test/generated-artifacts/IAssetProxyDispatcher.json",
 | 
			
		||||
        "test/generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/IERC20Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/IEth2Dai.json",
 | 
			
		||||
        "test/generated-artifacts/IUniswapExchange.json",
 | 
			
		||||
        "test/generated-artifacts/IUniswapExchangeFactory.json",
 | 
			
		||||
        "test/generated-artifacts/MixinAssetProxyDispatcher.json",
 | 
			
		||||
        "test/generated-artifacts/MixinAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/MultiAssetProxy.json",
 | 
			
		||||
        "test/generated-artifacts/Ownable.json",
 | 
			
		||||
        "test/generated-artifacts/StaticCallProxy.json",
 | 
			
		||||
        "test/generated-artifacts/TestERC20Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestEth2DaiBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestStaticCallTarget.json",
 | 
			
		||||
        "test/generated-artifacts/TestUniswapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/UniswapBridge.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								contracts/coordinator/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/coordinator/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Blacklist all files
 | 
			
		||||
.*
 | 
			
		||||
*
 | 
			
		||||
# Whitelist lib
 | 
			
		||||
!lib/**/*
 | 
			
		||||
# Whitelist Solidity contracts
 | 
			
		||||
!contracts/src/**/*
 | 
			
		||||
# Blacklist tests in lib
 | 
			
		||||
/lib/test/*
 | 
			
		||||
# Package specific ignore
 | 
			
		||||
@@ -1,4 +1,31 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.0-beta.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
			
		||||
                "pr": 2330
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Introduced new export CoordinatorRevertErrors",
 | 
			
		||||
                "pr": 2321
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added dependency on @0x/contracts-utils",
 | 
			
		||||
                "pr": 2321
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1574030254
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.0-beta.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1573159180
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.1.0-beta.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,16 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.1.0-beta.2 - _November 17, 2019_
 | 
			
		||||
 | 
			
		||||
    * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
 | 
			
		||||
    * Introduced new export CoordinatorRevertErrors (#2321)
 | 
			
		||||
    * Added dependency on @0x/contracts-utils (#2321)
 | 
			
		||||
 | 
			
		||||
## v2.1.0-beta.1 - _November 7, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.0-beta.0 - _October 3, 2019_
 | 
			
		||||
 | 
			
		||||
    * Add chainId to domain separator (#1742)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./generated-artifacts",
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,12 +19,15 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
import "./libs/LibCoordinatorApproval.sol";
 | 
			
		||||
import "./libs/LibCoordinatorRichErrors.sol";
 | 
			
		||||
import "./interfaces/ICoordinatorSignatureValidator.sol";
 | 
			
		||||
import "./interfaces/ICoordinatorApprovalVerifier.sol";
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +35,7 @@ import "./interfaces/ICoordinatorApprovalVerifier.sol";
 | 
			
		||||
// solhint-disable avoid-tx-origin
 | 
			
		||||
contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
    LibCoordinatorApproval,
 | 
			
		||||
    LibZeroExTransaction,
 | 
			
		||||
    LibEIP712ExchangeDomain,
 | 
			
		||||
    ICoordinatorSignatureValidator,
 | 
			
		||||
    ICoordinatorApprovalVerifier
 | 
			
		||||
{
 | 
			
		||||
@@ -44,13 +47,12 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
    /// @param transaction 0x transaction containing salt, signerAddress, and data.
 | 
			
		||||
    /// @param txOrigin Required signer of Ethereum transaction calling this function.
 | 
			
		||||
    /// @param transactionSignature Proof that the transaction has been signed by the signer.
 | 
			
		||||
    /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each
 | 
			
		||||
    ///        order in the transaction's Exchange calldata.
 | 
			
		||||
    function assertValidCoordinatorApprovals(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        address txOrigin,
 | 
			
		||||
        bytes memory transactionSignature,
 | 
			
		||||
        uint256[] memory approvalExpirationTimeSeconds,
 | 
			
		||||
        bytes[] memory approvalSignatures
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
@@ -67,7 +69,6 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
                orders,
 | 
			
		||||
                txOrigin,
 | 
			
		||||
                transactionSignature,
 | 
			
		||||
                approvalExpirationTimeSeconds,
 | 
			
		||||
                approvalSignatures
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
@@ -75,7 +76,7 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
 | 
			
		||||
    /// @dev Decodes the orders from Exchange calldata representing any fill method.
 | 
			
		||||
    /// @param data Exchange calldata representing a fill method.
 | 
			
		||||
    /// @return The orders from the Exchange calldata.
 | 
			
		||||
    /// @return orders The orders from the Exchange calldata.
 | 
			
		||||
    function decodeOrdersFromFillData(bytes memory data)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
@@ -84,7 +85,6 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
        bytes4 selector = data.readBytes4(0);
 | 
			
		||||
        if (
 | 
			
		||||
            selector == IExchange(address(0)).fillOrder.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).fillOrderNoThrow.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).fillOrKillOrder.selector
 | 
			
		||||
        ) {
 | 
			
		||||
            // Decode single order
 | 
			
		||||
@@ -98,8 +98,10 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
            selector == IExchange(address(0)).batchFillOrders.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).batchFillOrdersNoThrow.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).batchFillOrKillOrders.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).marketBuyOrders.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).marketSellOrders.selector
 | 
			
		||||
            selector == IExchange(address(0)).marketBuyOrdersNoThrow.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).marketBuyOrdersFillOrKill.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).marketSellOrdersNoThrow.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).marketSellOrdersFillOrKill.selector
 | 
			
		||||
        ) {
 | 
			
		||||
            // Decode all orders
 | 
			
		||||
            // solhint-disable indent
 | 
			
		||||
@@ -107,7 +109,10 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
                data.slice(4, data.length),
 | 
			
		||||
                (LibOrder.Order[])
 | 
			
		||||
            );
 | 
			
		||||
        } else if (selector == IExchange(address(0)).matchOrders.selector) {
 | 
			
		||||
        } else if (
 | 
			
		||||
            selector == IExchange(address(0)).matchOrders.selector ||
 | 
			
		||||
            selector == IExchange(address(0)).matchOrdersWithMaximalFill.selector
 | 
			
		||||
        ) {
 | 
			
		||||
            // Decode left and right orders
 | 
			
		||||
            (LibOrder.Order memory leftOrder, LibOrder.Order memory rightOrder) = abi.decode(
 | 
			
		||||
                data.slice(4, data.length),
 | 
			
		||||
@@ -127,27 +132,24 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
    /// @param orders Array of order structs containing order specifications.
 | 
			
		||||
    /// @param txOrigin Required signer of Ethereum transaction calling this function.
 | 
			
		||||
    /// @param transactionSignature Proof that the transaction has been signed by the signer.
 | 
			
		||||
    /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order.
 | 
			
		||||
    function _assertValidTransactionOrdersApproval(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        LibOrder.Order[] memory orders,
 | 
			
		||||
        address txOrigin,
 | 
			
		||||
        bytes memory transactionSignature,
 | 
			
		||||
        uint256[] memory approvalExpirationTimeSeconds,
 | 
			
		||||
        bytes[] memory approvalSignatures
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        // Verify that Ethereum tx signer is the same as the approved txOrigin
 | 
			
		||||
        require(
 | 
			
		||||
            tx.origin == txOrigin,
 | 
			
		||||
            "INVALID_ORIGIN"
 | 
			
		||||
        );
 | 
			
		||||
        if (tx.origin != txOrigin) {
 | 
			
		||||
            LibRichErrors.rrevert(LibCoordinatorRichErrors.InvalidOriginError(txOrigin));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Hash 0x transaction
 | 
			
		||||
        bytes32 transactionHash = getTransactionHash(transaction);
 | 
			
		||||
        bytes32 transactionHash = LibZeroExTransaction.getTypedDataHash(transaction, EIP712_EXCHANGE_DOMAIN_HASH);
 | 
			
		||||
 | 
			
		||||
        // Create empty list of approval signers
 | 
			
		||||
        address[] memory approvalSignerAddresses = new address[](0);
 | 
			
		||||
@@ -155,21 +157,12 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
        uint256 signaturesLength = approvalSignatures.length;
 | 
			
		||||
        for (uint256 i = 0; i != signaturesLength; i++) {
 | 
			
		||||
            // Create approval message
 | 
			
		||||
            uint256 currentApprovalExpirationTimeSeconds = approvalExpirationTimeSeconds[i];
 | 
			
		||||
            CoordinatorApproval memory approval = CoordinatorApproval({
 | 
			
		||||
                txOrigin: txOrigin,
 | 
			
		||||
                transactionHash: transactionHash,
 | 
			
		||||
                transactionSignature: transactionSignature,
 | 
			
		||||
                approvalExpirationTimeSeconds: currentApprovalExpirationTimeSeconds
 | 
			
		||||
                transactionSignature: transactionSignature
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Ensure approval has not expired
 | 
			
		||||
            require(
 | 
			
		||||
                // solhint-disable-next-line not-rely-on-time
 | 
			
		||||
                currentApprovalExpirationTimeSeconds > block.timestamp,
 | 
			
		||||
                "APPROVAL_EXPIRED"
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Hash approval message and recover signer address
 | 
			
		||||
            bytes32 approvalHash = getCoordinatorApprovalHash(approval);
 | 
			
		||||
            address approvalSignerAddress = getSignerAddress(approvalHash, approvalSignatures[i]);
 | 
			
		||||
@@ -191,10 +184,12 @@ contract MixinCoordinatorApprovalVerifier is
 | 
			
		||||
            // Ensure feeRecipient of order has approved this 0x transaction
 | 
			
		||||
            address approverAddress = orders[i].feeRecipientAddress;
 | 
			
		||||
            bool isOrderApproved = approvalSignerAddresses.contains(approverAddress);
 | 
			
		||||
            require(
 | 
			
		||||
                isOrderApproved,
 | 
			
		||||
                "INVALID_APPROVAL_SIGNATURE"
 | 
			
		||||
            );
 | 
			
		||||
            if (!isOrderApproved) {
 | 
			
		||||
                LibRichErrors.rrevert(LibCoordinatorRichErrors.InvalidApprovalSignatureError(
 | 
			
		||||
                    transactionHash,
 | 
			
		||||
                    approverAddress
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,41 +20,53 @@ pragma solidity ^0.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/Refundable.sol";
 | 
			
		||||
import "./libs/LibConstants.sol";
 | 
			
		||||
import "./interfaces/ICoordinatorCore.sol";
 | 
			
		||||
import "./interfaces/ICoordinatorApprovalVerifier.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-empty-blocks
 | 
			
		||||
contract MixinCoordinatorCore is
 | 
			
		||||
    Refundable,
 | 
			
		||||
    LibConstants,
 | 
			
		||||
    ICoordinatorApprovalVerifier,
 | 
			
		||||
    ICoordinatorCore
 | 
			
		||||
{
 | 
			
		||||
    /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata.
 | 
			
		||||
 | 
			
		||||
    /// @dev A payable fallback function that makes this contract "payable". This is necessary to allow
 | 
			
		||||
    ///      this contract to gracefully handle refunds from the Exchange.
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to
 | 
			
		||||
    ///      each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param transaction 0x transaction containing salt, signerAddress, and data.
 | 
			
		||||
    /// @param txOrigin Required signer of Ethereum transaction calling this function.
 | 
			
		||||
    /// @param transactionSignature Proof that the transaction has been signed by the signer.
 | 
			
		||||
    /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each
 | 
			
		||||
    ///        order in the transaction's Exchange calldata.
 | 
			
		||||
    function executeTransaction(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        address txOrigin,
 | 
			
		||||
        bytes memory transactionSignature,
 | 
			
		||||
        uint256[] memory approvalExpirationTimeSeconds,
 | 
			
		||||
        bytes[] memory approvalSignatures
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
    {
 | 
			
		||||
        // Validate that the 0x transaction has been approves by each feeRecipient
 | 
			
		||||
        assertValidCoordinatorApprovals(
 | 
			
		||||
            transaction,
 | 
			
		||||
            txOrigin,
 | 
			
		||||
            transactionSignature,
 | 
			
		||||
            approvalExpirationTimeSeconds,
 | 
			
		||||
            approvalSignatures
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Execute the transaction
 | 
			
		||||
        EXCHANGE.executeTransaction(transaction, transactionSignature);
 | 
			
		||||
        EXCHANGE.executeTransaction.value(msg.value)(transaction, transactionSignature);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,9 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
 | 
			
		||||
import "./interfaces/ICoordinatorSignatureValidator.sol";
 | 
			
		||||
import "./libs/LibCoordinatorRichErrors.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MixinSignatureValidator is
 | 
			
		||||
@@ -30,24 +32,32 @@ contract MixinSignatureValidator is
 | 
			
		||||
    /// @dev Recovers the address of a signer given a hash and signature.
 | 
			
		||||
    /// @param hash Any 32 byte hash.
 | 
			
		||||
    /// @param signature Proof that the hash has been signed by signer.
 | 
			
		||||
    /// @return signerAddress Address of the signer.
 | 
			
		||||
    function getSignerAddress(bytes32 hash, bytes memory signature)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (address signerAddress)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            signature.length > 0,
 | 
			
		||||
            "LENGTH_GREATER_THAN_0_REQUIRED"
 | 
			
		||||
        );
 | 
			
		||||
        uint256 signatureLength = signature.length;
 | 
			
		||||
        if (signatureLength == 0) {
 | 
			
		||||
            LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH,
 | 
			
		||||
                hash,
 | 
			
		||||
                signature
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Pop last byte off of signature byte array.
 | 
			
		||||
        uint8 signatureTypeRaw = uint8(signature.popLastByte());
 | 
			
		||||
        uint8 signatureTypeRaw = uint8(signature[signature.length - 1]);
 | 
			
		||||
 | 
			
		||||
        // Ensure signature is supported
 | 
			
		||||
        require(
 | 
			
		||||
            signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
 | 
			
		||||
            "SIGNATURE_UNSUPPORTED"
 | 
			
		||||
        );
 | 
			
		||||
        if (signatureTypeRaw >= uint8(SignatureType.NSignatureTypes)) {
 | 
			
		||||
            LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                LibCoordinatorRichErrors.SignatureErrorCodes.UNSUPPORTED,
 | 
			
		||||
                hash,
 | 
			
		||||
                signature
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SignatureType signatureType = SignatureType(signatureTypeRaw);
 | 
			
		||||
 | 
			
		||||
@@ -57,25 +67,32 @@ contract MixinSignatureValidator is
 | 
			
		||||
        // it an explicit option. This aids testing and analysis. It is
 | 
			
		||||
        // also the initialization value for the enum type.
 | 
			
		||||
        if (signatureType == SignatureType.Illegal) {
 | 
			
		||||
            revert("SIGNATURE_ILLEGAL");
 | 
			
		||||
            LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                LibCoordinatorRichErrors.SignatureErrorCodes.ILLEGAL,
 | 
			
		||||
                hash,
 | 
			
		||||
                signature
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
        // Always invalid signature.
 | 
			
		||||
        // Like Illegal, this is always implicitly available and therefore
 | 
			
		||||
        // offered explicitly. It can be implicitly created by providing
 | 
			
		||||
        // a correctly formatted but incorrect signature.
 | 
			
		||||
        } else if (signatureType == SignatureType.Invalid) {
 | 
			
		||||
            require(
 | 
			
		||||
                signature.length == 0,
 | 
			
		||||
                "LENGTH_0_REQUIRED"
 | 
			
		||||
            );
 | 
			
		||||
            revert("SIGNATURE_INVALID");
 | 
			
		||||
            LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                LibCoordinatorRichErrors.SignatureErrorCodes.INVALID,
 | 
			
		||||
                hash,
 | 
			
		||||
                signature
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
        // Signature using EIP712
 | 
			
		||||
        } else if (signatureType == SignatureType.EIP712) {
 | 
			
		||||
            require(
 | 
			
		||||
                signature.length == 65,
 | 
			
		||||
                "LENGTH_65_REQUIRED"
 | 
			
		||||
            );
 | 
			
		||||
            if (signatureLength != 66) {
 | 
			
		||||
                LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                    LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH,
 | 
			
		||||
                    hash,
 | 
			
		||||
                    signature
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
            uint8 v = uint8(signature[0]);
 | 
			
		||||
            bytes32 r = signature.readBytes32(1);
 | 
			
		||||
            bytes32 s = signature.readBytes32(33);
 | 
			
		||||
@@ -89,10 +106,13 @@ contract MixinSignatureValidator is
 | 
			
		||||
 | 
			
		||||
        // Signed using web3.eth_sign
 | 
			
		||||
        } else if (signatureType == SignatureType.EthSign) {
 | 
			
		||||
            require(
 | 
			
		||||
                signature.length == 65,
 | 
			
		||||
                "LENGTH_65_REQUIRED"
 | 
			
		||||
            );
 | 
			
		||||
            if (signatureLength != 66) {
 | 
			
		||||
                LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
                    LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH,
 | 
			
		||||
                    hash,
 | 
			
		||||
                    signature
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
            uint8 v = uint8(signature[0]);
 | 
			
		||||
            bytes32 r = signature.readBytes32(1);
 | 
			
		||||
            bytes32 s = signature.readBytes32(33);
 | 
			
		||||
@@ -113,6 +133,10 @@ contract MixinSignatureValidator is
 | 
			
		||||
        // that we currently support. In this case returning false
 | 
			
		||||
        // may lead the caller to incorrectly believe that the
 | 
			
		||||
        // signature was invalid.)
 | 
			
		||||
        revert("SIGNATURE_UNSUPPORTED");
 | 
			
		||||
        LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError(
 | 
			
		||||
            LibCoordinatorRichErrors.SignatureErrorCodes.UNSUPPORTED,
 | 
			
		||||
            hash,
 | 
			
		||||
            signature
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,13 +30,12 @@ contract ICoordinatorApprovalVerifier {
 | 
			
		||||
    /// @param transaction 0x transaction containing salt, signerAddress, and data.
 | 
			
		||||
    /// @param txOrigin Required signer of Ethereum transaction calling this function.
 | 
			
		||||
    /// @param transactionSignature Proof that the transaction has been signed by the signer.
 | 
			
		||||
    /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each
 | 
			
		||||
    ///        order in the transaction's Exchange calldata.
 | 
			
		||||
    function assertValidCoordinatorApprovals(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        address txOrigin,
 | 
			
		||||
        bytes memory transactionSignature,
 | 
			
		||||
        uint256[] memory approvalExpirationTimeSeconds,
 | 
			
		||||
        bytes[] memory approvalSignatures
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
@@ -44,7 +43,7 @@ contract ICoordinatorApprovalVerifier {
 | 
			
		||||
 | 
			
		||||
    /// @dev Decodes the orders from Exchange calldata representing any fill method.
 | 
			
		||||
    /// @param data Exchange calldata representing a fill method.
 | 
			
		||||
    /// @return The orders from the Exchange calldata.
 | 
			
		||||
    /// @return orders The orders from the Exchange calldata.
 | 
			
		||||
    function decodeOrdersFromFillData(bytes memory data)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
 
 | 
			
		||||
@@ -24,18 +24,19 @@ import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
 | 
			
		||||
 | 
			
		||||
contract ICoordinatorCore {
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to
 | 
			
		||||
    ///      each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param transaction 0x transaction containing salt, signerAddress, and data.
 | 
			
		||||
    /// @param txOrigin Required signer of Ethereum transaction calling this function.
 | 
			
		||||
    /// @param transactionSignature Proof that the transaction has been signed by the signer.
 | 
			
		||||
    /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata.
 | 
			
		||||
    /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each
 | 
			
		||||
    ///        order in the transaction's Exchange calldata.
 | 
			
		||||
    function executeTransaction(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        address txOrigin,
 | 
			
		||||
        bytes memory transactionSignature,
 | 
			
		||||
        uint256[] memory approvalExpirationTimeSeconds,
 | 
			
		||||
        bytes[] memory approvalSignatures
 | 
			
		||||
    )
 | 
			
		||||
        public;
 | 
			
		||||
        public
 | 
			
		||||
        payable;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,14 +30,14 @@ contract ICoordinatorSignatureValidator {
 | 
			
		||||
        Wallet,                 // 0x04
 | 
			
		||||
        Validator,              // 0x05
 | 
			
		||||
        PreSigned,              // 0x06
 | 
			
		||||
        OrderValidator,         // 0x07
 | 
			
		||||
        WalletOrderValidator,   // 0x08
 | 
			
		||||
        NSignatureTypes         // 0x09, number of signature types. Always leave at end.
 | 
			
		||||
        EIP1271Wallet,          // 0x07
 | 
			
		||||
        NSignatureTypes         // 0x08, number of signature types. Always leave at end.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Recovers the address of a signer given a hash and signature.
 | 
			
		||||
    /// @param hash Any 32 byte hash.
 | 
			
		||||
    /// @param signature Proof that the hash has been signed by signer.
 | 
			
		||||
    /// @return signerAddress Address of the signer. 
 | 
			
		||||
    function getSignerAddress(bytes32 hash, bytes memory signature)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
 
 | 
			
		||||
@@ -30,22 +30,24 @@ contract LibCoordinatorApproval is
 | 
			
		||||
    //     "CoordinatorApproval(",
 | 
			
		||||
    //     "address txOrigin,",
 | 
			
		||||
    //     "bytes32 transactionHash,",
 | 
			
		||||
    //     "bytes transactionSignature,",
 | 
			
		||||
    //     "uint256 approvalExpirationTimeSeconds",
 | 
			
		||||
    //     "bytes transactionSignature",
 | 
			
		||||
    //     ")"
 | 
			
		||||
    // ));
 | 
			
		||||
    bytes32 constant public EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05;
 | 
			
		||||
    bytes32 constant public EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH =
 | 
			
		||||
        0xa6511c04ca44625d50986f8c36bedc09366207a17b96e347094053a9f8507168;
 | 
			
		||||
 | 
			
		||||
    struct CoordinatorApproval {
 | 
			
		||||
        address txOrigin;                       // Required signer of Ethereum transaction that is submitting approval.
 | 
			
		||||
        bytes32 transactionHash;                // EIP712 hash of the transaction.
 | 
			
		||||
        bytes transactionSignature;             // Signature of the 0x transaction.
 | 
			
		||||
        uint256 approvalExpirationTimeSeconds;  // Timestamp in seconds for which the approval expires.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculated the EIP712 hash of the Coordinator approval mesasage using the domain separator of this contract.
 | 
			
		||||
    /// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval.
 | 
			
		||||
    /// @return EIP712 hash of the Coordinator approval message with the domain separator of this contract.
 | 
			
		||||
    /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage using the domain
 | 
			
		||||
    ///      separator of this contract.
 | 
			
		||||
    /// @param approval Coordinator approval message containing the transaction hash, and transaction
 | 
			
		||||
    ///        signature.
 | 
			
		||||
    /// @return approvalHash EIP712 hash of the Coordinator approval message with the domain
 | 
			
		||||
    ///         separator of this contract.
 | 
			
		||||
    function getCoordinatorApprovalHash(CoordinatorApproval memory approval)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
@@ -55,9 +57,10 @@ contract LibCoordinatorApproval is
 | 
			
		||||
        return approvalHash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculated the EIP712 hash of the Coordinator approval mesasage with no domain separator.
 | 
			
		||||
    /// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval.
 | 
			
		||||
    /// @return EIP712 hash of the Coordinator approval message with no domain separator.
 | 
			
		||||
    /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage with no domain separator.
 | 
			
		||||
    /// @param approval Coordinator approval message containing the transaction hash, and transaction
 | 
			
		||||
    //         signature.
 | 
			
		||||
    /// @return result EIP712 hash of the Coordinator approval message with no domain separator.
 | 
			
		||||
    function _hashCoordinatorApproval(CoordinatorApproval memory approval)
 | 
			
		||||
        internal
 | 
			
		||||
        pure
 | 
			
		||||
@@ -67,7 +70,6 @@ contract LibCoordinatorApproval is
 | 
			
		||||
        bytes memory transactionSignature = approval.transactionSignature;
 | 
			
		||||
        address txOrigin = approval.txOrigin;
 | 
			
		||||
        bytes32 transactionHash = approval.transactionHash;
 | 
			
		||||
        uint256 approvalExpirationTimeSeconds = approval.approvalExpirationTimeSeconds;
 | 
			
		||||
 | 
			
		||||
        // Assembly for more efficiently computing:
 | 
			
		||||
        // keccak256(abi.encodePacked(
 | 
			
		||||
@@ -75,7 +77,6 @@ contract LibCoordinatorApproval is
 | 
			
		||||
        //     approval.txOrigin,
 | 
			
		||||
        //     approval.transactionHash,
 | 
			
		||||
        //     keccak256(approval.transactionSignature)
 | 
			
		||||
        //     approval.approvalExpirationTimeSeconds,
 | 
			
		||||
        // ));
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
@@ -89,9 +90,8 @@ contract LibCoordinatorApproval is
 | 
			
		||||
            mstore(add(memPtr, 32), txOrigin)                        // txOrigin
 | 
			
		||||
            mstore(add(memPtr, 64), transactionHash)                 // transactionHash
 | 
			
		||||
            mstore(add(memPtr, 96), transactionSignatureHash)        // transactionSignatureHash
 | 
			
		||||
            mstore(add(memPtr, 128), approvalExpirationTimeSeconds)  // approvalExpirationTimeSeconds
 | 
			
		||||
            // Compute hash
 | 
			
		||||
            result := keccak256(memPtr, 160)
 | 
			
		||||
            result := keccak256(memPtr, 128)
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,87 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
library LibCoordinatorRichErrors {
 | 
			
		||||
    enum SignatureErrorCodes {
 | 
			
		||||
        INVALID_LENGTH,
 | 
			
		||||
        UNSUPPORTED,
 | 
			
		||||
        ILLEGAL,
 | 
			
		||||
        INVALID
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("SignatureError(uint8,bytes32,bytes)"))
 | 
			
		||||
    bytes4 internal constant SIGNATURE_ERROR_SELECTOR =
 | 
			
		||||
        0x779c5223;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("InvalidOriginError(address)"))
 | 
			
		||||
    bytes4 internal constant INVALID_ORIGIN_ERROR_SELECTOR =
 | 
			
		||||
        0xa458d7ff;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("InvalidApprovalSignatureError(bytes32,address)"))
 | 
			
		||||
    bytes4 internal constant INVALID_APPROVAL_SIGNATURE_ERROR_SELECTOR =
 | 
			
		||||
        0xd789b640;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable func-name-mixedcase
 | 
			
		||||
    function SignatureError(
 | 
			
		||||
        SignatureErrorCodes errorCode,
 | 
			
		||||
        bytes32 hash,
 | 
			
		||||
        bytes memory signature
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(
 | 
			
		||||
            SIGNATURE_ERROR_SELECTOR,
 | 
			
		||||
            errorCode,
 | 
			
		||||
            hash,
 | 
			
		||||
            signature
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function InvalidOriginError(
 | 
			
		||||
        address expectedOrigin
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(
 | 
			
		||||
            INVALID_ORIGIN_ERROR_SELECTOR,
 | 
			
		||||
            expectedOrigin
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function InvalidApprovalSignatureError(
 | 
			
		||||
        bytes32 transactionHash,
 | 
			
		||||
        address approverAddress
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(
 | 
			
		||||
            INVALID_APPROVAL_SIGNATURE_ERROR_SELECTOR,
 | 
			
		||||
            transactionHash,
 | 
			
		||||
            approverAddress
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -21,15 +21,13 @@ pragma solidity ^0.5.9;
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LibEIP712CoordinatorDomain is
 | 
			
		||||
    LibEIP712
 | 
			
		||||
{
 | 
			
		||||
contract LibEIP712CoordinatorDomain {
 | 
			
		||||
 | 
			
		||||
    // EIP712 Domain Name value for the Coordinator
 | 
			
		||||
    string constant public EIP712_COORDINATOR_DOMAIN_NAME = "0x Protocol Coordinator";
 | 
			
		||||
 | 
			
		||||
    // EIP712 Domain Version value for the Coordinator
 | 
			
		||||
    string constant public EIP712_COORDINATOR_DOMAIN_VERSION = "2.0.0";
 | 
			
		||||
    string constant public EIP712_COORDINATOR_DOMAIN_VERSION = "3.0.0";
 | 
			
		||||
 | 
			
		||||
    // Hash of the EIP712 Domain Separator data for the Coordinator
 | 
			
		||||
    // solhint-disable-next-line var-name-mixedcase
 | 
			
		||||
@@ -43,7 +41,9 @@ contract LibEIP712CoordinatorDomain is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        address verifyingContractAddress = verifyingContractAddressIfExists == address(0) ? address(this) : verifyingContractAddressIfExists;
 | 
			
		||||
        address verifyingContractAddress = verifyingContractAddressIfExists == address(0)
 | 
			
		||||
            ? address(this)
 | 
			
		||||
            : verifyingContractAddressIfExists;
 | 
			
		||||
        EIP712_COORDINATOR_DOMAIN_HASH = LibEIP712.hashEIP712Domain(
 | 
			
		||||
            EIP712_COORDINATOR_DOMAIN_NAME,
 | 
			
		||||
            EIP712_COORDINATOR_DOMAIN_VERSION,
 | 
			
		||||
@@ -55,7 +55,7 @@ contract LibEIP712CoordinatorDomain is
 | 
			
		||||
    /// @dev Calculates EIP712 encoding for a hash struct in the EIP712 domain
 | 
			
		||||
    ///      of this contract.
 | 
			
		||||
    /// @param hashStruct The EIP712 hash struct.
 | 
			
		||||
    /// @return EIP712 hash applied to this EIP712 Domain.
 | 
			
		||||
    /// @return result EIP712 hash applied to this EIP712 Domain.
 | 
			
		||||
    function _hashEIP712CoordinatorMessage(bytes32 hashStruct)
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ contract MixinCoordinatorRegistryCore is
 | 
			
		||||
    mapping (address => string) internal coordinatorEndpoints;
 | 
			
		||||
 | 
			
		||||
    /// @dev Called by a Coordinator operator to set the endpoint of their Coordinator.
 | 
			
		||||
    /// @param coordinatorEndpoint endpoint of the Coordinator.
 | 
			
		||||
    /// @param coordinatorEndpoint Endpoint of the Coordinator as a string.
 | 
			
		||||
    function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external {
 | 
			
		||||
        address coordinatorOperator = msg.sender;
 | 
			
		||||
        coordinatorEndpoints[coordinatorOperator] = coordinatorEndpoint;
 | 
			
		||||
@@ -37,7 +37,8 @@ contract MixinCoordinatorRegistryCore is
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets the endpoint for a Coordinator.
 | 
			
		||||
    /// @param coordinatorOperator operator of the Coordinator endpoint.
 | 
			
		||||
    /// @param coordinatorOperator Operator of the Coordinator endpoint.
 | 
			
		||||
    /// @return coordinatorEndpoint Endpoint of the Coordinator as a string.
 | 
			
		||||
    function getCoordinatorEndpoint(address coordinatorOperator)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
 
 | 
			
		||||
@@ -29,11 +29,12 @@ contract ICoordinatorRegistryCore
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Called by a Coordinator operator to set the endpoint of their Coordinator.
 | 
			
		||||
    /// @param coordinatorEndpoint endpoint of the Coordinator.
 | 
			
		||||
    /// @param coordinatorEndpoint Endpoint of the Coordinator as a string.
 | 
			
		||||
    function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets the endpoint for a Coordinator.
 | 
			
		||||
    /// @param coordinatorOperator operator of the Coordinator endpoint.
 | 
			
		||||
    /// @param coordinatorOperator Operator of the Coordinator endpoint.
 | 
			
		||||
    /// @return coordinatorEndpoint Endpoint of the Coordinator as a string.
 | 
			
		||||
    function getCoordinatorEndpoint(address coordinatorOperator)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-coordinator",
 | 
			
		||||
    "version": "2.1.0-beta.0",
 | 
			
		||||
    "version": "2.1.0-beta.2",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "build": "yarn pre_build && tsc -b",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
 | 
			
		||||
        "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",
 | 
			
		||||
@@ -21,21 +21,23 @@
 | 
			
		||||
        "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} --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",
 | 
			
		||||
        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/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",
 | 
			
		||||
        "contracts:gen": "contracts-gen generate",
 | 
			
		||||
        "contracts:copy": "contracts-gen copy",
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
 | 
			
		||||
        "compile:truffle": "truffle compile"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(Coordinator|CoordinatorRegistry).json",
 | 
			
		||||
        "publicInterfaceContracts": "Coordinator,CoordinatorRegistry,LibCoordinatorApproval,LibCoordinatorRichErrors,LibEIP712CoordinatorDomain,LibConstants",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(Coordinator|CoordinatorRegistry|ICoordinatorApprovalVerifier|ICoordinatorCore|ICoordinatorRegistryCore|ICoordinatorSignatureValidator|LibConstants|LibCoordinatorApproval|LibCoordinatorRichErrors|LibEIP712CoordinatorDomain|MixinCoordinatorApprovalVerifier|MixinCoordinatorCore|MixinCoordinatorRegistryCore|MixinSignatureValidator).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -48,12 +50,18 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^4.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@0x/abi-gen": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.3.0-beta.2",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^0.1.0-beta.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.3.0-beta.2",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.2.0-beta.2",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.2",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.2",
 | 
			
		||||
        "@0x/order-utils": "^8.5.0-beta.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/tslint-config": "^3.1.0-beta.2",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.2",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -61,6 +69,7 @@
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
        "dirty-chai": "^2.0.1",
 | 
			
		||||
        "lodash": "^4.17.11",
 | 
			
		||||
        "make-promises-safe": "^1.1.0",
 | 
			
		||||
        "mocha": "^6.2.0",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
@@ -71,20 +80,12 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.1.0-beta.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.0",
 | 
			
		||||
        "@0x/order-utils": "^8.5.0-beta.0",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.0",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.0",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.0",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.2",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.2",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.2"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,8 @@
 | 
			
		||||
import { signingUtils } from '@0x/contracts-test-utils';
 | 
			
		||||
import { hexConcat, signingUtils } from '@0x/contracts-test-utils';
 | 
			
		||||
import { SignatureType, SignedZeroExTransaction } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
 | 
			
		||||
import { hashUtils, SignedCoordinatorApproval } from './index';
 | 
			
		||||
import { hashUtils } from './hash_utils';
 | 
			
		||||
import { SignedCoordinatorApproval } from './types';
 | 
			
		||||
 | 
			
		||||
export class ApprovalFactory {
 | 
			
		||||
    private readonly _privateKey: Buffer;
 | 
			
		||||
@@ -14,24 +13,21 @@ export class ApprovalFactory {
 | 
			
		||||
        this._verifyingContractAddress = verifyingContract;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public newSignedApproval(
 | 
			
		||||
    public async newSignedApprovalAsync(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
        approvalExpirationTimeSeconds: BigNumber,
 | 
			
		||||
        signatureType: SignatureType = SignatureType.EthSign,
 | 
			
		||||
    ): SignedCoordinatorApproval {
 | 
			
		||||
        const approvalHashBuff = hashUtils.getApprovalHashBuffer(
 | 
			
		||||
    ): Promise<SignedCoordinatorApproval> {
 | 
			
		||||
        const approvalHashBuff = await hashUtils.getApprovalHashBufferAsync(
 | 
			
		||||
            transaction,
 | 
			
		||||
            this._verifyingContractAddress,
 | 
			
		||||
            txOrigin,
 | 
			
		||||
            approvalExpirationTimeSeconds,
 | 
			
		||||
        );
 | 
			
		||||
        const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
 | 
			
		||||
        const signedApproval = {
 | 
			
		||||
            txOrigin,
 | 
			
		||||
            transaction,
 | 
			
		||||
            approvalExpirationTimeSeconds,
 | 
			
		||||
            signature: ethUtil.addHexPrefix(signatureBuff.toString('hex')),
 | 
			
		||||
            signature: hexConcat(signatureBuff),
 | 
			
		||||
        };
 | 
			
		||||
        return signedApproval;
 | 
			
		||||
    }
 | 
			
		||||
@@ -7,7 +7,15 @@ import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as Coordinator from '../generated-artifacts/Coordinator.json';
 | 
			
		||||
import * as CoordinatorRegistry from '../generated-artifacts/CoordinatorRegistry.json';
 | 
			
		||||
import * as LibConstants from '../generated-artifacts/LibConstants.json';
 | 
			
		||||
import * as LibCoordinatorApproval from '../generated-artifacts/LibCoordinatorApproval.json';
 | 
			
		||||
import * as LibCoordinatorRichErrors from '../generated-artifacts/LibCoordinatorRichErrors.json';
 | 
			
		||||
import * as LibEIP712CoordinatorDomain from '../generated-artifacts/LibEIP712CoordinatorDomain.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    Coordinator: Coordinator as ContractArtifact,
 | 
			
		||||
    CoordinatorRegistry: CoordinatorRegistry as ContractArtifact,
 | 
			
		||||
    LibCoordinatorApproval: LibCoordinatorApproval as ContractArtifact,
 | 
			
		||||
    LibCoordinatorRichErrors: LibCoordinatorRichErrors as ContractArtifact,
 | 
			
		||||
    LibEIP712CoordinatorDomain: LibEIP712CoordinatorDomain as ContractArtifact,
 | 
			
		||||
    LibConstants: LibConstants as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,28 @@
 | 
			
		||||
import { hexConcat } from '@0x/contracts-test-utils';
 | 
			
		||||
import { eip712Utils } from '@0x/order-utils';
 | 
			
		||||
import { SignedZeroExTransaction } from '@0x/types';
 | 
			
		||||
import { BigNumber, signTypedDataUtils } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import { signTypedDataUtils } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
export const hashUtils = {
 | 
			
		||||
    getApprovalHashBuffer(
 | 
			
		||||
    async getApprovalHashBufferAsync(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        verifyingContract: string,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
        approvalExpirationTimeSeconds: BigNumber,
 | 
			
		||||
    ): Buffer {
 | 
			
		||||
        const typedData = eip712Utils.createCoordinatorApprovalTypedData(
 | 
			
		||||
    ): Promise<Buffer> {
 | 
			
		||||
        const typedData = await eip712Utils.createCoordinatorApprovalTypedDataAsync(
 | 
			
		||||
            transaction,
 | 
			
		||||
            verifyingContract,
 | 
			
		||||
            txOrigin,
 | 
			
		||||
            approvalExpirationTimeSeconds,
 | 
			
		||||
        );
 | 
			
		||||
        const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
 | 
			
		||||
        return hashBuffer;
 | 
			
		||||
    },
 | 
			
		||||
    getApprovalHashHex(
 | 
			
		||||
    async getApprovalHashHexAsync(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        verifyingContract: string,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
        approvalExpirationTimeSeconds: BigNumber,
 | 
			
		||||
    ): string {
 | 
			
		||||
        const hashHex = `0x${hashUtils
 | 
			
		||||
            .getApprovalHashBuffer(transaction, verifyingContract, txOrigin, approvalExpirationTimeSeconds)
 | 
			
		||||
            .toString('hex')}`;
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        const hashHex = hexConcat(await hashUtils.getApprovalHashBufferAsync(transaction, verifyingContract, txOrigin));
 | 
			
		||||
        return hashHex;
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
export * from './artifacts';
 | 
			
		||||
export * from './wrappers';
 | 
			
		||||
export * from '../test/utils';
 | 
			
		||||
export import CoordinatorRevertErrors = require('./revert_errors');
 | 
			
		||||
export { ApprovalFactory } from './approval_factory';
 | 
			
		||||
export { SignedCoordinatorApproval } from './types';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								contracts/coordinator/src/revert_errors.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								contracts/coordinator/src/revert_errors.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
import { BigNumber, RevertError } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
// tslint:disable:max-classes-per-file
 | 
			
		||||
 | 
			
		||||
export enum SignatureErrorCodes {
 | 
			
		||||
    InvalidLength,
 | 
			
		||||
    Unsupported,
 | 
			
		||||
    Illegal,
 | 
			
		||||
    Invalid,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class SignatureError extends RevertError {
 | 
			
		||||
    constructor(errorCode?: SignatureErrorCodes, hash?: string, signature?: string) {
 | 
			
		||||
        super('SignatureError', 'SignatureError(uint8 errorCode, bytes32 hash, bytes signature)', {
 | 
			
		||||
            errorCode,
 | 
			
		||||
            hash,
 | 
			
		||||
            signature,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class InvalidOriginError extends RevertError {
 | 
			
		||||
    constructor(expectedOrigin?: string) {
 | 
			
		||||
        super('InvalidOriginError', 'InvalidOriginError(address expectedOrigin)', { expectedOrigin });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ApprovalExpiredError extends RevertError {
 | 
			
		||||
    constructor(transactionHash?: string, approvalExpirationTime?: BigNumber | number | string) {
 | 
			
		||||
        super('ApprovalExpiredError', 'ApprovalExpiredError(bytes32 transactionHash, uint256 approvalExpirationTime)', {
 | 
			
		||||
            transactionHash,
 | 
			
		||||
            approvalExpirationTime,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class InvalidApprovalSignatureError extends RevertError {
 | 
			
		||||
    constructor(transactionHash?: string, approverAddress?: string) {
 | 
			
		||||
        super(
 | 
			
		||||
            'InvalidApprovalSignatureError',
 | 
			
		||||
            'InvalidApprovalSignatureError(bytes32 transactionHash, address approverAddress)',
 | 
			
		||||
            { transactionHash, approverAddress },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const types = [SignatureError, InvalidOriginError, ApprovalExpiredError, InvalidApprovalSignatureError];
 | 
			
		||||
 | 
			
		||||
// Register the types we've defined.
 | 
			
		||||
for (const type of types) {
 | 
			
		||||
    RevertError.registerType(type);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
import { SignedZeroExTransaction } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
export interface CoordinatorApproval {
 | 
			
		||||
    transaction: SignedZeroExTransaction;
 | 
			
		||||
    txOrigin: string;
 | 
			
		||||
    approvalExpirationTimeSeconds: BigNumber;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface SignedCoordinatorApproval extends CoordinatorApproval {
 | 
			
		||||
@@ -5,3 +5,7 @@
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/coordinator';
 | 
			
		||||
export * from '../generated-wrappers/coordinator_registry';
 | 
			
		||||
export * from '../generated-wrappers/lib_constants';
 | 
			
		||||
export * from '../generated-wrappers/lib_coordinator_approval';
 | 
			
		||||
export * from '../generated-wrappers/lib_coordinator_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_e_i_p712_coordinator_domain';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								contracts/coordinator/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								contracts/coordinator/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as Coordinator from '../test/generated-artifacts/Coordinator.json';
 | 
			
		||||
import * as CoordinatorRegistry from '../test/generated-artifacts/CoordinatorRegistry.json';
 | 
			
		||||
import * as ICoordinatorApprovalVerifier from '../test/generated-artifacts/ICoordinatorApprovalVerifier.json';
 | 
			
		||||
import * as ICoordinatorCore from '../test/generated-artifacts/ICoordinatorCore.json';
 | 
			
		||||
import * as ICoordinatorRegistryCore from '../test/generated-artifacts/ICoordinatorRegistryCore.json';
 | 
			
		||||
import * as ICoordinatorSignatureValidator from '../test/generated-artifacts/ICoordinatorSignatureValidator.json';
 | 
			
		||||
import * as LibConstants from '../test/generated-artifacts/LibConstants.json';
 | 
			
		||||
import * as LibCoordinatorApproval from '../test/generated-artifacts/LibCoordinatorApproval.json';
 | 
			
		||||
import * as LibCoordinatorRichErrors from '../test/generated-artifacts/LibCoordinatorRichErrors.json';
 | 
			
		||||
import * as LibEIP712CoordinatorDomain from '../test/generated-artifacts/LibEIP712CoordinatorDomain.json';
 | 
			
		||||
import * as MixinCoordinatorApprovalVerifier from '../test/generated-artifacts/MixinCoordinatorApprovalVerifier.json';
 | 
			
		||||
import * as MixinCoordinatorCore from '../test/generated-artifacts/MixinCoordinatorCore.json';
 | 
			
		||||
import * as MixinCoordinatorRegistryCore from '../test/generated-artifacts/MixinCoordinatorRegistryCore.json';
 | 
			
		||||
import * as MixinSignatureValidator from '../test/generated-artifacts/MixinSignatureValidator.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    Coordinator: Coordinator as ContractArtifact,
 | 
			
		||||
    MixinCoordinatorApprovalVerifier: MixinCoordinatorApprovalVerifier as ContractArtifact,
 | 
			
		||||
    MixinCoordinatorCore: MixinCoordinatorCore as ContractArtifact,
 | 
			
		||||
    MixinSignatureValidator: MixinSignatureValidator as ContractArtifact,
 | 
			
		||||
    ICoordinatorApprovalVerifier: ICoordinatorApprovalVerifier as ContractArtifact,
 | 
			
		||||
    ICoordinatorCore: ICoordinatorCore as ContractArtifact,
 | 
			
		||||
    ICoordinatorSignatureValidator: ICoordinatorSignatureValidator as ContractArtifact,
 | 
			
		||||
    LibConstants: LibConstants as ContractArtifact,
 | 
			
		||||
    LibCoordinatorApproval: LibCoordinatorApproval as ContractArtifact,
 | 
			
		||||
    LibCoordinatorRichErrors: LibCoordinatorRichErrors as ContractArtifact,
 | 
			
		||||
    LibEIP712CoordinatorDomain: LibEIP712CoordinatorDomain as ContractArtifact,
 | 
			
		||||
    CoordinatorRegistry: CoordinatorRegistry as ContractArtifact,
 | 
			
		||||
    MixinCoordinatorRegistryCore: MixinCoordinatorRegistryCore as ContractArtifact,
 | 
			
		||||
    ICoordinatorRegistryCore: ICoordinatorRegistryCore as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,531 +0,0 @@
 | 
			
		||||
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as exchangeArtifacts,
 | 
			
		||||
    constants as exchangeConstants,
 | 
			
		||||
    ExchangeCancelEventArgs,
 | 
			
		||||
    ExchangeCancelUpToEventArgs,
 | 
			
		||||
    ExchangeContract,
 | 
			
		||||
    exchangeDataEncoder,
 | 
			
		||||
    ExchangeFillEventArgs,
 | 
			
		||||
    ExchangeFunctionName,
 | 
			
		||||
} from '@0x/contracts-exchange';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectTransactionFailedAsync,
 | 
			
		||||
    getLatestBlockTimestampAsync,
 | 
			
		||||
    OrderFactory,
 | 
			
		||||
    provider,
 | 
			
		||||
    TransactionFactory,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber, providerUtils } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import { ApprovalFactory, artifacts, CoordinatorContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi);
 | 
			
		||||
// tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
describe('Coordinator tests', () => {
 | 
			
		||||
    let chainId: number;
 | 
			
		||||
    let makerAddress: string;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let takerAddress: string;
 | 
			
		||||
    let feeRecipientAddress: string;
 | 
			
		||||
 | 
			
		||||
    let erc20Proxy: ERC20ProxyContract;
 | 
			
		||||
    let erc20TokenA: DummyERC20TokenContract;
 | 
			
		||||
    let erc20TokenB: DummyERC20TokenContract;
 | 
			
		||||
    let makerFeeToken: DummyERC20TokenContract;
 | 
			
		||||
    let coordinatorContract: CoordinatorContract;
 | 
			
		||||
    let exchange: ExchangeContract;
 | 
			
		||||
 | 
			
		||||
    let erc20Wrapper: ERC20Wrapper;
 | 
			
		||||
    let orderFactory: OrderFactory;
 | 
			
		||||
    let takerTransactionFactory: TransactionFactory;
 | 
			
		||||
    let makerTransactionFactory: TransactionFactory;
 | 
			
		||||
    let approvalFactory: ApprovalFactory;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        chainId = await providerUtils.getChainIdAsync(provider);
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts.slice(0, 4));
 | 
			
		||||
 | 
			
		||||
        erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
			
		||||
        const numDummyErc20ToDeploy = 3;
 | 
			
		||||
        [erc20TokenA, erc20TokenB, makerFeeToken] = await erc20Wrapper.deployDummyTokensAsync(
 | 
			
		||||
            numDummyErc20ToDeploy,
 | 
			
		||||
            constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
        );
 | 
			
		||||
        await erc20Wrapper.setBalancesAndAllowancesAsync();
 | 
			
		||||
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            exchangeArtifacts.Exchange,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await exchange.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Coordinator,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Configure order defaults
 | 
			
		||||
        const defaultOrderParams = {
 | 
			
		||||
            ...constants.STATIC_ORDER_PARAMS,
 | 
			
		||||
            senderAddress: coordinatorContract.address,
 | 
			
		||||
            makerAddress,
 | 
			
		||||
            feeRecipientAddress,
 | 
			
		||||
            makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
 | 
			
		||||
            takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
 | 
			
		||||
            makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address),
 | 
			
		||||
            takerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address),
 | 
			
		||||
            exchangeAddress: exchange.address,
 | 
			
		||||
            chainId,
 | 
			
		||||
        };
 | 
			
		||||
        const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
 | 
			
		||||
        const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
 | 
			
		||||
        const feeRecipientPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(feeRecipientAddress)];
 | 
			
		||||
        orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
 | 
			
		||||
        makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address, chainId);
 | 
			
		||||
        takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address, chainId);
 | 
			
		||||
        approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address);
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('single order fills', () => {
 | 
			
		||||
        for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) {
 | 
			
		||||
            it(`${fnName} should fill the order with a signed approval`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: takerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const fillLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                    log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
 | 
			
		||||
                );
 | 
			
		||||
                expect(fillLogs.length).to.eq(1);
 | 
			
		||||
                const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
 | 
			
		||||
                expect(fillLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
                expect(fillLogArgs.takerAddress).to.eq(takerAddress);
 | 
			
		||||
                expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
                expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
                expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
 | 
			
		||||
                expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
 | 
			
		||||
                expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount);
 | 
			
		||||
                expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount);
 | 
			
		||||
                expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee);
 | 
			
		||||
                expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee);
 | 
			
		||||
                expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should fill the order if called by approver`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        feeRecipientAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [],
 | 
			
		||||
                        [],
 | 
			
		||||
                        { from: feeRecipientAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const fillLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                    log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
 | 
			
		||||
                );
 | 
			
		||||
                expect(fillLogs.length).to.eq(1);
 | 
			
		||||
                const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
 | 
			
		||||
                expect(fillLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
                expect(fillLogArgs.takerAddress).to.eq(takerAddress);
 | 
			
		||||
                expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
                expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
                expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
 | 
			
		||||
                expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
 | 
			
		||||
                expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount);
 | 
			
		||||
                expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount);
 | 
			
		||||
                expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee);
 | 
			
		||||
                expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee);
 | 
			
		||||
                expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert with no approval signature`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [],
 | 
			
		||||
                        [],
 | 
			
		||||
                        {
 | 
			
		||||
                            from: takerAddress,
 | 
			
		||||
                            gas: constants.MAX_EXECUTE_TRANSACTION_GAS,
 | 
			
		||||
                        },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert with an invalid approval signature`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [signature],
 | 
			
		||||
                        { from: takerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert with an expired approval`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: takerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.ApprovalExpired,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert if not called by tx signer or approver`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: owner },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidOrigin,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    describe('batch order fills', () => {
 | 
			
		||||
        for (const fnName of [...exchangeConstants.MARKET_FILL_FN_NAMES, ...exchangeConstants.BATCH_FILL_FN_NAMES]) {
 | 
			
		||||
            it(`${fnName} should fill the orders with a signed approval`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS },
 | 
			
		||||
                    ),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const fillLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                    log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
 | 
			
		||||
                );
 | 
			
		||||
                expect(fillLogs.length).to.eq(orders.length);
 | 
			
		||||
                orders.forEach((order, index) => {
 | 
			
		||||
                    const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
 | 
			
		||||
                    expect(fillLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
                    expect(fillLogArgs.takerAddress).to.eq(takerAddress);
 | 
			
		||||
                    expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
                    expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
                    expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData);
 | 
			
		||||
                    expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData);
 | 
			
		||||
                    expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount);
 | 
			
		||||
                    expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount);
 | 
			
		||||
                    expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee);
 | 
			
		||||
                    expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee);
 | 
			
		||||
                    expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should fill the orders if called by approver`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                    await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        feeRecipientAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [],
 | 
			
		||||
                        [],
 | 
			
		||||
                        { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS },
 | 
			
		||||
                    ),
 | 
			
		||||
                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                );
 | 
			
		||||
                const fillLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                    log => (log as LogWithDecodedArgs<ExchangeFillEventArgs>).event === 'Fill',
 | 
			
		||||
                );
 | 
			
		||||
                expect(fillLogs.length).to.eq(orders.length);
 | 
			
		||||
                orders.forEach((order, index) => {
 | 
			
		||||
                    const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs<ExchangeFillEventArgs>).args;
 | 
			
		||||
                    expect(fillLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
                    expect(fillLogArgs.takerAddress).to.eq(takerAddress);
 | 
			
		||||
                    expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
                    expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
                    expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData);
 | 
			
		||||
                    expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData);
 | 
			
		||||
                    expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount);
 | 
			
		||||
                    expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount);
 | 
			
		||||
                    expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee);
 | 
			
		||||
                    expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee);
 | 
			
		||||
                    expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert with an invalid approval signature`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [signature],
 | 
			
		||||
                        { from: takerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert with an expired approval`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: takerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.ApprovalExpired,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`${fnName} should revert if not called by tx signer or approver`, async () => {
 | 
			
		||||
                const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await expectTransactionFailedAsync(
 | 
			
		||||
                    coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        takerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: owner },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidOrigin,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    describe('cancels', () => {
 | 
			
		||||
        it('cancelOrder call should be successful without an approval', async () => {
 | 
			
		||||
            const orders = [await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
            const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrder, orders);
 | 
			
		||||
            const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
            const cancelLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                log => (log as LogWithDecodedArgs<ExchangeCancelEventArgs>).event === 'Cancel',
 | 
			
		||||
            );
 | 
			
		||||
            expect(cancelLogs.length).to.eq(1);
 | 
			
		||||
            const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs<ExchangeCancelEventArgs>).args;
 | 
			
		||||
            expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
            expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
            expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
            expect(cancelLogArgs.makerAssetData).to.eq(orders[0].makerAssetData);
 | 
			
		||||
            expect(cancelLogArgs.takerAssetData).to.eq(orders[0].takerAssetData);
 | 
			
		||||
            expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0]));
 | 
			
		||||
        });
 | 
			
		||||
        it('batchCancelOrders call should be successful without an approval', async () => {
 | 
			
		||||
            const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()];
 | 
			
		||||
            const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.BatchCancelOrders, orders);
 | 
			
		||||
            const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
            const cancelLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                log => (log as LogWithDecodedArgs<ExchangeCancelEventArgs>).event === 'Cancel',
 | 
			
		||||
            );
 | 
			
		||||
            expect(cancelLogs.length).to.eq(orders.length);
 | 
			
		||||
            orders.forEach((order, index) => {
 | 
			
		||||
                const cancelLogArgs = (cancelLogs[index] as LogWithDecodedArgs<ExchangeCancelEventArgs>).args;
 | 
			
		||||
                expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
                expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
                expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress);
 | 
			
		||||
                expect(cancelLogArgs.makerAssetData).to.eq(order.makerAssetData);
 | 
			
		||||
                expect(cancelLogArgs.takerAssetData).to.eq(order.takerAssetData);
 | 
			
		||||
                expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order));
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        it('cancelOrdersUpTo call should be successful without an approval', async () => {
 | 
			
		||||
            const targetEpoch = constants.ZERO_AMOUNT;
 | 
			
		||||
            const data = exchange.cancelOrdersUpTo.getABIEncodedTransactionData(targetEpoch);
 | 
			
		||||
            const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await coordinatorContract.executeTransaction.sendTransactionAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    makerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    {
 | 
			
		||||
                        from: makerAddress,
 | 
			
		||||
                    },
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
            const cancelLogs = transactionReceipt.logs.filter(
 | 
			
		||||
                log => (log as LogWithDecodedArgs<ExchangeCancelUpToEventArgs>).event === 'CancelUpTo',
 | 
			
		||||
            );
 | 
			
		||||
            expect(cancelLogs.length).to.eq(1);
 | 
			
		||||
            const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs<ExchangeCancelUpToEventArgs>).args;
 | 
			
		||||
            expect(cancelLogArgs.makerAddress).to.eq(makerAddress);
 | 
			
		||||
            expect(cancelLogArgs.orderSenderAddress).to.eq(coordinatorContract.address);
 | 
			
		||||
            expect(cancelLogArgs.orderEpoch).to.bignumber.eq(targetEpoch.plus(1));
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
@@ -1,81 +1,73 @@
 | 
			
		||||
import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange';
 | 
			
		||||
import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
import { blockchainTests, expect, verifyEvents } from '@0x/contracts-test-utils';
 | 
			
		||||
 | 
			
		||||
import { CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { CoordinatorRegistryWrapper } from './utils/coordinator_registry_wrapper';
 | 
			
		||||
import { CoordinatorRegistryContract, CoordinatorRegistryCoordinatorEndpointSetEventArgs } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi);
 | 
			
		||||
// tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
describe('Coordinator Registry tests', () => {
 | 
			
		||||
blockchainTests.resets('Coordinator Registry tests', env => {
 | 
			
		||||
    let coordinatorRegistry: CoordinatorRegistryContract;
 | 
			
		||||
    let coordinatorOperator: string;
 | 
			
		||||
    const coordinatorEndpoint = 'http://sometec.0x.org';
 | 
			
		||||
    const nilCoordinatorEndpoint = '';
 | 
			
		||||
    let coordinatorRegistryWrapper: CoordinatorRegistryWrapper;
 | 
			
		||||
    // tests
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        // setup accounts (skip owner)
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const accounts = await env.getAccountAddressesAsync();
 | 
			
		||||
        [, coordinatorOperator] = accounts;
 | 
			
		||||
        // deploy coordinator registry
 | 
			
		||||
        coordinatorRegistryWrapper = new CoordinatorRegistryWrapper(provider);
 | 
			
		||||
        await coordinatorRegistryWrapper.deployCoordinatorRegistryAsync();
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
        coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.CoordinatorRegistry,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    describe('core', () => {
 | 
			
		||||
        it('Should successfully set a Coordinator endpoint', async () => {
 | 
			
		||||
            await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint);
 | 
			
		||||
            const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
            );
 | 
			
		||||
            await coordinatorRegistry.setCoordinatorEndpoint(coordinatorEndpoint).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: coordinatorOperator,
 | 
			
		||||
            });
 | 
			
		||||
            const recordedCoordinatorEndpoint = await coordinatorRegistry
 | 
			
		||||
                .getCoordinatorEndpoint(coordinatorOperator)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
 | 
			
		||||
        });
 | 
			
		||||
        it('Should successfully unset a Coordinator endpoint', async () => {
 | 
			
		||||
            // set Coordinator endpoint
 | 
			
		||||
            await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint);
 | 
			
		||||
            let recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
            );
 | 
			
		||||
            await coordinatorRegistry.setCoordinatorEndpoint(coordinatorEndpoint).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: coordinatorOperator,
 | 
			
		||||
            });
 | 
			
		||||
            let recordedCoordinatorEndpoint = await coordinatorRegistry
 | 
			
		||||
                .getCoordinatorEndpoint(coordinatorOperator)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
 | 
			
		||||
            // unset Coordinator endpoint
 | 
			
		||||
            await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, nilCoordinatorEndpoint);
 | 
			
		||||
            recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
            );
 | 
			
		||||
            await coordinatorRegistry.setCoordinatorEndpoint(nilCoordinatorEndpoint).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: coordinatorOperator,
 | 
			
		||||
            });
 | 
			
		||||
            recordedCoordinatorEndpoint = await coordinatorRegistry
 | 
			
		||||
                .getCoordinatorEndpoint(coordinatorOperator)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(recordedCoordinatorEndpoint).to.be.equal(nilCoordinatorEndpoint);
 | 
			
		||||
        });
 | 
			
		||||
        it('Should emit an event when setting Coordinator endpoint', async () => {
 | 
			
		||||
            // set Coordinator endpoint
 | 
			
		||||
            const txReceipt = await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
                coordinatorEndpoint,
 | 
			
		||||
            );
 | 
			
		||||
            const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync(
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
            );
 | 
			
		||||
            const txReceipt = await coordinatorRegistry
 | 
			
		||||
                .setCoordinatorEndpoint(coordinatorEndpoint)
 | 
			
		||||
                .awaitTransactionSuccessAsync({
 | 
			
		||||
                    from: coordinatorOperator,
 | 
			
		||||
                });
 | 
			
		||||
            const recordedCoordinatorEndpoint = await coordinatorRegistry
 | 
			
		||||
                .getCoordinatorEndpoint(coordinatorOperator)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint);
 | 
			
		||||
            // validate event
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(1);
 | 
			
		||||
            const log = txReceipt.logs[0] as LogWithDecodedArgs<CoordinatorRegistryCoordinatorEndpointSetEventArgs>;
 | 
			
		||||
            expect(log.args.coordinatorOperator).to.be.equal(coordinatorOperator);
 | 
			
		||||
            expect(log.args.coordinatorEndpoint).to.be.equal(coordinatorEndpoint);
 | 
			
		||||
            const expectedEvent: CoordinatorRegistryCoordinatorEndpointSetEventArgs = {
 | 
			
		||||
                coordinatorOperator,
 | 
			
		||||
                coordinatorEndpoint,
 | 
			
		||||
            };
 | 
			
		||||
            verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,67 +1,35 @@
 | 
			
		||||
import { chaiSetup, constants, provider, randomAddress, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { transactionHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { BigNumber, providerUtils } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { blockchainTests, constants, expect, randomAddress, transactionHashUtils } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { artifacts, CoordinatorContract, hashUtils } from '../src';
 | 
			
		||||
import { hashUtils } from '../src/hash_utils';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
describe('Libs tests', () => {
 | 
			
		||||
import { CoordinatorContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('Libs tests', env => {
 | 
			
		||||
    let coordinatorContract: CoordinatorContract;
 | 
			
		||||
    let chainId: number;
 | 
			
		||||
    const exchangeAddress = randomAddress();
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        chainId = await providerUtils.getChainIdAsync(provider);
 | 
			
		||||
        chainId = await env.getChainIdAsync();
 | 
			
		||||
        coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Coordinator,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            exchangeAddress,
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getTransactionHash', () => {
 | 
			
		||||
        it('should return the correct transaction hash', async () => {
 | 
			
		||||
            const tx = {
 | 
			
		||||
                salt: new BigNumber(0),
 | 
			
		||||
                expirationTimeSeconds: new BigNumber(0),
 | 
			
		||||
                signerAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                data: '0x1234',
 | 
			
		||||
                domain: {
 | 
			
		||||
                    verifyingContract: exchangeAddress,
 | 
			
		||||
                    chainId,
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
            const expectedTxHash = transactionHashUtils.getTransactionHashHex(tx);
 | 
			
		||||
            const txHash = await coordinatorContract.getTransactionHash.callAsync(tx);
 | 
			
		||||
            expect(expectedTxHash).to.eq(txHash);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getApprovalHash', () => {
 | 
			
		||||
        it('should return the correct approval hash', async () => {
 | 
			
		||||
            const signedTx = {
 | 
			
		||||
                salt: new BigNumber(0),
 | 
			
		||||
                expirationTimeSeconds: new BigNumber(0),
 | 
			
		||||
                salt: constants.ZERO_AMOUNT,
 | 
			
		||||
                gasPrice: constants.ZERO_AMOUNT,
 | 
			
		||||
                expirationTimeSeconds: constants.ZERO_AMOUNT,
 | 
			
		||||
                signerAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                data: '0x1234',
 | 
			
		||||
                signature: '0x5678',
 | 
			
		||||
@@ -70,21 +38,18 @@ describe('Libs tests', () => {
 | 
			
		||||
                    chainId,
 | 
			
		||||
                },
 | 
			
		||||
            };
 | 
			
		||||
            const approvalExpirationTimeSeconds = new BigNumber(0);
 | 
			
		||||
            const txOrigin = constants.NULL_ADDRESS;
 | 
			
		||||
            const approval = {
 | 
			
		||||
                txOrigin,
 | 
			
		||||
                transactionHash: transactionHashUtils.getTransactionHashHex(signedTx),
 | 
			
		||||
                transactionSignature: signedTx.signature,
 | 
			
		||||
                approvalExpirationTimeSeconds,
 | 
			
		||||
            };
 | 
			
		||||
            const expectedApprovalHash = hashUtils.getApprovalHashHex(
 | 
			
		||||
            const expectedApprovalHash = await hashUtils.getApprovalHashHexAsync(
 | 
			
		||||
                signedTx,
 | 
			
		||||
                coordinatorContract.address,
 | 
			
		||||
                txOrigin,
 | 
			
		||||
                approvalExpirationTimeSeconds,
 | 
			
		||||
            );
 | 
			
		||||
            const approvalHash = await coordinatorContract.getCoordinatorApprovalHash.callAsync(approval);
 | 
			
		||||
            const approvalHash = await coordinatorContract.getCoordinatorApprovalHash(approval).callAsync();
 | 
			
		||||
            expect(expectedApprovalHash).to.eq(approvalHash);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,28 @@
 | 
			
		||||
import { constants as exchangeConstants, exchangeDataEncoder, ExchangeFunctionName } from '@0x/contracts-exchange';
 | 
			
		||||
import { exchangeDataEncoder } from '@0x/contracts-exchange';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectContractCallFailedAsync,
 | 
			
		||||
    getLatestBlockTimestampAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    ExchangeFunctionName,
 | 
			
		||||
    expect,
 | 
			
		||||
    hexConcat,
 | 
			
		||||
    hexSlice,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
    TransactionFactory,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
    transactionHashUtils,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { transactionHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber, LibBytesRevertErrors, providerUtils } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
import { LibBytesRevertErrors } from '@0x/contracts-utils';
 | 
			
		||||
import { SignatureType, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { ApprovalFactory, artifacts, CoordinatorContract } from '../src';
 | 
			
		||||
import CoordinatorRevertErrors = require('../src/revert_errors');
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
import { ApprovalFactory } from '../src/approval_factory';
 | 
			
		||||
 | 
			
		||||
describe('Mixins tests', () => {
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { CoordinatorContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
    let chainId: number;
 | 
			
		||||
    let transactionSignerAddress: string;
 | 
			
		||||
    let approvalSignerAddress1: string;
 | 
			
		||||
@@ -36,23 +35,17 @@ describe('Mixins tests', () => {
 | 
			
		||||
    const exchangeAddress = randomAddress();
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        chainId = await providerUtils.getChainIdAsync(provider);
 | 
			
		||||
        chainId = await env.getChainIdAsync();
 | 
			
		||||
        mixins = await CoordinatorContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Coordinator,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            exchangeAddress,
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3);
 | 
			
		||||
        const accounts = await env.getAccountAddressesAsync();
 | 
			
		||||
        [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts;
 | 
			
		||||
        defaultOrder = {
 | 
			
		||||
            makerAddress: constants.NULL_ADDRESS,
 | 
			
		||||
            takerAddress: constants.NULL_ADDRESS,
 | 
			
		||||
@@ -79,72 +72,91 @@ describe('Mixins tests', () => {
 | 
			
		||||
        approvalFactory1 = new ApprovalFactory(approvalSignerPrivateKey1, mixins.address);
 | 
			
		||||
        approvalFactory2 = new ApprovalFactory(approvalSignerPrivateKey2, mixins.address);
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getSignerAddress', () => {
 | 
			
		||||
        it('should return the correct address using the EthSign signature type', async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data }, SignatureType.EthSign);
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
 | 
			
		||||
            const signerAddress = await mixins.getSignerAddress(transactionHash, transaction.signature).callAsync();
 | 
			
		||||
            expect(transaction.signerAddress).to.eq(signerAddress);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return the correct address using the EIP712 signature type', async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data }, SignatureType.EIP712);
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            const signerAddress = await mixins.getSignerAddress.callAsync(transactionHash, transaction.signature);
 | 
			
		||||
            const signerAddress = await mixins.getSignerAddress(transactionHash, transaction.signature).callAsync();
 | 
			
		||||
            expect(transaction.signerAddress).to.eq(signerAddress);
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert with with the Illegal signature type', async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const illegalSignatureByte = ethUtil.toBuffer(SignatureType.Illegal).toString('hex');
 | 
			
		||||
            transaction.signature = `${transaction.signature.slice(
 | 
			
		||||
                0,
 | 
			
		||||
                transaction.signature.length - 2,
 | 
			
		||||
            )}${illegalSignatureByte}`;
 | 
			
		||||
            transaction.signature = hexConcat(
 | 
			
		||||
                hexSlice(transaction.signature, 0, transaction.signature.length - 1),
 | 
			
		||||
                SignatureType.Illegal,
 | 
			
		||||
            );
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
 | 
			
		||||
                RevertReason.SignatureIllegal,
 | 
			
		||||
            expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
 | 
			
		||||
                new CoordinatorRevertErrors.SignatureError(
 | 
			
		||||
                    CoordinatorRevertErrors.SignatureErrorCodes.Illegal,
 | 
			
		||||
                    transactionHash,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert with with the Invalid signature type', async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const invalidSignatureByte = ethUtil.toBuffer(SignatureType.Invalid).toString('hex');
 | 
			
		||||
            transaction.signature = `0x${invalidSignatureByte}`;
 | 
			
		||||
            transaction.signature = hexConcat(SignatureType.Invalid);
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
 | 
			
		||||
                RevertReason.SignatureInvalid,
 | 
			
		||||
            expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
 | 
			
		||||
                new CoordinatorRevertErrors.SignatureError(
 | 
			
		||||
                    CoordinatorRevertErrors.SignatureErrorCodes.Invalid,
 | 
			
		||||
                    transactionHash,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it("should revert with with a signature type that doesn't exist", async () => {
 | 
			
		||||
        it('should revert with with a signature type that equals `NSignatureTypes`', async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            const invalidSignatureByte = '04';
 | 
			
		||||
            transaction.signature = `${transaction.signature.slice(
 | 
			
		||||
                0,
 | 
			
		||||
                transaction.signature.length - 2,
 | 
			
		||||
            )}${invalidSignatureByte}`;
 | 
			
		||||
            transaction.signature = hexConcat(
 | 
			
		||||
                hexSlice(transaction.signature, 0, transaction.signature.length - 1),
 | 
			
		||||
                SignatureType.NSignatureTypes,
 | 
			
		||||
            );
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
 | 
			
		||||
                RevertReason.SignatureUnsupported,
 | 
			
		||||
            expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
 | 
			
		||||
                new CoordinatorRevertErrors.SignatureError(
 | 
			
		||||
                    CoordinatorRevertErrors.SignatureErrorCodes.Unsupported,
 | 
			
		||||
                    transactionHash,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it("should revert with with a signature type that isn't supported", async () => {
 | 
			
		||||
            const data = constants.NULL_BYTES;
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            transaction.signature = hexConcat(
 | 
			
		||||
                hexSlice(transaction.signature, 0, transaction.signature.length - 1),
 | 
			
		||||
                SignatureType.Wallet,
 | 
			
		||||
            );
 | 
			
		||||
            const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
            expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
 | 
			
		||||
                new CoordinatorRevertErrors.SignatureError(
 | 
			
		||||
                    CoordinatorRevertErrors.SignatureErrorCodes.Unsupported,
 | 
			
		||||
                    transactionHash,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('decodeOrdersFromFillData', () => {
 | 
			
		||||
        for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) {
 | 
			
		||||
        for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
 | 
			
		||||
            it(`should correctly decode the orders for ${fnName} data`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
                const decodedSignedOrders = decodedOrders.map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    signature: constants.NULL_BYTES,
 | 
			
		||||
@@ -154,11 +166,11 @@ describe('Mixins tests', () => {
 | 
			
		||||
                expect(orders).to.deep.eq(decodedSignedOrders);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        for (const fnName of exchangeConstants.BATCH_FILL_FN_NAMES) {
 | 
			
		||||
        for (const fnName of constants.BATCH_FILL_FN_NAMES) {
 | 
			
		||||
            it(`should correctly decode the orders for ${fnName} data`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
                const decodedSignedOrders = decodedOrders.map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    signature: constants.NULL_BYTES,
 | 
			
		||||
@@ -168,11 +180,11 @@ describe('Mixins tests', () => {
 | 
			
		||||
                expect(orders).to.deep.eq(decodedSignedOrders);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        for (const fnName of exchangeConstants.MARKET_FILL_FN_NAMES) {
 | 
			
		||||
        for (const fnName of constants.MARKET_FILL_FN_NAMES) {
 | 
			
		||||
            it(`should correctly decode the orders for ${fnName} data`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
                const decodedSignedOrders = decodedOrders.map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    signature: constants.NULL_BYTES,
 | 
			
		||||
@@ -182,22 +194,32 @@ describe('Mixins tests', () => {
 | 
			
		||||
                expect(orders).to.deep.eq(decodedSignedOrders);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        for (const fnName of [
 | 
			
		||||
            ExchangeFunctionName.CancelOrder,
 | 
			
		||||
            ExchangeFunctionName.BatchCancelOrders,
 | 
			
		||||
            ExchangeFunctionName.CancelOrdersUpTo,
 | 
			
		||||
        ]) {
 | 
			
		||||
        for (const fnName of constants.MATCH_ORDER_FN_NAMES) {
 | 
			
		||||
            it(`should correctly decode the orders for ${fnName} data`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
                const decodedSignedOrders = decodedOrders.map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    signature: constants.NULL_BYTES,
 | 
			
		||||
                    exchangeAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                    chainId,
 | 
			
		||||
                }));
 | 
			
		||||
                expect(orders).to.deep.eq(decodedSignedOrders);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        for (const fnName of constants.CANCEL_ORDER_FN_NAMES) {
 | 
			
		||||
            it(`should correctly decode the orders for ${fnName} data`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
                const emptyArray: any[] = [];
 | 
			
		||||
                expect(emptyArray).to.deep.eq(decodedOrders);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        it('should decode an empty array for invalid data', async () => {
 | 
			
		||||
            const data = '0x0123456789';
 | 
			
		||||
            const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data);
 | 
			
		||||
            const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
 | 
			
		||||
            const emptyArray: any[] = [];
 | 
			
		||||
            expect(emptyArray).to.deep.eq(decodedOrders);
 | 
			
		||||
        });
 | 
			
		||||
@@ -208,33 +230,24 @@ describe('Mixins tests', () => {
 | 
			
		||||
                new BigNumber(3), // the length of data
 | 
			
		||||
                new BigNumber(4),
 | 
			
		||||
            );
 | 
			
		||||
            return expect(mixins.decodeOrdersFromFillData.callAsync(data)).to.revertWith(expectedError);
 | 
			
		||||
            return expect(mixins.decodeOrdersFromFillData(data).callAsync()).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('Single order approvals', () => {
 | 
			
		||||
        for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
        for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const order = {
 | 
			
		||||
                    ...defaultOrder,
 | 
			
		||||
                    senderAddress: constants.NULL_ADDRESS,
 | 
			
		||||
@@ -242,457 +255,257 @@ describe('Mixins tests', () => {
 | 
			
		||||
                const orders = [order];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    approvalSignerAddress1,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    {
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
 | 
			
		||||
                    .callAsync({
 | 
			
		||||
                        from: approvalSignerAddress1,
 | 
			
		||||
                    },
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    approvalSignerAddress1,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: approvalSignerAddress1 },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress1 });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    approvalSignerAddress1,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    {
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
 | 
			
		||||
                    .callAsync({
 | 
			
		||||
                        from: approvalSignerAddress1,
 | 
			
		||||
                    },
 | 
			
		||||
                );
 | 
			
		||||
                    });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const signature = hexConcat(
 | 
			
		||||
                    hexSlice(approval.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
                    hexSlice(approval.signature, 6),
 | 
			
		||||
                );
 | 
			
		||||
                const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [signature],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
 | 
			
		||||
                const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
                expect(tx).to.revertWith(
 | 
			
		||||
                    new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.ApprovalExpired,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval.signature],
 | 
			
		||||
                        { from: approvalSignerAddress2 },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidOrigin,
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress2 });
 | 
			
		||||
                expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    describe('Batch order approvals', () => {
 | 
			
		||||
        for (const fnName of [
 | 
			
		||||
            ...exchangeConstants.BATCH_FILL_FN_NAMES,
 | 
			
		||||
            ...exchangeConstants.MARKET_FILL_FN_NAMES,
 | 
			
		||||
            ExchangeFunctionName.MatchOrders,
 | 
			
		||||
            ...constants.BATCH_FILL_FN_NAMES,
 | 
			
		||||
            ...constants.MARKET_FILL_FN_NAMES,
 | 
			
		||||
            ...constants.MATCH_ORDER_FN_NAMES,
 | 
			
		||||
        ]) {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder].map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    senderAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                }));
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder].map(order => ({
 | 
			
		||||
                    ...order,
 | 
			
		||||
                    senderAddress: constants.NULL_ADDRESS,
 | 
			
		||||
                }));
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2], expiration=[valid,valid]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
 | 
			
		||||
                    [approval1.signature, approval2.signature],
 | 
			
		||||
                    { from: transactionSignerAddress },
 | 
			
		||||
                );
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval1.signature,
 | 
			
		||||
                        approval2.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
 | 
			
		||||
            it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    approvalSignerAddress1,
 | 
			
		||||
                    transaction.signature,
 | 
			
		||||
                    [],
 | 
			
		||||
                    [],
 | 
			
		||||
                    { from: approvalSignerAddress1 },
 | 
			
		||||
                );
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress1 });
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval2.signature],
 | 
			
		||||
                        { from: approvalSignerAddress1 },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidOrigin,
 | 
			
		||||
                );
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval2.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress1 });
 | 
			
		||||
                expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [],
 | 
			
		||||
                        [],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
 | 
			
		||||
                const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
                expect(tx).to.revertWith(
 | 
			
		||||
                    new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const signature = hexConcat(
 | 
			
		||||
                    hexSlice(approval.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
                    hexSlice(approval.signature, 6),
 | 
			
		||||
                );
 | 
			
		||||
                const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`;
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [signature],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
 | 
			
		||||
                const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
                expect(tx).to.revertWith(
 | 
			
		||||
                    new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid], expiration=[valid,valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approvalSignature2 = hexConcat(
 | 
			
		||||
                    hexSlice(approval2.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
                    hexSlice(approval2.signature, 6),
 | 
			
		||||
                );
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`;
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval1.signature, approvalSignature2],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval1.signature,
 | 
			
		||||
                        approvalSignature2,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
 | 
			
		||||
                const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
                expect(tx).to.revertWith(
 | 
			
		||||
                    new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2),
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approvalSignature2 = hexConcat(
 | 
			
		||||
                    hexSlice(approval2.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
                    hexSlice(approval2.signature, 6),
 | 
			
		||||
                );
 | 
			
		||||
                const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`;
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        approvalSignerAddress1,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approvalSignature2],
 | 
			
		||||
                        { from: approvalSignerAddress1 },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidApprovalSignature,
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
 | 
			
		||||
                        approvalSignature2,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress1 });
 | 
			
		||||
 | 
			
		||||
                const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
 | 
			
		||||
                expect(tx).to.revertWith(
 | 
			
		||||
                    new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2),
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,valid], expiration=[valid,invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds1 = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approvalExpirationTimeSeconds2 = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds1,
 | 
			
		||||
                );
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds2,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2],
 | 
			
		||||
                        [approval1.signature, approval2.signature],
 | 
			
		||||
                        { from: transactionSignerAddress },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.ApprovalExpired,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid], expiration=[invalid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        approvalSignerAddress1,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval2.signature],
 | 
			
		||||
                        { from: approvalSignerAddress1 },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.ApprovalExpired,
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid], expiration=[valid]`, async () => {
 | 
			
		||||
            it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid]`, async () => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(
 | 
			
		||||
                    transaction,
 | 
			
		||||
                    transactionSignerAddress,
 | 
			
		||||
                    approvalExpirationTimeSeconds,
 | 
			
		||||
                );
 | 
			
		||||
                expectContractCallFailedAsync(
 | 
			
		||||
                    mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                        transaction,
 | 
			
		||||
                        transactionSignerAddress,
 | 
			
		||||
                        transaction.signature,
 | 
			
		||||
                        [approvalExpirationTimeSeconds],
 | 
			
		||||
                        [approval1.signature],
 | 
			
		||||
                        { from: approvalSignerAddress2 },
 | 
			
		||||
                    ),
 | 
			
		||||
                    RevertReason.InvalidOrigin,
 | 
			
		||||
                );
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval1.signature,
 | 
			
		||||
                    ])
 | 
			
		||||
                    .callAsync({ from: approvalSignerAddress2 });
 | 
			
		||||
                expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
@@ -701,39 +514,24 @@ describe('Mixins tests', () => {
 | 
			
		||||
            const orders = [defaultOrder];
 | 
			
		||||
            const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrder, orders);
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                transaction,
 | 
			
		||||
                transactionSignerAddress,
 | 
			
		||||
                transaction.signature,
 | 
			
		||||
                [],
 | 
			
		||||
                [],
 | 
			
		||||
                { from: transactionSignerAddress },
 | 
			
		||||
            );
 | 
			
		||||
            await mixins
 | 
			
		||||
                .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
 | 
			
		||||
                .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
        });
 | 
			
		||||
        it('should allow the tx signer to call `batchCancelOrders` without approval', async () => {
 | 
			
		||||
            const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
            const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.BatchCancelOrders, orders);
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                transaction,
 | 
			
		||||
                transactionSignerAddress,
 | 
			
		||||
                transaction.signature,
 | 
			
		||||
                [],
 | 
			
		||||
                [],
 | 
			
		||||
                { from: transactionSignerAddress },
 | 
			
		||||
            );
 | 
			
		||||
            await mixins
 | 
			
		||||
                .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
 | 
			
		||||
                .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
        });
 | 
			
		||||
        it('should allow the tx signer to call `cancelOrdersUpTo` without approval', async () => {
 | 
			
		||||
            const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrdersUpTo);
 | 
			
		||||
            const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
            await mixins.assertValidCoordinatorApprovals.callAsync(
 | 
			
		||||
                transaction,
 | 
			
		||||
                transactionSignerAddress,
 | 
			
		||||
                transaction.signature,
 | 
			
		||||
                [],
 | 
			
		||||
                [],
 | 
			
		||||
                { from: transactionSignerAddress },
 | 
			
		||||
            );
 | 
			
		||||
            await mixins
 | 
			
		||||
                .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
 | 
			
		||||
                .callAsync({ from: transactionSignerAddress });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,65 +0,0 @@
 | 
			
		||||
import { LogDecoder, txDefaults } from '@0x/contracts-test-utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import { TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import { artifacts, CoordinatorRegistryContract } from '../../src';
 | 
			
		||||
 | 
			
		||||
export class CoordinatorRegistryWrapper {
 | 
			
		||||
    private readonly _web3Wrapper: Web3Wrapper;
 | 
			
		||||
    private readonly _provider: ZeroExProvider;
 | 
			
		||||
    private readonly _logDecoder: LogDecoder;
 | 
			
		||||
    private _coordinatorRegistryContract?: CoordinatorRegistryContract;
 | 
			
		||||
    /**
 | 
			
		||||
     * Instanitates an CoordinatorRegistryWrapper
 | 
			
		||||
     * @param provider Web3 provider to use for all JSON RPC requests
 | 
			
		||||
     * Instance of CoordinatorRegistryWrapper
 | 
			
		||||
     */
 | 
			
		||||
    constructor(provider: ZeroExProvider) {
 | 
			
		||||
        this._web3Wrapper = new Web3Wrapper(provider);
 | 
			
		||||
        this._provider = provider;
 | 
			
		||||
        this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
 | 
			
		||||
    }
 | 
			
		||||
    public async deployCoordinatorRegistryAsync(): Promise<CoordinatorRegistryContract> {
 | 
			
		||||
        this._coordinatorRegistryContract = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.CoordinatorRegistry,
 | 
			
		||||
            this._provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        if (this._coordinatorRegistryContract === undefined) {
 | 
			
		||||
            throw new Error(`Failed to deploy Coordinator Registry contract.`);
 | 
			
		||||
        }
 | 
			
		||||
        return this._coordinatorRegistryContract;
 | 
			
		||||
    }
 | 
			
		||||
    public async setCoordinatorEndpointAsync(
 | 
			
		||||
        coordinatorOperator: string,
 | 
			
		||||
        coordinatorEndpoint: string,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        this._assertCoordinatorRegistryDeployed();
 | 
			
		||||
        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await (this
 | 
			
		||||
                ._coordinatorRegistryContract as CoordinatorRegistryContract).setCoordinatorEndpoint.sendTransactionAsync(
 | 
			
		||||
                coordinatorEndpoint,
 | 
			
		||||
                {
 | 
			
		||||
                    from: coordinatorOperator,
 | 
			
		||||
                },
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    public async getCoordinatorEndpointAsync(coordinatorOperator: string): Promise<string> {
 | 
			
		||||
        this._assertCoordinatorRegistryDeployed();
 | 
			
		||||
        const coordinatorEndpoint = await (this
 | 
			
		||||
            ._coordinatorRegistryContract as CoordinatorRegistryContract).getCoordinatorEndpoint.callAsync(
 | 
			
		||||
            coordinatorOperator,
 | 
			
		||||
        );
 | 
			
		||||
        return coordinatorEndpoint;
 | 
			
		||||
    }
 | 
			
		||||
    private _assertCoordinatorRegistryDeployed(): void {
 | 
			
		||||
        if (this._coordinatorRegistryContract === undefined) {
 | 
			
		||||
            throw new Error(
 | 
			
		||||
                'The Coordinator Registry contract was not deployed through the CoordinatorRegistryWrapper. Call `deployCoordinatorRegistryAsync` to deploy.',
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
export { hashUtils } from './hash_utils';
 | 
			
		||||
export { ApprovalFactory } from './approval_factory';
 | 
			
		||||
export * from './types';
 | 
			
		||||
							
								
								
									
										19
									
								
								contracts/coordinator/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								contracts/coordinator/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/coordinator';
 | 
			
		||||
export * from '../test/generated-wrappers/coordinator_registry';
 | 
			
		||||
export * from '../test/generated-wrappers/i_coordinator_approval_verifier';
 | 
			
		||||
export * from '../test/generated-wrappers/i_coordinator_core';
 | 
			
		||||
export * from '../test/generated-wrappers/i_coordinator_registry_core';
 | 
			
		||||
export * from '../test/generated-wrappers/i_coordinator_signature_validator';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_constants';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_coordinator_approval';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_coordinator_rich_errors';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_e_i_p712_coordinator_domain';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_coordinator_approval_verifier';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_coordinator_core';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_coordinator_registry_core';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_signature_validator';
 | 
			
		||||
@@ -2,6 +2,27 @@
 | 
			
		||||
    "extends": "../../tsconfig",
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": ["generated-artifacts/Coordinator.json", "generated-artifacts/CoordinatorRegistry.json"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/Coordinator.json",
 | 
			
		||||
        "generated-artifacts/CoordinatorRegistry.json",
 | 
			
		||||
        "generated-artifacts/LibConstants.json",
 | 
			
		||||
        "generated-artifacts/LibCoordinatorApproval.json",
 | 
			
		||||
        "generated-artifacts/LibCoordinatorRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibEIP712CoordinatorDomain.json",
 | 
			
		||||
        "test/generated-artifacts/Coordinator.json",
 | 
			
		||||
        "test/generated-artifacts/CoordinatorRegistry.json",
 | 
			
		||||
        "test/generated-artifacts/ICoordinatorApprovalVerifier.json",
 | 
			
		||||
        "test/generated-artifacts/ICoordinatorCore.json",
 | 
			
		||||
        "test/generated-artifacts/ICoordinatorRegistryCore.json",
 | 
			
		||||
        "test/generated-artifacts/ICoordinatorSignatureValidator.json",
 | 
			
		||||
        "test/generated-artifacts/LibConstants.json",
 | 
			
		||||
        "test/generated-artifacts/LibCoordinatorApproval.json",
 | 
			
		||||
        "test/generated-artifacts/LibCoordinatorRichErrors.json",
 | 
			
		||||
        "test/generated-artifacts/LibEIP712CoordinatorDomain.json",
 | 
			
		||||
        "test/generated-artifacts/MixinCoordinatorApprovalVerifier.json",
 | 
			
		||||
        "test/generated-artifacts/MixinCoordinatorCore.json",
 | 
			
		||||
        "test/generated-artifacts/MixinCoordinatorRegistryCore.json",
 | 
			
		||||
        "test/generated-artifacts/MixinSignatureValidator.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								contracts/dev-utils/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/dev-utils/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Blacklist all files
 | 
			
		||||
.*
 | 
			
		||||
*
 | 
			
		||||
# Whitelist lib
 | 
			
		||||
!lib/**/*
 | 
			
		||||
# Whitelist Solidity contracts
 | 
			
		||||
!contracts/src/**/*
 | 
			
		||||
# Blacklist tests in lib
 | 
			
		||||
/lib/test/*
 | 
			
		||||
# Package specific ignore
 | 
			
		||||
@@ -1,4 +1,36 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.1.0-beta.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
			
		||||
                "pr": 2330
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add new method getOrderHash() to DevUtils contract",
 | 
			
		||||
                "pr": 2321
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add new method getTransactionHash() to DevUtils contract",
 | 
			
		||||
                "pr": 2321
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1574030254
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.1.0-beta.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `encodeStaticCallAssetData` and `decodeStaticCallAssetData` in LibAssetData",
 | 
			
		||||
                "pr": 2034
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `revertIfInvalidAssetData` in LibAssetData",
 | 
			
		||||
                "pr": 2034
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1573159180
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.1.0-beta.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,17 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.1.0-beta.2 - _November 17, 2019_
 | 
			
		||||
 | 
			
		||||
    * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
 | 
			
		||||
    * Add new method getOrderHash() to DevUtils contract (#2321)
 | 
			
		||||
    * Add new method getTransactionHash() to DevUtils contract (#2321)
 | 
			
		||||
 | 
			
		||||
## v0.1.0-beta.1 - _November 7, 2019_
 | 
			
		||||
 | 
			
		||||
    * Add `encodeStaticCallAssetData` and `decodeStaticCallAssetData` in LibAssetData (#2034)
 | 
			
		||||
    * Add `revertIfInvalidAssetData` in LibAssetData (#2034)
 | 
			
		||||
 | 
			
		||||
## v0.1.0-beta.0 - _October 3, 2019_
 | 
			
		||||
 | 
			
		||||
    * Use built in selectors instead of hard coded constants (#2055)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./generated-artifacts",
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
        "evmVersion": "constantinople",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "runs": 10000,
 | 
			
		||||
            "runs": 1666,
 | 
			
		||||
            "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
 | 
			
		||||
        },
 | 
			
		||||
        "outputSelection": {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,11 @@
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "./OrderValidationUtils.sol";
 | 
			
		||||
import "./OrderTransferSimulationUtils.sol";
 | 
			
		||||
import "./LibTransactionDecoder.sol";
 | 
			
		||||
@@ -29,6 +34,7 @@ import "./EthBalanceChecker.sol";
 | 
			
		||||
contract DevUtils is
 | 
			
		||||
    OrderValidationUtils,
 | 
			
		||||
    LibTransactionDecoder,
 | 
			
		||||
    LibEIP712ExchangeDomain,
 | 
			
		||||
    EthBalanceChecker,
 | 
			
		||||
    OrderTransferSimulationUtils
 | 
			
		||||
{
 | 
			
		||||
@@ -36,5 +42,32 @@ contract DevUtils is
 | 
			
		||||
        public
 | 
			
		||||
        OrderValidationUtils(_exchange)
 | 
			
		||||
        OrderTransferSimulationUtils(_exchange)
 | 
			
		||||
        LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    function getOrderHash(LibOrder.Order memory order, uint256 chainId, address exchange)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes32 orderHash)
 | 
			
		||||
    {
 | 
			
		||||
        return LibOrder.getTypedDataHash(
 | 
			
		||||
            order,
 | 
			
		||||
            LibEIP712.hashEIP712Domain(_EIP712_EXCHANGE_DOMAIN_NAME, _EIP712_EXCHANGE_DOMAIN_VERSION, chainId, exchange)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getTransactionHash(
 | 
			
		||||
        LibZeroExTransaction.ZeroExTransaction memory transaction,
 | 
			
		||||
        uint256 chainId,
 | 
			
		||||
        address exchange
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes32 transactionHash)
 | 
			
		||||
    {
 | 
			
		||||
        return LibZeroExTransaction.getTypedDataHash(
 | 
			
		||||
            transaction,
 | 
			
		||||
            LibEIP712.hashEIP712Domain(_EIP712_EXCHANGE_DOMAIN_NAME, _EIP712_EXCHANGE_DOMAIN_VERSION, chainId, exchange)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -316,6 +316,29 @@ contract LibAssetData {
 | 
			
		||||
        return (balances, allowances);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode AssetProxy identifier 
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
 | 
			
		||||
    /// @return The AssetProxy identifier
 | 
			
		||||
    function decodeAssetProxyId(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).ERC20Token.selector ||
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).ERC721Token.selector ||
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).ERC1155Assets.selector ||
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).MultiAsset.selector ||
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).StaticCall.selector,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
        return assetProxyId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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.
 | 
			
		||||
@@ -330,7 +353,7 @@ contract LibAssetData {
 | 
			
		||||
 | 
			
		||||
    /// @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 
 | 
			
		||||
    /// @return The AssetProxy identifier, and the address of the ERC-20 
 | 
			
		||||
    /// contract hosting this asset.
 | 
			
		||||
    function decodeERC20AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
@@ -515,4 +538,75 @@ contract LibAssetData {
 | 
			
		||||
        );
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode StaticCall asset data into the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param staticCallTargetAddress Target address of StaticCall.
 | 
			
		||||
    /// @param staticCallData Data that will be passed to staticCallTargetAddress in the StaticCall.
 | 
			
		||||
    /// @param expectedReturnDataHash Expected Keccak-256 hash of the StaticCall return data.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the set of assets.
 | 
			
		||||
    function encodeStaticCallAssetData(
 | 
			
		||||
        address staticCallTargetAddress,
 | 
			
		||||
        bytes memory staticCallData,
 | 
			
		||||
        bytes32 expectedReturnDataHash
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        assetData = abi.encodeWithSelector(
 | 
			
		||||
            IAssetData(address(0)).StaticCall.selector,
 | 
			
		||||
            staticCallTargetAddress,
 | 
			
		||||
            staticCallData,
 | 
			
		||||
            expectedReturnDataHash
 | 
			
		||||
        );
 | 
			
		||||
        return assetData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode StaticCall asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing a StaticCall asset
 | 
			
		||||
    /// @return The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be
 | 
			
		||||
    /// passed to the target address, and the expected Keccak-256 hash of the static call return data.
 | 
			
		||||
    function decodeStaticCallAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address staticCallTargetAddress,
 | 
			
		||||
            bytes memory staticCallData,
 | 
			
		||||
            bytes32 expectedReturnDataHash
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            assetProxyId == IAssetData(address(0)).StaticCall.selector,
 | 
			
		||||
            "WRONG_PROXY_ID"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        (staticCallTargetAddress, staticCallData, expectedReturnDataHash) = abi.decode(
 | 
			
		||||
            assetData.slice(4, assetData.length),
 | 
			
		||||
            (address, bytes, bytes32)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function revertIfInvalidAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure 
 | 
			
		||||
    {
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
 | 
			
		||||
            decodeERC20AssetData(assetData);
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
 | 
			
		||||
            decodeERC721AssetData(assetData);
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
 | 
			
		||||
            decodeERC1155AssetData(assetData);
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
 | 
			
		||||
            decodeMultiAssetData(assetData);
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
 | 
			
		||||
            decodeStaticCallAssetData(assetData);
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("WRONG_PROXY_ID");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,42 +1,32 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-dev-utils",
 | 
			
		||||
    "version": "0.1.0-beta.0",
 | 
			
		||||
    "version": "0.1.0-beta.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",
 | 
			
		||||
        "test": "yarn assert_deployable && echo !!! Tests are run via @0x/contracts-tests !!!",
 | 
			
		||||
        "assert_deployable": "node -e \"const bytecodeLen = (require('./generated-artifacts/DevUtils.json').compilerOutput.evm.bytecode.object.length-2)/2; assert(bytecodeLen<=0x6000,'DevUtils contract is too big to deploy, per EIP-170. '+bytecodeLen+'>'+0x6000)\"",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile quantify_bytecode contracts:gen 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": "UNLIMITED_CONTRACT_SIZE=true mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
 | 
			
		||||
        "pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers contracts:copy",
 | 
			
		||||
        "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} --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",
 | 
			
		||||
        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "contracts:gen": "contracts-gen generate",
 | 
			
		||||
        "contracts:copy": "contracts-gen copy",
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
 | 
			
		||||
        "quantify_bytecode": "echo EVM bytecode object lengths:;for i in ./generated-artifacts/*.json; do node -e \"console.log('$i\t' + (require('$i').compilerOutput.evm.bytecode.object.length - 2) / 2)\"; done",
 | 
			
		||||
        "quantify_bytecode": "echo EVM bytecode object lengths:;for i in ./test/generated-artifacts/*.json; do node -e \"console.log('$i\t' + (require('$i').compilerOutput.evm.bytecode.object.length - 2) / 2)\"; done",
 | 
			
		||||
        "compile:truffle": "truffle compile"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
 | 
			
		||||
        "publicInterfaceContracts": "DevUtils,LibAssetData,LibTransactionDecoder",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -49,21 +39,13 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^4.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@0x/abi-gen": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/assert": "^2.2.0-beta.2",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/tslint-config": "^3.1.0-beta.2",
 | 
			
		||||
        "@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": "^6.2.0",
 | 
			
		||||
        "ethers": "~4.0.4",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
        "solhint": "^1.4.1",
 | 
			
		||||
@@ -72,21 +54,8 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^2.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^2.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^2.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^2.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^3.1.0-beta.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.0",
 | 
			
		||||
        "@0x/order-utils": "^8.5.0-beta.0",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.0",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.0",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.0",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1"
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.2",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.2"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,16 +6,10 @@
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DevUtils from '../generated-artifacts/DevUtils.json';
 | 
			
		||||
import * as EthBalanceChecker from '../generated-artifacts/EthBalanceChecker.json';
 | 
			
		||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
 | 
			
		||||
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
 | 
			
		||||
import * as OrderTransferSimulationUtils from '../generated-artifacts/OrderTransferSimulationUtils.json';
 | 
			
		||||
import * as OrderValidationUtils from '../generated-artifacts/OrderValidationUtils.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    DevUtils: DevUtils as ContractArtifact,
 | 
			
		||||
    EthBalanceChecker: EthBalanceChecker as ContractArtifact,
 | 
			
		||||
    LibAssetData: LibAssetData as ContractArtifact,
 | 
			
		||||
    LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
 | 
			
		||||
    OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
 | 
			
		||||
    OrderValidationUtils: OrderValidationUtils as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,5 @@
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/dev_utils';
 | 
			
		||||
export * from '../generated-wrappers/eth_balance_checker';
 | 
			
		||||
export * from '../generated-wrappers/lib_asset_data';
 | 
			
		||||
export * from '../generated-wrappers/lib_transaction_decoder';
 | 
			
		||||
export * from '../generated-wrappers/order_transfer_simulation_utils';
 | 
			
		||||
export * from '../generated-wrappers/order_validation_utils';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								contracts/dev-utils/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								contracts/dev-utils/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DevUtils from '../test/generated-artifacts/DevUtils.json';
 | 
			
		||||
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json';
 | 
			
		||||
import * as LibAssetData from '../test/generated-artifacts/LibAssetData.json';
 | 
			
		||||
import * as LibTransactionDecoder from '../test/generated-artifacts/LibTransactionDecoder.json';
 | 
			
		||||
import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json';
 | 
			
		||||
import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    DevUtils: DevUtils as ContractArtifact,
 | 
			
		||||
    EthBalanceChecker: EthBalanceChecker as ContractArtifact,
 | 
			
		||||
    LibAssetData: LibAssetData as ContractArtifact,
 | 
			
		||||
    LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
 | 
			
		||||
    OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
 | 
			
		||||
    OrderValidationUtils: OrderValidationUtils as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,651 +0,0 @@
 | 
			
		||||
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 { OrderTransferResults, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber, providerUtils } 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/OrderTransferSimulatorUtils', () => {
 | 
			
		||||
    let makerAddress: string;
 | 
			
		||||
    let takerAddress: string;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let erc20AssetData: string;
 | 
			
		||||
    let erc20AssetData2: string;
 | 
			
		||||
    let erc721AssetData: string;
 | 
			
		||||
    let feeAssetData: string;
 | 
			
		||||
 | 
			
		||||
    let erc20Token: DummyERC20TokenContract;
 | 
			
		||||
    let erc20Token2: DummyERC20TokenContract;
 | 
			
		||||
    let feeErc20Token: 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 chainId = await providerUtils.getChainIdAsync(provider);
 | 
			
		||||
 | 
			
		||||
        const erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
        const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
 | 
			
		||||
        const numDummyErc20ToDeploy = 3;
 | 
			
		||||
        [erc20Token, erc20Token2, feeErc20Token] = await erc20Wrapper.deployDummyTokensAsync(
 | 
			
		||||
            numDummyErc20ToDeploy,
 | 
			
		||||
            constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
        );
 | 
			
		||||
        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
 | 
			
		||||
        erc721Proxy = await erc721Wrapper.deployProxyAsync();
 | 
			
		||||
 | 
			
		||||
        feeAssetData = assetDataUtils.encodeERC20AssetData(feeErc20Token.address);
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            exchangeArtifacts.Exchange,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            proxyArtifacts.MultiAssetProxy,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        const exchangeWrapper = new ExchangeWrapper(exchange);
 | 
			
		||||
        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,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
 | 
			
		||||
        erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address);
 | 
			
		||||
        erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
 | 
			
		||||
        const defaultOrderParams = {
 | 
			
		||||
            ...constants.STATIC_ORDER_PARAMS,
 | 
			
		||||
            makerAddress,
 | 
			
		||||
            feeRecipientAddress: constants.NULL_ADDRESS,
 | 
			
		||||
            makerAssetData: erc20AssetData,
 | 
			
		||||
            takerAssetData: erc20AssetData2,
 | 
			
		||||
            makerFeeAssetData: feeAssetData,
 | 
			
		||||
            takerFeeAssetData: feeAssetData,
 | 
			
		||||
            exchangeAddress: exchange.address,
 | 
			
		||||
            chainId,
 | 
			
		||||
        };
 | 
			
		||||
        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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                makerAddress,
 | 
			
		||||
                signedOrder.makerFee.dividedToIntegerBy(divisor),
 | 
			
		||||
            );
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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: feeAssetData,
 | 
			
		||||
                makerAssetAmount: new BigNumber(10),
 | 
			
		||||
                takerAssetAmount: new BigNumber(20),
 | 
			
		||||
                makerFee: new BigNumber(40),
 | 
			
		||||
            });
 | 
			
		||||
            const transferableMakerAssetAmount = new BigNumber(10);
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableMakerAssetAmount);
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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 feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee);
 | 
			
		||||
 | 
			
		||||
            await feeErc20Token.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),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should return correct info even when there are no fees specified', async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                makerFee: new BigNumber(0),
 | 
			
		||||
                takerFee: new BigNumber(0),
 | 
			
		||||
                makerFeeAssetData: '0x',
 | 
			
		||||
                takerFeeAssetData: '0x',
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [
 | 
			
		||||
                orderInfo,
 | 
			
		||||
                fillableTakerAssetAmount,
 | 
			
		||||
                isValidSignature,
 | 
			
		||||
            ] = 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);
 | 
			
		||||
            expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
 | 
			
		||||
            expect(isValidSignature).to.equal(true);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getOrderRelevantStates', async () => {
 | 
			
		||||
        it('should return the correct information for multiple orders', async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
 | 
			
		||||
            await feeErc20Token.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);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getSimulatedOrderTransferResults', () => {
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
            signedOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
        });
 | 
			
		||||
        it('should return TakerAssetDataFailed if the takerAsset transfer fails', async () => {
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.TakerAssetDataFailed);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return MakerAssetDataFailed if the makerAsset transfer fails', async () => {
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.MakerAssetDataFailed);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return TakerFeeAssetDataFailed if the takerFeeAsset transfer fails', async () => {
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.TakerFeeAssetDataFailed);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return MakerFeeAssetDataFailed if the makerFeeAsset transfer fails', async () => {
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.MakerFeeAssetDataFailed);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return TransfersSuccessful if all transfers succeed', async () => {
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
 | 
			
		||||
        });
 | 
			
		||||
        it('should return TransfersSuccessful for a partial fill when taker has ample assets for the fill but not for the whole order', async () => {
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount.dividedBy(2),
 | 
			
		||||
                {
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const orderTransferResults = await devUtils.getSimulatedOrderTransferResults.callAsync(
 | 
			
		||||
                signedOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                signedOrder.takerAssetAmount.dividedBy(2),
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('getSimulatedOrdersTransferResults', async () => {
 | 
			
		||||
        it('should simulate the transfers of each order independently from one another', async () => {
 | 
			
		||||
            // Set balances and allowances to exactly enough to fill a single order
 | 
			
		||||
            await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
 | 
			
		||||
                from: takerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            await feeErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
 | 
			
		||||
                from: makerAddress,
 | 
			
		||||
            });
 | 
			
		||||
            const [
 | 
			
		||||
                orderTransferResults1,
 | 
			
		||||
                orderTransferResults2,
 | 
			
		||||
            ] = await devUtils.getSimulatedOrdersTransferResults.callAsync(
 | 
			
		||||
                [signedOrder, signedOrder],
 | 
			
		||||
                [takerAddress, takerAddress],
 | 
			
		||||
                [signedOrder.takerAssetAmount, signedOrder.takerAssetAmount],
 | 
			
		||||
            );
 | 
			
		||||
            expect(orderTransferResults1).to.equal(OrderTransferResults.TransfersSuccessful);
 | 
			
		||||
            expect(orderTransferResults2).to.equal(OrderTransferResults.TransfersSuccessful);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
							
								
								
									
										11
									
								
								contracts/dev-utils/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								contracts/dev-utils/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/dev_utils';
 | 
			
		||||
export * from '../test/generated-wrappers/eth_balance_checker';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_asset_data';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_transaction_decoder';
 | 
			
		||||
export * from '../test/generated-wrappers/order_transfer_simulation_utils';
 | 
			
		||||
export * from '../test/generated-wrappers/order_validation_utils';
 | 
			
		||||
@@ -4,11 +4,14 @@
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/DevUtils.json",
 | 
			
		||||
        "generated-artifacts/EthBalanceChecker.json",
 | 
			
		||||
        "generated-artifacts/LibAssetData.json",
 | 
			
		||||
        "generated-artifacts/LibTransactionDecoder.json",
 | 
			
		||||
        "generated-artifacts/OrderTransferSimulationUtils.json",
 | 
			
		||||
        "generated-artifacts/OrderValidationUtils.json"
 | 
			
		||||
        "test/generated-artifacts/DevUtils.json",
 | 
			
		||||
        "test/generated-artifacts/EthBalanceChecker.json",
 | 
			
		||||
        "test/generated-artifacts/LibAssetData.json",
 | 
			
		||||
        "test/generated-artifacts/LibTransactionDecoder.json",
 | 
			
		||||
        "test/generated-artifacts/OrderTransferSimulationUtils.json",
 | 
			
		||||
        "test/generated-artifacts/OrderValidationUtils.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								contracts/erc1155/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/erc1155/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Blacklist all files
 | 
			
		||||
.*
 | 
			
		||||
*
 | 
			
		||||
# Whitelist lib
 | 
			
		||||
!lib/**/*
 | 
			
		||||
# Whitelist Solidity contracts
 | 
			
		||||
!contracts/src/**/*
 | 
			
		||||
# Blacklist tests in lib
 | 
			
		||||
/lib/test/*
 | 
			
		||||
# Package specific ignore
 | 
			
		||||
@@ -1,10 +1,33 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.2.0-beta.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
			
		||||
                "pr": 2330
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1574030254
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.2.0-beta.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1573159180
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.2.0-beta.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `mintKnownFungibleTokensAsync()`, `isNonFungibleItemAsync()`, `isFungibleItemAsync()`, `getOwnerOfAsync()`, `getBalanceAsync()` to `Erc1155Wrapper`.",
 | 
			
		||||
                "pr": 1819
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Replaced `SafeMath` with `LibSafeMath`",
 | 
			
		||||
                "pr": 2254
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1570135330
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,18 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.2.0-beta.2 - _November 17, 2019_
 | 
			
		||||
 | 
			
		||||
    * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
 | 
			
		||||
 | 
			
		||||
## v1.2.0-beta.1 - _November 7, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.2.0-beta.0 - _October 3, 2019_
 | 
			
		||||
 | 
			
		||||
    * Add `mintKnownFungibleTokensAsync()`, `isNonFungibleItemAsync()`, `isFungibleItemAsync()`, `getOwnerOfAsync()`, `getBalanceAsync()` to `Erc1155Wrapper`. (#1819)
 | 
			
		||||
    * Replaced `SafeMath` with `LibSafeMath` (#2254)
 | 
			
		||||
 | 
			
		||||
## v1.1.15 - _September 17, 2019_
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./generated-artifacts",
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibAddress.sol";
 | 
			
		||||
import "./interfaces/IERC1155.sol";
 | 
			
		||||
import "./interfaces/IERC1155Receiver.sol";
 | 
			
		||||
@@ -26,11 +26,11 @@ import "./MixinNonFungibleToken.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract ERC1155 is
 | 
			
		||||
    SafeMath,
 | 
			
		||||
    IERC1155,
 | 
			
		||||
    MixinNonFungibleToken
 | 
			
		||||
{
 | 
			
		||||
    using LibAddress for address;
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    // selectors for receiver callbacks
 | 
			
		||||
    bytes4 constant public ERC1155_RECEIVED       = 0xf23a6e61;
 | 
			
		||||
@@ -88,11 +88,11 @@ contract ERC1155 is
 | 
			
		||||
            nfOwners[id] = to;
 | 
			
		||||
            // You could keep balance of NF type in base type id like so:
 | 
			
		||||
            // uint256 baseType = getNonFungibleBaseType(_id);
 | 
			
		||||
            // balances[baseType][_from] = balances[baseType][_from]._safeSub(_value);
 | 
			
		||||
            // balances[baseType][_to]   = balances[baseType][_to]._safeAdd(_value);
 | 
			
		||||
            // balances[baseType][_from] = balances[baseType][_from].safeSub(_value);
 | 
			
		||||
            // balances[baseType][_to]   = balances[baseType][_to].safeAdd(_value);
 | 
			
		||||
        } else {
 | 
			
		||||
            balances[id][from] = _safeSub(balances[id][from], value);
 | 
			
		||||
            balances[id][to] = _safeAdd(balances[id][to], value);
 | 
			
		||||
            balances[id][from] = balances[id][from].safeSub(value);
 | 
			
		||||
            balances[id][to] = balances[id][to].safeAdd(value);
 | 
			
		||||
        }
 | 
			
		||||
        emit TransferSingle(msg.sender, from, to, id, value);
 | 
			
		||||
 | 
			
		||||
@@ -170,8 +170,8 @@ contract ERC1155 is
 | 
			
		||||
                );
 | 
			
		||||
                nfOwners[id] = to;
 | 
			
		||||
            } else {
 | 
			
		||||
                balances[id][from] = _safeSub(balances[id][from], value);
 | 
			
		||||
                balances[id][to] = _safeAdd(balances[id][to], value);
 | 
			
		||||
                balances[id][from] = balances[id][from].safeSub(value);
 | 
			
		||||
                balances[id][to] = balances[id][to].safeAdd(value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        emit TransferBatch(msg.sender, from, to, ids, values);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "./ERC1155.sol";
 | 
			
		||||
import "./interfaces/IERC1155Mintable.sol";
 | 
			
		||||
 | 
			
		||||
@@ -11,6 +11,7 @@ contract ERC1155Mintable is
 | 
			
		||||
    IERC1155Mintable,
 | 
			
		||||
    ERC1155
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    /// token nonce
 | 
			
		||||
    uint256 internal nonce;
 | 
			
		||||
@@ -37,7 +38,7 @@ contract ERC1155Mintable is
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 type_)
 | 
			
		||||
    { 
 | 
			
		||||
    {
 | 
			
		||||
        // Store the type in the upper 128 bits
 | 
			
		||||
        type_ = (++nonce << 128);
 | 
			
		||||
 | 
			
		||||
@@ -114,7 +115,7 @@ contract ERC1155Mintable is
 | 
			
		||||
            uint256 quantity = quantities[i];
 | 
			
		||||
 | 
			
		||||
            // Grant the items to the caller
 | 
			
		||||
            balances[id][dst] = _safeAdd(quantity, balances[id][dst]);
 | 
			
		||||
            balances[id][dst] = quantity.safeAdd(balances[id][dst]);
 | 
			
		||||
 | 
			
		||||
            // Emit the Transfer/Mint event.
 | 
			
		||||
            // the 0x0 source address implies a mint
 | 
			
		||||
@@ -172,7 +173,7 @@ contract ERC1155Mintable is
 | 
			
		||||
            nfOwners[id] = dst;
 | 
			
		||||
 | 
			
		||||
            // You could use base-type id to store NF type balances if you wish.
 | 
			
		||||
            // balances[_type][dst] = quantity._safeAdd(balances[_type][dst]);
 | 
			
		||||
            // balances[_type][dst] = quantity.safeAdd(balances[_type][dst]);
 | 
			
		||||
 | 
			
		||||
            emit TransferSingle(msg.sender, address(0x0), dst, id, 1);
 | 
			
		||||
 | 
			
		||||
@@ -194,6 +195,6 @@ contract ERC1155Mintable is
 | 
			
		||||
 | 
			
		||||
        // record the `maxIndex` of this nft type
 | 
			
		||||
        // this allows us to mint more nft's of this type in a subsequent call.
 | 
			
		||||
        maxIndex[type_] = _safeAdd(to.length, maxIndex[type_]);
 | 
			
		||||
        maxIndex[type_] = to.length.safeAdd(maxIndex[type_]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc1155",
 | 
			
		||||
    "version": "1.2.0-beta.0",
 | 
			
		||||
    "version": "1.2.0-beta.2",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "build": "yarn pre_build && tsc -b",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
 | 
			
		||||
        "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",
 | 
			
		||||
@@ -21,21 +21,23 @@
 | 
			
		||||
        "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} --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",
 | 
			
		||||
        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
 | 
			
		||||
        "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/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",
 | 
			
		||||
        "contracts:gen": "contracts-gen generate",
 | 
			
		||||
        "contracts:copy": "contracts-gen copy",
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol",
 | 
			
		||||
        "compile:truffle": "truffle compile"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(DummyERC1155Receiver|ERC1155|ERC1155Mintable|IERC1155|IERC1155Mintable|IERC1155Receiver|MixinNonFungibleToken).json",
 | 
			
		||||
        "publicInterfaceContracts": "ERC1155,ERC1155Mintable,IERC1155Receiver,DummyERC1155Receiver",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(DummyERC1155Receiver|ERC1155|ERC1155Mintable|IERC1155|IERC1155Mintable|IERC1155Receiver|MixinNonFungibleToken).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -48,11 +50,13 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^4.3.0-beta.0",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.0",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.0",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/tslint-config": "^3.0.1",
 | 
			
		||||
        "@0x/abi-gen": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/contracts-gen": "^1.1.0-beta.2",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.2",
 | 
			
		||||
        "@0x/dev-utils": "^2.4.0-beta.2",
 | 
			
		||||
        "@0x/sol-compiler": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/tslint-config": "^3.1.0-beta.2",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.2",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
@@ -70,14 +74,12 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.0",
 | 
			
		||||
        "@0x/contracts-utils": "^3.3.0-beta.0",
 | 
			
		||||
        "@0x/types": "^2.5.0-beta.0",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.0",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.0",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.0",
 | 
			
		||||
        "@0x/base-contract": "^5.5.0-beta.2",
 | 
			
		||||
        "@0x/contracts-test-utils": "^3.2.0-beta.2",
 | 
			
		||||
        "@0x/typescript-typings": "^4.4.0-beta.2",
 | 
			
		||||
        "@0x/utils": "^4.6.0-beta.2",
 | 
			
		||||
        "@0x/web3-wrapper": "^6.1.0-beta.2",
 | 
			
		||||
        "ethereum-types": "^2.2.0-beta.2",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,16 +8,10 @@ import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
import * as DummyERC1155Receiver from '../generated-artifacts/DummyERC1155Receiver.json';
 | 
			
		||||
import * as ERC1155 from '../generated-artifacts/ERC1155.json';
 | 
			
		||||
import * as ERC1155Mintable from '../generated-artifacts/ERC1155Mintable.json';
 | 
			
		||||
import * as IERC1155 from '../generated-artifacts/IERC1155.json';
 | 
			
		||||
import * as IERC1155Mintable from '../generated-artifacts/IERC1155Mintable.json';
 | 
			
		||||
import * as IERC1155Receiver from '../generated-artifacts/IERC1155Receiver.json';
 | 
			
		||||
import * as MixinNonFungibleToken from '../generated-artifacts/MixinNonFungibleToken.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    ERC1155: ERC1155 as ContractArtifact,
 | 
			
		||||
    ERC1155Mintable: ERC1155Mintable as ContractArtifact,
 | 
			
		||||
    MixinNonFungibleToken: MixinNonFungibleToken as ContractArtifact,
 | 
			
		||||
    IERC1155: IERC1155 as ContractArtifact,
 | 
			
		||||
    IERC1155Mintable: IERC1155Mintable as ContractArtifact,
 | 
			
		||||
    IERC1155Receiver: IERC1155Receiver as ContractArtifact,
 | 
			
		||||
    DummyERC1155Receiver: DummyERC1155Receiver as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
import { constants, LogDecoder } from '@0x/contracts-test-utils';
 | 
			
		||||
import { LogDecoder } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC1155MintableContract, ERC1155TransferSingleEventArgs } from '../../src';
 | 
			
		||||
import { ERC1155MintableContract, ERC1155TransferSingleEventArgs } from './wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +27,7 @@ export class Erc1155Wrapper {
 | 
			
		||||
        return this._erc1155Contract;
 | 
			
		||||
    }
 | 
			
		||||
    public async getBalancesAsync(owners: string[], tokens: BigNumber[]): Promise<BigNumber[]> {
 | 
			
		||||
        const balances = await this._erc1155Contract.balanceOfBatch.callAsync(owners, tokens);
 | 
			
		||||
        const balances = await this._erc1155Contract.balanceOfBatch(owners, tokens).callAsync();
 | 
			
		||||
        return balances;
 | 
			
		||||
    }
 | 
			
		||||
    public async safeTransferFromAsync(
 | 
			
		||||
@@ -39,7 +41,7 @@ export class Erc1155Wrapper {
 | 
			
		||||
        const spender = delegatedSpender === undefined ? from : delegatedSpender;
 | 
			
		||||
        const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
 | 
			
		||||
        const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this._erc1155Contract.safeTransferFrom.sendTransactionAsync(from, to, token, value, callbackDataHex, {
 | 
			
		||||
            await this._erc1155Contract.safeTransferFrom(from, to, token, value, callbackDataHex).sendTransactionAsync({
 | 
			
		||||
                from: spender,
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
@@ -56,14 +58,9 @@ export class Erc1155Wrapper {
 | 
			
		||||
        const spender = delegatedSpender === undefined ? from : delegatedSpender;
 | 
			
		||||
        const callbackDataHex = callbackData === undefined ? '0x' : callbackData;
 | 
			
		||||
        const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this._erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
 | 
			
		||||
                from,
 | 
			
		||||
                to,
 | 
			
		||||
                tokens,
 | 
			
		||||
                values,
 | 
			
		||||
                callbackDataHex,
 | 
			
		||||
                { from: spender },
 | 
			
		||||
            ),
 | 
			
		||||
            await this._erc1155Contract
 | 
			
		||||
                .safeBatchTransferFrom(from, to, tokens, values, callbackDataHex)
 | 
			
		||||
                .sendTransactionAsync({ from: spender }),
 | 
			
		||||
        );
 | 
			
		||||
        return tx;
 | 
			
		||||
    }
 | 
			
		||||
@@ -74,7 +71,7 @@ export class Erc1155Wrapper {
 | 
			
		||||
        const tokenUri = 'dummyFungibleToken';
 | 
			
		||||
        const tokenIsNonFungible = false;
 | 
			
		||||
        const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this._erc1155Contract.create.sendTransactionAsync(tokenUri, tokenIsNonFungible, {
 | 
			
		||||
            await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).sendTransactionAsync({
 | 
			
		||||
                from: this._contractOwner,
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
@@ -95,31 +92,24 @@ export class Erc1155Wrapper {
 | 
			
		||||
                tokenAmountsAsArray.push(tokenAmounts);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        await this._erc1155Contract.mintFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
            tokenId,
 | 
			
		||||
            beneficiaries,
 | 
			
		||||
            tokenAmountsAsArray,
 | 
			
		||||
            { from: this._contractOwner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await this._erc1155Contract
 | 
			
		||||
            .mintFungible(tokenId, beneficiaries, tokenAmountsAsArray)
 | 
			
		||||
            .awaitTransactionSuccessAsync({ from: this._contractOwner });
 | 
			
		||||
    }
 | 
			
		||||
    public async mintNonFungibleTokensAsync(beneficiaries: string[]): Promise<[BigNumber, BigNumber[]]> {
 | 
			
		||||
        const tokenUri = 'dummyNonFungibleToken';
 | 
			
		||||
        const tokenIsNonFungible = true;
 | 
			
		||||
        const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this._erc1155Contract.create.sendTransactionAsync(tokenUri, tokenIsNonFungible, {
 | 
			
		||||
            await this._erc1155Contract.create(tokenUri, tokenIsNonFungible).sendTransactionAsync({
 | 
			
		||||
                from: this._contractOwner,
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
        // tslint:disable-next-line no-unnecessary-type-assertion
 | 
			
		||||
        const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
 | 
			
		||||
        const token = createFungibleTokenLog.args.id;
 | 
			
		||||
        await this._erc1155Contract.mintNonFungible.awaitTransactionSuccessAsync(
 | 
			
		||||
            token,
 | 
			
		||||
            beneficiaries,
 | 
			
		||||
            { from: this._contractOwner },
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await this._erc1155Contract.mintNonFungible(token, beneficiaries).awaitTransactionSuccessAsync({
 | 
			
		||||
            from: this._contractOwner,
 | 
			
		||||
        });
 | 
			
		||||
        const encodedNftIds: BigNumber[] = [];
 | 
			
		||||
        const nftIdBegin = 1;
 | 
			
		||||
        const nftIdEnd = beneficiaries.length + 1;
 | 
			
		||||
@@ -136,14 +126,14 @@ export class Erc1155Wrapper {
 | 
			
		||||
        isApproved: boolean,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const tx = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this._erc1155Contract.setApprovalForAll.sendTransactionAsync(beneficiary, isApproved, {
 | 
			
		||||
            await this._erc1155Contract.setApprovalForAll(beneficiary, isApproved).sendTransactionAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
        return tx;
 | 
			
		||||
    }
 | 
			
		||||
    public async isApprovedForAllAsync(owner: string, beneficiary: string): Promise<boolean> {
 | 
			
		||||
        const isApprovedForAll = await this._erc1155Contract.isApprovedForAll.callAsync(owner, beneficiary);
 | 
			
		||||
        const isApprovedForAll = await this._erc1155Contract.isApprovedForAll(owner, beneficiary).callAsync();
 | 
			
		||||
        return isApprovedForAll;
 | 
			
		||||
    }
 | 
			
		||||
    public async assertBalancesAsync(
 | 
			
		||||
@@ -165,18 +155,18 @@ export class Erc1155Wrapper {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public async isNonFungibleItemAsync(tokenId: BigNumber): Promise<boolean> {
 | 
			
		||||
        return this._erc1155Contract.isNonFungibleItem.callAsync(tokenId);
 | 
			
		||||
        return this._erc1155Contract.isNonFungibleItem(tokenId).callAsync();
 | 
			
		||||
    }
 | 
			
		||||
    public async isFungibleItemAsync(tokenId: BigNumber): Promise<boolean> {
 | 
			
		||||
        return !(await this.isNonFungibleItemAsync(tokenId));
 | 
			
		||||
    }
 | 
			
		||||
    public async getOwnerOfAsync(tokenId: BigNumber): Promise<string> {
 | 
			
		||||
        return this._erc1155Contract.ownerOf.callAsync(tokenId);
 | 
			
		||||
        return this._erc1155Contract.ownerOf(tokenId).callAsync();
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Get the balance of an ERC1155 token for a given owner and token ID.
 | 
			
		||||
     */
 | 
			
		||||
    public async getBalanceAsync(ownerAddress: string, tokenId: BigNumber): Promise<BigNumber> {
 | 
			
		||||
        return this._erc1155Contract.balanceOf.callAsync(ownerAddress, tokenId);
 | 
			
		||||
        return this._erc1155Contract.balanceOf(ownerAddress, tokenId).callAsync();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
export * from './wrappers';
 | 
			
		||||
export * from './artifacts';
 | 
			
		||||
export { Erc1155Wrapper } from '../test/utils/erc1155_wrapper';
 | 
			
		||||
export { Erc1155Wrapper } from './erc1155_wrapper';
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,4 @@
 | 
			
		||||
export * from '../generated-wrappers/dummy_erc1155_receiver';
 | 
			
		||||
export * from '../generated-wrappers/erc1155';
 | 
			
		||||
export * from '../generated-wrappers/erc1155_mintable';
 | 
			
		||||
export * from '../generated-wrappers/i_erc1155_mintable';
 | 
			
		||||
export * from '../generated-wrappers/i_erc1155_receiver';
 | 
			
		||||
export * from '../generated-wrappers/ierc1155';
 | 
			
		||||
export * from '../generated-wrappers/mixin_non_fungible_token';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								contracts/erc1155/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								contracts/erc1155/test/artifacts.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DummyERC1155Receiver from '../test/generated-artifacts/DummyERC1155Receiver.json';
 | 
			
		||||
import * as ERC1155 from '../test/generated-artifacts/ERC1155.json';
 | 
			
		||||
import * as ERC1155Mintable from '../test/generated-artifacts/ERC1155Mintable.json';
 | 
			
		||||
import * as IERC1155 from '../test/generated-artifacts/IERC1155.json';
 | 
			
		||||
import * as IERC1155Mintable from '../test/generated-artifacts/IERC1155Mintable.json';
 | 
			
		||||
import * as IERC1155Receiver from '../test/generated-artifacts/IERC1155Receiver.json';
 | 
			
		||||
import * as MixinNonFungibleToken from '../test/generated-artifacts/MixinNonFungibleToken.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    ERC1155: ERC1155 as ContractArtifact,
 | 
			
		||||
    ERC1155Mintable: ERC1155Mintable as ContractArtifact,
 | 
			
		||||
    MixinNonFungibleToken: MixinNonFungibleToken as ContractArtifact,
 | 
			
		||||
    IERC1155: IERC1155 as ContractArtifact,
 | 
			
		||||
    IERC1155Mintable: IERC1155Mintable as ContractArtifact,
 | 
			
		||||
    IERC1155Receiver: IERC1155Receiver as ContractArtifact,
 | 
			
		||||
    DummyERC1155Receiver: DummyERC1155Receiver as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -6,21 +6,19 @@ import {
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { SafeMathRevertErrors } from '@0x/contracts-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts,
 | 
			
		||||
    DummyERC1155ReceiverBatchTokenReceivedEventArgs,
 | 
			
		||||
    DummyERC1155ReceiverContract,
 | 
			
		||||
    ERC1155MintableContract,
 | 
			
		||||
} from '../src';
 | 
			
		||||
import { Erc1155Wrapper } from '../src/erc1155_wrapper';
 | 
			
		||||
import { ERC1155MintableContract } from '../src/wrappers';
 | 
			
		||||
 | 
			
		||||
import { Erc1155Wrapper } from './utils/erc1155_wrapper';
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { DummyERC1155ReceiverBatchTokenReceivedEventArgs, DummyERC1155ReceiverContract } from './wrappers';
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
@@ -179,14 +177,9 @@ describe('ERC1155Token', () => {
 | 
			
		||||
                valueToTransfer,
 | 
			
		||||
            );
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            const tx = erc1155Contract.safeTransferFrom.sendTransactionAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                tokenToTransfer,
 | 
			
		||||
                valueToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                { from: spender },
 | 
			
		||||
            );
 | 
			
		||||
            const tx = erc1155Contract
 | 
			
		||||
                .safeTransferFrom(spender, receiver, tokenToTransfer, valueToTransfer, receiverCallbackData)
 | 
			
		||||
                .sendTransactionAsync({ from: spender });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if callback reverts', async () => {
 | 
			
		||||
@@ -196,19 +189,14 @@ describe('ERC1155Token', () => {
 | 
			
		||||
            // set receiver to reject balances
 | 
			
		||||
            const shouldRejectTransfer = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc1155Receiver.setRejectTransferFlag.sendTransactionAsync(shouldRejectTransfer),
 | 
			
		||||
                await erc1155Receiver.setRejectTransferFlag(shouldRejectTransfer).sendTransactionAsync(),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155Contract.safeTransferFrom.sendTransactionAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    tokenToTransfer,
 | 
			
		||||
                    valueToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    { from: spender },
 | 
			
		||||
                ),
 | 
			
		||||
                erc1155Contract
 | 
			
		||||
                    .safeTransferFrom(spender, receiver, tokenToTransfer, valueToTransfer, receiverCallbackData)
 | 
			
		||||
                    .sendTransactionAsync({ from: spender }),
 | 
			
		||||
                RevertReason.TransferRejected,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
@@ -355,14 +343,9 @@ describe('ERC1155Token', () => {
 | 
			
		||||
                valuesToTransfer[0],
 | 
			
		||||
            );
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            const tx = erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                { from: spender },
 | 
			
		||||
            );
 | 
			
		||||
            const tx = erc1155Contract
 | 
			
		||||
                .safeBatchTransferFrom(spender, receiver, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .sendTransactionAsync({ from: spender });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if callback reverts', async () => {
 | 
			
		||||
@@ -372,19 +355,14 @@ describe('ERC1155Token', () => {
 | 
			
		||||
            // set receiver to reject balances
 | 
			
		||||
            const shouldRejectTransfer = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc1155Receiver.setRejectTransferFlag.sendTransactionAsync(shouldRejectTransfer),
 | 
			
		||||
                await erc1155Receiver.setRejectTransferFlag(shouldRejectTransfer).sendTransactionAsync(),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    { from: spender },
 | 
			
		||||
                ),
 | 
			
		||||
                erc1155Contract
 | 
			
		||||
                    .safeBatchTransferFrom(spender, receiver, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                    .sendTransactionAsync({ from: spender }),
 | 
			
		||||
                RevertReason.TransferRejected,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
@@ -432,14 +410,9 @@ describe('ERC1155Token', () => {
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155Contract.safeTransferFrom.sendTransactionAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    tokenToTransfer,
 | 
			
		||||
                    valueToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    { from: delegatedSpender },
 | 
			
		||||
                ),
 | 
			
		||||
                erc1155Contract
 | 
			
		||||
                    .safeTransferFrom(spender, receiver, tokenToTransfer, valueToTransfer, receiverCallbackData)
 | 
			
		||||
                    .sendTransactionAsync({ from: delegatedSpender }),
 | 
			
		||||
                RevertReason.InsufficientAllowance,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
@@ -485,14 +458,9 @@ describe('ERC1155Token', () => {
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155Contract.safeBatchTransferFrom.sendTransactionAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    { from: delegatedSpender },
 | 
			
		||||
                ),
 | 
			
		||||
                erc1155Contract
 | 
			
		||||
                    .safeBatchTransferFrom(spender, receiver, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                    .sendTransactionAsync({ from: delegatedSpender }),
 | 
			
		||||
                RevertReason.InsufficientAllowance,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								contracts/erc1155/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								contracts/erc1155/test/wrappers.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/dummy_erc1155_receiver';
 | 
			
		||||
export * from '../test/generated-wrappers/erc1155';
 | 
			
		||||
export * from '../test/generated-wrappers/erc1155_mintable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc1155_mintable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc1155_receiver';
 | 
			
		||||
export * from '../test/generated-wrappers/ierc1155';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_non_fungible_token';
 | 
			
		||||
@@ -6,10 +6,14 @@
 | 
			
		||||
        "generated-artifacts/DummyERC1155Receiver.json",
 | 
			
		||||
        "generated-artifacts/ERC1155.json",
 | 
			
		||||
        "generated-artifacts/ERC1155Mintable.json",
 | 
			
		||||
        "generated-artifacts/IERC1155.json",
 | 
			
		||||
        "generated-artifacts/IERC1155Mintable.json",
 | 
			
		||||
        "generated-artifacts/IERC1155Receiver.json",
 | 
			
		||||
        "generated-artifacts/MixinNonFungibleToken.json"
 | 
			
		||||
        "test/generated-artifacts/DummyERC1155Receiver.json",
 | 
			
		||||
        "test/generated-artifacts/ERC1155.json",
 | 
			
		||||
        "test/generated-artifacts/ERC1155Mintable.json",
 | 
			
		||||
        "test/generated-artifacts/IERC1155.json",
 | 
			
		||||
        "test/generated-artifacts/IERC1155Mintable.json",
 | 
			
		||||
        "test/generated-artifacts/IERC1155Receiver.json",
 | 
			
		||||
        "test/generated-artifacts/MixinNonFungibleToken.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								contracts/erc20/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contracts/erc20/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
# Blacklist all files
 | 
			
		||||
.*
 | 
			
		||||
*
 | 
			
		||||
# Whitelist lib
 | 
			
		||||
!lib/**/*
 | 
			
		||||
# Whitelist Solidity contracts
 | 
			
		||||
!contracts/src/**/*
 | 
			
		||||
# Blacklist tests in lib
 | 
			
		||||
/lib/test/*
 | 
			
		||||
# Package specific ignore
 | 
			
		||||
@@ -1,9 +1,33 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils",
 | 
			
		||||
                "pr": 2330
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1574030254
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Create `LibERC20Token`",
 | 
			
		||||
                "pr": 2309
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1573159180
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.3.0-beta.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Replaced `SafeMath` with `LibSafeMath`",
 | 
			
		||||
                "pr": 2254
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1570135330
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,18 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.2 - _November 17, 2019_
 | 
			
		||||
 | 
			
		||||
    * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330)
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.1 - _November 7, 2019_
 | 
			
		||||
 | 
			
		||||
    * Create `LibERC20Token` (#2309)
 | 
			
		||||
 | 
			
		||||
## v2.3.0-beta.0 - _October 3, 2019_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
    * Replaced `SafeMath` with `LibSafeMath` (#2254)
 | 
			
		||||
 | 
			
		||||
## v2.2.14 - _September 17, 2019_
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user