Compare commits
	
		
			1134 Commits
		
	
	
		
			@0x/json-s
			...
			protocol@9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9e152912fe | ||
| 
						 | 
					b2c2f1e1aa | ||
| 
						 | 
					629c7d8e92 | ||
| 
						 | 
					62f24d4356 | ||
| 
						 | 
					ae281c33ca | ||
| 
						 | 
					5d034dd106 | ||
| 
						 | 
					c1f8df0eca | ||
| 
						 | 
					76dda9eeda | ||
| 
						 | 
					a9b84a92ac | ||
| 
						 | 
					0f7e881899 | ||
| 
						 | 
					6045f777ab | ||
| 
						 | 
					5a15044ead | ||
| 
						 | 
					a69d76e487 | ||
| 
						 | 
					3adfcdffa8 | ||
| 
						 | 
					164a5d44d9 | ||
| 
						 | 
					70ddab0231 | ||
| 
						 | 
					7bf009fbf6 | ||
| 
						 | 
					525bc8197b | ||
| 
						 | 
					24397c51a8 | ||
| 
						 | 
					06b3464756 | ||
| 
						 | 
					bbaa90bd9a | ||
| 
						 | 
					5c683cbc0f | ||
| 
						 | 
					95345f18bc | ||
| 
						 | 
					4c3fbe83ac | ||
| 
						 | 
					7caa43d02c | ||
| 
						 | 
					3d4c03c9df | ||
| 
						 | 
					22e1ed35d3 | ||
| 
						 | 
					dabe6fd793 | ||
| 
						 | 
					3cc639c8d0 | ||
| 
						 | 
					22c8e0b6db | ||
| 
						 | 
					f3ca4293bc | ||
| 
						 | 
					db3e076d03 | ||
| 
						 | 
					1a6759820a | ||
| 
						 | 
					61c5e7b948 | ||
| 
						 | 
					5fd78ef32f | ||
| 
						 | 
					14ff9b827c | ||
| 
						 | 
					598dc2cd71 | ||
| 
						 | 
					08e1c5109f | ||
| 
						 | 
					6f7a843742 | ||
| 
						 | 
					c9c9615bb5 | ||
| 
						 | 
					f98609686d | ||
| 
						 | 
					5b8bbc34e8 | ||
| 
						 | 
					49cb00a9ab | ||
| 
						 | 
					74b240fb88 | ||
| 
						 | 
					514f9d2621 | ||
| 
						 | 
					fa78d1092a | ||
| 
						 | 
					297342092b | ||
| 
						 | 
					076f263a86 | ||
| 
						 | 
					0c56207abc | ||
| 
						 | 
					23953d8a5a | ||
| 
						 | 
					c6919eb25a | ||
| 
						 | 
					d509604b52 | ||
| 
						 | 
					a74a3450eb | ||
| 
						 | 
					72c5399b9d | ||
| 
						 | 
					b29196b983 | ||
| 
						 | 
					ce76a7033d | ||
| 
						 | 
					3f4bb933d1 | ||
| 
						 | 
					501b7b9b65 | ||
| 
						 | 
					c0ea88e864 | ||
| 
						 | 
					48f8bea460 | ||
| 
						 | 
					f4e5b6e38d | ||
| 
						 | 
					477cb0a48d | ||
| 
						 | 
					d6bc0a3368 | ||
| 
						 | 
					e544a804c2 | ||
| 
						 | 
					96e0ad7899 | ||
| 
						 | 
					5a1fee5d31 | ||
| 
						 | 
					3557a5e5a9 | ||
| 
						 | 
					0bd43d5265 | ||
| 
						 | 
					8fd7c1b386 | ||
| 
						 | 
					50068750f5 | ||
| 
						 | 
					a7a905de4c | ||
| 
						 | 
					f283108586 | ||
| 
						 | 
					9afe05095a | ||
| 
						 | 
					3dab892978 | ||
| 
						 | 
					e40ddb800e | ||
| 
						 | 
					72a74e7c66 | ||
| 
						 | 
					e8ae64673f | ||
| 
						 | 
					2451f419c8 | ||
| 
						 | 
					2394eb62aa | ||
| 
						 | 
					f9078bb1c3 | ||
| 
						 | 
					bf25c81f1c | ||
| 
						 | 
					03ecc530c3 | ||
| 
						 | 
					d52b1d24d0 | ||
| 
						 | 
					5083fab06a | ||
| 
						 | 
					1249bf9ccc | ||
| 
						 | 
					681f6b3f07 | ||
| 
						 | 
					d3ca1fe96b | ||
| 
						 | 
					9e4f5815e4 | ||
| 
						 | 
					c3c27eaedc | ||
| 
						 | 
					4bf6a23d23 | ||
| 
						 | 
					aaaf0d02de | ||
| 
						 | 
					825cc4d035 | ||
| 
						 | 
					c2d44e5c10 | ||
| 
						 | 
					0efd0860c8 | ||
| 
						 | 
					a890a06664 | ||
| 
						 | 
					5befb87071 | ||
| 
						 | 
					12ba4c373a | ||
| 
						 | 
					7fd25be02e | ||
| 
						 | 
					aa688c4a92 | ||
| 
						 | 
					fb437551c9 | ||
| 
						 | 
					6fa1de7889 | ||
| 
						 | 
					7a42df9a65 | ||
| 
						 | 
					15a508f3ea | ||
| 
						 | 
					b3c20ff909 | ||
| 
						 | 
					682c07cb73 | ||
| 
						 | 
					602605ab4b | ||
| 
						 | 
					0eff2548d5 | ||
| 
						 | 
					93ee681204 | ||
| 
						 | 
					d7bea98075 | ||
| 
						 | 
					437a3b048d | ||
| 
						 | 
					f55a9454b5 | ||
| 
						 | 
					3b03ad0db4 | ||
| 
						 | 
					27d679e1f1 | ||
| 
						 | 
					1e16d59c23 | ||
| 
						 | 
					1e7c9bbb1f | ||
| 
						 | 
					edda1edc50 | ||
| 
						 | 
					d1eb6279b4 | ||
| 
						 | 
					4ace79d947 | ||
| 
						 | 
					e5eee96487 | ||
| 
						 | 
					907adf9145 | ||
| 
						 | 
					c046fe6220 | ||
| 
						 | 
					84bf20de41 | ||
| 
						 | 
					f5a6f74d9a | ||
| 
						 | 
					7c7fc51ccf | ||
| 
						 | 
					fa22f6de0d | ||
| 
						 | 
					4f41214af2 | ||
| 
						 | 
					607b7169bc | ||
| 
						 | 
					1253490a38 | ||
| 
						 | 
					0a37a588e8 | ||
| 
						 | 
					23ee108089 | ||
| 
						 | 
					64feeeea75 | ||
| 
						 | 
					2ebef23b8c | ||
| 
						 | 
					cc9f43ba3b | ||
| 
						 | 
					5f1c139176 | ||
| 
						 | 
					9eea7de340 | ||
| 
						 | 
					4480f84efa | ||
| 
						 | 
					5a8b8afff1 | ||
| 
						 | 
					67c95bc0b7 | ||
| 
						 | 
					e70ec02be8 | ||
| 
						 | 
					db81a94adb | ||
| 
						 | 
					475b608338 | ||
| 
						 | 
					27e36b112e | ||
| 
						 | 
					f698721484 | ||
| 
						 | 
					0c08353b2c | ||
| 
						 | 
					a074b49732 | ||
| 
						 | 
					43b75c7953 | ||
| 
						 | 
					84a78eafc4 | ||
| 
						 | 
					3c1ab889dd | ||
| 
						 | 
					012fff46f6 | ||
| 
						 | 
					6307ebc3a2 | ||
| 
						 | 
					88d7e73eba | ||
| 
						 | 
					9653eb9e70 | ||
| 
						 | 
					ad337271d3 | ||
| 
						 | 
					7591e99316 | ||
| 
						 | 
					ca20df4752 | ||
| 
						 | 
					841e4ee666 | ||
| 
						 | 
					e2ee3414ea | ||
| 
						 | 
					5306cc03e9 | ||
| 
						 | 
					85f5d32de2 | ||
| 
						 | 
					ab698cec14 | ||
| 
						 | 
					b463a39bfa | ||
| 
						 | 
					018e25345b | ||
| 
						 | 
					b60fa8a7d7 | ||
| 
						 | 
					048d8dee60 | ||
| 
						 | 
					927fe2b58b | ||
| 
						 | 
					89948b360c | ||
| 
						 | 
					561b60a24d | ||
| 
						 | 
					4f82543bdf | ||
| 
						 | 
					3133c509f9 | ||
| 
						 | 
					426c15692d | ||
| 
						 | 
					8c87a77faa | ||
| 
						 | 
					d2018f07a2 | ||
| 
						 | 
					d2e57d8163 | ||
| 
						 | 
					7403c0255a | ||
| 
						 | 
					75dcd687e2 | ||
| 
						 | 
					afd4805421 | ||
| 
						 | 
					6aa582d140 | ||
| 
						 | 
					534d92fa00 | ||
| 
						 | 
					37aae134ab | ||
| 
						 | 
					36bd8f68c9 | ||
| 
						 | 
					c3ad42221e | ||
| 
						 | 
					602ac1f626 | ||
| 
						 | 
					3126795efe | ||
| 
						 | 
					dbcb221a59 | ||
| 
						 | 
					6bbc179f52 | ||
| 
						 | 
					48e7a391c8 | ||
| 
						 | 
					2334e64d0c | ||
| 
						 | 
					14f920ee84 | ||
| 
						 | 
					e10a81023a | ||
| 
						 | 
					f4709ed1cb | ||
| 
						 | 
					e2e14a977a | ||
| 
						 | 
					866f958a10 | ||
| 
						 | 
					717db99b38 | ||
| 
						 | 
					02006118c7 | ||
| 
						 | 
					9816019bc5 | ||
| 
						 | 
					9c821dbfc3 | ||
| 
						 | 
					af1b890423 | ||
| 
						 | 
					673835d2de | ||
| 
						 | 
					500b57e935 | ||
| 
						 | 
					3f7d0580c1 | ||
| 
						 | 
					a71c356bba | ||
| 
						 | 
					c3a95b7fb1 | ||
| 
						 | 
					f01540fb35 | ||
| 
						 | 
					689a8881c2 | ||
| 
						 | 
					99f5be8378 | ||
| 
						 | 
					8de0282d92 | ||
| 
						 | 
					f99804d56a | ||
| 
						 | 
					f13d27b749 | ||
| 
						 | 
					465fd59cbc | ||
| 
						 | 
					5fdabe6612 | ||
| 
						 | 
					861871134b | ||
| 
						 | 
					c246d98093 | ||
| 
						 | 
					02076dba1b | ||
| 
						 | 
					7b136a5ad8 | ||
| 
						 | 
					0c4a67fa35 | ||
| 
						 | 
					668aeb77f7 | ||
| 
						 | 
					135ae392d5 | ||
| 
						 | 
					88ba04307c | ||
| 
						 | 
					e4b8000a48 | ||
| 
						 | 
					b9df108314 | ||
| 
						 | 
					6106185bf6 | ||
| 
						 | 
					3a3e289864 | ||
| 
						 | 
					6558632f10 | ||
| 
						 | 
					376ee6bdff | ||
| 
						 | 
					fc5d759131 | ||
| 
						 | 
					7c16bb3df8 | ||
| 
						 | 
					5df74d35d0 | ||
| 
						 | 
					72fc0c845a | ||
| 
						 | 
					b995715a2c | ||
| 
						 | 
					857b5c97b0 | ||
| 
						 | 
					178d9c280a | ||
| 
						 | 
					2416deba25 | ||
| 
						 | 
					0ce6243653 | ||
| 
						 | 
					40dc10729b | ||
| 
						 | 
					0571244e9e | ||
| 
						 | 
					3213131cad | ||
| 
						 | 
					61bf93aac2 | ||
| 
						 | 
					a9d0cec6d1 | ||
| 
						 | 
					b5e3f0b90c | ||
| 
						 | 
					61f1fe42b0 | ||
| 
						 | 
					1cfdc49021 | ||
| 
						 | 
					c4d58277cf | ||
| 
						 | 
					9ac66c2130 | ||
| 
						 | 
					6366163006 | ||
| 
						 | 
					85fde8f9a5 | ||
| 
						 | 
					a03d0800b0 | ||
| 
						 | 
					9cb21006a7 | ||
| 
						 | 
					649202f1c4 | ||
| 
						 | 
					b798556774 | ||
| 
						 | 
					03bc15fbdf | ||
| 
						 | 
					b2dfd8740c | ||
| 
						 | 
					3182c12b4d | ||
| 
						 | 
					f783625d60 | ||
| 
						 | 
					891aa8e8bf | ||
| 
						 | 
					4b508d255d | ||
| 
						 | 
					1cad43bf5d | ||
| 
						 | 
					a0cd727832 | ||
| 
						 | 
					ab90e15015 | ||
| 
						 | 
					52cbddf054 | ||
| 
						 | 
					db98ff8cb7 | ||
| 
						 | 
					1d8dd2f89c | ||
| 
						 | 
					0ae1c926d3 | ||
| 
						 | 
					1fcab58e2f | ||
| 
						 | 
					a8cbd1a16c | ||
| 
						 | 
					3aaa0ad6b2 | ||
| 
						 | 
					e34bc77157 | ||
| 
						 | 
					088b331f19 | ||
| 
						 | 
					56f2dec441 | ||
| 
						 | 
					ac8b08d3cf | ||
| 
						 | 
					c4ead689a9 | ||
| 
						 | 
					07ab10b000 | ||
| 
						 | 
					c969a8652a | ||
| 
						 | 
					fb21ca5404 | ||
| 
						 | 
					bbfa9c34ab | ||
| 
						 | 
					7161bbe836 | ||
| 
						 | 
					ef65aa5bf6 | ||
| 
						 | 
					2cf31f05a1 | ||
| 
						 | 
					2b1a1ba0db | ||
| 
						 | 
					05b25c6229 | ||
| 
						 | 
					2db52c6983 | ||
| 
						 | 
					4803e2f68c | ||
| 
						 | 
					7030572f1d | ||
| 
						 | 
					6e2eb9c5bb | ||
| 
						 | 
					eb27e260e0 | ||
| 
						 | 
					c72aa653e8 | ||
| 
						 | 
					4d04b72674 | ||
| 
						 | 
					e3b92d2c8b | ||
| 
						 | 
					4aa5a89cd7 | ||
| 
						 | 
					c6b9ea5723 | ||
| 
						 | 
					2dc0bff1ea | ||
| 
						 | 
					408e66e8b4 | ||
| 
						 | 
					40fe12a86b | ||
| 
						 | 
					1adb56f092 | ||
| 
						 | 
					629d48c766 | ||
| 
						 | 
					c8886febb9 | ||
| 
						 | 
					efe598c8fd | ||
| 
						 | 
					32218ce25e | ||
| 
						 | 
					f7ae697475 | ||
| 
						 | 
					6e954385ce | ||
| 
						 | 
					f8df89b506 | ||
| 
						 | 
					a3ff406461 | ||
| 
						 | 
					221de054f4 | ||
| 
						 | 
					98e6aa4bac | ||
| 
						 | 
					199808dc44 | ||
| 
						 | 
					5d8e35fb68 | ||
| 
						 | 
					36546480b1 | ||
| 
						 | 
					cd9e408ea3 | ||
| 
						 | 
					7698f21517 | ||
| 
						 | 
					10724e5745 | ||
| 
						 | 
					dde76a4dbb | ||
| 
						 | 
					86ff5c53bb | ||
| 
						 | 
					efef5f122f | ||
| 
						 | 
					83c942ad8c | ||
| 
						 | 
					31e90e314c | ||
| 
						 | 
					33caae705e | ||
| 
						 | 
					961273a2ff | ||
| 
						 | 
					46e512a27c | ||
| 
						 | 
					290a04a0ad | ||
| 
						 | 
					12ff4ec438 | ||
| 
						 | 
					1c15ecacb0 | ||
| 
						 | 
					c6d738ed0c | ||
| 
						 | 
					f089f5d87f | ||
| 
						 | 
					78e3cd39d1 | ||
| 
						 | 
					1588c1f362 | ||
| 
						 | 
					a35d1b8a9d | ||
| 
						 | 
					32923ec7e1 | ||
| 
						 | 
					5a3bd716ad | ||
| 
						 | 
					84862f15c1 | ||
| 
						 | 
					9e42dce5c4 | ||
| 
						 | 
					a360109013 | ||
| 
						 | 
					68d6b3a033 | ||
| 
						 | 
					733c3046bc | ||
| 
						 | 
					23d4b6bf1c | ||
| 
						 | 
					39bd0c5459 | ||
| 
						 | 
					c13ffb2072 | ||
| 
						 | 
					38bcab1f86 | ||
| 
						 | 
					a24f01c90f | ||
| 
						 | 
					708e34602b | ||
| 
						 | 
					d60c8ddd5a | ||
| 
						 | 
					eea63292f0 | ||
| 
						 | 
					a97342a594 | ||
| 
						 | 
					00f55be83e | ||
| 
						 | 
					90ed283b20 | ||
| 
						 | 
					61272961a8 | ||
| 
						 | 
					507690f9db | ||
| 
						 | 
					90ad5eb6c4 | ||
| 
						 | 
					7bc9701c81 | ||
| 
						 | 
					a7d502a501 | ||
| 
						 | 
					fbe99b41f8 | ||
| 
						 | 
					66e2d93e9c | ||
| 
						 | 
					4672c72fef | ||
| 
						 | 
					ac6b03cd4a | ||
| 
						 | 
					d7de191947 | ||
| 
						 | 
					de7f1fc207 | ||
| 
						 | 
					99de5a3814 | ||
| 
						 | 
					4cf566cad8 | ||
| 
						 | 
					6138955f93 | ||
| 
						 | 
					a57cf68ee4 | ||
| 
						 | 
					20edcd1ae5 | ||
| 
						 | 
					5333befd89 | ||
| 
						 | 
					235e406620 | ||
| 
						 | 
					5f570b772d | ||
| 
						 | 
					f2507cb94a | ||
| 
						 | 
					f84b375cde | ||
| 
						 | 
					32d11d1ba5 | ||
| 
						 | 
					5c9b6eb078 | ||
| 
						 | 
					f53a512e70 | ||
| 
						 | 
					ec08715090 | ||
| 
						 | 
					79e0a9ef37 | ||
| 
						 | 
					1ce8a33937 | ||
| 
						 | 
					b3053dfb91 | ||
| 
						 | 
					3da05f2812 | ||
| 
						 | 
					0ba79b060d | ||
| 
						 | 
					c4bcc26e29 | ||
| 
						 | 
					630108ccb6 | ||
| 
						 | 
					1ab33aa132 | ||
| 
						 | 
					ee456ea6e7 | ||
| 
						 | 
					e7541ac2af | ||
| 
						 | 
					d34d46b7fd | ||
| 
						 | 
					08ae43aad3 | ||
| 
						 | 
					eb141075c7 | ||
| 
						 | 
					bd3387a408 | ||
| 
						 | 
					e1a48e80e1 | ||
| 
						 | 
					bf899d40a0 | ||
| 
						 | 
					dc66f1b886 | ||
| 
						 | 
					3753b1a7d0 | ||
| 
						 | 
					05c5acdb15 | ||
| 
						 | 
					ca63bcc9b0 | ||
| 
						 | 
					3733d503db | ||
| 
						 | 
					ab28e42c22 | ||
| 
						 | 
					7e53b4f834 | ||
| 
						 | 
					3bb60fee19 | ||
| 
						 | 
					9f7840e12b | ||
| 
						 | 
					f41e13b574 | ||
| 
						 | 
					4049143630 | ||
| 
						 | 
					705f46717f | ||
| 
						 | 
					a6cf8ae0b6 | ||
| 
						 | 
					dba6972281 | ||
| 
						 | 
					52d36f5a8b | ||
| 
						 | 
					889b58a914 | ||
| 
						 | 
					43810835d7 | ||
| 
						 | 
					4b9867f167 | ||
| 
						 | 
					e9c91e59bd | ||
| 
						 | 
					d8844f6970 | ||
| 
						 | 
					1cdc6e7184 | ||
| 
						 | 
					36ad373f03 | ||
| 
						 | 
					78dfb6d525 | ||
| 
						 | 
					79254de7bc | ||
| 
						 | 
					1d6aef5cd6 | ||
| 
						 | 
					f9d02c9e27 | ||
| 
						 | 
					228246089e | ||
| 
						 | 
					b6319ba3d8 | ||
| 
						 | 
					2636384ead | ||
| 
						 | 
					0425f76284 | ||
| 
						 | 
					d93e72f56a | ||
| 
						 | 
					195d543ce3 | ||
| 
						 | 
					9cda9f69cd | ||
| 
						 | 
					7b0a1c3630 | ||
| 
						 | 
					a8f3a47240 | ||
| 
						 | 
					db0f3a8780 | ||
| 
						 | 
					514db24ceb | ||
| 
						 | 
					e738743c89 | ||
| 
						 | 
					f471e1a8a3 | ||
| 
						 | 
					a2f0d5eedf | ||
| 
						 | 
					2f9b894d71 | ||
| 
						 | 
					bab34c2d21 | ||
| 
						 | 
					a68421b0f8 | ||
| 
						 | 
					e9b0ac8820 | ||
| 
						 | 
					4f78f55c2a | ||
| 
						 | 
					156093127b | ||
| 
						 | 
					47d91bb4e0 | ||
| 
						 | 
					cc31445189 | ||
| 
						 | 
					af78238507 | ||
| 
						 | 
					b30f87f50c | ||
| 
						 | 
					3cd03ed0f1 | ||
| 
						 | 
					e7ad7c3af7 | ||
| 
						 | 
					7e8b56eef4 | ||
| 
						 | 
					458a014e6d | ||
| 
						 | 
					9b6703398e | ||
| 
						 | 
					71700e69af | ||
| 
						 | 
					14d6330b40 | ||
| 
						 | 
					d31d646ecc | ||
| 
						 | 
					270d7a3f19 | ||
| 
						 | 
					e078f3d479 | ||
| 
						 | 
					6aa8f17ed5 | ||
| 
						 | 
					8e73ae3614 | ||
| 
						 | 
					89117beda2 | ||
| 
						 | 
					e27e6baabe | ||
| 
						 | 
					15ce90c0ec | ||
| 
						 | 
					39e157499d | ||
| 
						 | 
					d22c0641fb | ||
| 
						 | 
					82806b6fcb | ||
| 
						 | 
					fe293d91ee | ||
| 
						 | 
					7842bb4cad | ||
| 
						 | 
					6f7e156f49 | ||
| 
						 | 
					0d19cac487 | ||
| 
						 | 
					f30dfcc572 | ||
| 
						 | 
					3df39d8cfe | ||
| 
						 | 
					ece93fed78 | ||
| 
						 | 
					3a2c6ae9d6 | ||
| 
						 | 
					2ed71b36b6 | ||
| 
						 | 
					ae9c301795 | ||
| 
						 | 
					68206ffb6e | ||
| 
						 | 
					25a3c18bfe | ||
| 
						 | 
					d28476e9f7 | ||
| 
						 | 
					7cd30610f9 | ||
| 
						 | 
					ceb90989d0 | ||
| 
						 | 
					bb39d63d37 | ||
| 
						 | 
					213709d020 | ||
| 
						 | 
					d0e9081852 | ||
| 
						 | 
					71cde281b9 | ||
| 
						 | 
					c03f1586e6 | ||
| 
						 | 
					10aceb164d | ||
| 
						 | 
					34f516a417 | ||
| 
						 | 
					5dd686f22f | ||
| 
						 | 
					5f47ad3363 | ||
| 
						 | 
					e166e9762a | ||
| 
						 | 
					341c5782e5 | ||
| 
						 | 
					d5180d3ebc | ||
| 
						 | 
					2c73bbd689 | ||
| 
						 | 
					b10522479c | ||
| 
						 | 
					2b39ae4800 | ||
| 
						 | 
					788bdba8cd | ||
| 
						 | 
					222fd5d822 | ||
| 
						 | 
					eedfc64a8c | ||
| 
						 | 
					78170b26e9 | ||
| 
						 | 
					f966b6f4df | ||
| 
						 | 
					053b55fbbf | ||
| 
						 | 
					84a55a2d84 | ||
| 
						 | 
					498a50b229 | ||
| 
						 | 
					766888ec41 | ||
| 
						 | 
					466d962c07 | ||
| 
						 | 
					ae2a6fb685 | ||
| 
						 | 
					5afe2616a4 | ||
| 
						 | 
					72c869649a | ||
| 
						 | 
					34138fc3b5 | ||
| 
						 | 
					f67d2b96ac | ||
| 
						 | 
					d877d3686c | ||
| 
						 | 
					8260615b4e | ||
| 
						 | 
					c3f6d48966 | ||
| 
						 | 
					02f979bc74 | ||
| 
						 | 
					de1c71aacc | ||
| 
						 | 
					ca2aa72e0f | ||
| 
						 | 
					9a16f5736e | ||
| 
						 | 
					82774df715 | ||
| 
						 | 
					314f53c0b3 | ||
| 
						 | 
					6553ee0130 | ||
| 
						 | 
					d7918ea047 | ||
| 
						 | 
					4aa9c85503 | ||
| 
						 | 
					f172591059 | ||
| 
						 | 
					dfa7e30e42 | ||
| 
						 | 
					3fe2013398 | ||
| 
						 | 
					391d501ce6 | ||
| 
						 | 
					9edaa3a64e | ||
| 
						 | 
					6e4e313792 | ||
| 
						 | 
					e6dcf92ec8 | ||
| 
						 | 
					f359de2cac | ||
| 
						 | 
					2d29014091 | ||
| 
						 | 
					0450e430f1 | ||
| 
						 | 
					b6700af6a8 | ||
| 
						 | 
					bcee7546ae | ||
| 
						 | 
					4dac620156 | ||
| 
						 | 
					74d9df2fb0 | ||
| 
						 | 
					9d1615fa23 | ||
| 
						 | 
					b1b9949e72 | ||
| 
						 | 
					957ef5ab77 | ||
| 
						 | 
					07a681c77e | ||
| 
						 | 
					145ec8ede1 | ||
| 
						 | 
					5f5a158060 | ||
| 
						 | 
					3e99c95791 | ||
| 
						 | 
					4f83521be8 | ||
| 
						 | 
					aae93bb6a7 | ||
| 
						 | 
					b5eb1c9ee8 | ||
| 
						 | 
					9d3755db36 | ||
| 
						 | 
					762e0aec2d | ||
| 
						 | 
					ff9c9241d8 | ||
| 
						 | 
					5c1ffe7fc8 | ||
| 
						 | 
					b1c3c60def | ||
| 
						 | 
					8763713596 | ||
| 
						 | 
					3e823cc9e3 | ||
| 
						 | 
					1c84709db3 | ||
| 
						 | 
					9150d6bd2a | ||
| 
						 | 
					10f29b66b8 | ||
| 
						 | 
					259aec52a9 | ||
| 
						 | 
					6554bf9f08 | ||
| 
						 | 
					d8558f5956 | ||
| 
						 | 
					18bc701e8b | ||
| 
						 | 
					a47795fd3f | ||
| 
						 | 
					a55e8b268c | ||
| 
						 | 
					e8106f04b5 | ||
| 
						 | 
					bdc1dbf08a | ||
| 
						 | 
					06eeb2088b | ||
| 
						 | 
					7da9ec2c75 | ||
| 
						 | 
					297ff10c14 | ||
| 
						 | 
					1305f4314d | ||
| 
						 | 
					55474c0599 | ||
| 
						 | 
					687c79ae81 | ||
| 
						 | 
					829a353b14 | ||
| 
						 | 
					aced474dc5 | ||
| 
						 | 
					7c08d5f198 | ||
| 
						 | 
					c546787994 | ||
| 
						 | 
					31fa530845 | ||
| 
						 | 
					120714ecfc | ||
| 
						 | 
					615874d2ec | ||
| 
						 | 
					67b195c942 | ||
| 
						 | 
					75689cee96 | ||
| 
						 | 
					8ba77e95a4 | ||
| 
						 | 
					7967a8416c | ||
| 
						 | 
					934fbca860 | ||
| 
						 | 
					e78c8038c7 | ||
| 
						 | 
					f64a42ebb5 | ||
| 
						 | 
					9164cff234 | ||
| 
						 | 
					017f98e87e | ||
| 
						 | 
					f33d8670aa | ||
| 
						 | 
					e79db7de89 | ||
| 
						 | 
					845a42e73a | ||
| 
						 | 
					e58c25aa18 | ||
| 
						 | 
					8ec44b63b1 | ||
| 
						 | 
					41907936a1 | ||
| 
						 | 
					406d2cefc5 | ||
| 
						 | 
					41cdbc0ec4 | ||
| 
						 | 
					c6ec261c5c | ||
| 
						 | 
					a2db1a3275 | ||
| 
						 | 
					1e8f2f0e83 | ||
| 
						 | 
					8491abe142 | ||
| 
						 | 
					d4302538bf | ||
| 
						 | 
					c34e3765ef | ||
| 
						 | 
					1f86bc06ef | ||
| 
						 | 
					7e892fac2d | ||
| 
						 | 
					23789b0692 | ||
| 
						 | 
					89adbe4127 | ||
| 
						 | 
					11940fb98e | ||
| 
						 | 
					13ae335811 | ||
| 
						 | 
					b2dc6ad2fa | ||
| 
						 | 
					85ca926fd0 | ||
| 
						 | 
					676698a59b | ||
| 
						 | 
					22408ecd58 | ||
| 
						 | 
					d36acc7ec7 | ||
| 
						 | 
					a5a68acfec | ||
| 
						 | 
					7431651666 | ||
| 
						 | 
					4f91bfd907 | ||
| 
						 | 
					8d2086870b | ||
| 
						 | 
					1511ef1a98 | ||
| 
						 | 
					4e030ce1e8 | ||
| 
						 | 
					2507ad274b | ||
| 
						 | 
					fb1c149eb9 | ||
| 
						 | 
					d4662f428a | ||
| 
						 | 
					73c779c13a | ||
| 
						 | 
					b8cc164af1 | ||
| 
						 | 
					64a391b5f8 | ||
| 
						 | 
					21a202dd16 | ||
| 
						 | 
					187dd2fdc3 | ||
| 
						 | 
					c18f3f0b33 | ||
| 
						 | 
					7162935028 | ||
| 
						 | 
					9215a73b6c | ||
| 
						 | 
					edd840794c | ||
| 
						 | 
					c30a6eb1aa | ||
| 
						 | 
					233642af29 | ||
| 
						 | 
					7dffd0a03e | ||
| 
						 | 
					f7bc3ff49d | ||
| 
						 | 
					53aabe3cdb | ||
| 
						 | 
					09b8d7cfc9 | ||
| 
						 | 
					1512afc7e6 | ||
| 
						 | 
					dde0c76112 | ||
| 
						 | 
					f14b6f2ba2 | ||
| 
						 | 
					4fced276c4 | ||
| 
						 | 
					7590471d62 | ||
| 
						 | 
					0b6bcf6739 | ||
| 
						 | 
					3a5ce86ed9 | ||
| 
						 | 
					7b298939e2 | ||
| 
						 | 
					f1f6aa7d80 | ||
| 
						 | 
					7ce7dd7252 | ||
| 
						 | 
					01aa556ede | ||
| 
						 | 
					48ad39c1c7 | ||
| 
						 | 
					9cab034448 | ||
| 
						 | 
					0d7a22634c | ||
| 
						 | 
					3e3bc5c06d | ||
| 
						 | 
					2a81e468c7 | ||
| 
						 | 
					0ba67a363e | ||
| 
						 | 
					deae846864 | ||
| 
						 | 
					3a0d48ad77 | ||
| 
						 | 
					81d4803b4d | ||
| 
						 | 
					e936c7c507 | ||
| 
						 | 
					ad868af96e | ||
| 
						 | 
					cd14a45414 | ||
| 
						 | 
					f7cd7110ea | ||
| 
						 | 
					44262bf747 | ||
| 
						 | 
					0fbbabe208 | ||
| 
						 | 
					b39189fde3 | ||
| 
						 | 
					18fc1d78f4 | ||
| 
						 | 
					d44a91d10b | ||
| 
						 | 
					5e9829b2d8 | ||
| 
						 | 
					2176deae36 | ||
| 
						 | 
					7c5035aa39 | ||
| 
						 | 
					5707993995 | ||
| 
						 | 
					f81697527c | ||
| 
						 | 
					967eff4c58 | ||
| 
						 | 
					d5d07dd34e | ||
| 
						 | 
					b91cc3781d | ||
| 
						 | 
					87ed0071c4 | ||
| 
						 | 
					0fed48630c | ||
| 
						 | 
					7b3e7c98ac | ||
| 
						 | 
					09f44b0375 | ||
| 
						 | 
					ebfa62637e | ||
| 
						 | 
					cb2cc05cac | ||
| 
						 | 
					f9c9131d81 | ||
| 
						 | 
					1be9a1cbc7 | ||
| 
						 | 
					b7fda8ecf0 | ||
| 
						 | 
					db16392821 | ||
| 
						 | 
					7127f541c3 | ||
| 
						 | 
					32793cc008 | ||
| 
						 | 
					fbaf55cb25 | ||
| 
						 | 
					b8d51fc4e8 | ||
| 
						 | 
					0c6e05d220 | ||
| 
						 | 
					4066c17a0f | ||
| 
						 | 
					429f2bb8dd | ||
| 
						 | 
					112f4fc4f0 | ||
| 
						 | 
					ecfbd6280f | ||
| 
						 | 
					bf84409839 | ||
| 
						 | 
					a7ce72cae0 | ||
| 
						 | 
					28402ff7d8 | ||
| 
						 | 
					e1d213d1a3 | ||
| 
						 | 
					c610dd96f5 | ||
| 
						 | 
					2ba3818b65 | ||
| 
						 | 
					0e1a5a375a | ||
| 
						 | 
					cfc3daeb65 | ||
| 
						 | 
					6359f1950e | ||
| 
						 | 
					d2f581853d | ||
| 
						 | 
					030cb285da | ||
| 
						 | 
					af45409959 | ||
| 
						 | 
					d9a9bc35e3 | ||
| 
						 | 
					c911c3352c | ||
| 
						 | 
					654abbac25 | ||
| 
						 | 
					46d5f42c9d | ||
| 
						 | 
					1509da1215 | ||
| 
						 | 
					98a99d96aa | ||
| 
						 | 
					d62d81af17 | ||
| 
						 | 
					dba67eb927 | ||
| 
						 | 
					548c30d6a0 | ||
| 
						 | 
					1b8b9186a8 | ||
| 
						 | 
					a8cfcfb371 | ||
| 
						 | 
					f7a414bc29 | ||
| 
						 | 
					e05cd1d66b | ||
| 
						 | 
					511cd90c44 | ||
| 
						 | 
					8fb2d8da88 | ||
| 
						 | 
					2fce332ed7 | ||
| 
						 | 
					b23f1eb145 | ||
| 
						 | 
					f694072b5a | ||
| 
						 | 
					10de266e0f | ||
| 
						 | 
					71811ed04f | ||
| 
						 | 
					e9638ef95e | ||
| 
						 | 
					5226bb5596 | ||
| 
						 | 
					b9984b6df4 | ||
| 
						 | 
					9c11835fee | ||
| 
						 | 
					d9e13d6b99 | ||
| 
						 | 
					dede076835 | ||
| 
						 | 
					c929782e0d | ||
| 
						 | 
					a43c7e36f8 | ||
| 
						 | 
					b95cec9c32 | ||
| 
						 | 
					9a7d9abe3c | ||
| 
						 | 
					c77b620453 | ||
| 
						 | 
					b348084e2a | ||
| 
						 | 
					ff1811ef90 | ||
| 
						 | 
					39cf4a7576 | ||
| 
						 | 
					21b67625a6 | ||
| 
						 | 
					fb0311e675 | ||
| 
						 | 
					8a14b4afff | ||
| 
						 | 
					e42701599a | ||
| 
						 | 
					352b1b43f2 | ||
| 
						 | 
					2922ebd095 | ||
| 
						 | 
					a9e72085dd | ||
| 
						 | 
					ed3d194c90 | ||
| 
						 | 
					125c53827b | ||
| 
						 | 
					38781807cd | ||
| 
						 | 
					c046943269 | ||
| 
						 | 
					fe36cd86bb | ||
| 
						 | 
					401410089c | ||
| 
						 | 
					fa23337519 | ||
| 
						 | 
					ae5421f76e | ||
| 
						 | 
					a2e2b429d5 | ||
| 
						 | 
					ac852b23b3 | ||
| 
						 | 
					e12389a002 | ||
| 
						 | 
					da18e42d2a | ||
| 
						 | 
					93bdaba8ee | ||
| 
						 | 
					4cb08a61d5 | ||
| 
						 | 
					133692ca92 | ||
| 
						 | 
					4bcc4b3cf8 | ||
| 
						 | 
					4eb20ca4b6 | ||
| 
						 | 
					69f7343be5 | ||
| 
						 | 
					19b28a58d6 | ||
| 
						 | 
					3c33a93b9c | ||
| 
						 | 
					f2e16dfb21 | ||
| 
						 | 
					0f689e8051 | ||
| 
						 | 
					5b44e6ef64 | ||
| 
						 | 
					49e4ade66f | ||
| 
						 | 
					3bae27d039 | ||
| 
						 | 
					a77f0c606d | ||
| 
						 | 
					f1de64dcaf | ||
| 
						 | 
					feb672c3cd | ||
| 
						 | 
					a90b463a7d | ||
| 
						 | 
					5f5f25c978 | ||
| 
						 | 
					351ea8bc1c | ||
| 
						 | 
					b34edcbf87 | ||
| 
						 | 
					160519e1fe | ||
| 
						 | 
					44d626e12e | ||
| 
						 | 
					efb9dc51c9 | ||
| 
						 | 
					deb51434fd | ||
| 
						 | 
					501070bfb0 | ||
| 
						 | 
					712958d8c8 | ||
| 
						 | 
					4d8d944fe5 | ||
| 
						 | 
					0042e42160 | ||
| 
						 | 
					85509ea251 | ||
| 
						 | 
					6063854d06 | ||
| 
						 | 
					456f8a90b1 | ||
| 
						 | 
					980246d07a | ||
| 
						 | 
					141c30b173 | ||
| 
						 | 
					22f9b03fce | ||
| 
						 | 
					be2db504b9 | ||
| 
						 | 
					cac6f5234f | ||
| 
						 | 
					eb6b32b6ee | ||
| 
						 | 
					07acc9529e | ||
| 
						 | 
					f7f0152573 | ||
| 
						 | 
					153533f1d5 | ||
| 
						 | 
					11622c586a | ||
| 
						 | 
					7396bb508a | ||
| 
						 | 
					7df6530f3a | ||
| 
						 | 
					80787456fa | ||
| 
						 | 
					4446ac1ca3 | ||
| 
						 | 
					220039ab00 | ||
| 
						 | 
					12f2250ab5 | ||
| 
						 | 
					0c33aa16a1 | ||
| 
						 | 
					72908b02fe | ||
| 
						 | 
					223aa04424 | ||
| 
						 | 
					e53248cca6 | ||
| 
						 | 
					c11d661b39 | ||
| 
						 | 
					4212a08337 | ||
| 
						 | 
					c0553fa9eb | ||
| 
						 | 
					7f26fafed7 | ||
| 
						 | 
					3e9309c003 | ||
| 
						 | 
					1017707475 | ||
| 
						 | 
					e8ff5da209 | ||
| 
						 | 
					03ed3ac1b0 | ||
| 
						 | 
					2c97208e74 | ||
| 
						 | 
					a458e81f8d | ||
| 
						 | 
					83289bc801 | ||
| 
						 | 
					ba2ac6a7b5 | ||
| 
						 | 
					245b6da577 | ||
| 
						 | 
					8875f924b0 | ||
| 
						 | 
					ad7868ebe1 | ||
| 
						 | 
					5effc6ec90 | ||
| 
						 | 
					4cc9ceabd2 | ||
| 
						 | 
					464c918134 | ||
| 
						 | 
					2456adcb68 | ||
| 
						 | 
					45bc967f30 | ||
| 
						 | 
					d6d4d29257 | ||
| 
						 | 
					33fdfdc8c0 | ||
| 
						 | 
					80c8712b2a | ||
| 
						 | 
					957e3eb93c | ||
| 
						 | 
					110e1afa8e | ||
| 
						 | 
					1da8f68871 | ||
| 
						 | 
					513ddb4cca | ||
| 
						 | 
					3bdfcb8542 | ||
| 
						 | 
					aee758eca2 | ||
| 
						 | 
					47ef7fffce | ||
| 
						 | 
					58d6256607 | ||
| 
						 | 
					b854fcdb72 | ||
| 
						 | 
					27ca75d94f | ||
| 
						 | 
					bb15f78af0 | ||
| 
						 | 
					ccc9e18132 | ||
| 
						 | 
					d55108ab60 | ||
| 
						 | 
					84adbcb683 | ||
| 
						 | 
					0cb5e4553b | ||
| 
						 | 
					264407b707 | ||
| 
						 | 
					eb5ec58453 | ||
| 
						 | 
					39c2a757be | ||
| 
						 | 
					8cdc05f582 | ||
| 
						 | 
					5f4778c852 | ||
| 
						 | 
					70add44fc1 | ||
| 
						 | 
					fa617d2e9d | ||
| 
						 | 
					3c795d365d | ||
| 
						 | 
					93872ad7a3 | ||
| 
						 | 
					227676c150 | ||
| 
						 | 
					5f23833b43 | ||
| 
						 | 
					121d51b414 | ||
| 
						 | 
					0e196a59d9 | ||
| 
						 | 
					63bfd23310 | ||
| 
						 | 
					aadcf8fed0 | ||
| 
						 | 
					37390e03b4 | ||
| 
						 | 
					98fc780ade | ||
| 
						 | 
					1670b21123 | ||
| 
						 | 
					5602aacbd2 | ||
| 
						 | 
					6ddbea207f | ||
| 
						 | 
					261bced822 | ||
| 
						 | 
					a80d1f861c | ||
| 
						 | 
					c541340ef5 | ||
| 
						 | 
					434af0ae64 | ||
| 
						 | 
					c6379ca1d4 | ||
| 
						 | 
					cdbcada49b | ||
| 
						 | 
					282930cb9b | ||
| 
						 | 
					b09c751942 | ||
| 
						 | 
					b2047b90b3 | ||
| 
						 | 
					0c8aec30bd | ||
| 
						 | 
					fafaa3e69b | ||
| 
						 | 
					d19bb3de8d | ||
| 
						 | 
					481136166c | ||
| 
						 | 
					4df81a0b9e | ||
| 
						 | 
					da1e9c2d97 | ||
| 
						 | 
					4b5a02c246 | ||
| 
						 | 
					0e1572cfd7 | ||
| 
						 | 
					343caa1ff6 | ||
| 
						 | 
					403fb3826d | ||
| 
						 | 
					3cdccb7b4e | ||
| 
						 | 
					d9be78cdb4 | ||
| 
						 | 
					16dc8255e1 | ||
| 
						 | 
					2086bfff25 | ||
| 
						 | 
					b9a68c0b8e | ||
| 
						 | 
					74647f0e88 | ||
| 
						 | 
					6e29c8bea9 | ||
| 
						 | 
					b36373ab81 | ||
| 
						 | 
					dc437aacf1 | ||
| 
						 | 
					e19dae9b28 | ||
| 
						 | 
					424cbd4831 | ||
| 
						 | 
					350feed993 | ||
| 
						 | 
					7ca4aa0ff4 | ||
| 
						 | 
					bf00e67245 | ||
| 
						 | 
					c5a6e49681 | ||
| 
						 | 
					a509af2875 | ||
| 
						 | 
					1f789bf396 | ||
| 
						 | 
					0ccbc7d3d2 | ||
| 
						 | 
					f3c6f26f85 | ||
| 
						 | 
					338c358df2 | ||
| 
						 | 
					4bdaa48303 | ||
| 
						 | 
					36267746da | ||
| 
						 | 
					7775541eed | ||
| 
						 | 
					5029be4c83 | ||
| 
						 | 
					277dbacf68 | ||
| 
						 | 
					0fdfb03f3c | ||
| 
						 | 
					17d81bf014 | ||
| 
						 | 
					568e9be07e | ||
| 
						 | 
					99b0a95f8a | ||
| 
						 | 
					0fdd31892a | ||
| 
						 | 
					7a682604f9 | ||
| 
						 | 
					ce96e35d7d | ||
| 
						 | 
					b7fb5394a7 | ||
| 
						 | 
					aaa62beca7 | ||
| 
						 | 
					2b58a7242b | ||
| 
						 | 
					5ed919df79 | ||
| 
						 | 
					baf6372179 | ||
| 
						 | 
					1a9063a55b | ||
| 
						 | 
					87999f402f | ||
| 
						 | 
					109d466260 | ||
| 
						 | 
					37597eca75 | ||
| 
						 | 
					5fd767b739 | ||
| 
						 | 
					0e7a473116 | ||
| 
						 | 
					05bf55dca8 | ||
| 
						 | 
					cc12ad8d86 | ||
| 
						 | 
					847a7f470c | ||
| 
						 | 
					95bebd6d1d | ||
| 
						 | 
					8179a964ea | ||
| 
						 | 
					d0805d4bbb | ||
| 
						 | 
					f901c401b7 | ||
| 
						 | 
					6ccadcb928 | ||
| 
						 | 
					58b6c25d5c | ||
| 
						 | 
					9cbab26202 | ||
| 
						 | 
					74bcb468ca | ||
| 
						 | 
					07a6ba88f4 | ||
| 
						 | 
					49dff49993 | ||
| 
						 | 
					68207aac80 | ||
| 
						 | 
					64652b2ff0 | ||
| 
						 | 
					659e8991de | ||
| 
						 | 
					9f495b6dc9 | ||
| 
						 | 
					d8498134ad | ||
| 
						 | 
					17b2320b0d | ||
| 
						 | 
					36c457f483 | ||
| 
						 | 
					b8ec7f5e26 | ||
| 
						 | 
					dbc5c0d5d8 | ||
| 
						 | 
					fa886aa849 | ||
| 
						 | 
					32e1ae2b18 | ||
| 
						 | 
					61f03b0ea2 | ||
| 
						 | 
					c47825a820 | ||
| 
						 | 
					2d7cb63c7b | ||
| 
						 | 
					c3d4c13936 | ||
| 
						 | 
					3f51b9322f | ||
| 
						 | 
					b604e2bd4e | ||
| 
						 | 
					bcd92473d1 | ||
| 
						 | 
					6f5bf9d146 | ||
| 
						 | 
					490094939f | ||
| 
						 | 
					d0d7d2772f | ||
| 
						 | 
					59091896b4 | ||
| 
						 | 
					3eb1429a25 | ||
| 
						 | 
					bc7504c469 | ||
| 
						 | 
					99dc4b8e07 | ||
| 
						 | 
					807904bb86 | ||
| 
						 | 
					7b8c8348f4 | ||
| 
						 | 
					9c5ac26170 | ||
| 
						 | 
					5db065644c | ||
| 
						 | 
					0cc3a99169 | ||
| 
						 | 
					2b1545145b | ||
| 
						 | 
					49b7c9c8a4 | ||
| 
						 | 
					114119f7c8 | ||
| 
						 | 
					b4ef866c10 | ||
| 
						 | 
					15f75a08d5 | ||
| 
						 | 
					29f9c5473d | ||
| 
						 | 
					ea1528aea6 | ||
| 
						 | 
					18ce19a84d | ||
| 
						 | 
					b0fd78d68d | ||
| 
						 | 
					8186d6277e | ||
| 
						 | 
					599af2b1a9 | ||
| 
						 | 
					82de5adbe9 | ||
| 
						 | 
					82b0f85258 | ||
| 
						 | 
					cded58c30d | ||
| 
						 | 
					da17b49b81 | ||
| 
						 | 
					4728cdfa7c | ||
| 
						 | 
					d97b30dcee | ||
| 
						 | 
					fa8e8ad52d | ||
| 
						 | 
					7495ac8111 | ||
| 
						 | 
					08619e2c06 | ||
| 
						 | 
					5d4bbd5b37 | ||
| 
						 | 
					9d2aef5006 | ||
| 
						 | 
					bcc3e5ebb0 | ||
| 
						 | 
					e5df51a83a | ||
| 
						 | 
					97fb843f01 | ||
| 
						 | 
					8afb044877 | ||
| 
						 | 
					7f869868c9 | ||
| 
						 | 
					31275228ac | ||
| 
						 | 
					7181be8768 | ||
| 
						 | 
					3b446e887a | ||
| 
						 | 
					431196c391 | ||
| 
						 | 
					9608d8fb46 | ||
| 
						 | 
					d574ca1628 | ||
| 
						 | 
					8be60e2ff5 | ||
| 
						 | 
					3c0fd540b1 | ||
| 
						 | 
					23a7dc9a8a | ||
| 
						 | 
					f97e6892b6 | ||
| 
						 | 
					7742901e5c | ||
| 
						 | 
					de68cb25d0 | ||
| 
						 | 
					77d7afe505 | ||
| 
						 | 
					68fb6c2c27 | ||
| 
						 | 
					a47c031ad1 | ||
| 
						 | 
					817049456c | ||
| 
						 | 
					e1a061789f | ||
| 
						 | 
					28573ba772 | ||
| 
						 | 
					880b9413f6 | ||
| 
						 | 
					9a7c4b21a9 | ||
| 
						 | 
					ac56038eca | ||
| 
						 | 
					4dd2fb6903 | ||
| 
						 | 
					0baec61f06 | ||
| 
						 | 
					d4751788d1 | ||
| 
						 | 
					ae68c061d1 | ||
| 
						 | 
					b0387245f0 | ||
| 
						 | 
					c2d06a4a23 | ||
| 
						 | 
					270108abb7 | ||
| 
						 | 
					e76c33232d | ||
| 
						 | 
					58ff2dc492 | ||
| 
						 | 
					13c45a0e96 | ||
| 
						 | 
					90cb86911a | ||
| 
						 | 
					be7b1a1bd4 | ||
| 
						 | 
					132a3c6705 | ||
| 
						 | 
					5e73257557 | ||
| 
						 | 
					e83346fbbb | ||
| 
						 | 
					2dd47a2103 | ||
| 
						 | 
					f31e530b6e | ||
| 
						 | 
					eb50f3fa9c | ||
| 
						 | 
					8417fe4fdb | ||
| 
						 | 
					0f1c15a6ca | ||
| 
						 | 
					9345c4fb7f | ||
| 
						 | 
					5e0758917b | ||
| 
						 | 
					f56839ec6b | ||
| 
						 | 
					cbb23a42e2 | ||
| 
						 | 
					5a59c286d0 | ||
| 
						 | 
					2e8c600d7a | ||
| 
						 | 
					e851cb1cbc | ||
| 
						 | 
					3da03da32a | ||
| 
						 | 
					3ec8924e7f | ||
| 
						 | 
					a04722b612 | ||
| 
						 | 
					f9a7857a90 | ||
| 
						 | 
					58f772c74e | ||
| 
						 | 
					a425c7e260 | ||
| 
						 | 
					809885afd0 | ||
| 
						 | 
					bf9b4b993f | ||
| 
						 | 
					d94a26f0f4 | ||
| 
						 | 
					bd9c9cedca | ||
| 
						 | 
					651e94bd94 | ||
| 
						 | 
					162b6f1a74 | ||
| 
						 | 
					865a253eb5 | ||
| 
						 | 
					9b3781abf1 | ||
| 
						 | 
					d89243a0d3 | ||
| 
						 | 
					b4cefc64b4 | ||
| 
						 | 
					2fd26587e5 | ||
| 
						 | 
					282a351859 | ||
| 
						 | 
					a84b848ea9 | ||
| 
						 | 
					d329320fc2 | ||
| 
						 | 
					bc096554b5 | ||
| 
						 | 
					5902d878d8 | ||
| 
						 | 
					4a133ca36f | ||
| 
						 | 
					f7252f919a | ||
| 
						 | 
					e05a03a842 | ||
| 
						 | 
					dcce8276b8 | ||
| 
						 | 
					fd47947e55 | ||
| 
						 | 
					ae151df2eb | ||
| 
						 | 
					79de188683 | ||
| 
						 | 
					6e5c788e13 | ||
| 
						 | 
					f53606007d | ||
| 
						 | 
					a4ac418bc9 | ||
| 
						 | 
					a8c09d0bdb | ||
| 
						 | 
					871105a48a | ||
| 
						 | 
					3b61129ade | ||
| 
						 | 
					f471c79b59 | ||
| 
						 | 
					dfd9443f74 | ||
| 
						 | 
					a36ff9e365 | ||
| 
						 | 
					12e65bbf26 | ||
| 
						 | 
					ab9841e60b | ||
| 
						 | 
					7a52f12e57 | ||
| 
						 | 
					11fd4506ac | ||
| 
						 | 
					0c9c68030e | ||
| 
						 | 
					55d6eddbb2 | ||
| 
						 | 
					8341e60edb | ||
| 
						 | 
					6273a1ca73 | ||
| 
						 | 
					1b83ebdf89 | ||
| 
						 | 
					fef7f0506f | ||
| 
						 | 
					f44eb4e383 | ||
| 
						 | 
					05df485c4a | ||
| 
						 | 
					44857c526b | ||
| 
						 | 
					b8ad5d5d32 | ||
| 
						 | 
					e3e0d00e21 | ||
| 
						 | 
					a9b1ea9690 | ||
| 
						 | 
					8e5dd0f8d9 | ||
| 
						 | 
					3b0c8f6d92 | ||
| 
						 | 
					21058c2227 | ||
| 
						 | 
					f3b8ae0781 | ||
| 
						 | 
					d590b004c1 | ||
| 
						 | 
					02e21141c6 | ||
| 
						 | 
					f839a3087d | ||
| 
						 | 
					f458815541 | ||
| 
						 | 
					7ba754d2a4 | ||
| 
						 | 
					09706e4ae2 | ||
| 
						 | 
					d18de4c541 | ||
| 
						 | 
					001c7bfdbc | ||
| 
						 | 
					d4e04dc712 | ||
| 
						 | 
					8650cb5217 | ||
| 
						 | 
					0eaaddeb95 | ||
| 
						 | 
					1cf8663f20 | ||
| 
						 | 
					5130259552 | ||
| 
						 | 
					ba5e19a015 | ||
| 
						 | 
					c0400fa986 | ||
| 
						 | 
					51179d10ce | ||
| 
						 | 
					78752f9178 | ||
| 
						 | 
					762db417d7 | ||
| 
						 | 
					85bdccbc06 | ||
| 
						 | 
					9f8cb99340 | ||
| 
						 | 
					87b90bb04b | ||
| 
						 | 
					e961d88277 | ||
| 
						 | 
					5754c11e34 | ||
| 
						 | 
					7bd88c1bb8 | ||
| 
						 | 
					445b686c6c | ||
| 
						 | 
					0cb7b75214 | ||
| 
						 | 
					a08399dfee | ||
| 
						 | 
					4016808fa4 | ||
| 
						 | 
					8635849977 | ||
| 
						 | 
					1a9ed4d4fe | ||
| 
						 | 
					e7b3246dd0 | ||
| 
						 | 
					19589aec57 | ||
| 
						 | 
					4d33ff0417 | ||
| 
						 | 
					93a5ab5b33 | ||
| 
						 | 
					59ada06cdf | ||
| 
						 | 
					ae650849b0 | ||
| 
						 | 
					3e8f9a6b53 | ||
| 
						 | 
					79362b0dba | ||
| 
						 | 
					3e3df06d57 | ||
| 
						 | 
					6b220eb1c5 | ||
| 
						 | 
					a1c61cae11 | ||
| 
						 | 
					d48a917bf3 | ||
| 
						 | 
					646b6dafb2 | ||
| 
						 | 
					8d10f33a3f | 
@@ -4,23 +4,13 @@ jobs:
 | 
			
		||||
    build:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        environment:
 | 
			
		||||
            CONTRACTS_COMMIT_HASH: '9ed05f5'
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - checkout
 | 
			
		||||
            - run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
 | 
			
		||||
            # HACK(feuGeneA): commented out this hack as we're changing
 | 
			
		||||
            # from a circleci-maintained container to a different
 | 
			
		||||
            # container, and this hack may not apply anymore, as
 | 
			
		||||
            # suggested by the non-existance of `/home/circleci/.bashrc`
 | 
			
		||||
            # when running the command below.
 | 
			
		||||
            # - run:
 | 
			
		||||
            #       # HACK(albrow): Without this, yarn commands will sometimes
 | 
			
		||||
            #       # fail with a "permission denied" error.
 | 
			
		||||
            #       name: Set npm path
 | 
			
		||||
            #       command: npm set prefix=/home/circleci/npm && echo 'export PATH=$HOME/circleci/npm/bin:$PATH' >> /home/circleci/.bashrc
 | 
			
		||||
            - run:
 | 
			
		||||
                  name: install-yarn
 | 
			
		||||
                  command: npm install --force --global yarn@1.17.0
 | 
			
		||||
@@ -38,54 +28,60 @@ jobs:
 | 
			
		||||
                  path: ~/repo/packages/abi-gen/test-cli/output
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/packages/contract-wrappers/generated_docs
 | 
			
		||||
    test-contracts-ganache:
 | 
			
		||||
    test-exchange-ganache:
 | 
			
		||||
        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-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:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange
 | 
			
		||||
    test-integrations-ganache-3.0:
 | 
			
		||||
    test-integrations-ganache:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        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:
 | 
			
		||||
    test-contracts-staking-ganache:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - 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-tests @0x/contracts-staking @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler
 | 
			
		||||
            # 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
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-staking
 | 
			
		||||
    test-contracts-extra-ganache:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-exchange-forwarder @0x/contracts-coordinator
 | 
			
		||||
    test-contracts-rest-ganache:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - 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-broker @0x/contracts-zero-ex
 | 
			
		||||
    test-publish:
 | 
			
		||||
        resource_class: medium+
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
            - image: 0xorg/verdaccio
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
@@ -95,9 +91,11 @@ jobs:
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: yarn test:publish:circleci
 | 
			
		||||
                  no_output_timeout: 1800
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/.npm/_logs
 | 
			
		||||
    test-doc-generation:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
@@ -108,228 +106,35 @@ jobs:
 | 
			
		||||
                  no_output_timeout: 1200
 | 
			
		||||
    test-rest:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contracts-test-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/abi-gen
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/asset-swapper
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contract-artifacts
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/assert
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/base-contract
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/connect
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/contract-wrappers-test
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/dev-utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/json-schemas
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/migrations
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/order-utils
 | 
			
		||||
            - 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
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/subproviders
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/web3-wrapper
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/utils
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/instant
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/abi-gen/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/assert/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-asset-swapper-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/asset-swapper/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/base-contract/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/connect/coverage/lcov.info
 | 
			
		||||
            - run: yarn wsrun test:circleci @0x/asset-swapper
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/contract-wrappers-test/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/dev-utils/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/json-schemas/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/order-utils/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/sol-compiler/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-sol-tracing-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/sol-tracing-utils/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/sol-doc/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/subproviders/coverage/lcov.info
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/packages/web3-wrapper/coverage/lcov.info
 | 
			
		||||
    test-python:
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: 0xorg/ganache-cli:6.0.0
 | 
			
		||||
            - image: 0xorg/mesh:0xV3
 | 
			
		||||
              environment:
 | 
			
		||||
                  ETHEREUM_RPC_URL: 'http://localhost:8545'
 | 
			
		||||
                  ETHEREUM_CHAIN_ID: '1337'
 | 
			
		||||
                  VERBOSITY: 5
 | 
			
		||||
                  BLOCK_POLLING_INTERVAL: '50ms'
 | 
			
		||||
                  ETHEREUM_RPC_MAX_REQUESTS_PER_24_HR_UTC: '1778000'
 | 
			
		||||
              command: |
 | 
			
		||||
                  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 30; }; waitForMesh && node_modules/.bin/forever ts/lib/index.js"
 | 
			
		||||
        steps:
 | 
			
		||||
            - checkout
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      ./pre_install
 | 
			
		||||
                      ./install
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - '/usr/local/bin'
 | 
			
		||||
                      - '/usr/local/lib/python3.7/site-packages'
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      ./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:
 | 
			
		||||
                      - ~/repo/python-packages/contract_addresses/.coverage
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-contract-artifacts-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/contract_artifacts/.coverage
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-contract-demo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/contract_demo/.coverage
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/json_schemas/.coverage
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-order-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/order_utils/.coverage
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - ~/repo/python-packages/sra_client/.coverage
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/contract_addresses/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/contract_artifacts/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/contract_wrappers/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/json_schemas/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/middlewares/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/order_utils/build
 | 
			
		||||
            - store_artifacts:
 | 
			
		||||
                  path: ~/repo/python-packages/sra_client/build
 | 
			
		||||
    test-rest-python:
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
        steps:
 | 
			
		||||
            - checkout
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages/order_utils
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      python -m pip install .
 | 
			
		||||
            - save_cache:
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
                  paths:
 | 
			
		||||
                      - '/usr/local/bin'
 | 
			
		||||
                      - '/usr/local/lib/python3.7/site-packages'
 | 
			
		||||
                      - '.eggs'
 | 
			
		||||
                      - '.mypy_cache'
 | 
			
		||||
                      - '.pytest_cache'
 | 
			
		||||
                      - '.tox'
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      cd python-packages/order_utils
 | 
			
		||||
                      tox
 | 
			
		||||
    static-tests-python:
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
        steps:
 | 
			
		||||
            - checkout
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run:
 | 
			
		||||
                  command: |
 | 
			
		||||
                      python -m ensurepip
 | 
			
		||||
                      cd python-packages
 | 
			
		||||
                      ./pre_install
 | 
			
		||||
                      ./install
 | 
			
		||||
                      ./lint
 | 
			
		||||
    static-tests:
 | 
			
		||||
        resource_class: large
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
@@ -338,92 +143,43 @@ jobs:
 | 
			
		||||
            - run: yarn prettier:ci
 | 
			
		||||
            - run: yarn deps_versions:ci
 | 
			
		||||
            - run: yarn diff_md_docs:ci
 | 
			
		||||
            - run: cd packages/0x.js && yarn build:umd:prod
 | 
			
		||||
            - run: yarn bundlewatch
 | 
			
		||||
    submit-coverage:
 | 
			
		||||
        docker:
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs8
 | 
			
		||||
            - image: nikolaik/python-nodejs:python3.7-nodejs10
 | 
			
		||||
        working_directory: ~/repo
 | 
			
		||||
        steps:
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - repo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-asset-swapper-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-sol-tracing-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-sol-doc-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-contract-artifacts-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-contract-demo-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - restore_cache:
 | 
			
		||||
                  keys:
 | 
			
		||||
                      - coverage-python-order-utils-{{ .Environment.CIRCLE_SHA1 }}
 | 
			
		||||
            - run: yarn report_coverage
 | 
			
		||||
workflows:
 | 
			
		||||
    version: 2
 | 
			
		||||
    main:
 | 
			
		||||
        jobs:
 | 
			
		||||
            - build
 | 
			
		||||
            - test-exchange-ganache-3.0:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-integrations-ganache-3.0:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-contracts-rest-ganache-3.0:
 | 
			
		||||
            # Disabled until we begin actively developing on these packages again.
 | 
			
		||||
            # - test-exchange-ganache:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            # - test-integrations-ganache:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            # - test-contracts-staking-ganache:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            # - test-contracts-extra-ganache:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           - build
 | 
			
		||||
            - test-contracts-rest-ganache:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - test-rest:
 | 
			
		||||
@@ -438,17 +194,14 @@ workflows:
 | 
			
		||||
            - test-doc-generation:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - build
 | 
			
		||||
            - submit-coverage:
 | 
			
		||||
                  requires:
 | 
			
		||||
                      - test-contracts-rest-ganache-3.0
 | 
			
		||||
                      - test-exchange-ganache-3.0
 | 
			
		||||
                      - test-rest
 | 
			
		||||
                      - static-tests
 | 
			
		||||
            - 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
 | 
			
		||||
            # Disabled until this repo has a coveralls API key
 | 
			
		||||
            # - submit-coverage:
 | 
			
		||||
            #       requires:
 | 
			
		||||
            #           # Disabled until we begin actively developing on these packages again.
 | 
			
		||||
            #           # - test-exchange-ganache
 | 
			
		||||
            #           # - test-integrations-ganache
 | 
			
		||||
            #           # - test-contracts-staking-ganache
 | 
			
		||||
            #           # - test-contracts-extra-ganache
 | 
			
		||||
            #           - test-contracts-rest-ganache
 | 
			
		||||
            #           - test-rest
 | 
			
		||||
            #           - static-tests
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,3 @@
 | 
			
		||||
 | 
			
		||||
# Automatically collapse generated files in GitHub.
 | 
			
		||||
*.svg linguist-generated=true
 | 
			
		||||
packages/contract-artifacts/artifacts/*json linguist-generated=true
 | 
			
		||||
packages/abi-gen-wrappers/src/generated-wrappers/*.ts linguist-generated=true
 | 
			
		||||
packages/contract-wrappers/src/generated-wrappers/*.ts linguist-generated=true
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,33 +1,7 @@
 | 
			
		||||
python: ['python-packages']
 | 
			
		||||
contracts: ['contracts']
 | 
			
		||||
@0x/sol-doc: ['packages/sol-doc']
 | 
			
		||||
@0x/sol-resolver: ['packages/sol-resolver']
 | 
			
		||||
@0x/contracts-gen: ['packages/contracts-gen']
 | 
			
		||||
@0x/sra-spec: ['packages/sra-spec']
 | 
			
		||||
@0x/subproviders: ['packages/subproviders']
 | 
			
		||||
@0x/contract-addresses: ['packages/contract-addresses']
 | 
			
		||||
@0x/migrations: ['packages/migrations']
 | 
			
		||||
@0x/web3-wrapper: ['packages/web3-wrapper']
 | 
			
		||||
@0x/sol-compiler: ['packages/sol-compiler']
 | 
			
		||||
@0x/types: ['packages/types']
 | 
			
		||||
@0x/instant: ['packages/instant']
 | 
			
		||||
@0x/abi-gen-templates: ['packages/abi-gen-templates']
 | 
			
		||||
@0x/abi-gen: ['packages/abi-gen']
 | 
			
		||||
@0x/sol-coverage: ['packages/sol-coverage']
 | 
			
		||||
@0x/sol-profiler: ['packages/sol-profiler']
 | 
			
		||||
@0x/sol-trace: ['packages/sol-trace']
 | 
			
		||||
@0x/sol-tracing-utils: ['packages/sol-tracing-utils']
 | 
			
		||||
@0x/utils: ['packages/utils']
 | 
			
		||||
@0x/tslint-config: ['packages/tslint-config']
 | 
			
		||||
@0x/asset-swapper: ['packages/asset-swapper']
 | 
			
		||||
@0x/order-utils: ['packages/order-utils']
 | 
			
		||||
@0x/assert: ['packages/assert']
 | 
			
		||||
@0x/base-contract: ['packages/base-contract']
 | 
			
		||||
@0x/typescript-typings: ['packages/typescript-typings']
 | 
			
		||||
0x.js: ['packages/0x.js']
 | 
			
		||||
@0x/contract-artifacts: ['packages/contract-artifacts']
 | 
			
		||||
@0x/dev-utils: ['packages/dev-utils']
 | 
			
		||||
@0x/contract-wrappers: ['packages/contract-wrappers']
 | 
			
		||||
@0x/json-schemas: ['packages/json-schemas']
 | 
			
		||||
@0x/ethereum-types: ['ethereum-types']
 | 
			
		||||
@0x/connect: ['packages/connect']
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
name: publish
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
      inputs:
 | 
			
		||||
          ci_status:
 | 
			
		||||
              description: 'required CI status'
 | 
			
		||||
              default: 'success'
 | 
			
		||||
              required: true
 | 
			
		||||
          prerelease:
 | 
			
		||||
              description: 'prerelease name'
 | 
			
		||||
              required: false
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
    publish:
 | 
			
		||||
        runs-on: ubuntu-latest
 | 
			
		||||
        steps:
 | 
			
		||||
            - name: 'check successful status'
 | 
			
		||||
              run: |
 | 
			
		||||
                  REF_STATUS=$(curl -s \
 | 
			
		||||
                  'https://api.github.com/repos/${{ github.repository }}/commits/${{ github.ref }}/status' \
 | 
			
		||||
                  | jq .state)
 | 
			
		||||
                  [[ "${REF_STATUS}" == '"${{ github.event.inputs.ci_status }}"' ]] || \
 | 
			
		||||
                  (echo "::error ::${{ github.ref }} does not have a successful CI status" && false)
 | 
			
		||||
            - uses: actions/checkout@v2
 | 
			
		||||
              with:
 | 
			
		||||
                ref: ${{ github.ref }}
 | 
			
		||||
                fetch-depth: 0
 | 
			
		||||
            - uses: actions/setup-node@v1
 | 
			
		||||
              with:
 | 
			
		||||
                node-version: 10
 | 
			
		||||
            - uses: actions/setup-python@v2
 | 
			
		||||
            - name: 'configure git'
 | 
			
		||||
              run: |
 | 
			
		||||
                  git config --global user.email "github-actions@github.com"
 | 
			
		||||
                  git config --global user.name "Github Actions"
 | 
			
		||||
            - name: 'install dependencies'
 | 
			
		||||
              run: |
 | 
			
		||||
                  yarn -D
 | 
			
		||||
            - name: 'build and publish'
 | 
			
		||||
              run: |
 | 
			
		||||
                  echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > .npmrc
 | 
			
		||||
                  npm run run:publish:gha
 | 
			
		||||
              env:
 | 
			
		||||
                  NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
 | 
			
		||||
                  GITHUB_TOKEN: ${{ github.token }}
 | 
			
		||||
                  PUBLISH_PRERELEASE: ${{ github.event.inputs.prerelease }}
 | 
			
		||||
            - name: 'merge into main branch'
 | 
			
		||||
              if: github.event.inputs.prerelease == '' # unless it's a prerelease
 | 
			
		||||
              run: |
 | 
			
		||||
                  git checkout main && \
 | 
			
		||||
                  git merge ${{ github.ref }} && \
 | 
			
		||||
                  git push
 | 
			
		||||
							
								
								
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -111,8 +111,10 @@ 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/
 | 
			
		||||
contracts/zero-ex/generated-artifacts/
 | 
			
		||||
contracts/zero-ex/test/generated-artifacts/
 | 
			
		||||
contracts/treasury/generated-artifacts/
 | 
			
		||||
contracts/treasury/test/generated-artifacts/
 | 
			
		||||
 | 
			
		||||
# generated truffle contract artifacts/
 | 
			
		||||
contracts/broker/build/
 | 
			
		||||
@@ -165,24 +167,10 @@ 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/*/__init__.py
 | 
			
		||||
 | 
			
		||||
# solc-bin in sol-compiler
 | 
			
		||||
packages/sol-compiler/solc_bin/
 | 
			
		||||
 | 
			
		||||
# python stuff
 | 
			
		||||
.eggs
 | 
			
		||||
.mypy_cache
 | 
			
		||||
.tox
 | 
			
		||||
python-packages/*/build
 | 
			
		||||
python-packages/*/dist
 | 
			
		||||
__pycache__
 | 
			
		||||
python-packages/*/src/*.egg-info
 | 
			
		||||
python-packages/*/.coverage
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
contracts/zero-ex/generated-wrappers/
 | 
			
		||||
contracts/zero-ex/test/generated-wrappers/
 | 
			
		||||
contracts/treasury/generated-wrappers/
 | 
			
		||||
contracts/treasury/test/generated-wrappers/
 | 
			
		||||
 | 
			
		||||
# Doc README copy
 | 
			
		||||
packages/*/docs/README.md
 | 
			
		||||
 
 | 
			
		||||
@@ -40,10 +40,6 @@ lib
 | 
			
		||||
/contracts/erc20/test/generated-wrappers
 | 
			
		||||
/contracts/erc20/generated-artifacts
 | 
			
		||||
/contracts/erc20/test/generated-artifacts
 | 
			
		||||
/contracts/erc20-bridge-sampler/generated-wrappers
 | 
			
		||||
/contracts/erc20-bridge-sampler/test/generated-wrappers
 | 
			
		||||
/contracts/erc20-bridge-sampler/generated-artifacts
 | 
			
		||||
/contracts/erc20-bridge-sampler/test/generated-artifacts
 | 
			
		||||
/contracts/erc721/generated-wrappers
 | 
			
		||||
/contracts/erc721/test/generated-wrappers
 | 
			
		||||
/contracts/erc721/generated-artifacts
 | 
			
		||||
@@ -64,6 +60,14 @@ lib
 | 
			
		||||
/contracts/dev-utils/test/generated-wrappers
 | 
			
		||||
/contracts/dev-utils/generated-artifacts
 | 
			
		||||
/contracts/dev-utils/test/generated-artifacts
 | 
			
		||||
/contracts/zero-ex/generated-wrappers
 | 
			
		||||
/contracts/zero-ex/test/generated-wrappers
 | 
			
		||||
/contracts/zero-ex/generated-artifacts
 | 
			
		||||
/contracts/zero-ex/test/generated-artifacts
 | 
			
		||||
/contracts/treasury/generated-wrappers
 | 
			
		||||
/contracts/treasury/test/generated-wrappers
 | 
			
		||||
/contracts/treasury/generated-artifacts
 | 
			
		||||
/contracts/treasury/test/generated-artifacts
 | 
			
		||||
/contracts/staking/build/
 | 
			
		||||
/contracts/coordinator/build/
 | 
			
		||||
/contracts/exchange/build/
 | 
			
		||||
@@ -76,18 +80,11 @@ lib
 | 
			
		||||
/contracts/erc1155/build/
 | 
			
		||||
/contracts/extensions/build/
 | 
			
		||||
/contracts/exchange-forwarder/build/
 | 
			
		||||
/contracts/dev-utils/build/
 | 
			
		||||
/packages/abi-gen/test-cli/output
 | 
			
		||||
/packages/json-schemas/schemas
 | 
			
		||||
/python-packages/json_schemas/src/zero_ex/json_schemas/schemas
 | 
			
		||||
/packages/sra-spec/public/
 | 
			
		||||
/packages/asset-swapper/generated-artifacts
 | 
			
		||||
/packages/asset-swapper/generated-wrappers
 | 
			
		||||
/packages/asset-swapper/test/generated-artifacts
 | 
			
		||||
/packages/asset-swapper/test/generated-wrappers
 | 
			
		||||
package.json
 | 
			
		||||
scripts/postpublish_utils.js
 | 
			
		||||
packages/sol-coverage/test/fixtures/artifacts
 | 
			
		||||
.pytest_cache
 | 
			
		||||
.mypy_cache
 | 
			
		||||
.tox
 | 
			
		||||
packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json
 | 
			
		||||
packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json
 | 
			
		||||
packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json
 | 
			
		||||
packages/*/docs
 | 
			
		||||
docs/
 | 
			
		||||
*.sol
 | 
			
		||||
 
 | 
			
		||||
@@ -2,5 +2,6 @@
 | 
			
		||||
    "printWidth": 120,
 | 
			
		||||
    "tabWidth": 4,
 | 
			
		||||
    "singleQuote": true,
 | 
			
		||||
    "trailingComma": "all"
 | 
			
		||||
    "trailingComma": "all",
 | 
			
		||||
    "bracketSpacing": true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
# Read the Docs configuration file
 | 
			
		||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
 | 
			
		||||
 | 
			
		||||
# Required
 | 
			
		||||
version: 2
 | 
			
		||||
 | 
			
		||||
# Build documentation in the docs/ directory with Sphinx
 | 
			
		||||
sphinx:
 | 
			
		||||
  configuration: docs/conf.py
 | 
			
		||||
 | 
			
		||||
# Build documentation with MkDocs
 | 
			
		||||
#mkdocs:
 | 
			
		||||
#  configuration: mkdocs.yml
 | 
			
		||||
 | 
			
		||||
# Optionally build your docs in additional formats such as PDF
 | 
			
		||||
#formats:
 | 
			
		||||
#  - pdf
 | 
			
		||||
 | 
			
		||||
# Optionally set the version of Python and requirements required to build your docs
 | 
			
		||||
python:
 | 
			
		||||
  version: 3.7
 | 
			
		||||
  install:
 | 
			
		||||
    - requirements: docs/requirements.txt
 | 
			
		||||
							
								
								
									
										26
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								CODEOWNERS
									
									
									
									
									
								
							@@ -9,30 +9,10 @@ packages/asset-swapper/  @BMillman19 @fragosti @dave4506
 | 
			
		||||
packages/instant/  @BMillman19 @fragosti @dave4506
 | 
			
		||||
 | 
			
		||||
# Dev tools & setup
 | 
			
		||||
.circleci/ @LogvinovLeon
 | 
			
		||||
packages/abi-gen/ @feuGeneA
 | 
			
		||||
packages/base-contract/ @xianny
 | 
			
		||||
packages/connect/ @fragosti 
 | 
			
		||||
packages/abi-gen-templates/ @feuGeneA @xianny
 | 
			
		||||
.circleci/ @dorothy-zbornak
 | 
			
		||||
packages/contract-addresses/ @abandeali1
 | 
			
		||||
packages/contract-artifacts/ @abandeali1
 | 
			
		||||
packages/dev-utils/ @LogvinovLeon @fabioberger
 | 
			
		||||
packages/devnet/ @albrow
 | 
			
		||||
packages/ethereum-types/ @LogvinovLeon
 | 
			
		||||
packages/monorepo-scripts/ @fabioberger
 | 
			
		||||
packages/order-utils/ @fabioberger @LogvinovLeon 
 | 
			
		||||
packages/python-contract-wrappers/ @feuGeneA
 | 
			
		||||
packages/sol-compiler/ @LogvinovLeon
 | 
			
		||||
packages/sol-coverage/ @LogvinovLeon
 | 
			
		||||
packages/sol-profiler/ @LogvinovLeon
 | 
			
		||||
packages/sol-trace/ @LogvinovLeon
 | 
			
		||||
packages/sol-tracing-utils/ @LogvinovLeon
 | 
			
		||||
packages/sol-resolver/ @LogvinovLeon
 | 
			
		||||
packages/subproviders/ @fabioberger @dekz
 | 
			
		||||
packages/verdaccio/ @albrow
 | 
			
		||||
packages/web3-wrapper/ @LogvinovLeon @fabioberger
 | 
			
		||||
python-packages/ @feuGeneA
 | 
			
		||||
packages/utils/ @hysz
 | 
			
		||||
packages/order-utils/ @dorothy-zbornak 
 | 
			
		||||
 | 
			
		||||
# Protocol/smart contracts
 | 
			
		||||
contracts/ @abandeali1 @hysz
 | 
			
		||||
contracts/ @abandeali1 @hysz @dorothy-zbornak @mzhu25
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,9 @@ We welcome contributions from anyone on the internet and are grateful for even t
 | 
			
		||||
 | 
			
		||||
### Getting started
 | 
			
		||||
 | 
			
		||||
1.  Fork `0xproject/0x-monorepo`
 | 
			
		||||
1.  Fork `0xproject/0x-tools`
 | 
			
		||||
2.  Clone your fork
 | 
			
		||||
3.  Follow the [installation & build steps](https://github.com/0xProject/0x-monorepo#install-dependencies) in the repo's top-level README.
 | 
			
		||||
3.  Follow the [installation & build steps](https://github.com/0xProject/0x-tools#install-dependencies) in the repo's top-level README.
 | 
			
		||||
4.  Setup the recommended [Development Tooling](#development-tooling).
 | 
			
		||||
5.  Open a PR with the `[WIP]` flag against the `development` branch and describe the change you are intending to undertake in the PR description. (see [our branch naming conventions](#branch-structure))
 | 
			
		||||
 | 
			
		||||
@@ -59,11 +59,11 @@ We strongly recommend you use the [VSCode](https://code.visualstudio.com/) text
 | 
			
		||||
 | 
			
		||||
#### Linter
 | 
			
		||||
 | 
			
		||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code-style consistent.
 | 
			
		||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-tools/tree/development/packages/tslint-config) to keep our code-style consistent.
 | 
			
		||||
 | 
			
		||||
Use `yarn:lint` to lint the entire monorepo, and `PKG={PACKAGE_NAME} yarn lint` to lint a specific package.
 | 
			
		||||
 | 
			
		||||
If you want to change a rule, or add a custom rule, please make these changes to our [tslint-config](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) package. All other packages have it as a dependency.
 | 
			
		||||
If you want to change a rule, or add a custom rule, please make these changes to our [tslint-config](https://github.com/0xProject/0x-tools/tree/development/packages/tslint-config) package. All other packages have it as a dependency.
 | 
			
		||||
 | 
			
		||||
Integrate it into your text editor:
 | 
			
		||||
 | 
			
		||||
@@ -94,12 +94,12 @@ A few of our coding conventions are not yet enforced by the linter/auto-formatte
 | 
			
		||||
 | 
			
		||||
### Fix `submit-coverage` CI failure
 | 
			
		||||
 | 
			
		||||
If you simply fork the repo and then create a PR from it, your PR will fail the `submit-coverage` check on CI. This is because the 0x CircleCI configuration sets the `COVERALLS_REPO_TOKEN` environment variable to the token for `0xProject/0x-monorepo`, but when running the check against your fork the token needs to match your repo's name `your-username/0x-monorepo`.
 | 
			
		||||
If you simply fork the repo and then create a PR from it, your PR will fail the `submit-coverage` check on CI. This is because the 0x CircleCI configuration sets the `COVERALLS_REPO_TOKEN` environment variable to the token for `0xProject/0x-tools`, but when running the check against your fork the token needs to match your repo's name `your-username/0x-tools`.
 | 
			
		||||
 | 
			
		||||
To facilitate this check, after creating your fork, but before creating the branch for your PR, do the following:
 | 
			
		||||
 | 
			
		||||
1.  Log in to [coveralls.io](https://coveralls.io/), go to `Add Repos`, and enable your fork. Then go to the settings for that repo, and copy the `Repo Token` identifier.
 | 
			
		||||
2.  Log in to [CircleCI](https://circleci.com/login), go to `Add Projects`, click the `Set Up Project` button corresponding to your fork, and then click `Start Building`. (Aside from step 3 below, no actual set up is needed, since it will use the `.circleci/config.yml` file in 0x-monorepo, so you can ignore all of the instruction/explanation given on the page with the `Start Building` button.)
 | 
			
		||||
2.  Log in to [CircleCI](https://circleci.com/login), go to `Add Projects`, click the `Set Up Project` button corresponding to your fork, and then click `Start Building`. (Aside from step 3 below, no actual set up is needed, since it will use the `.circleci/config.yml` file in 0x-tools, so you can ignore all of the instruction/explanation given on the page with the `Start Building` button.)
 | 
			
		||||
3.  In CircleCI, configure your project to add an environment variable, with name `COVERALLS_REPO_TOKEN`, and for the value paste in the `Repo Token` you copied in step 1.
 | 
			
		||||
 | 
			
		||||
Now, when you push to your branch, CircleCI will automatically run all of the checks in your own instance, and the coverage check will work since it has the proper `Repo Token`, and the PR will magically refer to your own checks rather than running them in the 0x CircleCI instance.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
Copyright 2017 ZeroEx Intl.
 | 
			
		||||
Copyright 2020 ZeroEx Labs
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								README.md
									
									
									
									
									
								
							@@ -8,7 +8,7 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
 | 
			
		||||
 | 
			
		||||
[website-url]: https://0x.org
 | 
			
		||||
 | 
			
		||||
[](https://circleci.com/gh/0xProject/0x-monorepo)
 | 
			
		||||
[](https://circleci.com/gh/0xProject/protocool)
 | 
			
		||||
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)
 | 
			
		||||
[](https://discordapp.com/invite/d3FTX3M)
 | 
			
		||||
[](https://opensource.org/licenses/Apache-2.0)
 | 
			
		||||
@@ -17,17 +17,6 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
 | 
			
		||||
 | 
			
		||||
Visit our [developer portal](https://0x.org/docs/tools/order-utils) for a comprehensive list of core & community maintained packages. All packages maintained with this monorepo are listed below.
 | 
			
		||||
 | 
			
		||||
### Python Packages
 | 
			
		||||
 | 
			
		||||
| Package                                                        | Version                                                                                                             | Description                                                                                       |
 | 
			
		||||
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
 | 
			
		||||
| [`0x-contract-addresses`](/python-packages/contract_addresses) | [](https://pypi.org/project/0x-contract-addresses/) | A tiny utility library for getting known deployed contract addresses for a particular network     |
 | 
			
		||||
| [`0x-contract-artifacts`](/python-packages/contract_artifacts) | [](https://pypi.org/project/0x-contract-artifacts/) | 0x smart contract compilation artifacts                                                           |
 | 
			
		||||
| [`0x-contract-wrappers`](/python-packages/contract_wrappers)   | [](https://pypi.org/project/0x-contract-wrappers/)   | 0x smart contract wrappers                                                                        |
 | 
			
		||||
| [`0x-json-schemas`](/python-packages/json_schemas)             | [](https://pypi.org/project/0x-json-schemas/)             | 0x-related JSON schemas                                                                           |
 | 
			
		||||
| [`0x-order-utils`](/python-packages/order_utils)               | [](https://pypi.org/project/0x-order-utils/)               | A set of utilities for generating, parsing, signing and validating 0x orders                      |
 | 
			
		||||
| [`0x-sra-client`](/python-packages/sra_client)                 | [](https://pypi.org/project/0x-sra-client/)                 | A Python client for interacting with servers conforming to the Standard Relayer API specification |
 | 
			
		||||
 | 
			
		||||
### Solidity Packages
 | 
			
		||||
 | 
			
		||||
These packages are all under development. See [/contracts/README.md](/contracts/README.md) for a list of deployed packages.
 | 
			
		||||
@@ -53,50 +42,13 @@ These packages are all under development. See [/contracts/README.md](/contracts/
 | 
			
		||||
 | 
			
		||||
#### 0x-specific packages
 | 
			
		||||
 | 
			
		||||
| Package                                                  | Version                                                                                                                 | Description                                                                                       |
 | 
			
		||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
 | 
			
		||||
| [`0x.js`](/packages/0x.js)                               | [](https://www.npmjs.com/package/0x.js)                                   | An aggregate package combining many smaller utility packages for interacting with the 0x protocol |
 | 
			
		||||
| [`@0x/contract-addresses`](/packages/contract-addresses) | [](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network.    |
 | 
			
		||||
| [`@0x/contract-wrappers`](/packages/contract-wrappers)   | [](https://www.npmjs.com/package/@0x/contract-wrappers)   | JS/TS wrappers for interacting with the 0x smart contracts                                        |
 | 
			
		||||
| [`@0x/order-utils`](/packages/order-utils)               | [](https://www.npmjs.com/package/@0x/order-utils)               | A set of utilities for generating, parsing, signing and validating 0x orders                      |
 | 
			
		||||
| [`@0x/json-schemas`](/packages/json-schemas)             | [](https://www.npmjs.com/package/@0x/json-schemas)             | 0x-related JSON schemas                                                                           |  |
 | 
			
		||||
| [`@0x/migrations`](/packages/migrations)                 | [](https://www.npmjs.com/package/@0x/migrations)                 | Migration tool for deploying 0x smart contracts on private testnets                               |
 | 
			
		||||
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts                                                           |  |
 | 
			
		||||
| [`@0x/sra-spec`](/packages/sra-spec)                     | [](https://www.npmjs.com/package/@0x/sra-spec)                     | OpenAPI specification for the Standard Relayer API                                                |
 | 
			
		||||
| [`@0x/connect`](/packages/connect)                       | [](https://www.npmjs.com/package/@0x/connect)                       | An HTTP/WS client for interacting with the Standard Relayer API                                   |
 | 
			
		||||
| [`@0x/asset-swapper`](/packages/asset-swapper)           | [](https://www.npmjs.com/package/@0x/asset-swapper)           | Convenience package for discovering and performing swaps for any ERC20 Assets                     |
 | 
			
		||||
 | 
			
		||||
#### Ethereum tooling
 | 
			
		||||
 | 
			
		||||
| Package                                      | Version                                                                                                     | Description                                                                                                                                                                             |
 | 
			
		||||
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0x/web3-wrapper) | An Ethereum JSON RPC client                                                                                                                                                             |
 | 
			
		||||
| [`@0x/sol-compiler`](/packages/sol-compiler) | [](https://www.npmjs.com/package/@0x/sol-compiler) | A wrapper around solc-js that adds smart re-compilation, ability to compile an entire project, Solidity version specific compilation, standard input description support and much more. |
 | 
			
		||||
| [`@0x/sol-coverage`](/packages/sol-coverage) | [](https://www.npmjs.com/package/@0x/sol-coverage) | A solidity test coverage tool                                                                                                                                                           |
 | 
			
		||||
| [`@0x/sol-profiler`](/packages/sol-profiler) | [](https://www.npmjs.com/package/@0x/sol-profiler) | A solidity gas cost profiler                                                                                                                                                            |
 | 
			
		||||
| [`@0x/sol-trace`](/packages/sol-trace)       | [](https://www.npmjs.com/package/@0x/sol-trace)       | A solidity stack trace tool                                                                                                                                                             |
 | 
			
		||||
| [`@0x/sol-resolver`](/packages/sol-resolver) | [](https://www.npmjs.com/package/@0x/sol-resolver) | Import resolver for smart contracts dependencies                                                                                                                                        |
 | 
			
		||||
| [`@0x/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0x/subproviders) | Web3 provider middlewares (e.g. LedgerSubprovider)                                                                                                                                      |
 | 
			
		||||
| [`@0x/sol-doc`](/packages/sol-doc)           | [](https://www.npmjs.com/package/@0x/sol-doc)           | Solidity documentation generator                                                                                                                                                        |
 | 
			
		||||
 | 
			
		||||
#### Utilities
 | 
			
		||||
 | 
			
		||||
| Package                                                  | Version                                                                                                                 | Description                                                     |
 | 
			
		||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/abi-gen`](/packages/abi-gen)                       | [](https://www.npmjs.com/package/@0x/abi-gen)                       | Tool to generate TS wrappers from smart contract ABIs           |
 | 
			
		||||
| [`@0x/tslint-config`](/packages/tslint-config)           | [](https://www.npmjs.com/package/@0x/tslint-config)           | Custom TSLint rules used by the 0x core team                    |
 | 
			
		||||
| [`@0x/types`](/packages/types)                           | [](https://www.npmjs.com/package/@0x/types)                           | Shared type declarations                                        |
 | 
			
		||||
| [`@0x/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0x/typescript-typings) | Repository of types for external packages                       |
 | 
			
		||||
| [`@0x/utils`](/packages/utils)                           | [](https://www.npmjs.com/package/@0x/utils)                           | Shared utilities                                                |
 | 
			
		||||
| [`@0x/assert`](/packages/assert)                         | [](https://www.npmjs.com/package/@0x/assert)                         | Type and schema assertions used by our packages                 |
 | 
			
		||||
| [`@0x/base-contract`](/packages/base-contract)           | [](https://www.npmjs.com/package/@0x/base-contract)           | BaseContract used by auto-generated `abi-gen` wrapper contracts |
 | 
			
		||||
| [`@0x/dev-utils`](/packages/dev-utils)                   | [](https://www.npmjs.com/package/@0x/dev-utils)                   | Dev utils to be shared across 0x packages                       |
 | 
			
		||||
 | 
			
		||||
#### Private Packages
 | 
			
		||||
 | 
			
		||||
| Package                            | Description                                                                      |
 | 
			
		||||
| ---------------------------------- | -------------------------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/instant`](/packages/instant) | A free and flexible way to offer simple crypto purchasing in any app or website. |
 | 
			
		||||
| Package                                                  | Version                                                                                                                 | Description                                                                                    |
 | 
			
		||||
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
 | 
			
		||||
| [`@0x/contract-addresses`](/packages/contract-addresses) | [](https://www.npmjs.com/package/@0x/contract-addresses) | A tiny utility library for getting known deployed contract addresses for a particular network. |
 | 
			
		||||
| [`@0x/contract-wrappers`](/packages/contract-wrappers)   | [](https://www.npmjs.com/package/@0x/contract-wrappers)   | JS/TS wrappers for interacting with the 0x smart contracts                                     |
 | 
			
		||||
| [`@0x/order-utils`](/packages/order-utils)               | [](https://www.npmjs.com/package/@0x/order-utils)               | A set of utilities for generating, parsing, signing and validating 0x orders                   |
 | 
			
		||||
| [`@0x/migrations`](/packages/migrations)                 | [](https://www.npmjs.com/package/@0x/migrations)                 | Migration tool for deploying 0x smart contracts on private testnets                            |
 | 
			
		||||
| [`@0x/contract-artifacts`](/packages/contract-artifacts) | [](https://www.npmjs.com/package/@0x/contract-artifacts) | 0x smart contract compilation artifacts                                                        |  |
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
@@ -129,8 +81,6 @@ Then install dependencies
 | 
			
		||||
yarn install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You will also need to have Python 3 installed, in order to build and run the tests of `abi-gen`'s command-line interface, which is integrated with the yarn build, yarn test, and yarn lint commands described below. More specifically, your local pip should resolve to the Python 3 version of pip, not a Python 2.x version.
 | 
			
		||||
 | 
			
		||||
### Build
 | 
			
		||||
 | 
			
		||||
To build all packages:
 | 
			
		||||
@@ -142,7 +92,7 @@ yarn build
 | 
			
		||||
To build a specific package:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=@0x/web3-wrapper yarn build
 | 
			
		||||
PKG=@0x/contract-wrappers yarn build
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To build all contracts packages:
 | 
			
		||||
@@ -165,7 +115,7 @@ To watch a specific package and all it's dependent packages:
 | 
			
		||||
PKG=[NPM_PACKAGE_NAME] yarn watch
 | 
			
		||||
 | 
			
		||||
e.g
 | 
			
		||||
PKG=@0x/web3-wrapper yarn watch
 | 
			
		||||
PKG=@0x/contract-wrappers yarn watch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Clean
 | 
			
		||||
@@ -193,7 +143,7 @@ yarn rebuild
 | 
			
		||||
To re-build (clean & build) a specific package & it's deps:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=0x.js yarn rebuild
 | 
			
		||||
PKG=@0x/contract-wrappers yarn rebuild
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Lint
 | 
			
		||||
@@ -207,7 +157,7 @@ yarn lint
 | 
			
		||||
Lint a specific package:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=0x.js yarn lint
 | 
			
		||||
PKG=@0x/contract-wrappers yarn lint
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Run Tests
 | 
			
		||||
@@ -221,7 +171,7 @@ yarn test
 | 
			
		||||
Run a specific package's test:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
PKG=@0x/web3-wrapper yarn test
 | 
			
		||||
PKG=@0x/contract-wrappers yarn test
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Run all contracts packages tests:
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
        "quotes": ["error", "double"],
 | 
			
		||||
        "separate-by-one-line-in-contract": "error",
 | 
			
		||||
        "space-after-comma": "error",
 | 
			
		||||
        "statement-indent": "error"
 | 
			
		||||
        "statement-indent": "error",
 | 
			
		||||
        "no-empty-blocks": false
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,351 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1617311315,
 | 
			
		||||
        "version": "3.7.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1616005394,
 | 
			
		||||
        "version": "3.7.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.7.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1612950500,
 | 
			
		||||
        "version": "3.7.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1611648096,
 | 
			
		||||
        "version": "3.7.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1610510890,
 | 
			
		||||
        "version": "3.7.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1609802516,
 | 
			
		||||
        "version": "3.7.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608692071,
 | 
			
		||||
        "version": "3.7.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608245516,
 | 
			
		||||
        "version": "3.7.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.7.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fix Bancor support of ETH",
 | 
			
		||||
                "pr": 88
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1608105788
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607485227,
 | 
			
		||||
        "version": "3.6.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607381756,
 | 
			
		||||
        "version": "3.6.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1606961263,
 | 
			
		||||
        "version": "3.6.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605763885,
 | 
			
		||||
        "version": "3.6.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605302002,
 | 
			
		||||
        "version": "3.6.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604385937,
 | 
			
		||||
        "version": "3.6.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604376968,
 | 
			
		||||
        "version": "3.6.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604355662,
 | 
			
		||||
        "version": "3.6.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603851023,
 | 
			
		||||
        "version": "3.6.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.6.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `SwerveBridge` and `SnowSwapBridge` (duplicate of `CurveBridge`)",
 | 
			
		||||
                "pr": 2707
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1603833198
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.5.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Update `CurveBridge` to support more varied curves",
 | 
			
		||||
                "pr": 2633
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Export DexForwarderBridgeContract",
 | 
			
		||||
                "pr": 2656
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add BancorBridge and IBancorNetwork, ",
 | 
			
		||||
                "pr": 2650
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `MStableBridge`",
 | 
			
		||||
                "pr": 2662
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `MooniswapBridge`",
 | 
			
		||||
                "pr": 2675
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Reworked `KyberBridge`",
 | 
			
		||||
                "pr": 2683
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `CreamBridge`",
 | 
			
		||||
                "pr": 2715
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `ShellBridge`",
 | 
			
		||||
                "pr": 2722
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `DODOBridge`",
 | 
			
		||||
                "pr": 2701
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1603265572
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.4.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fix instability with DFB.",
 | 
			
		||||
                "pr": 2616
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `BalancerBridge`",
 | 
			
		||||
                "pr": 2613
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1594788383
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.3.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals.",
 | 
			
		||||
                "pr": 2512
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Emit `ERC20BridgeTransfer` events in bridges.",
 | 
			
		||||
                "pr": 2512
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Change names of `ERC20BridgeTransfer` args to be less ambiguous.",
 | 
			
		||||
                "pr": 2524
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `MixinGasToken` allowing Gas Tokens to be freed",
 | 
			
		||||
                "pr": 2523
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `DexForwaderBridge` bridge contract.",
 | 
			
		||||
                "pr": 2525
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `UniswapV2Bridge` bridge contract.",
 | 
			
		||||
                "pr": 2590
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add Gas Token freeing to `DexForwarderBridge` contract.",
 | 
			
		||||
                "pr": 2536
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1592969527
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1583220306,
 | 
			
		||||
        "version": "3.2.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582837861,
 | 
			
		||||
        "version": "3.2.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582677073,
 | 
			
		||||
        "version": "3.2.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582623685,
 | 
			
		||||
        "version": "3.2.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1581748629,
 | 
			
		||||
        "version": "3.2.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.2.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add more types and functions to `IDydx`",
 | 
			
		||||
                "pr": 2466
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx`",
 | 
			
		||||
                "pr": 2466
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fix broken tests.",
 | 
			
		||||
                "pr": 2462
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Remove dependency on `@0x/contracts-dev-utils`",
 | 
			
		||||
                "pr": 2462
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add asset data decoding functions",
 | 
			
		||||
                "pr": 2462
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `setOperators()` to `IDydx`",
 | 
			
		||||
                "pr": 2462
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1581204851
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1580988106,
 | 
			
		||||
        "version": "3.1.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,142 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.7.9 - _April 1, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.8 - _March 17, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.7 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.6 - _February 10, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.5 - _January 26, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.4 - _January 13, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.3 - _January 4, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.2 - _December 23, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.1 - _December 17, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.0 - _December 16, 2020_
 | 
			
		||||
 | 
			
		||||
    * Fix Bancor support of ETH (#88)
 | 
			
		||||
 | 
			
		||||
## v3.6.9 - _December 9, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.8 - _December 7, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.7 - _December 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.6 - _November 19, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.5 - _November 13, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.4 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.3 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.2 - _November 2, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.1 - _October 28, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.6.0 - _October 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Add `SwerveBridge` and `SnowSwapBridge` (duplicate of `CurveBridge`) (#2707)
 | 
			
		||||
 | 
			
		||||
## v3.5.0 - _October 21, 2020_
 | 
			
		||||
 | 
			
		||||
    * Update `CurveBridge` to support more varied curves (#2633)
 | 
			
		||||
    * Export DexForwarderBridgeContract (#2656)
 | 
			
		||||
    * Add BancorBridge and IBancorNetwork,  (#2650)
 | 
			
		||||
    * Added `MStableBridge` (#2662)
 | 
			
		||||
    * Added `MooniswapBridge` (#2675)
 | 
			
		||||
    * Reworked `KyberBridge` (#2683)
 | 
			
		||||
    * Added `CreamBridge` (#2715)
 | 
			
		||||
    * Added `ShellBridge` (#2722)
 | 
			
		||||
    * Added `DODOBridge` (#2701)
 | 
			
		||||
 | 
			
		||||
## v3.4.0 - _July 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Fix instability with DFB. (#2616)
 | 
			
		||||
    * Add `BalancerBridge` (#2613)
 | 
			
		||||
 | 
			
		||||
## v3.3.0 - _June 24, 2020_
 | 
			
		||||
 | 
			
		||||
    * Use `LibERC20Token.approveIfBelow()` in DEX bridges for for approvals. (#2512)
 | 
			
		||||
    * Emit `ERC20BridgeTransfer` events in bridges. (#2512)
 | 
			
		||||
    * Change names of `ERC20BridgeTransfer` args to be less ambiguous. (#2524)
 | 
			
		||||
    * Added `MixinGasToken` allowing Gas Tokens to be freed (#2523)
 | 
			
		||||
    * Add `DexForwaderBridge` bridge contract. (#2525)
 | 
			
		||||
    * Add `UniswapV2Bridge` bridge contract. (#2590)
 | 
			
		||||
    * Add Gas Token freeing to `DexForwarderBridge` contract. (#2536)
 | 
			
		||||
 | 
			
		||||
## v3.2.5 - _March 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.4 - _February 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.3 - _February 26, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.2 - _February 25, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.1 - _February 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.0 - _February 8, 2020_
 | 
			
		||||
 | 
			
		||||
    * Add more types and functions to `IDydx` (#2466)
 | 
			
		||||
    * Rename `DydxBrigeAction.accountId` to `DydxBridgeAction.accountIdx` (#2466)
 | 
			
		||||
    * Fix broken tests. (#2462)
 | 
			
		||||
    * Remove dependency on `@0x/contracts-dev-utils` (#2462)
 | 
			
		||||
    * Add asset data decoding functions (#2462)
 | 
			
		||||
    * Add `setOperators()` to `IDydx` (#2462)
 | 
			
		||||
 | 
			
		||||
## v3.1.3 - _February 6, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
    "shouldSaveStandardInput": true,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "istanbul",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								contracts/asset-proxy/contracts/src/bridges/BalancerBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								contracts/asset-proxy/contracts/src/bridges/BalancerBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IBalancerPool.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract BalancerBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
 | 
			
		||||
    ///      token encoded in the bridge data, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to buy and transfer to `to`.
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded addresses of the "from" token and Balancer pool.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data.
 | 
			
		||||
        (address fromTokenAddress, address poolAddress) = abi.decode(
 | 
			
		||||
            bridgeData,
 | 
			
		||||
            (address, address)
 | 
			
		||||
        );
 | 
			
		||||
        require(toTokenAddress != fromTokenAddress, "BalancerBridge/INVALID_PAIR");
 | 
			
		||||
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        (uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn(
 | 
			
		||||
            fromTokenAddress, // tokenIn
 | 
			
		||||
            fromTokenBalance, // tokenAmountIn
 | 
			
		||||
            toTokenAddress,   // tokenOut
 | 
			
		||||
            amount,           // minAmountOut
 | 
			
		||||
            uint256(-1)       // maxPrice
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										144
									
								
								contracts/asset-proxy/contracts/src/bridges/BancorBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								contracts/asset-proxy/contracts/src/bridges/BancorBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IBancorNetwork.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract BancorBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        address bancorNetworkAddress;
 | 
			
		||||
        address[] path;
 | 
			
		||||
        IEtherToken weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Bancor ETH pseudo-address.
 | 
			
		||||
    address constant public BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable no-empty-blocks
 | 
			
		||||
    /// @dev Payable fallback to receive ETH from Bancor/WETH.
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        // Poor man's receive in 0.5.9
 | 
			
		||||
        require(msg.data.length == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
 | 
			
		||||
    ///      token encoded in the bridge data, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to buy and transfer to `to`.
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded conversion path addresses and Bancor network 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)
 | 
			
		||||
    {
 | 
			
		||||
        // hold variables to get around stack depth limitations
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
        // Decode the bridge data.
 | 
			
		||||
        (
 | 
			
		||||
            state.path,
 | 
			
		||||
            state.bancorNetworkAddress
 | 
			
		||||
        // solhint-disable indent
 | 
			
		||||
        ) = abi.decode(bridgeData, (address[], address));
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
        state.weth = IEtherToken(_getWethAddress());
 | 
			
		||||
 | 
			
		||||
        require(state.path.length >= 2, "BancorBridge/PATH_LENGTH_MUST_BE_GREATER_THAN_TWO");
 | 
			
		||||
 | 
			
		||||
        // Grant an allowance to the Bancor Network to spend `fromTokenAddress` token.
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        uint256 payableAmount = 0;
 | 
			
		||||
        // If it's ETH in the path then withdraw from WETH
 | 
			
		||||
        // The Bancor path will have ETH as the 0xeee address
 | 
			
		||||
        // Bancor expects to be paid in ETH not WETH
 | 
			
		||||
        if (state.path[0] == BANCOR_ETH_ADDRESS) {
 | 
			
		||||
            fromTokenBalance = state.weth.balanceOf(address(this));
 | 
			
		||||
            state.weth.withdraw(fromTokenBalance);
 | 
			
		||||
            payableAmount = fromTokenBalance;
 | 
			
		||||
        } else {
 | 
			
		||||
            fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
 | 
			
		||||
            LibERC20Token.approveIfBelow(state.path[0], state.bancorNetworkAddress, fromTokenBalance);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Convert the tokens
 | 
			
		||||
        uint256 boughtAmount = IBancorNetwork(state.bancorNetworkAddress).convertByPath.value(payableAmount)(
 | 
			
		||||
            state.path, // path originating with source token and terminating in destination token
 | 
			
		||||
            fromTokenBalance, // amount of source token to trade
 | 
			
		||||
            amount, // minimum amount of destination token expected to receive
 | 
			
		||||
            state.path[state.path.length-1] == BANCOR_ETH_ADDRESS ? address(this) : to, // beneficiary
 | 
			
		||||
            address(0), // affiliateAccount; no fee paid
 | 
			
		||||
            0 // affiliateFee; no fee paid
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (state.path[state.path.length-1] == BANCOR_ETH_ADDRESS) {
 | 
			
		||||
            state.weth.deposit.value(boughtAmount)();
 | 
			
		||||
            state.weth.transfer(to, boughtAmount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            state.path[0] == BANCOR_ETH_ADDRESS ? address(state.weth) : state.path[0],
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -35,7 +35,7 @@ contract ChaiBridge is
 | 
			
		||||
    /// @param from Address to transfer asset from.
 | 
			
		||||
    /// @param to Address to transfer asset to.
 | 
			
		||||
    /// @param amount Amount of asset to transfer.
 | 
			
		||||
    /// @return success The magic bytes `0x37708e9b` if successful.
 | 
			
		||||
    /// @return success The magic bytes `0xdc1600f3` if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address /* tokenAddress */,
 | 
			
		||||
        address from,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IBalancerPool.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract CreamBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
 | 
			
		||||
    ///      token encoded in the bridge data, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to buy and transfer to `to`.
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded addresses of the "from" token and Balancer pool.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data.
 | 
			
		||||
        (address fromTokenAddress, address poolAddress) = abi.decode(
 | 
			
		||||
            bridgeData,
 | 
			
		||||
            (address, address)
 | 
			
		||||
        );
 | 
			
		||||
        require(toTokenAddress != fromTokenAddress, "CreamBridge/INVALID_PAIR");
 | 
			
		||||
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        (uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn(
 | 
			
		||||
            fromTokenAddress, // tokenIn
 | 
			
		||||
            fromTokenBalance, // tokenAmountIn
 | 
			
		||||
            toTokenAddress,   // tokenOut
 | 
			
		||||
            amount,           // minAmountOut
 | 
			
		||||
            uint256(-1)       // maxPrice
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								contracts/asset-proxy/contracts/src/bridges/CryptoComBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								contracts/asset-proxy/contracts/src/bridges/CryptoComBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IUniswapV2Router01.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
contract CryptoComBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        address[] path;
 | 
			
		||||
        address router;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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 from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // hold variables to get around stack depth limitations
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        // solhint-disable indent
 | 
			
		||||
        (state.path, state.router) = abi.decode(bridgeData, (address[], address));
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
 | 
			
		||||
        require(state.path.length >= 2, "CryptoComBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
 | 
			
		||||
        require(state.path[state.path.length - 1] == toTokenAddress, "CryptoComBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
 | 
			
		||||
 | 
			
		||||
        // Just transfer the tokens if they're the same.
 | 
			
		||||
        if (state.path[0] == toTokenAddress) {
 | 
			
		||||
            LibERC20Token.transfer(state.path[0], to, amount);
 | 
			
		||||
            return BRIDGE_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        // Grant the SushiSwap router an allowance.
 | 
			
		||||
        LibERC20Token.approveIfBelow(
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            state.router,
 | 
			
		||||
            state.fromTokenBalance
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Buy as much `toTokenAddress` token with `fromTokenAddress` token
 | 
			
		||||
        // and transfer it to `to`.
 | 
			
		||||
        IUniswapV2Router01 router = IUniswapV2Router01(state.router);
 | 
			
		||||
        uint[] memory amounts = router.swapExactTokensForTokens(
 | 
			
		||||
             // Sell all tokens we hold.
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
             // Minimum buy amount.
 | 
			
		||||
            amount,
 | 
			
		||||
            // Convert `fromTokenAddress` to `toTokenAddress`.
 | 
			
		||||
            state.path,
 | 
			
		||||
            // Recipient is `to`.
 | 
			
		||||
            to,
 | 
			
		||||
            // Expires after this block.
 | 
			
		||||
            block.timestamp
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            // input token
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            // output token
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            // input token amount
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            // output token amount
 | 
			
		||||
            amounts[amounts.length - 1],
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/CurveBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/CurveBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/ICurve.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
contract CurveBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct CurveBridgeData {
 | 
			
		||||
        address curveAddress;
 | 
			
		||||
        bytes4 exchangeFunctionSelector;
 | 
			
		||||
        address fromTokenAddress;
 | 
			
		||||
        int128 fromCoinIdx;
 | 
			
		||||
        int128 toCoinIdx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `ICurve`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the opposing asset
 | 
			
		||||
    ///      (DAI, USDC) to the Curve contract, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @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 bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data to get the Curve metadata.
 | 
			
		||||
        CurveBridgeData memory data = abi.decode(bridgeData, (CurveBridgeData));
 | 
			
		||||
 | 
			
		||||
        require(toTokenAddress != data.fromTokenAddress, "CurveBridge/INVALID_PAIR");
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        {
 | 
			
		||||
            (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
                data.curveAddress.call(abi.encodeWithSelector(
 | 
			
		||||
                    data.exchangeFunctionSelector,
 | 
			
		||||
                    data.fromCoinIdx,
 | 
			
		||||
                    data.toCoinIdx,
 | 
			
		||||
                    // dx
 | 
			
		||||
                    fromTokenBalance,
 | 
			
		||||
                    // min dy
 | 
			
		||||
                    amount
 | 
			
		||||
                ));
 | 
			
		||||
            if (!didSucceed) {
 | 
			
		||||
                assembly { revert(add(resultData, 32), mload(resultData)) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            data.fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            toTokenBalance,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										147
									
								
								contracts/asset-proxy/contracts/src/bridges/DODOBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								contracts/asset-proxy/contracts/src/bridges/DODOBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IDODOHelper {
 | 
			
		||||
 | 
			
		||||
    function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IDODO {
 | 
			
		||||
 | 
			
		||||
    function sellBaseToken(uint256 amount, uint256 minReceiveQuote, bytes calldata data) external returns (uint256);
 | 
			
		||||
 | 
			
		||||
    function buyBaseToken(uint256 amount, uint256 maxPayQuote, bytes calldata data) external returns (uint256);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract DODOBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        address fromTokenAddress;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        address pool;
 | 
			
		||||
        bool isSellBase;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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 from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        (state.fromTokenAddress, state.pool, state.isSellBase) = abi.decode(bridgeData, (address, address, bool));
 | 
			
		||||
        require(state.pool != address(0), "DODOBridge/InvalidPool");
 | 
			
		||||
        IDODO exchange = IDODO(state.pool);
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        // Grant the pool an allowance.
 | 
			
		||||
        LibERC20Token.approveIfBelow(
 | 
			
		||||
            state.fromTokenAddress,
 | 
			
		||||
            address(exchange),
 | 
			
		||||
            state.fromTokenBalance
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        uint256 boughtAmount;
 | 
			
		||||
        if (state.isSellBase) {
 | 
			
		||||
            boughtAmount = exchange.sellBaseToken(
 | 
			
		||||
                // amount to sell
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                // min receive amount
 | 
			
		||||
                1,
 | 
			
		||||
                new bytes(0)
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            // Need to re-calculate the sell quote amount into buyBase
 | 
			
		||||
            boughtAmount = IDODOHelper(_getDODOHelperAddress()).querySellQuoteToken(
 | 
			
		||||
                address(exchange),
 | 
			
		||||
                state.fromTokenBalance
 | 
			
		||||
            );
 | 
			
		||||
            exchange.buyBaseToken(
 | 
			
		||||
                // amount to buy
 | 
			
		||||
                boughtAmount,
 | 
			
		||||
                // max pay amount
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                new bytes(0)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        // Transfer funds to `to`
 | 
			
		||||
        IERC20Token(toTokenAddress).transfer(to, boughtAmount);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            // input token
 | 
			
		||||
            state.fromTokenAddress,
 | 
			
		||||
            // output token
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            // input token amount
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            // output token amount
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,200 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "./MixinGasToken.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma, indent
 | 
			
		||||
contract DexForwarderBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants,
 | 
			
		||||
    MixinGasToken
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    /// @dev Data needed to reconstruct a bridge call.
 | 
			
		||||
    struct BridgeCall {
 | 
			
		||||
        address target;
 | 
			
		||||
        uint256 inputTokenAmount;
 | 
			
		||||
        uint256 outputTokenAmount;
 | 
			
		||||
        bytes bridgeData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Intermediate state variables used by `bridgeTransferFrom()`, in
 | 
			
		||||
    ///      struct form to get around stack limits.
 | 
			
		||||
    struct TransferFromState {
 | 
			
		||||
        address inputToken;
 | 
			
		||||
        uint256 initialInputTokenBalance;
 | 
			
		||||
        uint256 callInputTokenAmount;
 | 
			
		||||
        uint256 callOutputTokenAmount;
 | 
			
		||||
        uint256 totalInputTokenSold;
 | 
			
		||||
        BridgeCall[] calls;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Spends this contract's entire balance of input tokens by forwarding
 | 
			
		||||
    /// them to other bridges. Reverts if the entire balance is not spent.
 | 
			
		||||
    /// @param outputToken The token being bought.
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param bridgeData The abi-encoded input token address.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        address /* from */,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 /* amount */,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        freesGasTokensFromCollector
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            msg.sender == _getERC20BridgeProxyAddress(),
 | 
			
		||||
            "DexForwarderBridge/SENDER_NOT_AUTHORIZED"
 | 
			
		||||
        );
 | 
			
		||||
        TransferFromState memory state;
 | 
			
		||||
        (
 | 
			
		||||
            state.inputToken,
 | 
			
		||||
            state.calls
 | 
			
		||||
        ) = abi.decode(bridgeData, (address, BridgeCall[]));
 | 
			
		||||
 | 
			
		||||
        state.initialInputTokenBalance =
 | 
			
		||||
            IERC20Token(state.inputToken).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < state.calls.length; ++i) {
 | 
			
		||||
            // Stop if the we've sold all our input tokens.
 | 
			
		||||
            if (state.totalInputTokenSold >= state.initialInputTokenBalance) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Compute token amounts.
 | 
			
		||||
            state.callInputTokenAmount = LibSafeMath.min256(
 | 
			
		||||
                state.calls[i].inputTokenAmount,
 | 
			
		||||
                state.initialInputTokenBalance.safeSub(state.totalInputTokenSold)
 | 
			
		||||
            );
 | 
			
		||||
            state.callOutputTokenAmount = LibMath.getPartialAmountFloor(
 | 
			
		||||
                state.callInputTokenAmount,
 | 
			
		||||
                state.calls[i].inputTokenAmount,
 | 
			
		||||
                state.calls[i].outputTokenAmount
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Execute the call in a new context so we can recoup transferred
 | 
			
		||||
            // funds by reverting.
 | 
			
		||||
            (bool didSucceed, ) = address(this)
 | 
			
		||||
                .call(abi.encodeWithSelector(
 | 
			
		||||
                    this.executeBridgeCall.selector,
 | 
			
		||||
                    state.calls[i].target,
 | 
			
		||||
                    to,
 | 
			
		||||
                    state.inputToken,
 | 
			
		||||
                    outputToken,
 | 
			
		||||
                    state.callInputTokenAmount,
 | 
			
		||||
                    state.callOutputTokenAmount,
 | 
			
		||||
                    state.calls[i].bridgeData
 | 
			
		||||
                ));
 | 
			
		||||
 | 
			
		||||
            if (didSucceed) {
 | 
			
		||||
                // Increase the amount of tokens sold.
 | 
			
		||||
                state.totalInputTokenSold = state.totalInputTokenSold.safeAdd(
 | 
			
		||||
                    state.callInputTokenAmount
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Always succeed.
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Transfers `inputToken` token to a bridge contract then calls
 | 
			
		||||
    ///      its `bridgeTransferFrom()`. This is executed in separate context
 | 
			
		||||
    ///      so we can revert the transfer on error. This can only be called
 | 
			
		||||
    //       by this contract itself.
 | 
			
		||||
    /// @param bridge The bridge contract.
 | 
			
		||||
    /// @param to The recipient of `outputToken` tokens.
 | 
			
		||||
    /// @param inputToken The input token.
 | 
			
		||||
    /// @param outputToken The output token.
 | 
			
		||||
    /// @param inputTokenAmount The amount of input tokens to transfer to `bridge`.
 | 
			
		||||
    /// @param outputTokenAmount The amount of expected output tokens to be sent
 | 
			
		||||
    ///        to `to` by `bridge`.
 | 
			
		||||
    function executeBridgeCall(
 | 
			
		||||
        address bridge,
 | 
			
		||||
        address to,
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        uint256 outputTokenAmount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        // Must be called through `bridgeTransferFrom()`.
 | 
			
		||||
        require(msg.sender == address(this), "DexForwarderBridge/ONLY_SELF");
 | 
			
		||||
        // `bridge` must not be this contract.
 | 
			
		||||
        require(bridge != address(this));
 | 
			
		||||
 | 
			
		||||
        // Get the starting balance of output tokens for `to`.
 | 
			
		||||
        uint256 initialRecipientBalance = IERC20Token(outputToken).balanceOf(to);
 | 
			
		||||
 | 
			
		||||
        // Transfer input tokens to the bridge.
 | 
			
		||||
        LibERC20Token.transfer(inputToken, bridge, inputTokenAmount);
 | 
			
		||||
 | 
			
		||||
        // Call the bridge.
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
            bridge.call(abi.encodeWithSelector(
 | 
			
		||||
                IERC20Bridge(0).bridgeTransferFrom.selector,
 | 
			
		||||
                outputToken,
 | 
			
		||||
                bridge,
 | 
			
		||||
                to,
 | 
			
		||||
                outputTokenAmount,
 | 
			
		||||
                bridgeData
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
        // Revert if the call failed or not enough tokens were bought.
 | 
			
		||||
        // This will also undo the token transfer.
 | 
			
		||||
        require(
 | 
			
		||||
            didSucceed
 | 
			
		||||
            && resultData.length == 32
 | 
			
		||||
            && LibBytes.readBytes32(resultData, 0) == bytes32(BRIDGE_SUCCESS)
 | 
			
		||||
            && IERC20Token(outputToken).balanceOf(to).safeSub(initialRecipientBalance) >= outputTokenAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
 | 
			
		||||
    ///      and sign for itself in orders. Always succeeds.
 | 
			
		||||
    /// @return magicValue Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -50,7 +50,7 @@ contract DydxBridge is
 | 
			
		||||
    /// @param encodedBridgeData An abi-encoded `BridgeData` struct.
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address,
 | 
			
		||||
        address, /* toTokenAddress */
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
@@ -81,6 +81,7 @@ contract DydxBridge is
 | 
			
		||||
 | 
			
		||||
        // Run operation. This will revert on failure.
 | 
			
		||||
        IDydx(_getDydxAddress()).operate(accounts, actions);
 | 
			
		||||
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -191,12 +192,12 @@ contract DydxBridge is
 | 
			
		||||
        depositAction = IDydx.ActionArgs({
 | 
			
		||||
            actionType: IDydx.ActionType.Deposit,           // deposit tokens.
 | 
			
		||||
            amount: dydxAmount,                             // amount to deposit.
 | 
			
		||||
            accountId: bridgeAction.accountId,              // index in the `accounts` when calling `operate`.
 | 
			
		||||
            accountIdx: bridgeAction.accountIdx,             // index in the `accounts` when calling `operate`.
 | 
			
		||||
            primaryMarketId: bridgeAction.marketId,         // indicates which token to deposit.
 | 
			
		||||
            otherAddress: depositFrom,                      // deposit from the account owner.
 | 
			
		||||
            // unused parameters
 | 
			
		||||
            secondaryMarketId: 0,
 | 
			
		||||
            otherAccountId: 0,
 | 
			
		||||
            otherAccountIdx: 0,
 | 
			
		||||
            data: hex''
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@@ -229,12 +230,12 @@ contract DydxBridge is
 | 
			
		||||
        withdrawAction = IDydx.ActionArgs({
 | 
			
		||||
            actionType: IDydx.ActionType.Withdraw,          // withdraw tokens.
 | 
			
		||||
            amount: amountToWithdraw,                       // amount to withdraw.
 | 
			
		||||
            accountId: bridgeAction.accountId,              // index in the `accounts` when calling `operate`.
 | 
			
		||||
            accountIdx: bridgeAction.accountIdx,            // index in the `accounts` when calling `operate`.
 | 
			
		||||
            primaryMarketId: bridgeAction.marketId,         // indicates which token to withdraw.
 | 
			
		||||
            otherAddress: withdrawTo,                       // withdraw tokens to this address.
 | 
			
		||||
            // unused parameters
 | 
			
		||||
            secondaryMarketId: 0,
 | 
			
		||||
            otherAccountId: 0,
 | 
			
		||||
            otherAccountIdx: 0,
 | 
			
		||||
            data: hex''
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -38,13 +38,14 @@ contract Eth2DaiBridge is
 | 
			
		||||
    ///      (DAI or WETH) to the Eth2Dai contract, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to` (either DAI or WETH).
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @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 bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address /* from */,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
@@ -56,18 +57,28 @@ contract Eth2DaiBridge is
 | 
			
		||||
        (address fromTokenAddress) = abi.decode(bridgeData, (address));
 | 
			
		||||
 | 
			
		||||
        IEth2Dai exchange = IEth2Dai(_getEth2DaiAddress());
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
 | 
			
		||||
        LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        uint256 boughtAmount = exchange.sellAllAmount(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            IERC20Token(fromTokenAddress).balanceOf(address(this)),
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
  Copyright 2020 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
@@ -45,6 +45,7 @@ contract KyberBridge is
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        uint256 payableAmount;
 | 
			
		||||
        uint256 conversionRate;
 | 
			
		||||
        bytes hint;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Kyber ETH pseudo-address.
 | 
			
		||||
@@ -55,24 +56,28 @@ contract KyberBridge is
 | 
			
		||||
    uint256 constant private KYBER_RATE_BASE = 10 ** 18;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable no-empty-blocks
 | 
			
		||||
    /// @dev Payable fallback to receive ETH from Kyber.
 | 
			
		||||
    /// @dev Payable fallback to receive ETH from Kyber/WETH.
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {}
 | 
			
		||||
    {
 | 
			
		||||
        // Poor man's receive in 0.5.9
 | 
			
		||||
        require(msg.data.length == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `IKyberBridge`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the opposing asset
 | 
			
		||||
    ///      to the `KyberNetworkProxy` contract, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to`.
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @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 bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address /* from */,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
@@ -84,43 +89,35 @@ contract KyberBridge is
 | 
			
		||||
        state.kyber = IKyberNetworkProxy(_getKyberNetworkProxyAddress());
 | 
			
		||||
        state.weth = IEtherToken(_getWethAddress());
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        (state.fromTokenAddress) = abi.decode(bridgeData, (address));
 | 
			
		||||
        (state.fromTokenAddress, state.hint) = abi.decode(bridgeData, (address, bytes));
 | 
			
		||||
        // Query the balance of "from" tokens.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        if (state.fromTokenBalance == 0) {
 | 
			
		||||
            // Return failure if no input tokens.
 | 
			
		||||
            return BRIDGE_FAILED;
 | 
			
		||||
        }
 | 
			
		||||
        // Compute the conversion rate, expressed in 18 decimals.
 | 
			
		||||
        // The sequential notation is to get around stack limits.
 | 
			
		||||
        state.conversionRate = KYBER_RATE_BASE;
 | 
			
		||||
        state.conversionRate = state.conversionRate.safeMul(amount);
 | 
			
		||||
        state.conversionRate = state.conversionRate.safeMul(
 | 
			
		||||
            10 ** uint256(LibERC20Token.decimals(state.fromTokenAddress))
 | 
			
		||||
        );
 | 
			
		||||
        state.conversionRate = state.conversionRate.safeDiv(state.fromTokenBalance);
 | 
			
		||||
        state.conversionRate = state.conversionRate.safeDiv(
 | 
			
		||||
            10 ** uint256(LibERC20Token.decimals(toTokenAddress))
 | 
			
		||||
        );
 | 
			
		||||
        if (state.fromTokenAddress == toTokenAddress) {
 | 
			
		||||
            // Just transfer the tokens if they're the same.
 | 
			
		||||
            LibERC20Token.transfer(state.fromTokenAddress, to, state.fromTokenBalance);
 | 
			
		||||
            return BRIDGE_SUCCESS;
 | 
			
		||||
        } else if (state.fromTokenAddress != address(state.weth)) {
 | 
			
		||||
            // If the input token is not WETH, grant an allowance to the exchange
 | 
			
		||||
            // to spend them.
 | 
			
		||||
            LibERC20Token.approve(state.fromTokenAddress, address(state.kyber), uint256(-1));
 | 
			
		||||
        } else {
 | 
			
		||||
            // If the input token is WETH, unwrap it and attach it to the call.
 | 
			
		||||
        }
 | 
			
		||||
        if (state.fromTokenAddress == address(state.weth)) {
 | 
			
		||||
            // From WETH
 | 
			
		||||
            state.fromTokenAddress = KYBER_ETH_ADDRESS;
 | 
			
		||||
            state.payableAmount = state.fromTokenBalance;
 | 
			
		||||
            state.weth.withdraw(state.fromTokenBalance);
 | 
			
		||||
        } else {
 | 
			
		||||
            LibERC20Token.approveIfBelow(
 | 
			
		||||
                state.fromTokenAddress,
 | 
			
		||||
                address(state.kyber),
 | 
			
		||||
                state.fromTokenBalance
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        bool isToTokenWeth = toTokenAddress == address(state.weth);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's input token balance through
 | 
			
		||||
        // `KyberNetworkProxy.trade()`.
 | 
			
		||||
        uint256 boughtAmount = state.kyber.trade.value(state.payableAmount)(
 | 
			
		||||
        uint256 boughtAmount = state.kyber.tradeWithHint.value(state.payableAmount)(
 | 
			
		||||
            // Input token.
 | 
			
		||||
            state.fromTokenAddress,
 | 
			
		||||
            // Sell amount.
 | 
			
		||||
@@ -132,17 +129,26 @@ contract KyberBridge is
 | 
			
		||||
            isToTokenWeth ? address(uint160(address(this))) : address(uint160(to)),
 | 
			
		||||
            // Buy as much as possible.
 | 
			
		||||
            uint256(-1),
 | 
			
		||||
            // Compute the minimum conversion rate, which is expressed in units with
 | 
			
		||||
            // 18 decimal places.
 | 
			
		||||
            state.conversionRate,
 | 
			
		||||
            // The minimum conversion rate
 | 
			
		||||
            1,
 | 
			
		||||
            // No affiliate address.
 | 
			
		||||
            address(0)
 | 
			
		||||
            address(0),
 | 
			
		||||
            state.hint
 | 
			
		||||
        );
 | 
			
		||||
        // Wrap ETH output and transfer to recipient.
 | 
			
		||||
        if (isToTokenWeth) {
 | 
			
		||||
            state.weth.deposit.value(boughtAmount)();
 | 
			
		||||
            state.weth.transfer(to, boughtAmount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            state.fromTokenAddress == KYBER_ETH_ADDRESS ? address(state.weth) : state.fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -159,4 +165,5 @@ contract KyberBridge is
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,94 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IMStable.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MStableBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// @dev Swaps specified tokens against the mStable mUSD contract
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @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.
 | 
			
		||||
    // solhint-disable no-unused-vars
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        (address fromTokenAddress) = abi.decode(bridgeData, (address));
 | 
			
		||||
 | 
			
		||||
        IMStable exchange = IMStable(_getMUsdAddress());
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        uint256 boughtAmount = exchange.swap(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.16;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IGasToken.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MixinGasToken is
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// @dev Frees gas tokens based on the amount of gas consumed in the function
 | 
			
		||||
    modifier freesGasTokens {
 | 
			
		||||
        uint256 gasBefore = gasleft();
 | 
			
		||||
        _;
 | 
			
		||||
        IGasToken gst = IGasToken(_getGstAddress());
 | 
			
		||||
        if (address(gst) != address(0)) {
 | 
			
		||||
            // (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
 | 
			
		||||
            //            14154             24000        6870
 | 
			
		||||
            uint256 value = (gasBefore - gasleft() + 14154) / 41130;
 | 
			
		||||
            gst.freeUpTo(value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Frees gas tokens using the balance of `from`. Amount freed is based
 | 
			
		||||
    ///     on the gas consumed in the function
 | 
			
		||||
    modifier freesGasTokensFromCollector() {
 | 
			
		||||
        uint256 gasBefore = gasleft();
 | 
			
		||||
        _;
 | 
			
		||||
        IGasToken gst = IGasToken(_getGstAddress());
 | 
			
		||||
        if (address(gst) != address(0)) {
 | 
			
		||||
            // (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN)
 | 
			
		||||
            //            14154             24000        6870
 | 
			
		||||
            uint256 value = (gasBefore - gasleft() + 14154) / 41130;
 | 
			
		||||
            gst.freeFromUpTo(_getGstCollectorAddress(), value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										148
									
								
								contracts/asset-proxy/contracts/src/bridges/MooniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								contracts/asset-proxy/contracts/src/bridges/MooniswapBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,148 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IMooniswap.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
contract MooniswapBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        IMooniswap pool;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        IEtherToken weth;
 | 
			
		||||
        uint256 boughtAmount;
 | 
			
		||||
        address fromTokenAddress;
 | 
			
		||||
        address toTokenAddress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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 from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
 | 
			
		||||
    /// @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.
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        address fromTokenAddress = abi.decode(bridgeData, (address));
 | 
			
		||||
        // Get the weth contract.
 | 
			
		||||
        state.weth = IEtherToken(_getWethAddress());
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        state.fromTokenAddress = fromTokenAddress == address(state.weth) ? address(0) : fromTokenAddress;
 | 
			
		||||
        state.toTokenAddress = toTokenAddress == address(state.weth) ? address(0) : toTokenAddress;
 | 
			
		||||
        state.pool = IMooniswap(
 | 
			
		||||
            IMooniswapRegistry(_getMooniswapAddress()).pools(
 | 
			
		||||
                state.fromTokenAddress,
 | 
			
		||||
                state.toTokenAddress
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // withdraw WETH to ETH
 | 
			
		||||
        if (state.fromTokenAddress == address(0)) {
 | 
			
		||||
            state.weth.withdraw(state.fromTokenBalance);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Grant the pool an allowance.
 | 
			
		||||
            LibERC20Token.approveIfBelow(
 | 
			
		||||
                state.fromTokenAddress,
 | 
			
		||||
                address(state.pool),
 | 
			
		||||
                state.fromTokenBalance
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        uint256 ethValue = state.fromTokenAddress == address(0) ? state.fromTokenBalance : 0;
 | 
			
		||||
        state.boughtAmount = state.pool.swap.value(ethValue)(
 | 
			
		||||
            state.fromTokenAddress,
 | 
			
		||||
            state.toTokenAddress,
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            amount,
 | 
			
		||||
            address(0)
 | 
			
		||||
        );
 | 
			
		||||
        // Deposit to WETH
 | 
			
		||||
        if (state.toTokenAddress == address(0)) {
 | 
			
		||||
            state.weth.deposit.value(state.boughtAmount)();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Transfer funds to `to`
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, state.boughtAmount);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            // input token
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            // output token
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            // input token amount
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            // output token amount
 | 
			
		||||
            state.boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								contracts/asset-proxy/contracts/src/bridges/ShellBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								contracts/asset-proxy/contracts/src/bridges/ShellBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/IShell.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract ShellBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// @dev Swaps specified tokens against the Shell contract
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to`.
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @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.
 | 
			
		||||
    // solhint-disable no-unused-vars
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress` and `pool`.
 | 
			
		||||
        (address fromTokenAddress, address pool) = abi.decode(bridgeData, (address, address));
 | 
			
		||||
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(fromTokenAddress, pool, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        uint256 boughtAmount = IShell(pool).originSwap(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            amount, // min amount
 | 
			
		||||
            block.timestamp + 1
 | 
			
		||||
        );
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, boughtAmount);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/SnowSwapBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/SnowSwapBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/ICurve.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
contract SnowSwapBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct SnowSwapBridgeData {
 | 
			
		||||
        address curveAddress;
 | 
			
		||||
        bytes4 exchangeFunctionSelector;
 | 
			
		||||
        address fromTokenAddress;
 | 
			
		||||
        int128 fromCoinIdx;
 | 
			
		||||
        int128 toCoinIdx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `ICurve`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the opposing asset
 | 
			
		||||
    ///      (DAI, USDC) to the Curve contract, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @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 bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data to get the SnowSwap metadata.
 | 
			
		||||
        SnowSwapBridgeData memory data = abi.decode(bridgeData, (SnowSwapBridgeData));
 | 
			
		||||
 | 
			
		||||
        require(toTokenAddress != data.fromTokenAddress, "SnowSwapBridge/INVALID_PAIR");
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        {
 | 
			
		||||
            (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
                data.curveAddress.call(abi.encodeWithSelector(
 | 
			
		||||
                    data.exchangeFunctionSelector,
 | 
			
		||||
                    data.fromCoinIdx,
 | 
			
		||||
                    data.toCoinIdx,
 | 
			
		||||
                    // dx
 | 
			
		||||
                    fromTokenBalance,
 | 
			
		||||
                    // min dy
 | 
			
		||||
                    amount
 | 
			
		||||
                ));
 | 
			
		||||
            if (!didSucceed) {
 | 
			
		||||
                assembly { revert(add(resultData, 32), mload(resultData)) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            data.fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            toTokenBalance,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								contracts/asset-proxy/contracts/src/bridges/SushiSwapBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								contracts/asset-proxy/contracts/src/bridges/SushiSwapBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IUniswapV2Router01.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
contract SushiSwapBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        address[] path;
 | 
			
		||||
        address router;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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 from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // hold variables to get around stack depth limitations
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        // solhint-disable indent
 | 
			
		||||
        (state.path, state.router) = abi.decode(bridgeData, (address[], address));
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
 | 
			
		||||
        require(state.path.length >= 2, "SushiSwapBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
 | 
			
		||||
        require(state.path[state.path.length - 1] == toTokenAddress, "SushiSwapBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
 | 
			
		||||
 | 
			
		||||
        // Just transfer the tokens if they're the same.
 | 
			
		||||
        if (state.path[0] == toTokenAddress) {
 | 
			
		||||
            LibERC20Token.transfer(state.path[0], to, amount);
 | 
			
		||||
            return BRIDGE_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        // Grant the SushiSwap router an allowance.
 | 
			
		||||
        LibERC20Token.approveIfBelow(
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            state.router,
 | 
			
		||||
            state.fromTokenBalance
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Buy as much `toTokenAddress` token with `fromTokenAddress` token
 | 
			
		||||
        // and transfer it to `to`.
 | 
			
		||||
        IUniswapV2Router01 router = IUniswapV2Router01(state.router);
 | 
			
		||||
        uint[] memory amounts = router.swapExactTokensForTokens(
 | 
			
		||||
             // Sell all tokens we hold.
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
             // Minimum buy amount.
 | 
			
		||||
            amount,
 | 
			
		||||
            // Convert `fromTokenAddress` to `toTokenAddress`.
 | 
			
		||||
            state.path,
 | 
			
		||||
            // Recipient is `to`.
 | 
			
		||||
            to,
 | 
			
		||||
            // Expires after this block.
 | 
			
		||||
            block.timestamp
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            // input token
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            // output token
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            // input token amount
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            // output token amount
 | 
			
		||||
            amounts[amounts.length - 1],
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/SwerveBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								contracts/asset-proxy/contracts/src/bridges/SwerveBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
import "../interfaces/ICurve.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
contract SwerveBridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct SwerveBridgeData {
 | 
			
		||||
        address curveAddress;
 | 
			
		||||
        bytes4 exchangeFunctionSelector;
 | 
			
		||||
        address fromTokenAddress;
 | 
			
		||||
        int128 fromCoinIdx;
 | 
			
		||||
        int128 toCoinIdx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Callback for `ICurve`. Tries to buy `amount` of
 | 
			
		||||
    ///      `toTokenAddress` tokens by selling the entirety of the opposing asset
 | 
			
		||||
    ///      (DAI, USDC) to the Curve contract, then transfers the bought
 | 
			
		||||
    ///      tokens to `to`.
 | 
			
		||||
    /// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
 | 
			
		||||
    /// @param from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @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 bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // Decode the bridge data to get the SwerveBridgeData metadata.
 | 
			
		||||
        SwerveBridgeData memory data = abi.decode(bridgeData, (SwerveBridgeData));
 | 
			
		||||
 | 
			
		||||
        require(toTokenAddress != data.fromTokenAddress, "SwerveBridge/INVALID_PAIR");
 | 
			
		||||
        uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Grant an allowance to the exchange to spend `fromTokenAddress` token.
 | 
			
		||||
        LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
 | 
			
		||||
 | 
			
		||||
        // Try to sell all of this contract's `fromTokenAddress` token balance.
 | 
			
		||||
        {
 | 
			
		||||
            (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
                data.curveAddress.call(abi.encodeWithSelector(
 | 
			
		||||
                    data.exchangeFunctionSelector,
 | 
			
		||||
                    data.fromCoinIdx,
 | 
			
		||||
                    data.toCoinIdx,
 | 
			
		||||
                    // dx
 | 
			
		||||
                    fromTokenBalance,
 | 
			
		||||
                    // min dy
 | 
			
		||||
                    amount
 | 
			
		||||
                ));
 | 
			
		||||
            if (!didSucceed) {
 | 
			
		||||
                assembly { revert(add(resultData, 32), mload(resultData)) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
 | 
			
		||||
        // Transfer the converted `toToken`s to `to`.
 | 
			
		||||
        LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            data.fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            fromTokenBalance,
 | 
			
		||||
            toTokenBalance,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        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 Magic success bytes, always.
 | 
			
		||||
    function isValidSignature(
 | 
			
		||||
        bytes32,
 | 
			
		||||
        bytes calldata
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes4 magicValue)
 | 
			
		||||
    {
 | 
			
		||||
        return LEGACY_WALLET_MAGIC_VALUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -38,10 +38,11 @@ contract UniswapBridge is
 | 
			
		||||
{
 | 
			
		||||
    // Struct to hold `bridgeTransferFrom()` local variables in memory and to avoid
 | 
			
		||||
    // stack overflows.
 | 
			
		||||
    struct WithdrawToState {
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        IUniswapExchange exchange;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
        IEtherToken weth;
 | 
			
		||||
        uint256 boughtAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // solhint-disable no-empty-blocks
 | 
			
		||||
@@ -55,13 +56,14 @@ contract UniswapBridge is
 | 
			
		||||
    ///      `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 from The maker (this contract).
 | 
			
		||||
    /// @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 from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
@@ -70,7 +72,7 @@ contract UniswapBridge is
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // State memory object to avoid stack overflows.
 | 
			
		||||
        WithdrawToState memory state;
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        (address fromTokenAddress) = abi.decode(bridgeData, (address));
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +98,7 @@ contract UniswapBridge is
 | 
			
		||||
            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)(
 | 
			
		||||
            state.boughtAmount = state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)(
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
                amount,
 | 
			
		||||
                // Expires after this block.
 | 
			
		||||
@@ -108,9 +110,9 @@ contract UniswapBridge is
 | 
			
		||||
        // Convert from a token to WETH.
 | 
			
		||||
        } else if (toTokenAddress == address(state.weth)) {
 | 
			
		||||
            // Grant the exchange an allowance.
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress);
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
 | 
			
		||||
            // Buy as much ETH with `fromTokenAddress` token as possible.
 | 
			
		||||
            uint256 ethBought = state.exchange.tokenToEthSwapInput(
 | 
			
		||||
            state.boughtAmount = state.exchange.tokenToEthSwapInput(
 | 
			
		||||
                // Sell all tokens we hold.
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
@@ -119,17 +121,17 @@ contract UniswapBridge is
 | 
			
		||||
                block.timestamp
 | 
			
		||||
            );
 | 
			
		||||
            // Wrap the ETH.
 | 
			
		||||
            state.weth.deposit.value(ethBought)();
 | 
			
		||||
            state.weth.deposit.value(state.boughtAmount)();
 | 
			
		||||
            // Transfer the WETH to `to`.
 | 
			
		||||
            IEtherToken(toTokenAddress).transfer(to, ethBought);
 | 
			
		||||
            IEtherToken(toTokenAddress).transfer(to, state.boughtAmount);
 | 
			
		||||
 | 
			
		||||
        // Convert from one token to another.
 | 
			
		||||
        } else {
 | 
			
		||||
            // Grant the exchange an allowance.
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress);
 | 
			
		||||
            _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance);
 | 
			
		||||
            // Buy as much `toTokenAddress` token with `fromTokenAddress` token
 | 
			
		||||
            // and transfer it to `to`.
 | 
			
		||||
            state.exchange.tokenToTokenTransferInput(
 | 
			
		||||
            state.boughtAmount = state.exchange.tokenToTokenTransferInput(
 | 
			
		||||
                // Sell all tokens we hold.
 | 
			
		||||
                state.fromTokenBalance,
 | 
			
		||||
                // Minimum buy amount.
 | 
			
		||||
@@ -144,6 +146,15 @@ contract UniswapBridge is
 | 
			
		||||
                toTokenAddress
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            fromTokenAddress,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            state.boughtAmount,
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
        return BRIDGE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -165,10 +176,19 @@ contract UniswapBridge is
 | 
			
		||||
    ///      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)
 | 
			
		||||
    /// @param minimumAllowance The minimum necessary allowance.
 | 
			
		||||
    function _grantExchangeAllowance(
 | 
			
		||||
        IUniswapExchange exchange,
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256 minimumAllowance
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
    {
 | 
			
		||||
        LibERC20Token.approve(tokenAddress, address(exchange), uint256(-1));
 | 
			
		||||
        LibERC20Token.approveIfBelow(
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            address(exchange),
 | 
			
		||||
            minimumAllowance
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the uniswap exchange for a given token pair.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								contracts/asset-proxy/contracts/src/bridges/UniswapV2Bridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								contracts/asset-proxy/contracts/src/bridges/UniswapV2Bridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "../interfaces/IUniswapV2Router01.sol";
 | 
			
		||||
import "../interfaces/IERC20Bridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable space-after-comma
 | 
			
		||||
// solhint-disable not-rely-on-time
 | 
			
		||||
contract UniswapV2Bridge is
 | 
			
		||||
    IERC20Bridge,
 | 
			
		||||
    IWallet,
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    struct TransferState {
 | 
			
		||||
        address[] path;
 | 
			
		||||
        uint256 fromTokenBalance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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 from The maker (this contract).
 | 
			
		||||
    /// @param to The recipient of the bought tokens.
 | 
			
		||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
			
		||||
    /// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
 | 
			
		||||
    /// @return success The magic bytes if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes calldata bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        // hold variables to get around stack depth limitations
 | 
			
		||||
        TransferState memory state;
 | 
			
		||||
 | 
			
		||||
        // Decode the bridge data to get the `fromTokenAddress`.
 | 
			
		||||
        // solhint-disable indent
 | 
			
		||||
        state.path = abi.decode(bridgeData, (address[]));
 | 
			
		||||
        // solhint-enable indent
 | 
			
		||||
 | 
			
		||||
        require(state.path.length >= 2, "UniswapV2Bridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
 | 
			
		||||
        require(state.path[state.path.length - 1] == toTokenAddress, "UniswapV2Bridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
 | 
			
		||||
 | 
			
		||||
        // Just transfer the tokens if they're the same.
 | 
			
		||||
        if (state.path[0] == toTokenAddress) {
 | 
			
		||||
            LibERC20Token.transfer(state.path[0], to, amount);
 | 
			
		||||
            return BRIDGE_SUCCESS;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get our balance of `fromTokenAddress` token.
 | 
			
		||||
        state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        // Grant the Uniswap router an allowance.
 | 
			
		||||
        LibERC20Token.approveIfBelow(
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            _getUniswapV2Router01Address(),
 | 
			
		||||
            state.fromTokenBalance
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Buy as much `toTokenAddress` token with `fromTokenAddress` token
 | 
			
		||||
        // and transfer it to `to`.
 | 
			
		||||
        IUniswapV2Router01 router = IUniswapV2Router01(_getUniswapV2Router01Address());
 | 
			
		||||
        uint[] memory amounts = router.swapExactTokensForTokens(
 | 
			
		||||
             // Sell all tokens we hold.
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
             // Minimum buy amount.
 | 
			
		||||
            amount,
 | 
			
		||||
            // Convert `fromTokenAddress` to `toTokenAddress`.
 | 
			
		||||
            state.path,
 | 
			
		||||
            // Recipient is `to`.
 | 
			
		||||
            to,
 | 
			
		||||
            // Expires after this block.
 | 
			
		||||
            block.timestamp
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        emit ERC20BridgeTransfer(
 | 
			
		||||
            // input token
 | 
			
		||||
            state.path[0],
 | 
			
		||||
            // output token
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            // input token amount
 | 
			
		||||
            state.fromTokenBalance,
 | 
			
		||||
            // output token amount
 | 
			
		||||
            amounts[amounts.length - 1],
 | 
			
		||||
            from,
 | 
			
		||||
            to
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 IBalancerPool {
 | 
			
		||||
    /// @dev Sell `tokenAmountIn` of `tokenIn` and receive `tokenOut`.
 | 
			
		||||
    /// @param tokenIn The token being sold
 | 
			
		||||
    /// @param tokenAmountIn The amount of `tokenIn` to sell.
 | 
			
		||||
    /// @param tokenOut The token being bought.
 | 
			
		||||
    /// @param minAmountOut The minimum amount of `tokenOut` to buy.
 | 
			
		||||
    /// @param maxPrice The maximum value for `spotPriceAfter`.
 | 
			
		||||
    /// @return tokenAmountOut The amount of `tokenOut` bought.
 | 
			
		||||
    /// @return spotPriceAfter The new marginal spot price of the given
 | 
			
		||||
    ///         token pair for this pool.
 | 
			
		||||
    function swapExactAmountIn(
 | 
			
		||||
        address tokenIn,
 | 
			
		||||
        uint tokenAmountIn,
 | 
			
		||||
        address tokenOut,
 | 
			
		||||
        uint minAmountOut,
 | 
			
		||||
        uint maxPrice
 | 
			
		||||
    ) external returns (uint tokenAmountOut, uint spotPriceAfter);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract IContractRegistry {
 | 
			
		||||
    function addressOf(
 | 
			
		||||
        bytes32 contractName
 | 
			
		||||
    ) external returns(address);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract IBancorNetwork {
 | 
			
		||||
    function convertByPath(
 | 
			
		||||
        address[] calldata _path,
 | 
			
		||||
        uint256 _amount,
 | 
			
		||||
        uint256 _minReturn,
 | 
			
		||||
        address _beneficiary,
 | 
			
		||||
        address _affiliateAccount,
 | 
			
		||||
        uint256 _affiliateFee
 | 
			
		||||
    ) external payable returns (uint256);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								contracts/asset-proxy/contracts/src/interfaces/ICurve.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								contracts/asset-proxy/contracts/src/interfaces/ICurve.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable func-name-mixedcase
 | 
			
		||||
interface ICurve {
 | 
			
		||||
 | 
			
		||||
    /// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
 | 
			
		||||
    ///      This function exists on later versions of Curve (USDC/DAI/USDT)
 | 
			
		||||
    /// @param i The token index being sold.
 | 
			
		||||
    /// @param j The token index being bought.
 | 
			
		||||
    /// @param sellAmount The amount of token being bought.
 | 
			
		||||
    /// @param minBuyAmount The minimum buy amount of the token being bought.
 | 
			
		||||
    function exchange_underlying(
 | 
			
		||||
        int128 i,
 | 
			
		||||
        int128 j,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        uint256 minBuyAmount
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
 | 
			
		||||
    /// @param i The token index being sold.
 | 
			
		||||
    /// @param j The token index being bought.
 | 
			
		||||
    /// @param sellAmount The amount of token being bought.
 | 
			
		||||
    function get_dy_underlying(
 | 
			
		||||
        int128 i,
 | 
			
		||||
        int128 j,
 | 
			
		||||
        uint256 sellAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 dy);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
 | 
			
		||||
    /// @param i The token index being sold.
 | 
			
		||||
    /// @param j The token index being bought.
 | 
			
		||||
    /// @param buyAmount The amount of token being bought.
 | 
			
		||||
    function get_dx_underlying(
 | 
			
		||||
        int128 i,
 | 
			
		||||
        int128 j,
 | 
			
		||||
        uint256 buyAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 dx);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the underlying token address from the token index
 | 
			
		||||
    /// @param i The token index.
 | 
			
		||||
    function underlying_coins(
 | 
			
		||||
        int128 i
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (address tokenAddress);
 | 
			
		||||
}
 | 
			
		||||
@@ -45,12 +45,12 @@ interface IDydx {
 | 
			
		||||
    /// parsed into before being processed.
 | 
			
		||||
    struct ActionArgs {
 | 
			
		||||
        ActionType actionType;
 | 
			
		||||
        uint256 accountId;
 | 
			
		||||
        uint256 accountIdx;
 | 
			
		||||
        AssetAmount amount;
 | 
			
		||||
        uint256 primaryMarketId;
 | 
			
		||||
        uint256 secondaryMarketId;
 | 
			
		||||
        address otherAddress;
 | 
			
		||||
        uint256 otherAccountId;
 | 
			
		||||
        uint256 otherAccountIdx;
 | 
			
		||||
        bytes data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -71,6 +71,36 @@ interface IDydx {
 | 
			
		||||
        uint256 value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct D256 {
 | 
			
		||||
        uint256 value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct Value {
 | 
			
		||||
        uint256 value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct Price {
 | 
			
		||||
        uint256 value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct OperatorArg {
 | 
			
		||||
        address operator;
 | 
			
		||||
        bool trusted;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev The global risk parameters that govern the health and security of the system
 | 
			
		||||
    struct RiskParams {
 | 
			
		||||
        // Required ratio of over-collateralization
 | 
			
		||||
        D256 marginRatio;
 | 
			
		||||
        // Percentage penalty incurred by liquidated accounts
 | 
			
		||||
        D256 liquidationSpread;
 | 
			
		||||
        // Percentage of the borrower's interest fee that gets passed to the suppliers
 | 
			
		||||
        D256 earningsRate;
 | 
			
		||||
        // The minimum absolute borrow value of an account
 | 
			
		||||
        // There must be sufficient incentivize to liquidate undercollateralized accounts
 | 
			
		||||
        Value minBorrowedValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev The main entry-point to Solo that allows users and contracts to manage accounts.
 | 
			
		||||
    ///      Take one or more actions on one or more accounts. The msg.sender must be the owner or
 | 
			
		||||
    ///      operator of all accounts except for those being liquidated, vaporized, or traded with.
 | 
			
		||||
@@ -86,4 +116,77 @@ interface IDydx {
 | 
			
		||||
        ActionArgs[] calldata actions
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    // @dev Approves/disapproves any number of operators. An operator is an external address that has the
 | 
			
		||||
    //      same permissions to manipulate an account as the owner of the account. Operators are simply
 | 
			
		||||
    //      addresses and therefore may either be externally-owned Ethereum accounts OR smart contracts.
 | 
			
		||||
    //      Operators are also able to act as AutoTrader contracts on behalf of the account owner if the
 | 
			
		||||
    //      operator is a smart contract and implements the IAutoTrader interface.
 | 
			
		||||
    // @param args A list of OperatorArgs which have an address and a boolean. The boolean value
 | 
			
		||||
    //        denotes whether to approve (true) or revoke approval (false) for that address.
 | 
			
		||||
    function setOperators(OperatorArg[] calldata args) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Return true if a particular address is approved as an operator for an owner's accounts.
 | 
			
		||||
    ///      Approved operators can act on the accounts of the owner as if it were the operator's own.
 | 
			
		||||
    /// @param owner The owner of the accounts
 | 
			
		||||
    /// @param operator The possible operator
 | 
			
		||||
    /// @return isLocalOperator True if operator is approved for owner's accounts
 | 
			
		||||
    function getIsLocalOperator(
 | 
			
		||||
        address owner,
 | 
			
		||||
        address operator
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bool isLocalOperator);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the ERC20 token address for a market.
 | 
			
		||||
    /// @param marketId The market to query
 | 
			
		||||
    /// @return tokenAddress The token address
 | 
			
		||||
    function getMarketTokenAddress(
 | 
			
		||||
        uint256 marketId
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address tokenAddress);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get all risk parameters in a single struct.
 | 
			
		||||
    /// @return riskParams All global risk parameters
 | 
			
		||||
    function getRiskParams()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (RiskParams memory riskParams);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the price of the token for a market.
 | 
			
		||||
    /// @param marketId The market to query
 | 
			
		||||
    /// @return price The price of each atomic unit of the token
 | 
			
		||||
    function getMarketPrice(
 | 
			
		||||
        uint256 marketId
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (Price memory price);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the margin premium for a market. A margin premium makes it so that any positions that
 | 
			
		||||
    ///      include the market require a higher collateralization to avoid being liquidated.
 | 
			
		||||
    /// @param  marketId  The market to query
 | 
			
		||||
    /// @return premium The market's margin premium
 | 
			
		||||
    function getMarketMarginPremium(uint256 marketId)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (D256 memory premium);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the total supplied and total borrowed values of an account adjusted by the marginPremium
 | 
			
		||||
    ///      of each market. Supplied values are divided by (1 + marginPremium) for each market and
 | 
			
		||||
    ///      borrowed values are multiplied by (1 + marginPremium) for each market. Comparing these
 | 
			
		||||
    ///      adjusted values gives the margin-ratio of the account which will be compared to the global
 | 
			
		||||
    ///      margin-ratio when determining if the account can be liquidated.
 | 
			
		||||
    /// @param account The account to query
 | 
			
		||||
    /// @return supplyValue The supplied value of the account (adjusted for marginPremium)
 | 
			
		||||
    /// @return borrowValue The borrowed value of the account (adjusted for marginPremium)
 | 
			
		||||
    function getAdjustedAccountValues(
 | 
			
		||||
        AccountInfo calldata account
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (Value memory supplyValue, Value memory borrowValue);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ interface IDydxBridge {
 | 
			
		||||
 | 
			
		||||
    struct BridgeAction {
 | 
			
		||||
        BridgeActionType actionType;            // Action to run on dydx account.
 | 
			
		||||
        uint256 accountId;                      // Index in `BridgeData.accountNumbers` for this action.
 | 
			
		||||
        uint256 accountIdx;                     // Index in `BridgeData.accountNumbers` for this action.
 | 
			
		||||
        uint256 marketId;                       // Market to operate on.
 | 
			
		||||
        uint256 conversionRateNumerator;        // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
 | 
			
		||||
        uint256 conversionRateDenominator;      // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
 | 
			
		||||
@@ -39,4 +39,4 @@ interface IDydxBridge {
 | 
			
		||||
        uint256[] accountNumbers;               // Account number used to identify the owner's specific account.
 | 
			
		||||
        BridgeAction[] actions;                 // Actions to carry out on the owner's accounts.
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,16 +21,32 @@ pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
contract IERC20Bridge {
 | 
			
		||||
 | 
			
		||||
    // @dev Result of a successful bridge call.
 | 
			
		||||
    /// @dev Result of a successful bridge call.
 | 
			
		||||
    bytes4 constant internal BRIDGE_SUCCESS = 0xdc1600f3;
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted when a trade occurs.
 | 
			
		||||
    /// @param inputToken The token the bridge is converting from.
 | 
			
		||||
    /// @param outputToken The token the bridge is converting to.
 | 
			
		||||
    /// @param inputTokenAmount Amount of input token.
 | 
			
		||||
    /// @param outputTokenAmount Amount of output token.
 | 
			
		||||
    /// @param from The `from` address in `bridgeTransferFrom()`
 | 
			
		||||
    /// @param to The `to` address in `bridgeTransferFrom()`
 | 
			
		||||
    event ERC20BridgeTransfer(
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        uint256 outputTokenAmount,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC20 token to transfer.
 | 
			
		||||
    /// @param from Address to transfer asset from.
 | 
			
		||||
    /// @param to Address to transfer asset to.
 | 
			
		||||
    /// @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.
 | 
			
		||||
    /// @return success The magic bytes `0xdc1600f3` if successful.
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        address from,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								contracts/asset-proxy/contracts/src/interfaces/IGasToken.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								contracts/asset-proxy/contracts/src/interfaces/IGasToken.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.15;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract IGasToken is IERC20Token {
 | 
			
		||||
 | 
			
		||||
    /// @dev Frees up to `value` sub-tokens
 | 
			
		||||
    /// @param value The amount of tokens to free
 | 
			
		||||
    /// @return How many tokens were freed
 | 
			
		||||
    function freeUpTo(uint256 value) external returns (uint256 freed);
 | 
			
		||||
 | 
			
		||||
    /// @dev Frees up to `value` sub-tokens owned by `from`
 | 
			
		||||
    /// @param from The owner of tokens to spend
 | 
			
		||||
    /// @param value The amount of tokens to free
 | 
			
		||||
    /// @return How many tokens were freed
 | 
			
		||||
    function freeFromUpTo(address from, uint256 value) external returns (uint256 freed);
 | 
			
		||||
 | 
			
		||||
    /// @dev Mints `value` amount of tokens
 | 
			
		||||
    /// @param value The amount of tokens to mint
 | 
			
		||||
    function mint(uint256 value) external;
 | 
			
		||||
}
 | 
			
		||||
@@ -42,5 +42,31 @@ interface IKyberNetworkProxy {
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns(uint256 boughtAmount);
 | 
			
		||||
        returns (uint256 boughtAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens
 | 
			
		||||
    /// using a hint for the reserve.
 | 
			
		||||
    /// @param sellTokenAddress Token to sell.
 | 
			
		||||
    /// @param sellAmount Amount of tokens to sell.
 | 
			
		||||
    /// @param buyTokenAddress Token to buy.
 | 
			
		||||
    /// @param recipientAddress Address to send bought tokens to.
 | 
			
		||||
    /// @param maxBuyTokenAmount A limit on the amount of tokens to buy.
 | 
			
		||||
    /// @param minConversionRate The minimal conversion rate. If actual rate
 | 
			
		||||
    ///        is lower, trade is canceled.
 | 
			
		||||
    /// @param walletId The wallet ID to send part of the fees
 | 
			
		||||
    /// @param hint The hint for the selective inclusion (or exclusion) of reserves
 | 
			
		||||
    /// @return boughtAmount Amount of tokens bought.
 | 
			
		||||
    function tradeWithHint(
 | 
			
		||||
        address sellTokenAddress,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        address buyTokenAddress,
 | 
			
		||||
        address payable recipientAddress,
 | 
			
		||||
        uint256 maxBuyTokenAmount,
 | 
			
		||||
        uint256 minConversionRate,
 | 
			
		||||
        address payable walletId,
 | 
			
		||||
        bytes calldata hint
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 boughtAmount);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
  Copyright 2020 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
@@ -19,14 +19,14 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IKyberNetwork {
 | 
			
		||||
interface IMStable {
 | 
			
		||||
 | 
			
		||||
    function getExpectedRate(
 | 
			
		||||
        address fromToken,
 | 
			
		||||
        address toToken,
 | 
			
		||||
        uint256 fromAmount
 | 
			
		||||
    function swap(
 | 
			
		||||
        address _input,
 | 
			
		||||
        address _output,
 | 
			
		||||
        uint256 _quantity,
 | 
			
		||||
        address _recipient
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 expectedRate, uint256 slippageRate);
 | 
			
		||||
        returns (uint256 output);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 IMooniswapRegistry {
 | 
			
		||||
 | 
			
		||||
    function pools(address token1, address token2) external view returns(address);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IMooniswap {
 | 
			
		||||
 | 
			
		||||
    function swap(
 | 
			
		||||
        address fromToken,
 | 
			
		||||
        address destToken,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        uint256 minReturn,
 | 
			
		||||
        address referral
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns(uint256 returnAmount);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								contracts/asset-proxy/contracts/src/interfaces/IShell.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								contracts/asset-proxy/contracts/src/interfaces/IShell.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 IShell {
 | 
			
		||||
 | 
			
		||||
    function originSwap(
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 fromAmount,
 | 
			
		||||
        uint256 minTargetAmount,
 | 
			
		||||
        uint256 deadline
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint256 toAmount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 IUniswapV2Router01 {
 | 
			
		||||
 | 
			
		||||
    /// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path.
 | 
			
		||||
    ///      The first element of path is the input token, the last is the output token, and any intermediate elements represent
 | 
			
		||||
    ///      intermediate pairs to trade through (if, for example, a direct pair does not exist).
 | 
			
		||||
    /// @param amountIn The amount of input tokens to send.
 | 
			
		||||
    /// @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.
 | 
			
		||||
    /// @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
 | 
			
		||||
    /// @param to Recipient of the output tokens.
 | 
			
		||||
    /// @param deadline Unix timestamp after which the transaction will revert.
 | 
			
		||||
    /// @return amounts The input token amount and all subsequent output token amounts.
 | 
			
		||||
    function swapExactTokensForTokens(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address[] calldata path,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint deadline
 | 
			
		||||
    ) external returns (uint[] memory amounts);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										247
									
								
								contracts/asset-proxy/contracts/test/TestBancorBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								contracts/asset-proxy/contracts/test/TestBancorBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,247 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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 "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "../src/bridges/BancorBridge.sol";
 | 
			
		||||
import "../src/interfaces/IBancorNetwork.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestEventsRaiser {
 | 
			
		||||
 | 
			
		||||
    event TokenTransfer(
 | 
			
		||||
        address token,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenApprove(
 | 
			
		||||
        address spender,
 | 
			
		||||
        uint256 allowance
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event ConvertByPathInput(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address to,
 | 
			
		||||
        address feeRecipient,
 | 
			
		||||
        uint256 feeAmount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    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 raiseConvertByPathInput(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address to,
 | 
			
		||||
        address feeRecipient,
 | 
			
		||||
        uint256 feeAmount
 | 
			
		||||
    ) external
 | 
			
		||||
    {
 | 
			
		||||
        emit ConvertByPathInput(
 | 
			
		||||
            amountIn,
 | 
			
		||||
            amountOutMin,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            to,
 | 
			
		||||
            feeRecipient,
 | 
			
		||||
            feeAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev A minimalist ERC20 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, uint256 balance)
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        balances[owner] = balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just emits a TokenTransfer event on the caller
 | 
			
		||||
    function transfer(address to, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just emits a TokenApprove event on the caller
 | 
			
		||||
    function approve(address spender, uint256 allowance)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function allowance(address, address) external view returns (uint256) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieve the balance for `owner`.
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256)
 | 
			
		||||
    {
 | 
			
		||||
        return balances[owner];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Mock the BancorNetwork contract
 | 
			
		||||
contract TestBancorNetwork is
 | 
			
		||||
    IBancorNetwork
 | 
			
		||||
{
 | 
			
		||||
    string private _nextRevertReason;
 | 
			
		||||
 | 
			
		||||
    /// @dev Set the revert reason for `swapExactTokensForTokens`.
 | 
			
		||||
    function setRevertReason(string calldata reason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _nextRevertReason = reason;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function convertByPath(
 | 
			
		||||
        address[] calldata _path,
 | 
			
		||||
        uint256 _amount,
 | 
			
		||||
        uint256 _minReturn,
 | 
			
		||||
        address _beneficiary,
 | 
			
		||||
        address _affiliateAccount,
 | 
			
		||||
        uint256 _affiliateFee
 | 
			
		||||
    ) external payable returns (uint256)
 | 
			
		||||
    {
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseConvertByPathInput(
 | 
			
		||||
            // tokens sold
 | 
			
		||||
            _amount,
 | 
			
		||||
            // tokens bought
 | 
			
		||||
            _minReturn,
 | 
			
		||||
            // output token
 | 
			
		||||
            _path[_path.length - 1],
 | 
			
		||||
            // recipient
 | 
			
		||||
            _beneficiary,
 | 
			
		||||
            // fee recipient
 | 
			
		||||
            _affiliateAccount,
 | 
			
		||||
            // fee amount
 | 
			
		||||
            _affiliateFee
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _revertIfReasonExists()
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        if (bytes(_nextRevertReason).length != 0) {
 | 
			
		||||
            revert(_nextRevertReason);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev BancorBridge overridden to mock tokens and BancorNetwork
 | 
			
		||||
contract TestBancorBridge is
 | 
			
		||||
    BancorBridge,
 | 
			
		||||
    TestEventsRaiser
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    // Token address to TestToken instance.
 | 
			
		||||
    mapping (address => TestToken) private _testTokens;
 | 
			
		||||
    // TestRouter instance.
 | 
			
		||||
    TestBancorNetwork private _testNetwork;
 | 
			
		||||
 | 
			
		||||
    constructor() public {
 | 
			
		||||
        _testNetwork = new TestBancorNetwork();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setNetworkRevertReason(string calldata revertReason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _testNetwork.setRevertReason(revertReason);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sets the balance of this contract for an existing token.
 | 
			
		||||
    function setTokenBalance(address tokenAddress, uint256 balance)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        TestToken token = _testTokens[tokenAddress];
 | 
			
		||||
        token.setBalance(address(this), balance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Create a new token
 | 
			
		||||
    /// @param tokenAddress The token address. If zero, one will be created.
 | 
			
		||||
    function createToken(
 | 
			
		||||
        address tokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (TestToken token)
 | 
			
		||||
    {
 | 
			
		||||
        token = TestToken(tokenAddress);
 | 
			
		||||
        if (tokenAddress == address(0)) {
 | 
			
		||||
            token = new TestToken();
 | 
			
		||||
        }
 | 
			
		||||
        _testTokens[address(token)] = token;
 | 
			
		||||
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getNetworkAddress()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address)
 | 
			
		||||
    {
 | 
			
		||||
        return address(_testNetwork);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										244
									
								
								contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,244 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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 "../src/bridges/DexForwarderBridge.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface ITestDexForwarderBridge {
 | 
			
		||||
    event BridgeTransferFromCalled(
 | 
			
		||||
        address caller,
 | 
			
		||||
        uint256 inputTokenBalance,
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenTransferCalled(
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    function emitBridgeTransferFromCalled(
 | 
			
		||||
        address caller,
 | 
			
		||||
        uint256 inputTokenBalance,
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    function emitTokenTransferCalled(
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    ) external;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface ITestDexForwarderBridgeTestToken {
 | 
			
		||||
 | 
			
		||||
    function transfer(address to, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool);
 | 
			
		||||
 | 
			
		||||
    function mint(address to, uint256 amount)
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    function balanceOf(address owner) external view returns (uint256);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestDexForwarderBridgeTestBridge {
 | 
			
		||||
 | 
			
		||||
    bytes4 private _returnCode;
 | 
			
		||||
    string private _revertError;
 | 
			
		||||
    uint256 private _transferAmount;
 | 
			
		||||
    ITestDexForwarderBridge private _testContract;
 | 
			
		||||
 | 
			
		||||
    constructor(bytes4 returnCode, string memory revertError) public {
 | 
			
		||||
        _testContract = ITestDexForwarderBridge(msg.sender);
 | 
			
		||||
        _returnCode = returnCode;
 | 
			
		||||
        _revertError = revertError;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setTransferAmount(uint256 amount) external {
 | 
			
		||||
        _transferAmount = amount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function bridgeTransferFrom(
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount,
 | 
			
		||||
        bytes memory bridgeData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        if (bytes(_revertError).length != 0) {
 | 
			
		||||
            revert(_revertError);
 | 
			
		||||
        }
 | 
			
		||||
        address inputToken = abi.decode(bridgeData, (address));
 | 
			
		||||
        _testContract.emitBridgeTransferFromCalled(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            ITestDexForwarderBridgeTestToken(inputToken).balanceOf(address(this)),
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
        ITestDexForwarderBridgeTestToken(outputToken).mint(to, _transferAmount);
 | 
			
		||||
        return _returnCode;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestDexForwarderBridgeTestToken {
 | 
			
		||||
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    mapping(address => uint256) public balanceOf;
 | 
			
		||||
    ITestDexForwarderBridge private _testContract;
 | 
			
		||||
 | 
			
		||||
    constructor() public {
 | 
			
		||||
        _testContract = ITestDexForwarderBridge(msg.sender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function transfer(address to, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        balanceOf[msg.sender] = balanceOf[msg.sender].safeSub(amount);
 | 
			
		||||
        balanceOf[to] = balanceOf[to].safeAdd(amount);
 | 
			
		||||
        _testContract.emitTokenTransferCalled(msg.sender, to, amount);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function mint(address owner, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        balanceOf[owner] = balanceOf[owner].safeAdd(amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setBalance(address owner, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        balanceOf[owner] = amount;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestDexForwarderBridge is
 | 
			
		||||
    ITestDexForwarderBridge,
 | 
			
		||||
    DexForwarderBridge
 | 
			
		||||
{
 | 
			
		||||
    address private AUTHORIZED_ADDRESS; // solhint-disable-line var-name-mixedcase
 | 
			
		||||
 | 
			
		||||
    function setAuthorized(address authorized)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        AUTHORIZED_ADDRESS = authorized;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createBridge(
 | 
			
		||||
        bytes4 returnCode,
 | 
			
		||||
        string memory revertError
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (address bridge)
 | 
			
		||||
    {
 | 
			
		||||
        return address(new TestDexForwarderBridgeTestBridge(returnCode, revertError));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createToken() public returns (address token) {
 | 
			
		||||
        return address(new TestDexForwarderBridgeTestToken());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setTokenBalance(address token, address owner, uint256 amount) public {
 | 
			
		||||
        TestDexForwarderBridgeTestToken(token).setBalance(owner, amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setBridgeTransferAmount(address bridge, uint256 amount) public {
 | 
			
		||||
        TestDexForwarderBridgeTestBridge(bridge).setTransferAmount(amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function emitBridgeTransferFromCalled(
 | 
			
		||||
        address caller,
 | 
			
		||||
        uint256 inputTokenBalance,
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        emit BridgeTransferFromCalled(
 | 
			
		||||
            caller,
 | 
			
		||||
            inputTokenBalance,
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function emitTokenTransferCalled(
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        emit TokenTransferCalled(
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            amount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function balanceOf(address token, address owner) public view returns (uint256) {
 | 
			
		||||
        return TestDexForwarderBridgeTestToken(token).balanceOf(owner);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _getGstAddress()
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
        returns (address gst)
 | 
			
		||||
    {
 | 
			
		||||
        return address(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _getERC20BridgeProxyAddress()
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
        returns (address erc20BridgeProxyAddress)
 | 
			
		||||
    {
 | 
			
		||||
        return AUTHORIZED_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,6 +23,7 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "../src/bridges/DydxBridge.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-empty-blocks
 | 
			
		||||
contract TestDydxBridgeToken {
 | 
			
		||||
 | 
			
		||||
    uint256 private constant INIT_HOLDER_BALANCE = 10 * 10**18; // 10 tokens
 | 
			
		||||
@@ -79,7 +80,7 @@ contract TestDydxBridge is
 | 
			
		||||
 | 
			
		||||
    event OperateAction(
 | 
			
		||||
        ActionType actionType,
 | 
			
		||||
        uint256 accountId,
 | 
			
		||||
        uint256 accountIdx,
 | 
			
		||||
        bool amountSign,
 | 
			
		||||
        AssetDenomination amountDenomination,
 | 
			
		||||
        AssetReference amountRef,
 | 
			
		||||
@@ -120,7 +121,7 @@ contract TestDydxBridge is
 | 
			
		||||
        for (uint i = 0; i < actions.length; ++i) {
 | 
			
		||||
            emit OperateAction(
 | 
			
		||||
                actions[i].actionType,
 | 
			
		||||
                actions[i].accountId,
 | 
			
		||||
                actions[i].accountIdx,
 | 
			
		||||
                actions[i].amount.sign,
 | 
			
		||||
                actions[i].amount.denomination,
 | 
			
		||||
                actions[i].amount.ref,
 | 
			
		||||
@@ -128,7 +129,7 @@ contract TestDydxBridge is
 | 
			
		||||
                actions[i].primaryMarketId,
 | 
			
		||||
                actions[i].secondaryMarketId,
 | 
			
		||||
                actions[i].otherAddress,
 | 
			
		||||
                actions[i].otherAccountId,
 | 
			
		||||
                actions[i].otherAccountIdx,
 | 
			
		||||
                actions[i].data
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
@@ -171,6 +172,60 @@ contract TestDydxBridge is
 | 
			
		||||
        return _testTokenAddress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Unused.
 | 
			
		||||
    function setOperators(OperatorArg[] calldata args) external {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unused.
 | 
			
		||||
    function getIsLocalOperator(
 | 
			
		||||
        address owner,
 | 
			
		||||
        address operator
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bool isLocalOperator)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unused.
 | 
			
		||||
    function getMarketTokenAddress(
 | 
			
		||||
        uint256 marketId
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address tokenAddress)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unused.
 | 
			
		||||
    function getRiskParams()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (RiskParams memory riskParams)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unsused.
 | 
			
		||||
    function getMarketPrice(
 | 
			
		||||
        uint256 marketId
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (Price memory price)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unsused
 | 
			
		||||
    function getMarketMarginPremium(uint256 marketId)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (IDydx.D256 memory premium)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Unused.
 | 
			
		||||
    function getAdjustedAccountValues(
 | 
			
		||||
        AccountInfo calldata account
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (Value memory supplyValue, Value memory borrowValue)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    /// @dev overrides `_getDydxAddress()` from `DeploymentConstants` to return this address.
 | 
			
		||||
    function _getDydxAddress()
 | 
			
		||||
        internal
 | 
			
		||||
@@ -188,4 +243,4 @@ contract TestDydxBridge is
 | 
			
		||||
    {
 | 
			
		||||
        return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -110,6 +110,10 @@ contract TestToken {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function allowance(address, address) external view returns (uint256) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieve the balance for `owner`.
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
 
 | 
			
		||||
@@ -110,6 +110,10 @@ contract TestToken {
 | 
			
		||||
        return _testContract.wethDeposit.value(msg.value)(msg.sender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function allowance(address, address) external view returns (uint256) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
@@ -197,6 +201,33 @@ contract TestKyberBridge is
 | 
			
		||||
        return _nextFillAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function tradeWithHint(
 | 
			
		||||
        address sellTokenAddress,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        address buyTokenAddress,
 | 
			
		||||
        address payable recipientAddress,
 | 
			
		||||
        uint256 maxBuyTokenAmount,
 | 
			
		||||
        uint256 minConversionRate,
 | 
			
		||||
        address payable walletId,
 | 
			
		||||
        bytes calldata hint
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
    {
 | 
			
		||||
        emit KyberBridgeTrade(
 | 
			
		||||
            msg.value,
 | 
			
		||||
            sellTokenAddress,
 | 
			
		||||
            sellAmount,
 | 
			
		||||
            buyTokenAddress,
 | 
			
		||||
            recipientAddress,
 | 
			
		||||
            maxBuyTokenAmount,
 | 
			
		||||
            minConversionRate,
 | 
			
		||||
            walletId
 | 
			
		||||
        );
 | 
			
		||||
        return _nextFillAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createToken(uint8 decimals)
 | 
			
		||||
        external
 | 
			
		||||
        returns (address tokenAddress)
 | 
			
		||||
 
 | 
			
		||||
@@ -224,6 +224,10 @@ contract TestToken {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseWethWithdraw(amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function allowance(address, address) external view returns (uint256) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieve the balance for `owner`.
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										253
									
								
								contracts/asset-proxy/contracts/test/TestUniswapV2Bridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								contracts/asset-proxy/contracts/test/TestUniswapV2Bridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,253 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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 "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
 | 
			
		||||
import "../src/bridges/UniswapV2Bridge.sol";
 | 
			
		||||
import "../src/interfaces/IUniswapV2Router01.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestEventsRaiser {
 | 
			
		||||
 | 
			
		||||
    event TokenTransfer(
 | 
			
		||||
        address token,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event TokenApprove(
 | 
			
		||||
        address spender,
 | 
			
		||||
        uint256 allowance
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event SwapExactTokensForTokensInput(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint deadline
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    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 raiseSwapExactTokensForTokensInput(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address toTokenAddress,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint deadline
 | 
			
		||||
    ) external
 | 
			
		||||
    {
 | 
			
		||||
        emit SwapExactTokensForTokensInput(
 | 
			
		||||
            amountIn,
 | 
			
		||||
            amountOutMin,
 | 
			
		||||
            toTokenAddress,
 | 
			
		||||
            to,
 | 
			
		||||
            deadline
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev A minimalist ERC20 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, uint256 balance)
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        balances[owner] = balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just emits a TokenTransfer event on the caller
 | 
			
		||||
    function transfer(address to, uint256 amount)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Just emits a TokenApprove event on the caller
 | 
			
		||||
    function approve(address spender, uint256 allowance)
 | 
			
		||||
        external
 | 
			
		||||
        returns (bool)
 | 
			
		||||
    {
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function allowance(address, address) external view returns (uint256) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieve the balance for `owner`.
 | 
			
		||||
    function balanceOf(address owner)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256)
 | 
			
		||||
    {
 | 
			
		||||
        return balances[owner];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Mock the UniswapV2Router01 contract
 | 
			
		||||
contract TestRouter is
 | 
			
		||||
    IUniswapV2Router01
 | 
			
		||||
{
 | 
			
		||||
    string private _nextRevertReason;
 | 
			
		||||
 | 
			
		||||
    /// @dev Set the revert reason for `swapExactTokensForTokens`.
 | 
			
		||||
    function setRevertReason(string calldata reason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _nextRevertReason = reason;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function swapExactTokensForTokens(
 | 
			
		||||
        uint amountIn,
 | 
			
		||||
        uint amountOutMin,
 | 
			
		||||
        address[] calldata path,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint deadline
 | 
			
		||||
    ) external returns (uint[] memory amounts)
 | 
			
		||||
    {
 | 
			
		||||
        _revertIfReasonExists();
 | 
			
		||||
 | 
			
		||||
        amounts = new uint[](path.length);
 | 
			
		||||
        amounts[0] = amountIn;
 | 
			
		||||
        amounts[amounts.length - 1] = amountOutMin;
 | 
			
		||||
 | 
			
		||||
        TestEventsRaiser(msg.sender).raiseSwapExactTokensForTokensInput(
 | 
			
		||||
            // tokens sold
 | 
			
		||||
            amountIn,
 | 
			
		||||
            // tokens bought
 | 
			
		||||
            amountOutMin,
 | 
			
		||||
            // output token (toTokenAddress)
 | 
			
		||||
            path[path.length - 1],
 | 
			
		||||
            // recipient
 | 
			
		||||
            to,
 | 
			
		||||
            // deadline
 | 
			
		||||
            deadline
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _revertIfReasonExists()
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        if (bytes(_nextRevertReason).length != 0) {
 | 
			
		||||
            revert(_nextRevertReason);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev UniswapV2Bridge overridden to mock tokens and Uniswap router
 | 
			
		||||
contract TestUniswapV2Bridge is
 | 
			
		||||
    UniswapV2Bridge,
 | 
			
		||||
    TestEventsRaiser
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    // Token address to TestToken instance.
 | 
			
		||||
    mapping (address => TestToken) private _testTokens;
 | 
			
		||||
    // TestRouter instance.
 | 
			
		||||
    TestRouter private _testRouter;
 | 
			
		||||
 | 
			
		||||
    constructor() public {
 | 
			
		||||
        _testRouter = new TestRouter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setRouterRevertReason(string calldata revertReason)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        _testRouter.setRevertReason(revertReason);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sets the balance of this contract for an existing token.
 | 
			
		||||
    ///      The wei attached will be the balance.
 | 
			
		||||
    function setTokenBalance(address tokenAddress, uint256 balance)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        TestToken token = _testTokens[tokenAddress];
 | 
			
		||||
        token.setBalance(address(this), balance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Create a new token
 | 
			
		||||
    /// @param tokenAddress The token address. If zero, one will be created.
 | 
			
		||||
    function createToken(
 | 
			
		||||
        address tokenAddress
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (TestToken token)
 | 
			
		||||
    {
 | 
			
		||||
        token = TestToken(tokenAddress);
 | 
			
		||||
        if (tokenAddress == address(0)) {
 | 
			
		||||
            token = new TestToken();
 | 
			
		||||
        }
 | 
			
		||||
        _testTokens[address(token)] = token;
 | 
			
		||||
 | 
			
		||||
        return token;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getRouterAddress()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (address)
 | 
			
		||||
    {
 | 
			
		||||
        return address(_testRouter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _getUniswapV2Router01Address()
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
        returns (address)
 | 
			
		||||
    {
 | 
			
		||||
        return address(_testRouter);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-asset-proxy",
 | 
			
		||||
    "version": "3.1.3",
 | 
			
		||||
    "version": "3.7.9",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -38,31 +38,31 @@
 | 
			
		||||
        "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(ChaiBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CreamBridge|CryptoComBridge|CurveBridge|DODOBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IShell|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|ShellBridge|SnowSwapBridge|StaticCallProxy|SushiSwapBridge|SwerveBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo.git"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol.git"
 | 
			
		||||
    },
 | 
			
		||||
    "license": "Apache-2.0",
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo/issues"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.1.2",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.6",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.1.3",
 | 
			
		||||
        "@0x/contracts-utils": "^4.2.1",
 | 
			
		||||
        "@0x/dev-utils": "^3.1.3",
 | 
			
		||||
        "@0x/sol-compiler": "^4.0.6",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.22",
 | 
			
		||||
        "@0x/tslint-config": "^4.0.0",
 | 
			
		||||
        "@0x/types": "^3.1.1",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.15.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.24",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.6",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
        "@types/node": "12.12.54",
 | 
			
		||||
        "chai": "^4.0.1",
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
@@ -75,24 +75,25 @@
 | 
			
		||||
        "solhint": "^1.4.1",
 | 
			
		||||
        "truffle": "^5.0.32",
 | 
			
		||||
        "tslint": "5.11.0",
 | 
			
		||||
        "typedoc": "^0.15.0",
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
        "typedoc": "~0.16.11",
 | 
			
		||||
        "typescript": "4.2.2"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.1.2",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.0.6",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.0.6",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.0.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.0.6",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.2.0",
 | 
			
		||||
        "@0x/order-utils": "^10.1.3",
 | 
			
		||||
        "@0x/typescript-typings": "^5.0.1",
 | 
			
		||||
        "@0x/utils": "^5.3.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.0.5",
 | 
			
		||||
        "ethereum-types": "^3.0.0",
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.27",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.27",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.27",
 | 
			
		||||
        "@0x/order-utils": "^10.4.19",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "ethereum-types": "^3.4.0",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    "gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,14 @@
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as BalancerBridge from '../generated-artifacts/BalancerBridge.json';
 | 
			
		||||
import * as BancorBridge from '../generated-artifacts/BancorBridge.json';
 | 
			
		||||
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
 | 
			
		||||
import * as CreamBridge from '../generated-artifacts/CreamBridge.json';
 | 
			
		||||
import * as CryptoComBridge from '../generated-artifacts/CryptoComBridge.json';
 | 
			
		||||
import * as CurveBridge from '../generated-artifacts/CurveBridge.json';
 | 
			
		||||
import * as DexForwarderBridge from '../generated-artifacts/DexForwarderBridge.json';
 | 
			
		||||
import * as DODOBridge from '../generated-artifacts/DODOBridge.json';
 | 
			
		||||
import * as DydxBridge from '../generated-artifacts/DydxBridge.json';
 | 
			
		||||
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
 | 
			
		||||
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
 | 
			
		||||
@@ -16,28 +23,47 @@ 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 IBalancerPool from '../generated-artifacts/IBalancerPool.json';
 | 
			
		||||
import * as IBancorNetwork from '../generated-artifacts/IBancorNetwork.json';
 | 
			
		||||
import * as IChai from '../generated-artifacts/IChai.json';
 | 
			
		||||
import * as ICurve from '../generated-artifacts/ICurve.json';
 | 
			
		||||
import * as IDydx from '../generated-artifacts/IDydx.json';
 | 
			
		||||
import * as IDydxBridge from '../generated-artifacts/IDydxBridge.json';
 | 
			
		||||
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
 | 
			
		||||
import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json';
 | 
			
		||||
import * as IGasToken from '../generated-artifacts/IGasToken.json';
 | 
			
		||||
import * as IKyberNetworkProxy from '../generated-artifacts/IKyberNetworkProxy.json';
 | 
			
		||||
import * as IMooniswap from '../generated-artifacts/IMooniswap.json';
 | 
			
		||||
import * as IMStable from '../generated-artifacts/IMStable.json';
 | 
			
		||||
import * as IShell from '../generated-artifacts/IShell.json';
 | 
			
		||||
import * as IUniswapExchange from '../generated-artifacts/IUniswapExchange.json';
 | 
			
		||||
import * as IUniswapExchangeFactory from '../generated-artifacts/IUniswapExchangeFactory.json';
 | 
			
		||||
import * as IUniswapV2Router01 from '../generated-artifacts/IUniswapV2Router01.json';
 | 
			
		||||
import * as KyberBridge from '../generated-artifacts/KyberBridge.json';
 | 
			
		||||
import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json';
 | 
			
		||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
 | 
			
		||||
import * as MixinGasToken from '../generated-artifacts/MixinGasToken.json';
 | 
			
		||||
import * as MooniswapBridge from '../generated-artifacts/MooniswapBridge.json';
 | 
			
		||||
import * as MStableBridge from '../generated-artifacts/MStableBridge.json';
 | 
			
		||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
import * as Ownable from '../generated-artifacts/Ownable.json';
 | 
			
		||||
import * as ShellBridge from '../generated-artifacts/ShellBridge.json';
 | 
			
		||||
import * as SnowSwapBridge from '../generated-artifacts/SnowSwapBridge.json';
 | 
			
		||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
 | 
			
		||||
import * as SushiSwapBridge from '../generated-artifacts/SushiSwapBridge.json';
 | 
			
		||||
import * as SwerveBridge from '../generated-artifacts/SwerveBridge.json';
 | 
			
		||||
import * as TestBancorBridge from '../generated-artifacts/TestBancorBridge.json';
 | 
			
		||||
import * as TestChaiBridge from '../generated-artifacts/TestChaiBridge.json';
 | 
			
		||||
import * as TestDexForwarderBridge from '../generated-artifacts/TestDexForwarderBridge.json';
 | 
			
		||||
import * as TestDydxBridge from '../generated-artifacts/TestDydxBridge.json';
 | 
			
		||||
import * as TestERC20Bridge from '../generated-artifacts/TestERC20Bridge.json';
 | 
			
		||||
import * as TestEth2DaiBridge from '../generated-artifacts/TestEth2DaiBridge.json';
 | 
			
		||||
import * as TestKyberBridge from '../generated-artifacts/TestKyberBridge.json';
 | 
			
		||||
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
 | 
			
		||||
import * as TestUniswapBridge from '../generated-artifacts/TestUniswapBridge.json';
 | 
			
		||||
import * as TestUniswapV2Bridge from '../generated-artifacts/TestUniswapV2Bridge.json';
 | 
			
		||||
import * as UniswapBridge from '../generated-artifacts/UniswapBridge.json';
 | 
			
		||||
import * as UniswapV2Bridge from '../generated-artifacts/UniswapV2Bridge.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
@@ -48,28 +74,54 @@ export const artifacts = {
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
			
		||||
    BalancerBridge: BalancerBridge as ContractArtifact,
 | 
			
		||||
    BancorBridge: BancorBridge as ContractArtifact,
 | 
			
		||||
    ChaiBridge: ChaiBridge as ContractArtifact,
 | 
			
		||||
    CreamBridge: CreamBridge as ContractArtifact,
 | 
			
		||||
    CryptoComBridge: CryptoComBridge as ContractArtifact,
 | 
			
		||||
    CurveBridge: CurveBridge as ContractArtifact,
 | 
			
		||||
    DODOBridge: DODOBridge as ContractArtifact,
 | 
			
		||||
    DexForwarderBridge: DexForwarderBridge as ContractArtifact,
 | 
			
		||||
    DydxBridge: DydxBridge as ContractArtifact,
 | 
			
		||||
    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
			
		||||
    KyberBridge: KyberBridge as ContractArtifact,
 | 
			
		||||
    MStableBridge: MStableBridge as ContractArtifact,
 | 
			
		||||
    MixinGasToken: MixinGasToken as ContractArtifact,
 | 
			
		||||
    MooniswapBridge: MooniswapBridge as ContractArtifact,
 | 
			
		||||
    ShellBridge: ShellBridge as ContractArtifact,
 | 
			
		||||
    SnowSwapBridge: SnowSwapBridge as ContractArtifact,
 | 
			
		||||
    SushiSwapBridge: SushiSwapBridge as ContractArtifact,
 | 
			
		||||
    SwerveBridge: SwerveBridge as ContractArtifact,
 | 
			
		||||
    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
			
		||||
    UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
			
		||||
    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IBalancerPool: IBalancerPool as ContractArtifact,
 | 
			
		||||
    IBancorNetwork: IBancorNetwork as ContractArtifact,
 | 
			
		||||
    IChai: IChai as ContractArtifact,
 | 
			
		||||
    ICurve: ICurve as ContractArtifact,
 | 
			
		||||
    IDydx: IDydx as ContractArtifact,
 | 
			
		||||
    IDydxBridge: IDydxBridge as ContractArtifact,
 | 
			
		||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
			
		||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
			
		||||
    IGasToken: IGasToken as ContractArtifact,
 | 
			
		||||
    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
			
		||||
    IMStable: IMStable as ContractArtifact,
 | 
			
		||||
    IMooniswap: IMooniswap as ContractArtifact,
 | 
			
		||||
    IShell: IShell as ContractArtifact,
 | 
			
		||||
    IUniswapExchange: IUniswapExchange as ContractArtifact,
 | 
			
		||||
    IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact,
 | 
			
		||||
    IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
 | 
			
		||||
    TestBancorBridge: TestBancorBridge as ContractArtifact,
 | 
			
		||||
    TestChaiBridge: TestChaiBridge as ContractArtifact,
 | 
			
		||||
    TestDexForwarderBridge: TestDexForwarderBridge as ContractArtifact,
 | 
			
		||||
    TestDydxBridge: TestDydxBridge as ContractArtifact,
 | 
			
		||||
    TestERC20Bridge: TestERC20Bridge as ContractArtifact,
 | 
			
		||||
    TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
 | 
			
		||||
    TestKyberBridge: TestKyberBridge as ContractArtifact,
 | 
			
		||||
    TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
 | 
			
		||||
    TestUniswapBridge: TestUniswapBridge as ContractArtifact,
 | 
			
		||||
    TestUniswapV2Bridge: TestUniswapV2Bridge as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								contracts/asset-proxy/src/asset_data.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								contracts/asset-proxy/src/asset_data.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { BigNumber, hexUtils } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { IAssetDataContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
const assetDataIface = new IAssetDataContract('0x0000000000000000000000000000000000000000', { isEIP1193: true } as any);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the proxy ID from encoded asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function getAssetDataProxyId(encoded: string): AssetProxyId {
 | 
			
		||||
    // tslint:disable-next-line: no-unnecessary-type-assertion
 | 
			
		||||
    return hexUtils.slice(encoded, 0, 4) as AssetProxyId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode ERC20 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeERC20AssetData(encoded: string): string {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<string>('ERC20Token', encoded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode ERC721 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeERC721AssetData(encoded: string): [string, BigNumber] {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<[string, BigNumber]>('ERC721Token', encoded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode ERC1155 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeERC1155AssetData(encoded: string): [string, BigNumber[], BigNumber[], string] {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<[string, BigNumber[], BigNumber[], string]>(
 | 
			
		||||
        'ERC1155Assets',
 | 
			
		||||
        encoded,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode MultiAsset asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeMultiAssetData(encoded: string): [BigNumber[], string[]] {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<[BigNumber[], string[]]>('MultiAsset', encoded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode StaticCall asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeStaticCallAssetData(encoded: string): [string, string, string] {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('StaticCall', encoded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode ERC20Bridge asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeERC20BridgeAssetData(encoded: string): [string, string, string] {
 | 
			
		||||
    return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('ERC20Bridge', encoded);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode ERC20 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeERC20AssetData(tokenAddress: string): string {
 | 
			
		||||
    return assetDataIface.ERC20Token(tokenAddress).getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode ERC721 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
 | 
			
		||||
    return assetDataIface.ERC721Token(tokenAddress, tokenId).getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode ERC1155 asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeERC1155AssetData(
 | 
			
		||||
    tokenAddress: string,
 | 
			
		||||
    tokenIds: BigNumber[],
 | 
			
		||||
    values: BigNumber[],
 | 
			
		||||
    callbackData: string,
 | 
			
		||||
): string {
 | 
			
		||||
    return assetDataIface.ERC1155Assets(tokenAddress, tokenIds, values, callbackData).getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode MultiAsset asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeMultiAssetData(values: BigNumber[], nestedAssetData: string[]): string {
 | 
			
		||||
    return assetDataIface.MultiAsset(values, nestedAssetData).getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode StaticCall asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeStaticCallAssetData(
 | 
			
		||||
    staticCallTargetAddress: string,
 | 
			
		||||
    staticCallData: string,
 | 
			
		||||
    expectedReturnDataHash: string,
 | 
			
		||||
): string {
 | 
			
		||||
    return assetDataIface
 | 
			
		||||
        .StaticCall(staticCallTargetAddress, staticCallData, expectedReturnDataHash)
 | 
			
		||||
        .getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encode ERC20Bridge asset data.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeERC20BridgeAssetData(tokenAddress: string, bridgeAddress: string, bridgeData: string): string {
 | 
			
		||||
    return assetDataIface.ERC20Bridge(tokenAddress, bridgeAddress, bridgeData).getABIEncodedTransactionData();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								contracts/asset-proxy/src/dex_forwarder_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								contracts/asset-proxy/src/dex_forwarder_bridge.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
import { AbiEncoder, BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
export interface DexForwarderBridgeCall {
 | 
			
		||||
    target: string;
 | 
			
		||||
    inputTokenAmount: BigNumber;
 | 
			
		||||
    outputTokenAmount: BigNumber;
 | 
			
		||||
    bridgeData: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface DexForwaderBridgeData {
 | 
			
		||||
    inputToken: string;
 | 
			
		||||
    calls: DexForwarderBridgeCall[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const dexForwarderBridgeDataEncoder = AbiEncoder.create([
 | 
			
		||||
    { name: 'inputToken', type: 'address' },
 | 
			
		||||
    {
 | 
			
		||||
        name: 'calls',
 | 
			
		||||
        type: 'tuple[]',
 | 
			
		||||
        components: [
 | 
			
		||||
            { name: 'target', type: 'address' },
 | 
			
		||||
            { name: 'inputTokenAmount', type: 'uint256' },
 | 
			
		||||
            { name: 'outputTokenAmount', type: 'uint256' },
 | 
			
		||||
            { name: 'bridgeData', type: 'bytes' },
 | 
			
		||||
        ],
 | 
			
		||||
    },
 | 
			
		||||
]);
 | 
			
		||||
@@ -5,9 +5,9 @@ export enum DydxBridgeActionType {
 | 
			
		||||
    Withdraw,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface DydxBrigeAction {
 | 
			
		||||
export interface DydxBridgeAction {
 | 
			
		||||
    actionType: DydxBridgeActionType;
 | 
			
		||||
    accountId: BigNumber;
 | 
			
		||||
    accountIdx: BigNumber;
 | 
			
		||||
    marketId: BigNumber;
 | 
			
		||||
    conversionRateNumerator: BigNumber;
 | 
			
		||||
    conversionRateDenominator: BigNumber;
 | 
			
		||||
@@ -15,7 +15,7 @@ export interface DydxBrigeAction {
 | 
			
		||||
 | 
			
		||||
export interface DydxBridgeData {
 | 
			
		||||
    accountNumbers: BigNumber[];
 | 
			
		||||
    actions: DydxBrigeAction[];
 | 
			
		||||
    actions: DydxBridgeAction[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const dydxBridgeDataEncoder = AbiEncoder.create([
 | 
			
		||||
@@ -29,7 +29,7 @@ export const dydxBridgeDataEncoder = AbiEncoder.create([
 | 
			
		||||
                type: 'tuple[]',
 | 
			
		||||
                components: [
 | 
			
		||||
                    { name: 'actionType', type: 'uint8' },
 | 
			
		||||
                    { name: 'accountId', type: 'uint256' },
 | 
			
		||||
                    { name: 'accountIdx', type: 'uint256' },
 | 
			
		||||
                    { name: 'marketId', type: 'uint256' },
 | 
			
		||||
                    { name: 'conversionRateNumerator', type: 'uint256' },
 | 
			
		||||
                    { name: 'conversionRateDenominator', type: 'uint256' },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
    constants,
 | 
			
		||||
@@ -15,7 +14,7 @@ import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC1155ProxyContract, IAssetProxyContract } from './wrappers';
 | 
			
		||||
import { ERC1155ProxyContract, IAssetDataContract, IAssetProxyContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
export class ERC1155ProxyWrapper {
 | 
			
		||||
    private readonly _tokenOwnerAddresses: string[];
 | 
			
		||||
@@ -28,7 +27,7 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
    private readonly _logDecoder: LogDecoder;
 | 
			
		||||
    private readonly _dummyTokenWrappers: Erc1155Wrapper[];
 | 
			
		||||
    private readonly _assetProxyInterface: IAssetProxyContract;
 | 
			
		||||
    private readonly _devUtils: DevUtilsContract;
 | 
			
		||||
    private readonly _assetDataInterface: IAssetDataContract;
 | 
			
		||||
    private _proxyContract?: ERC1155ProxyContract;
 | 
			
		||||
    private _proxyIdIfExists?: string;
 | 
			
		||||
    private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
 | 
			
		||||
@@ -40,7 +39,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._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._fungibleTokenIds = [];
 | 
			
		||||
@@ -113,9 +112,9 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? await this._devUtils
 | 
			
		||||
                      .encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .callAsync()
 | 
			
		||||
                ? this._assetDataInterface
 | 
			
		||||
                      .ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .getABIEncodedTransactionData()
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface
 | 
			
		||||
            .transferFrom(assetData, from, to, valueMultiplier)
 | 
			
		||||
@@ -167,9 +166,9 @@ export class ERC1155ProxyWrapper {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const assetData =
 | 
			
		||||
            assetData_ === undefined
 | 
			
		||||
                ? await this._devUtils
 | 
			
		||||
                      .encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .callAsync()
 | 
			
		||||
                ? this._assetDataInterface
 | 
			
		||||
                      .ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                      .getABIEncodedTransactionData()
 | 
			
		||||
                : assetData_;
 | 
			
		||||
        const data = this._assetProxyInterface
 | 
			
		||||
            .transferFrom(assetData, from, to, valueMultiplier)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
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 { BigNumber } from '@0x/utils';
 | 
			
		||||
@@ -7,14 +6,14 @@ import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { ERC20ProxyContract } from './wrappers';
 | 
			
		||||
import { ERC20ProxyContract, IAssetDataContract } 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 readonly _assetDataInterface: IAssetDataContract;
 | 
			
		||||
    private _proxyContract?: ERC20ProxyContract;
 | 
			
		||||
    private _proxyIdIfExists?: string;
 | 
			
		||||
    /**
 | 
			
		||||
@@ -29,7 +28,7 @@ export class ERC20Wrapper {
 | 
			
		||||
        this._provider = provider;
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        this._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
    }
 | 
			
		||||
    public async deployDummyTokensAsync(
 | 
			
		||||
        numberToDeploy: number,
 | 
			
		||||
@@ -145,7 +144,7 @@ export class ERC20Wrapper {
 | 
			
		||||
        return tokenAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
 | 
			
		||||
        const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData(assetData).callAsync(); // tslint:disable-line:no-unused-variable
 | 
			
		||||
        const tokenAddress = this._assetDataInterface.getABIDecodedTransactionData<string>('ERC20Token', assetData); // 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`);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,24 @@
 | 
			
		||||
export { artifacts } from './artifacts';
 | 
			
		||||
export {
 | 
			
		||||
    BalancerBridgeContract,
 | 
			
		||||
    ChaiBridgeContract,
 | 
			
		||||
    ERC1155ProxyContract,
 | 
			
		||||
    ERC20BridgeProxyContract,
 | 
			
		||||
    ERC20ProxyContract,
 | 
			
		||||
    ERC721ProxyContract,
 | 
			
		||||
    Eth2DaiBridgeContract,
 | 
			
		||||
    DydxBridgeContract,
 | 
			
		||||
    TestDydxBridgeContract,
 | 
			
		||||
    IAssetDataContract,
 | 
			
		||||
    IAssetProxyContract,
 | 
			
		||||
    IChaiContract,
 | 
			
		||||
    IDydxContract,
 | 
			
		||||
    KyberBridgeContract,
 | 
			
		||||
    MultiAssetProxyContract,
 | 
			
		||||
    StaticCallProxyContract,
 | 
			
		||||
    TestDydxBridgeContract,
 | 
			
		||||
    TestStaticCallTargetContract,
 | 
			
		||||
    UniswapBridgeContract,
 | 
			
		||||
    KyberBridgeContract,
 | 
			
		||||
    ChaiBridgeContract,
 | 
			
		||||
    IChaiContract,
 | 
			
		||||
    DexForwarderBridgeContract,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
export { ERC20Wrapper } from './erc20_wrapper';
 | 
			
		||||
@@ -24,6 +27,7 @@ export { ERC1155ProxyWrapper } from './erc1155_proxy_wrapper';
 | 
			
		||||
export { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
 | 
			
		||||
export { DummyERC20TokenContract } from '@0x/contracts-erc20';
 | 
			
		||||
export { DummyERC721TokenContract } from '@0x/contracts-erc721';
 | 
			
		||||
export { AssetProxyId } from '@0x/types';
 | 
			
		||||
export {
 | 
			
		||||
    ERC1155HoldingsByOwner,
 | 
			
		||||
    ERC20BalancesByOwner,
 | 
			
		||||
@@ -54,6 +58,7 @@ export {
 | 
			
		||||
    OutputField,
 | 
			
		||||
    ParamDescription,
 | 
			
		||||
    EvmBytecodeOutput,
 | 
			
		||||
    EvmBytecodeOutputLinkReferences,
 | 
			
		||||
    AbiDefinition,
 | 
			
		||||
    FunctionAbi,
 | 
			
		||||
    EventAbi,
 | 
			
		||||
@@ -67,4 +72,22 @@ export {
 | 
			
		||||
    TupleDataItem,
 | 
			
		||||
    StateMutability,
 | 
			
		||||
} from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    decodeERC1155AssetData,
 | 
			
		||||
    decodeERC20AssetData,
 | 
			
		||||
    decodeERC20BridgeAssetData,
 | 
			
		||||
    decodeERC721AssetData,
 | 
			
		||||
    decodeMultiAssetData,
 | 
			
		||||
    decodeStaticCallAssetData,
 | 
			
		||||
    encodeERC1155AssetData,
 | 
			
		||||
    encodeERC20AssetData,
 | 
			
		||||
    encodeERC20BridgeAssetData,
 | 
			
		||||
    encodeERC721AssetData,
 | 
			
		||||
    encodeMultiAssetData,
 | 
			
		||||
    encodeStaticCallAssetData,
 | 
			
		||||
    getAssetDataProxyId,
 | 
			
		||||
} from './asset_data';
 | 
			
		||||
 | 
			
		||||
export * from './dydx_bridge_encoder';
 | 
			
		||||
export * from './dex_forwarder_bridge';
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,14 @@
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/balancer_bridge';
 | 
			
		||||
export * from '../generated-wrappers/bancor_bridge';
 | 
			
		||||
export * from '../generated-wrappers/chai_bridge';
 | 
			
		||||
export * from '../generated-wrappers/cream_bridge';
 | 
			
		||||
export * from '../generated-wrappers/crypto_com_bridge';
 | 
			
		||||
export * from '../generated-wrappers/curve_bridge';
 | 
			
		||||
export * from '../generated-wrappers/d_o_d_o_bridge';
 | 
			
		||||
export * from '../generated-wrappers/dex_forwarder_bridge';
 | 
			
		||||
export * from '../generated-wrappers/dydx_bridge';
 | 
			
		||||
export * from '../generated-wrappers/erc1155_proxy';
 | 
			
		||||
export * from '../generated-wrappers/erc20_bridge_proxy';
 | 
			
		||||
@@ -14,25 +21,44 @@ 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_balancer_pool';
 | 
			
		||||
export * from '../generated-wrappers/i_bancor_network';
 | 
			
		||||
export * from '../generated-wrappers/i_chai';
 | 
			
		||||
export * from '../generated-wrappers/i_curve';
 | 
			
		||||
export * from '../generated-wrappers/i_dydx';
 | 
			
		||||
export * from '../generated-wrappers/i_dydx_bridge';
 | 
			
		||||
export * from '../generated-wrappers/i_erc20_bridge';
 | 
			
		||||
export * from '../generated-wrappers/i_eth2_dai';
 | 
			
		||||
export * from '../generated-wrappers/i_gas_token';
 | 
			
		||||
export * from '../generated-wrappers/i_kyber_network_proxy';
 | 
			
		||||
export * from '../generated-wrappers/i_m_stable';
 | 
			
		||||
export * from '../generated-wrappers/i_mooniswap';
 | 
			
		||||
export * from '../generated-wrappers/i_shell';
 | 
			
		||||
export * from '../generated-wrappers/i_uniswap_exchange';
 | 
			
		||||
export * from '../generated-wrappers/i_uniswap_exchange_factory';
 | 
			
		||||
export * from '../generated-wrappers/i_uniswap_v2_router01';
 | 
			
		||||
export * from '../generated-wrappers/kyber_bridge';
 | 
			
		||||
export * from '../generated-wrappers/m_stable_bridge';
 | 
			
		||||
export * from '../generated-wrappers/mixin_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../generated-wrappers/mixin_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/mixin_gas_token';
 | 
			
		||||
export * from '../generated-wrappers/mooniswap_bridge';
 | 
			
		||||
export * from '../generated-wrappers/multi_asset_proxy';
 | 
			
		||||
export * from '../generated-wrappers/ownable';
 | 
			
		||||
export * from '../generated-wrappers/shell_bridge';
 | 
			
		||||
export * from '../generated-wrappers/snow_swap_bridge';
 | 
			
		||||
export * from '../generated-wrappers/static_call_proxy';
 | 
			
		||||
export * from '../generated-wrappers/sushi_swap_bridge';
 | 
			
		||||
export * from '../generated-wrappers/swerve_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_bancor_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_chai_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_dex_forwarder_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_dydx_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_erc20_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_eth2_dai_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_kyber_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_static_call_target';
 | 
			
		||||
export * from '../generated-wrappers/test_uniswap_bridge';
 | 
			
		||||
export * from '../generated-wrappers/test_uniswap_v2_bridge';
 | 
			
		||||
export * from '../generated-wrappers/uniswap_bridge';
 | 
			
		||||
export * from '../generated-wrappers/uniswap_v2_bridge';
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,14 @@
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as BalancerBridge from '../test/generated-artifacts/BalancerBridge.json';
 | 
			
		||||
import * as BancorBridge from '../test/generated-artifacts/BancorBridge.json';
 | 
			
		||||
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
 | 
			
		||||
import * as CreamBridge from '../test/generated-artifacts/CreamBridge.json';
 | 
			
		||||
import * as CryptoComBridge from '../test/generated-artifacts/CryptoComBridge.json';
 | 
			
		||||
import * as CurveBridge from '../test/generated-artifacts/CurveBridge.json';
 | 
			
		||||
import * as DexForwarderBridge from '../test/generated-artifacts/DexForwarderBridge.json';
 | 
			
		||||
import * as DODOBridge from '../test/generated-artifacts/DODOBridge.json';
 | 
			
		||||
import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
 | 
			
		||||
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
 | 
			
		||||
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
 | 
			
		||||
@@ -16,28 +23,47 @@ 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 IBalancerPool from '../test/generated-artifacts/IBalancerPool.json';
 | 
			
		||||
import * as IBancorNetwork from '../test/generated-artifacts/IBancorNetwork.json';
 | 
			
		||||
import * as IChai from '../test/generated-artifacts/IChai.json';
 | 
			
		||||
import * as ICurve from '../test/generated-artifacts/ICurve.json';
 | 
			
		||||
import * as IDydx from '../test/generated-artifacts/IDydx.json';
 | 
			
		||||
import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
 | 
			
		||||
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
			
		||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
			
		||||
import * as IGasToken from '../test/generated-artifacts/IGasToken.json';
 | 
			
		||||
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
 | 
			
		||||
import * as IMooniswap from '../test/generated-artifacts/IMooniswap.json';
 | 
			
		||||
import * as IMStable from '../test/generated-artifacts/IMStable.json';
 | 
			
		||||
import * as IShell from '../test/generated-artifacts/IShell.json';
 | 
			
		||||
import * as IUniswapExchange from '../test/generated-artifacts/IUniswapExchange.json';
 | 
			
		||||
import * as IUniswapExchangeFactory from '../test/generated-artifacts/IUniswapExchangeFactory.json';
 | 
			
		||||
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
 | 
			
		||||
import * as KyberBridge from '../test/generated-artifacts/KyberBridge.json';
 | 
			
		||||
import * as MixinAssetProxyDispatcher from '../test/generated-artifacts/MixinAssetProxyDispatcher.json';
 | 
			
		||||
import * as MixinAuthorizable from '../test/generated-artifacts/MixinAuthorizable.json';
 | 
			
		||||
import * as MixinGasToken from '../test/generated-artifacts/MixinGasToken.json';
 | 
			
		||||
import * as MooniswapBridge from '../test/generated-artifacts/MooniswapBridge.json';
 | 
			
		||||
import * as MStableBridge from '../test/generated-artifacts/MStableBridge.json';
 | 
			
		||||
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
import * as Ownable from '../test/generated-artifacts/Ownable.json';
 | 
			
		||||
import * as ShellBridge from '../test/generated-artifacts/ShellBridge.json';
 | 
			
		||||
import * as SnowSwapBridge from '../test/generated-artifacts/SnowSwapBridge.json';
 | 
			
		||||
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
 | 
			
		||||
import * as SushiSwapBridge from '../test/generated-artifacts/SushiSwapBridge.json';
 | 
			
		||||
import * as SwerveBridge from '../test/generated-artifacts/SwerveBridge.json';
 | 
			
		||||
import * as TestBancorBridge from '../test/generated-artifacts/TestBancorBridge.json';
 | 
			
		||||
import * as TestChaiBridge from '../test/generated-artifacts/TestChaiBridge.json';
 | 
			
		||||
import * as TestDexForwarderBridge from '../test/generated-artifacts/TestDexForwarderBridge.json';
 | 
			
		||||
import * as TestDydxBridge from '../test/generated-artifacts/TestDydxBridge.json';
 | 
			
		||||
import * as TestERC20Bridge from '../test/generated-artifacts/TestERC20Bridge.json';
 | 
			
		||||
import * as TestEth2DaiBridge from '../test/generated-artifacts/TestEth2DaiBridge.json';
 | 
			
		||||
import * as TestKyberBridge from '../test/generated-artifacts/TestKyberBridge.json';
 | 
			
		||||
import * as TestStaticCallTarget from '../test/generated-artifacts/TestStaticCallTarget.json';
 | 
			
		||||
import * as TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridge.json';
 | 
			
		||||
import * as TestUniswapV2Bridge from '../test/generated-artifacts/TestUniswapV2Bridge.json';
 | 
			
		||||
import * as UniswapBridge from '../test/generated-artifacts/UniswapBridge.json';
 | 
			
		||||
import * as UniswapV2Bridge from '../test/generated-artifacts/UniswapV2Bridge.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
@@ -48,28 +74,54 @@ export const artifacts = {
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
			
		||||
    BalancerBridge: BalancerBridge as ContractArtifact,
 | 
			
		||||
    BancorBridge: BancorBridge as ContractArtifact,
 | 
			
		||||
    ChaiBridge: ChaiBridge as ContractArtifact,
 | 
			
		||||
    CreamBridge: CreamBridge as ContractArtifact,
 | 
			
		||||
    CryptoComBridge: CryptoComBridge as ContractArtifact,
 | 
			
		||||
    CurveBridge: CurveBridge as ContractArtifact,
 | 
			
		||||
    DODOBridge: DODOBridge as ContractArtifact,
 | 
			
		||||
    DexForwarderBridge: DexForwarderBridge as ContractArtifact,
 | 
			
		||||
    DydxBridge: DydxBridge as ContractArtifact,
 | 
			
		||||
    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
			
		||||
    KyberBridge: KyberBridge as ContractArtifact,
 | 
			
		||||
    MStableBridge: MStableBridge as ContractArtifact,
 | 
			
		||||
    MixinGasToken: MixinGasToken as ContractArtifact,
 | 
			
		||||
    MooniswapBridge: MooniswapBridge as ContractArtifact,
 | 
			
		||||
    ShellBridge: ShellBridge as ContractArtifact,
 | 
			
		||||
    SnowSwapBridge: SnowSwapBridge as ContractArtifact,
 | 
			
		||||
    SushiSwapBridge: SushiSwapBridge as ContractArtifact,
 | 
			
		||||
    SwerveBridge: SwerveBridge as ContractArtifact,
 | 
			
		||||
    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
			
		||||
    UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
			
		||||
    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IBalancerPool: IBalancerPool as ContractArtifact,
 | 
			
		||||
    IBancorNetwork: IBancorNetwork as ContractArtifact,
 | 
			
		||||
    IChai: IChai as ContractArtifact,
 | 
			
		||||
    ICurve: ICurve as ContractArtifact,
 | 
			
		||||
    IDydx: IDydx as ContractArtifact,
 | 
			
		||||
    IDydxBridge: IDydxBridge as ContractArtifact,
 | 
			
		||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
			
		||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
			
		||||
    IGasToken: IGasToken as ContractArtifact,
 | 
			
		||||
    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
			
		||||
    IMStable: IMStable as ContractArtifact,
 | 
			
		||||
    IMooniswap: IMooniswap as ContractArtifact,
 | 
			
		||||
    IShell: IShell as ContractArtifact,
 | 
			
		||||
    IUniswapExchange: IUniswapExchange as ContractArtifact,
 | 
			
		||||
    IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact,
 | 
			
		||||
    IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
 | 
			
		||||
    TestBancorBridge: TestBancorBridge as ContractArtifact,
 | 
			
		||||
    TestChaiBridge: TestChaiBridge as ContractArtifact,
 | 
			
		||||
    TestDexForwarderBridge: TestDexForwarderBridge as ContractArtifact,
 | 
			
		||||
    TestDydxBridge: TestDydxBridge as ContractArtifact,
 | 
			
		||||
    TestERC20Bridge: TestERC20Bridge as ContractArtifact,
 | 
			
		||||
    TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
 | 
			
		||||
    TestKyberBridge: TestKyberBridge as ContractArtifact,
 | 
			
		||||
    TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
 | 
			
		||||
    TestUniswapBridge: TestUniswapBridge as ContractArtifact,
 | 
			
		||||
    TestUniswapV2Bridge: TestUniswapV2Bridge as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +1,20 @@
 | 
			
		||||
import { chaiSetup, expectTransactionFailedAsync, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { blockchainTests, expect, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { MixinAuthorizableContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('Authorizable', () => {
 | 
			
		||||
blockchainTests.resets('Authorizable', () => {
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let notOwner: string;
 | 
			
		||||
    let address: string;
 | 
			
		||||
    let authorizable: MixinAuthorizableContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        [owner, address, notOwner] = _.slice(accounts, 0, 3);
 | 
			
		||||
        [owner, address, notOwner] = accounts.slice(0, 3);
 | 
			
		||||
        authorizable = await MixinAuthorizableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.MixinAuthorizable,
 | 
			
		||||
            provider,
 | 
			
		||||
@@ -38,20 +23,10 @@ describe('Authorizable', () => {
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('addAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to add an authorized address', async () => {
 | 
			
		||||
@@ -62,20 +37,16 @@ describe('Authorizable', () => {
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to authorize a duplicate address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                RevertReason.TargetAlreadyAuthorized,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.TargetAlreadyAuthorized);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('removeAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
@@ -86,12 +57,8 @@ describe('Authorizable', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddress(address).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.TargetNotAuthorized,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -99,33 +66,27 @@ describe('Authorizable', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: notOwner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.OnlyContractOwner,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable
 | 
			
		||||
                .removeAuthorizedAddressAtIndex(address, index)
 | 
			
		||||
                .sendTransactionAsync({ from: notOwner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if index is >= authorities.length', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(1);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.IndexOutOfBounds,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable
 | 
			
		||||
                .removeAuthorizedAddressAtIndex(address, index)
 | 
			
		||||
                .sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.IndexOutOfBounds);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.TargetNotAuthorized,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable
 | 
			
		||||
                .removeAuthorizedAddressAtIndex(address, index)
 | 
			
		||||
                .sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if address at index does not match target', async () => {
 | 
			
		||||
@@ -134,12 +95,10 @@ describe('Authorizable', () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const address1Index = new BigNumber(0);
 | 
			
		||||
            return expectTransactionFailedAsync(
 | 
			
		||||
                authorizable.removeAuthorizedAddressAtIndex(address2, address1Index).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
                RevertReason.AuthorizedAddressMismatch,
 | 
			
		||||
            );
 | 
			
		||||
            const tx = authorizable
 | 
			
		||||
                .removeAuthorizedAddressAtIndex(address2, address1Index)
 | 
			
		||||
                .sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(RevertReason.AuthorizedAddressMismatch);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										185
									
								
								contracts/asset-proxy/test/bancor_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								contracts/asset-proxy/test/bancor_bridge.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
import {
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    expect,
 | 
			
		||||
    filterLogsToArguments,
 | 
			
		||||
    getRandomInteger,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { AbiEncoder, BigNumber, hexUtils } from '@0x/utils';
 | 
			
		||||
import { DecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestBancorBridgeContract } from './generated-wrappers/test_bancor_bridge';
 | 
			
		||||
import {
 | 
			
		||||
    TestBancorBridgeConvertByPathInputEventArgs as ConvertByPathArgs,
 | 
			
		||||
    TestBancorBridgeEvents as ContractEvents,
 | 
			
		||||
    TestBancorBridgeTokenApproveEventArgs as TokenApproveArgs,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('Bancor unit tests', env => {
 | 
			
		||||
    const FROM_TOKEN_DECIMALS = 6;
 | 
			
		||||
    const TO_TOKEN_DECIMALS = 18;
 | 
			
		||||
    const FROM_TOKEN_BASE = new BigNumber(10).pow(FROM_TOKEN_DECIMALS);
 | 
			
		||||
    const TO_TOKEN_BASE = new BigNumber(10).pow(TO_TOKEN_DECIMALS);
 | 
			
		||||
    let testContract: TestBancorBridgeContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        testContract = await TestBancorBridgeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestBancorBridge,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isValidSignature()', () => {
 | 
			
		||||
        it('returns success bytes', async () => {
 | 
			
		||||
            const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
 | 
			
		||||
            const result = await testContract
 | 
			
		||||
                .isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('bridgeTransferFrom()', () => {
 | 
			
		||||
        interface TransferFromOpts {
 | 
			
		||||
            tokenAddressesPath: string[];
 | 
			
		||||
            toAddress: string;
 | 
			
		||||
            // Amount to pass into `bridgeTransferFrom()`
 | 
			
		||||
            amount: BigNumber;
 | 
			
		||||
            // Token balance of the bridge.
 | 
			
		||||
            fromTokenBalance: BigNumber;
 | 
			
		||||
            // Router reverts with this reason
 | 
			
		||||
            routerRevertReason: string;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        interface TransferFromResult {
 | 
			
		||||
            opts: TransferFromOpts;
 | 
			
		||||
            result: string;
 | 
			
		||||
            logs: DecodedLogs;
 | 
			
		||||
            blocktime: number;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts {
 | 
			
		||||
            const amount = getRandomInteger(1, TO_TOKEN_BASE.times(100));
 | 
			
		||||
            return {
 | 
			
		||||
                tokenAddressesPath: Array(3).fill(constants.NULL_ADDRESS),
 | 
			
		||||
                amount,
 | 
			
		||||
                toAddress: randomAddress(),
 | 
			
		||||
                fromTokenBalance: getRandomInteger(1, FROM_TOKEN_BASE.times(100)),
 | 
			
		||||
                routerRevertReason: '',
 | 
			
		||||
                ...opts,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const bridgeDataEncoder = AbiEncoder.create('(address[], address)');
 | 
			
		||||
 | 
			
		||||
        async function transferFromAsync(opts?: Partial<TransferFromOpts>): Promise<TransferFromResult> {
 | 
			
		||||
            const _opts = createTransferFromOpts(opts);
 | 
			
		||||
 | 
			
		||||
            for (let i = 0; i < _opts.tokenAddressesPath.length; i++) {
 | 
			
		||||
                const createFromTokenFn = testContract.createToken(_opts.tokenAddressesPath[i]);
 | 
			
		||||
                _opts.tokenAddressesPath[i] = await createFromTokenFn.callAsync();
 | 
			
		||||
                await createFromTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set the token balance for the token we're converting from.
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setTokenBalance(_opts.tokenAddressesPath[0], _opts.fromTokenBalance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
 | 
			
		||||
            // Set revert reason for the router.
 | 
			
		||||
            await testContract.setNetworkRevertReason(_opts.routerRevertReason).awaitTransactionSuccessAsync();
 | 
			
		||||
 | 
			
		||||
            // Call bridgeTransferFrom().
 | 
			
		||||
            const bridgeTransferFromFn = testContract.bridgeTransferFrom(
 | 
			
		||||
                // Output token
 | 
			
		||||
                _opts.tokenAddressesPath[_opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                // Random maker address.
 | 
			
		||||
                randomAddress(),
 | 
			
		||||
                // Recipient address.
 | 
			
		||||
                _opts.toAddress,
 | 
			
		||||
                // Transfer amount.
 | 
			
		||||
                _opts.amount,
 | 
			
		||||
                // ABI-encode the input token address as the bridge data.
 | 
			
		||||
                bridgeDataEncoder.encode([
 | 
			
		||||
                    _opts.tokenAddressesPath,
 | 
			
		||||
                    await testContract.getNetworkAddress().callAsync(),
 | 
			
		||||
                ]),
 | 
			
		||||
            );
 | 
			
		||||
            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),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        it('returns magic bytes on success', async () => {
 | 
			
		||||
            const { result } = await transferFromAsync();
 | 
			
		||||
            expect(result).to.eq(AssetProxyId.ERC20Bridge);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('token -> token', async () => {
 | 
			
		||||
            it('calls BancorNetwork.convertByPath()', async () => {
 | 
			
		||||
                const { opts, result, logs } = await transferFromAsync();
 | 
			
		||||
                expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
 | 
			
		||||
                const transfers = filterLogsToArguments<ConvertByPathArgs>(logs, ContractEvents.ConvertByPathInput);
 | 
			
		||||
 | 
			
		||||
                expect(transfers.length).to.eq(1);
 | 
			
		||||
                expect(transfers[0].toTokenAddress).to.eq(
 | 
			
		||||
                    opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                    'output token address',
 | 
			
		||||
                );
 | 
			
		||||
                expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
 | 
			
		||||
                expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
 | 
			
		||||
                expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
 | 
			
		||||
                expect(transfers[0].feeRecipient).to.eq(constants.NULL_ADDRESS);
 | 
			
		||||
                expect(transfers[0].feeAmount).to.bignumber.eq(new BigNumber(0));
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token', async () => {
 | 
			
		||||
                const { logs } = await transferFromAsync();
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const networkAddress = await testContract.getNetworkAddress().callAsync();
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(networkAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the router fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = transferFromAsync({
 | 
			
		||||
                    routerRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        describe('token -> token -> token', async () => {
 | 
			
		||||
            it('calls BancorNetwork.convertByPath()', async () => {
 | 
			
		||||
                const { opts, result, logs } = await transferFromAsync({
 | 
			
		||||
                    tokenAddressesPath: Array(5).fill(constants.NULL_ADDRESS),
 | 
			
		||||
                });
 | 
			
		||||
                expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
 | 
			
		||||
                const transfers = filterLogsToArguments<ConvertByPathArgs>(logs, ContractEvents.ConvertByPathInput);
 | 
			
		||||
 | 
			
		||||
                expect(transfers.length).to.eq(1);
 | 
			
		||||
                expect(transfers[0].toTokenAddress).to.eq(
 | 
			
		||||
                    opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                    'output token address',
 | 
			
		||||
                );
 | 
			
		||||
                expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
 | 
			
		||||
                expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
 | 
			
		||||
                expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
 | 
			
		||||
                expect(transfers[0].feeRecipient).to.eq(constants.NULL_ADDRESS);
 | 
			
		||||
                expect(transfers[0].feeAmount).to.bignumber.eq(new BigNumber(0));
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -17,14 +17,14 @@ blockchainTests.resets('DydxBridge unit tests', env => {
 | 
			
		||||
    const notAuthorized = '0x0000000000000000000000000000000000000001';
 | 
			
		||||
    const defaultDepositAction = {
 | 
			
		||||
        actionType: DydxBridgeActionType.Deposit,
 | 
			
		||||
        accountId: constants.ZERO_AMOUNT,
 | 
			
		||||
        accountIdx: constants.ZERO_AMOUNT,
 | 
			
		||||
        marketId,
 | 
			
		||||
        conversionRateNumerator: constants.ZERO_AMOUNT,
 | 
			
		||||
        conversionRateDenominator: constants.ZERO_AMOUNT,
 | 
			
		||||
    };
 | 
			
		||||
    const defaultWithdrawAction = {
 | 
			
		||||
        actionType: DydxBridgeActionType.Withdraw,
 | 
			
		||||
        accountId: constants.ZERO_AMOUNT,
 | 
			
		||||
        accountIdx: constants.ZERO_AMOUNT,
 | 
			
		||||
        marketId,
 | 
			
		||||
        conversionRateNumerator: constants.ZERO_AMOUNT,
 | 
			
		||||
        conversionRateDenominator: constants.ZERO_AMOUNT,
 | 
			
		||||
@@ -118,7 +118,7 @@ blockchainTests.resets('DydxBridge unit tests', env => {
 | 
			
		||||
            for (const action of bridgeData.actions) {
 | 
			
		||||
                expectedOperateActionEvents.push({
 | 
			
		||||
                    actionType: action.actionType as number,
 | 
			
		||||
                    accountId: action.accountId,
 | 
			
		||||
                    accountIdx: action.accountIdx,
 | 
			
		||||
                    amountSign: action.actionType === DydxBridgeActionType.Deposit ? true : false,
 | 
			
		||||
                    amountDenomination: weiDenomination,
 | 
			
		||||
                    amountRef: deltaAmountRef,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc1155Artifacts,
 | 
			
		||||
    DummyERC1155ReceiverBatchTokenReceivedEventArgs,
 | 
			
		||||
@@ -63,8 +62,8 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
    // tokens
 | 
			
		||||
    let fungibleTokens: BigNumber[];
 | 
			
		||||
    let nonFungibleTokensOwnedBySpender: BigNumber[];
 | 
			
		||||
    // devUtils for encoding and decoding assetData
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    // IAssetData for encoding and decoding assetData
 | 
			
		||||
    let assetDataContract: IAssetDataContract;
 | 
			
		||||
    // tests
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
@@ -101,8 +100,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 });
 | 
			
		||||
        // set up assetDataContract
 | 
			
		||||
        assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider, { from: owner });
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
@@ -638,14 +637,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const extraData = '0102030405060708091001020304050607080910010203040506070809100102';
 | 
			
		||||
            const assetDataWithExtraData = `${assetData}${extraData}`;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
@@ -745,8 +739,7 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = tokensToTransfer;
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
 | 
			
		||||
            // 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);
 | 
			
		||||
            // hand encode optimized assetData because our tooling (based on LibAssetData.sol/ERC1155Assets) does not use optimized encoding
 | 
			
		||||
            const selector = assetDataContract.getSelector('ERC1155Assets');
 | 
			
		||||
            const assetDataWithoutContractAddress =
 | 
			
		||||
                '0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000';
 | 
			
		||||
@@ -857,14 +850,9 @@ 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 = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const generatedAssetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // remove the function selector and contract address from check, as these change on each test
 | 
			
		||||
            const offsetToTokenIds = 74;
 | 
			
		||||
            const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
 | 
			
		||||
@@ -983,14 +971,9 @@ 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 = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const generatedAssetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // remove the function selector and contract address from check, as these change on each test
 | 
			
		||||
            const offsetToTokenIds = 74;
 | 
			
		||||
            const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
 | 
			
		||||
@@ -1048,14 +1031,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1097,14 +1075,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1150,14 +1123,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1203,14 +1171,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1256,14 +1219,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1310,14 +1268,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1359,14 +1312,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1412,14 +1360,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1461,14 +1404,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            // The asset data we just generated will look like this:
 | 
			
		||||
            // a7cb5fb7
 | 
			
		||||
            // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
 | 
			
		||||
@@ -1514,14 +1452,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
@@ -1547,14 +1480,9 @@ describe('ERC1155Proxy', () => {
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const erc1155ContractAddress = erc1155Wrapper.getContract().address;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeERC1155AssetData(
 | 
			
		||||
                    erc1155ContractAddress,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                )
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataContract
 | 
			
		||||
                .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,8 @@ import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { TestKyberBridgeContract, TestKyberBridgeEvents } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('KyberBridge unit tests', env => {
 | 
			
		||||
// TODO(dorothy-zbornak): Tests need to be updated.
 | 
			
		||||
blockchainTests.resets.skip('KyberBridge unit tests', env => {
 | 
			
		||||
    const KYBER_ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
 | 
			
		||||
    const FROM_TOKEN_DECIMALS = 6;
 | 
			
		||||
    const TO_TOKEN_DECIMALS = 18;
 | 
			
		||||
@@ -115,7 +116,7 @@ blockchainTests.resets('KyberBridge unit tests', env => {
 | 
			
		||||
                // Transfer amount.
 | 
			
		||||
                _opts.amount,
 | 
			
		||||
                // ABI-encode the input token address as the bridge data.
 | 
			
		||||
                hexUtils.leftPad(_opts.fromTokenAddress),
 | 
			
		||||
                hexUtils.concat(hexUtils.leftPad(_opts.fromTokenAddress), hexUtils.leftPad(32), hexUtils.leftPad(0)),
 | 
			
		||||
            );
 | 
			
		||||
            const result = await bridgeTransferFromFn.callAsync();
 | 
			
		||||
            const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc20Artifacts,
 | 
			
		||||
@@ -29,19 +28,24 @@ import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    encodeERC1155AssetData,
 | 
			
		||||
    encodeERC20AssetData,
 | 
			
		||||
    encodeERC721AssetData,
 | 
			
		||||
    encodeMultiAssetData,
 | 
			
		||||
} from '../src/asset_data';
 | 
			
		||||
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
 | 
			
		||||
import { ERC20Wrapper } from '../src/erc20_wrapper';
 | 
			
		||||
import { ERC721Wrapper } from '../src/erc721_wrapper';
 | 
			
		||||
import { ERC1155ProxyContract, ERC20ProxyContract, ERC721ProxyContract } from '../src/wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { IAssetDataContract, IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
 | 
			
		||||
import { IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
const assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
const assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
 | 
			
		||||
// tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
describe('Asset Transfer Proxies', () => {
 | 
			
		||||
@@ -51,7 +55,6 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
    let fromAddress: string;
 | 
			
		||||
    let toAddress: string;
 | 
			
		||||
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    let erc20TokenA: DummyERC20TokenContract;
 | 
			
		||||
    let erc20TokenB: DummyERC20TokenContract;
 | 
			
		||||
    let erc721TokenA: DummyERC721TokenContract;
 | 
			
		||||
@@ -87,7 +90,6 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5));
 | 
			
		||||
 | 
			
		||||
        devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
        erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
			
		||||
 | 
			
		||||
@@ -221,7 +223,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
        describe('transferFrom', () => {
 | 
			
		||||
            it('should successfully transfer tokens', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                // Perform a transfer from fromAddress to toAddress
 | 
			
		||||
                const erc20Balances = await erc20Wrapper.getBalancesAsync();
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
@@ -248,7 +250,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should successfully transfer tokens that do not return a value', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
 | 
			
		||||
                // Perform a transfer from fromAddress to toAddress
 | 
			
		||||
                const initialFromBalance = await noReturnErc20Token.balanceOf(fromAddress).callAsync();
 | 
			
		||||
                const initialToBalance = await noReturnErc20Token.balanceOf(toAddress).callAsync();
 | 
			
		||||
@@ -274,9 +276,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should successfully transfer tokens and ignore extra assetData', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const extraData = '0102030405060708';
 | 
			
		||||
                const encodedAssetData = `${await devUtils
 | 
			
		||||
                    .encodeERC20AssetData(erc20TokenA.address)
 | 
			
		||||
                    .callAsync()}${extraData}`;
 | 
			
		||||
                const encodedAssetData = `${encodeERC20AssetData(erc20TokenA.address)}${extraData}`;
 | 
			
		||||
                // Perform a transfer from fromAddress to toAddress
 | 
			
		||||
                const erc20Balances = await erc20Wrapper.getBalancesAsync();
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
@@ -303,7 +303,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should do nothing if transferring 0 amount of a token', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                // Perform a transfer from fromAddress to toAddress
 | 
			
		||||
                const erc20Balances = await erc20Wrapper.getBalancesAsync();
 | 
			
		||||
                const amount = new BigNumber(0);
 | 
			
		||||
@@ -330,7 +330,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if allowances are too low', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                // Create allowance less than transfer amount. Set allowance on proxy.
 | 
			
		||||
                const allowance = new BigNumber(0);
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
@@ -356,7 +356,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if allowances are too low and token does not return a value', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
 | 
			
		||||
                // Create allowance less than transfer amount. Set allowance on proxy.
 | 
			
		||||
                const allowance = new BigNumber(0);
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
@@ -385,7 +385,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if caller is not authorized', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                // Perform a transfer from fromAddress to toAddress
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
@@ -406,9 +406,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if token returns more than 32 bytes', async () => {
 | 
			
		||||
                // Construct ERC20 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC20AssetData(multipleReturnErc20Token.address)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC20AssetData(multipleReturnErc20Token.address);
 | 
			
		||||
                const amount = new BigNumber(10);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(encodedAssetData, fromAddress, toAddress, amount)
 | 
			
		||||
@@ -452,9 +450,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
        describe('transferFrom', () => {
 | 
			
		||||
            it('should successfully transfer tokens', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -479,9 +475,10 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should successfully transfer tokens and ignore extra assetData', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const extraData = '0102030405060708';
 | 
			
		||||
                const encodedAssetData = `${await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync()}${extraData}`;
 | 
			
		||||
                const encodedAssetData = `${encodeERC721AssetData(
 | 
			
		||||
                    erc721TokenA.address,
 | 
			
		||||
                    erc721AFromTokenId,
 | 
			
		||||
                )}${extraData}`;
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -505,9 +502,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should not call onERC721Received when transferring to a smart contract', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -534,9 +529,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if transferring 0 amount of a token', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -559,9 +552,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if transferring > 1 amount of a token', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -584,9 +575,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if allowances are too low', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -617,9 +606,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
 | 
			
		||||
            it('should revert if caller is not authorized', async () => {
 | 
			
		||||
                // Construct ERC721 asset data
 | 
			
		||||
                const encodedAssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                // Verify pre-condition
 | 
			
		||||
                const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(ownerFromAsset).to.be.equal(fromAddress);
 | 
			
		||||
@@ -663,10 +650,10 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should transfer a single ERC20 token', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const amounts = [erc20Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -691,12 +678,10 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should dispatch an ERC20 transfer when input amount is 0', async () => {
 | 
			
		||||
                const inputAmount = constants.ZERO_AMOUNT;
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const amounts = [erc20Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData];
 | 
			
		||||
                const assetData = assetDataInterface
 | 
			
		||||
                    .MultiAsset(amounts, nestedAssetData)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -721,11 +706,11 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount1 = new BigNumber(10);
 | 
			
		||||
                const erc20Amount2 = new BigNumber(20);
 | 
			
		||||
                const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc20AssetData2 = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const amounts = [erc20Amount1, erc20Amount2];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData1, erc20AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -751,11 +736,11 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount1 = new BigNumber(10);
 | 
			
		||||
                const erc20Amount2 = new BigNumber(20);
 | 
			
		||||
                const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
 | 
			
		||||
                const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
 | 
			
		||||
                const amounts = [erc20Amount1, erc20Amount2];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData1, erc20AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -787,12 +772,10 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should transfer a single ERC721 token', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -812,17 +795,13 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should successfully transfer multiple of the same ERC721 token', async () => {
 | 
			
		||||
                const erc721Balances = await erc721Wrapper.getBalancesAsync();
 | 
			
		||||
                const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
 | 
			
		||||
                const erc721AssetData1 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData2 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const amounts = [erc721Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc721AssetData1, erc721AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -845,17 +824,13 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                expect(newOwnerFromAsset2).to.be.equal(toAddress);
 | 
			
		||||
            });
 | 
			
		||||
            it('should successfully transfer multiple different ERC721 tokens', async () => {
 | 
			
		||||
                const erc721AssetData1 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData2 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const erc721AssetData2 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const amounts = [erc721Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc721AssetData1, erc721AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -893,19 +868,17 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                ];
 | 
			
		||||
                await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
                // encode erc1155 asset data
 | 
			
		||||
                const erc1155AssetData = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract.address,
 | 
			
		||||
                        tokensToTransfer,
 | 
			
		||||
                        valuesToTransfer,
 | 
			
		||||
                        receiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                // encode multi-asset data
 | 
			
		||||
                const multiAssetAmount = new BigNumber(5);
 | 
			
		||||
                const amounts = [valueMultiplier];
 | 
			
		||||
                const nestedAssetData = [erc1155AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -948,19 +921,17 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                ];
 | 
			
		||||
                await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
                // encode erc1155 asset data
 | 
			
		||||
                const erc1155AssetData = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract.address,
 | 
			
		||||
                        tokensToTransfer,
 | 
			
		||||
                        valuesToTransfer,
 | 
			
		||||
                        receiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                // encode multi-asset data
 | 
			
		||||
                const multiAssetAmount = new BigNumber(5);
 | 
			
		||||
                const amounts = [valueMultiplier];
 | 
			
		||||
                const nestedAssetData = [erc1155AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1011,19 +982,17 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                ];
 | 
			
		||||
                await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
                // encode erc1155 asset data
 | 
			
		||||
                const erc1155AssetData = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract.address,
 | 
			
		||||
                        tokensToTransfer,
 | 
			
		||||
                        valuesToTransfer,
 | 
			
		||||
                        receiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                // encode multi-asset data
 | 
			
		||||
                const multiAssetAmount = new BigNumber(1);
 | 
			
		||||
                const amounts = [valueMultiplier];
 | 
			
		||||
                const nestedAssetData = [erc1155AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1050,7 +1019,8 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                ];
 | 
			
		||||
                await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
            });
 | 
			
		||||
            it('should successfully transfer multiple different ERC1155 tokens', async () => {
 | 
			
		||||
            // TODO(dorothy-zbornak): Figure out why this test fails.
 | 
			
		||||
            it.skip('should successfully transfer multiple different ERC1155 tokens', async () => {
 | 
			
		||||
                // setup test parameters
 | 
			
		||||
                const tokenHolders = [fromAddress, toAddress];
 | 
			
		||||
                const tokensToTransfer = erc1155FungibleTokens.slice(0, 1);
 | 
			
		||||
@@ -1067,27 +1037,23 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
                await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
                // encode erc1155 asset data
 | 
			
		||||
                const erc1155AssetData1 = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract.address,
 | 
			
		||||
                        tokensToTransfer,
 | 
			
		||||
                        valuesToTransfer,
 | 
			
		||||
                        receiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData2 = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract2.address,
 | 
			
		||||
                        tokensToTransfer,
 | 
			
		||||
                        valuesToTransfer,
 | 
			
		||||
                        receiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData1 = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                const erc1155AssetData2 = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract2.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                // encode multi-asset data
 | 
			
		||||
                const multiAssetAmount = new BigNumber(5);
 | 
			
		||||
                const amounts = [valueMultiplier, valueMultiplier];
 | 
			
		||||
                const nestedAssetData = [erc1155AssetData1, erc1155AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1115,27 +1081,23 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                // setup test parameters
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const erc1155TokenHolders = [fromAddress, toAddress];
 | 
			
		||||
                const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1);
 | 
			
		||||
                const erc1155ValuesToTransfer = [new BigNumber(25)];
 | 
			
		||||
                const erc1155Amount = new BigNumber(23);
 | 
			
		||||
                const erc1155ReceiverCallbackData = '0x0102030405';
 | 
			
		||||
                const erc1155AssetData = await devUtils
 | 
			
		||||
                    .encodeERC1155AssetData(
 | 
			
		||||
                        erc1155Contract.address,
 | 
			
		||||
                        erc1155TokensToTransfer,
 | 
			
		||||
                        erc1155ValuesToTransfer,
 | 
			
		||||
                        erc1155ReceiverCallbackData,
 | 
			
		||||
                    )
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc1155AssetData = encodeERC1155AssetData(
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    erc1155TokensToTransfer,
 | 
			
		||||
                    erc1155ValuesToTransfer,
 | 
			
		||||
                    erc1155ReceiverCallbackData,
 | 
			
		||||
                );
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount, erc1155Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1187,14 +1149,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1220,20 +1180,17 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                const newOwnerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
 | 
			
		||||
                expect(newOwnerFromAsset).to.be.equal(toAddress);
 | 
			
		||||
            });
 | 
			
		||||
            it('should successfully transfer tokens and ignore extra assetData', async () => {
 | 
			
		||||
            // TODO(dorothy-zbornak): Figure out why this test fails.
 | 
			
		||||
            it.skip('should successfully transfer tokens and ignore extra assetData', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const extraData = '0102030405060708090001020304050607080900010203040506070809000102';
 | 
			
		||||
                const assetData = `${await devUtils
 | 
			
		||||
                    .encodeMultiAssetData(amounts, nestedAssetData)
 | 
			
		||||
                    .callAsync()}${extraData}`;
 | 
			
		||||
                const assetData = `${encodeMultiAssetData(amounts, nestedAssetData)}${extraData}`;
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1263,11 +1220,11 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                const inputAmount = new BigNumber(100);
 | 
			
		||||
                const erc20Amount1 = new BigNumber(10);
 | 
			
		||||
                const erc20Amount2 = new BigNumber(20);
 | 
			
		||||
                const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
 | 
			
		||||
                const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
 | 
			
		||||
                const amounts = [erc20Amount1, erc20Amount2];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData1, erc20AssetData2];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1300,24 +1257,16 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount1 = new BigNumber(10);
 | 
			
		||||
                const erc20Amount2 = new BigNumber(20);
 | 
			
		||||
                const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
 | 
			
		||||
                const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721Balances = await erc721Wrapper.getBalancesAsync();
 | 
			
		||||
                const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
 | 
			
		||||
                const erc721BFromTokenId2 = erc721Balances[fromAddress][erc721TokenB.address][1];
 | 
			
		||||
                const erc721AssetData1 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData2 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData3 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData4 = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
 | 
			
		||||
                const erc721AssetData3 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
 | 
			
		||||
                const erc721AssetData4 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2);
 | 
			
		||||
                const amounts = [erc721Amount, erc20Amount1, erc721Amount, erc20Amount2, erc721Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [
 | 
			
		||||
                    erc721AssetData1,
 | 
			
		||||
@@ -1327,7 +1276,7 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                    erc721AssetData3,
 | 
			
		||||
                    erc721AssetData4,
 | 
			
		||||
                ];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1376,15 +1325,13 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if a single transfer fails', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                // 2 is an invalid erc721 amount
 | 
			
		||||
                const erc721Amount = new BigNumber(2);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1400,16 +1347,14 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if an AssetProxy is not registered', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const invalidProxyId = '0x12345678';
 | 
			
		||||
                const invalidErc721AssetData = `${invalidProxyId}${erc721AssetData.slice(10)}`;
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, invalidErc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1425,13 +1370,11 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1447,10 +1390,10 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if amounts multiplication results in an overflow', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(2).pow(128);
 | 
			
		||||
                const erc20Amount = new BigNumber(2).pow(128);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const amounts = [erc20Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1466,12 +1409,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = '0x123456';
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1487,14 +1430,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if caller is not authorized', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1510,14 +1451,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if asset data overflows beyond the bounds of calldata', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1539,14 +1478,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
            it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => {
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const data = assetProxyInterface
 | 
			
		||||
                    .transferFrom(assetData, fromAddress, toAddress, inputAmount)
 | 
			
		||||
                    .getABIEncodedTransactionData();
 | 
			
		||||
@@ -1569,14 +1506,12 @@ describe('Asset Transfer Proxies', () => {
 | 
			
		||||
                // setup test parameters
 | 
			
		||||
                const inputAmount = new BigNumber(1);
 | 
			
		||||
                const erc20Amount = new BigNumber(10);
 | 
			
		||||
                const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
 | 
			
		||||
                const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
 | 
			
		||||
                const erc721Amount = new BigNumber(1);
 | 
			
		||||
                const erc721AssetData = await devUtils
 | 
			
		||||
                    .encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
 | 
			
		||||
                    .callAsync();
 | 
			
		||||
                const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
 | 
			
		||||
                const amounts = [erc20Amount, erc721Amount];
 | 
			
		||||
                const nestedAssetData = [erc20AssetData, erc721AssetData];
 | 
			
		||||
                const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
 | 
			
		||||
                const assetData = encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
                const extraData = '01';
 | 
			
		||||
                const assetDataWithExtraData = `${assetData}${extraData}`;
 | 
			
		||||
                const badData = assetProxyInterface
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectTransactionFailedAsync,
 | 
			
		||||
    expectTransactionFailedWithoutReasonAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
@@ -16,7 +14,12 @@ import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import { IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from './wrappers';
 | 
			
		||||
import {
 | 
			
		||||
    IAssetDataContract,
 | 
			
		||||
    IAssetProxyContract,
 | 
			
		||||
    StaticCallProxyContract,
 | 
			
		||||
    TestStaticCallTargetContract,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
@@ -27,7 +30,7 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
    let fromAddress: string;
 | 
			
		||||
    let toAddress: string;
 | 
			
		||||
 | 
			
		||||
    let devUtils: DevUtilsContract;
 | 
			
		||||
    let assetDataInterface: IAssetDataContract;
 | 
			
		||||
    let staticCallProxy: IAssetProxyContract;
 | 
			
		||||
    let staticCallTarget: TestStaticCallTargetContract;
 | 
			
		||||
 | 
			
		||||
@@ -46,7 +49,7 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
 | 
			
		||||
        staticCallProxy = new IAssetProxyContract(
 | 
			
		||||
            staticCallProxyWithoutTransferFrom.address,
 | 
			
		||||
            provider,
 | 
			
		||||
@@ -90,9 +93,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        it('should revert if assetData lies outside the bounds of calldata', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const txData = staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
@@ -113,9 +116,10 @@ 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 = (await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync()).slice(0, -128);
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData()
 | 
			
		||||
                .slice(0, -128);
 | 
			
		||||
            const assetDataByteLen = (assetData.length - 2) / 2;
 | 
			
		||||
            expect((assetDataByteLen - 4) % 32).to.equal(0);
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
@@ -125,9 +129,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
 | 
			
		||||
            const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
 | 
			
		||||
            const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
 | 
			
		||||
@@ -144,9 +148,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        it('should revert if the callTarget attempts to write to state', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.updateState().getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
            );
 | 
			
		||||
@@ -154,32 +158,30 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.assertEvenNumber(new BigNumber(1)).getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
                RevertReason.TargetNotEven,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            return expect(
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
 | 
			
		||||
            ).to.revertWith(RevertReason.TargetNotEven);
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if the hash of the output is different than expected expected', async () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
 | 
			
		||||
                RevertReason.UnexpectedStaticCallResult,
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            return expect(
 | 
			
		||||
                staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
 | 
			
		||||
            ).to.revertWith(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 expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
@@ -187,9 +189,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
        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 = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(toAddress, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
@@ -198,9 +200,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
 | 
			
		||||
            const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
@@ -209,9 +211,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            const dynamicInput = '0x0102030405060708';
 | 
			
		||||
            const staticCallData = staticCallTarget.dynamicInputFunction(dynamicInput).getABIEncodedTransactionData();
 | 
			
		||||
            const expectedResultHash = constants.KECCAK256_NULL;
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
@@ -232,9 +234,9 @@ describe('StaticCallProxy', () => {
 | 
			
		||||
            const expectedResultHash = ethUtil.bufferToHex(
 | 
			
		||||
                ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
 | 
			
		||||
            );
 | 
			
		||||
            const assetData = await devUtils
 | 
			
		||||
                .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            const assetData = assetDataInterface
 | 
			
		||||
                .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
 | 
			
		||||
                .getABIEncodedTransactionData();
 | 
			
		||||
            await staticCallProxy
 | 
			
		||||
                .transferFrom(assetData, fromAddress, toAddress, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										216
									
								
								contracts/asset-proxy/test/uniswapv2_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								contracts/asset-proxy/test/uniswapv2_bridge.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,216 @@
 | 
			
		||||
import {
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    expect,
 | 
			
		||||
    filterLogsToArguments,
 | 
			
		||||
    getRandomInteger,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { AssetProxyId } from '@0x/types';
 | 
			
		||||
import { AbiEncoder, BigNumber, hexUtils } from '@0x/utils';
 | 
			
		||||
import { DecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    TestUniswapV2BridgeContract,
 | 
			
		||||
    TestUniswapV2BridgeEvents as ContractEvents,
 | 
			
		||||
    TestUniswapV2BridgeSwapExactTokensForTokensInputEventArgs as SwapExactTokensForTokensArgs,
 | 
			
		||||
    TestUniswapV2BridgeTokenApproveEventArgs as TokenApproveArgs,
 | 
			
		||||
    TestUniswapV2BridgeTokenTransferEventArgs as TokenTransferArgs,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('UniswapV2 unit tests', env => {
 | 
			
		||||
    const FROM_TOKEN_DECIMALS = 6;
 | 
			
		||||
    const TO_TOKEN_DECIMALS = 18;
 | 
			
		||||
    const FROM_TOKEN_BASE = new BigNumber(10).pow(FROM_TOKEN_DECIMALS);
 | 
			
		||||
    const TO_TOKEN_BASE = new BigNumber(10).pow(TO_TOKEN_DECIMALS);
 | 
			
		||||
    let testContract: TestUniswapV2BridgeContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        testContract = await TestUniswapV2BridgeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestUniswapV2Bridge,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isValidSignature()', () => {
 | 
			
		||||
        it('returns success bytes', async () => {
 | 
			
		||||
            const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381';
 | 
			
		||||
            const result = await testContract
 | 
			
		||||
                .isValidSignature(hexUtils.random(), hexUtils.random(_.random(0, 32)))
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('bridgeTransferFrom()', () => {
 | 
			
		||||
        interface TransferFromOpts {
 | 
			
		||||
            tokenAddressesPath: string[];
 | 
			
		||||
            toAddress: string;
 | 
			
		||||
            // Amount to pass into `bridgeTransferFrom()`
 | 
			
		||||
            amount: BigNumber;
 | 
			
		||||
            // Token balance of the bridge.
 | 
			
		||||
            fromTokenBalance: BigNumber;
 | 
			
		||||
            // Router reverts with this reason
 | 
			
		||||
            routerRevertReason: string;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        interface TransferFromResult {
 | 
			
		||||
            opts: TransferFromOpts;
 | 
			
		||||
            result: string;
 | 
			
		||||
            logs: DecodedLogs;
 | 
			
		||||
            blocktime: number;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts {
 | 
			
		||||
            const amount = getRandomInteger(1, TO_TOKEN_BASE.times(100));
 | 
			
		||||
            return {
 | 
			
		||||
                tokenAddressesPath: Array(2).fill(constants.NULL_ADDRESS),
 | 
			
		||||
                amount,
 | 
			
		||||
                toAddress: randomAddress(),
 | 
			
		||||
                fromTokenBalance: getRandomInteger(1, FROM_TOKEN_BASE.times(100)),
 | 
			
		||||
                routerRevertReason: '',
 | 
			
		||||
                ...opts,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const bridgeDataEncoder = AbiEncoder.create('(address[])');
 | 
			
		||||
 | 
			
		||||
        async function transferFromAsync(opts?: Partial<TransferFromOpts>): Promise<TransferFromResult> {
 | 
			
		||||
            const _opts = createTransferFromOpts(opts);
 | 
			
		||||
 | 
			
		||||
            for (let i = 0; i < _opts.tokenAddressesPath.length; i++) {
 | 
			
		||||
                const createFromTokenFn = testContract.createToken(_opts.tokenAddressesPath[i]);
 | 
			
		||||
                _opts.tokenAddressesPath[i] = await createFromTokenFn.callAsync();
 | 
			
		||||
                await createFromTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set the token balance for the token we're converting from.
 | 
			
		||||
            await testContract
 | 
			
		||||
                .setTokenBalance(_opts.tokenAddressesPath[0], _opts.fromTokenBalance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
 | 
			
		||||
            // Set revert reason for the router.
 | 
			
		||||
            await testContract.setRouterRevertReason(_opts.routerRevertReason).awaitTransactionSuccessAsync();
 | 
			
		||||
 | 
			
		||||
            // Call bridgeTransferFrom().
 | 
			
		||||
            const bridgeTransferFromFn = testContract.bridgeTransferFrom(
 | 
			
		||||
                // Output token
 | 
			
		||||
                _opts.tokenAddressesPath[_opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                // Random maker address.
 | 
			
		||||
                randomAddress(),
 | 
			
		||||
                // Recipient address.
 | 
			
		||||
                _opts.toAddress,
 | 
			
		||||
                // Transfer amount.
 | 
			
		||||
                _opts.amount,
 | 
			
		||||
                // ABI-encode the input token address as the bridge data. // FIXME
 | 
			
		||||
                bridgeDataEncoder.encode([_opts.tokenAddressesPath]),
 | 
			
		||||
            );
 | 
			
		||||
            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),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        it('returns magic bytes on success', async () => {
 | 
			
		||||
            const { result } = await transferFromAsync();
 | 
			
		||||
            expect(result).to.eq(AssetProxyId.ERC20Bridge);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('performs transfer when both tokens are the same', async () => {
 | 
			
		||||
            const createTokenFn = testContract.createToken(constants.NULL_ADDRESS);
 | 
			
		||||
            const tokenAddress = await createTokenFn.callAsync();
 | 
			
		||||
            await createTokenFn.awaitTransactionSuccessAsync();
 | 
			
		||||
 | 
			
		||||
            const { opts, result, logs } = await transferFromAsync({
 | 
			
		||||
                tokenAddressesPath: [tokenAddress, tokenAddress],
 | 
			
		||||
            });
 | 
			
		||||
            expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
 | 
			
		||||
            const transfers = filterLogsToArguments<TokenTransferArgs>(logs, ContractEvents.TokenTransfer);
 | 
			
		||||
 | 
			
		||||
            expect(transfers.length).to.eq(1);
 | 
			
		||||
            expect(transfers[0].token).to.eq(tokenAddress, 'input token address');
 | 
			
		||||
            expect(transfers[0].from).to.eq(testContract.address);
 | 
			
		||||
            expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
 | 
			
		||||
            expect(transfers[0].amount).to.bignumber.eq(opts.amount, 'amount');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('token -> token', async () => {
 | 
			
		||||
            it('calls UniswapV2Router01.swapExactTokensForTokens()', async () => {
 | 
			
		||||
                const { opts, result, logs, blocktime } = await transferFromAsync();
 | 
			
		||||
                expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
 | 
			
		||||
                const transfers = filterLogsToArguments<SwapExactTokensForTokensArgs>(
 | 
			
		||||
                    logs,
 | 
			
		||||
                    ContractEvents.SwapExactTokensForTokensInput,
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                expect(transfers.length).to.eq(1);
 | 
			
		||||
                expect(transfers[0].toTokenAddress).to.eq(
 | 
			
		||||
                    opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                    'output token address',
 | 
			
		||||
                );
 | 
			
		||||
                expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
 | 
			
		||||
                expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
 | 
			
		||||
                expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
 | 
			
		||||
                expect(transfers[0].deadline).to.bignumber.eq(blocktime, 'deadline');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token', async () => {
 | 
			
		||||
                const { logs } = await transferFromAsync();
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const routerAddress = await testContract.getRouterAddress().callAsync();
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(routerAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('sets allowance for "from" token on subsequent calls', async () => {
 | 
			
		||||
                const { opts } = await transferFromAsync();
 | 
			
		||||
                const { logs } = await transferFromAsync(opts);
 | 
			
		||||
                const approvals = filterLogsToArguments<TokenApproveArgs>(logs, ContractEvents.TokenApprove);
 | 
			
		||||
                const routerAddress = await testContract.getRouterAddress().callAsync();
 | 
			
		||||
                expect(approvals.length).to.eq(1);
 | 
			
		||||
                expect(approvals[0].spender).to.eq(routerAddress);
 | 
			
		||||
                expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('fails if the router fails', async () => {
 | 
			
		||||
                const revertReason = 'FOOBAR';
 | 
			
		||||
                const tx = transferFromAsync({
 | 
			
		||||
                    routerRevertReason: revertReason,
 | 
			
		||||
                });
 | 
			
		||||
                return expect(tx).to.eventually.be.rejectedWith(revertReason);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        describe('token -> token -> token', async () => {
 | 
			
		||||
            it('calls UniswapV2Router01.swapExactTokensForTokens()', async () => {
 | 
			
		||||
                const { opts, result, logs, blocktime } = await transferFromAsync({
 | 
			
		||||
                    tokenAddressesPath: Array(3).fill(constants.NULL_ADDRESS),
 | 
			
		||||
                });
 | 
			
		||||
                expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
 | 
			
		||||
                const transfers = filterLogsToArguments<SwapExactTokensForTokensArgs>(
 | 
			
		||||
                    logs,
 | 
			
		||||
                    ContractEvents.SwapExactTokensForTokensInput,
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                expect(transfers.length).to.eq(1);
 | 
			
		||||
                expect(transfers[0].toTokenAddress).to.eq(
 | 
			
		||||
                    opts.tokenAddressesPath[opts.tokenAddressesPath.length - 1],
 | 
			
		||||
                    'output token address',
 | 
			
		||||
                );
 | 
			
		||||
                expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
 | 
			
		||||
                expect(transfers[0].amountIn).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
 | 
			
		||||
                expect(transfers[0].amountOutMin).to.bignumber.eq(opts.amount, 'output token amount');
 | 
			
		||||
                expect(transfers[0].deadline).to.bignumber.eq(blocktime, 'deadline');
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -3,7 +3,14 @@
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/balancer_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/bancor_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/chai_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/cream_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/crypto_com_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/curve_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/d_o_d_o_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/dex_forwarder_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/dydx_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/erc1155_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/erc20_bridge_proxy';
 | 
			
		||||
@@ -14,25 +21,44 @@ 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_balancer_pool';
 | 
			
		||||
export * from '../test/generated-wrappers/i_bancor_network';
 | 
			
		||||
export * from '../test/generated-wrappers/i_chai';
 | 
			
		||||
export * from '../test/generated-wrappers/i_curve';
 | 
			
		||||
export * from '../test/generated-wrappers/i_dydx';
 | 
			
		||||
export * from '../test/generated-wrappers/i_dydx_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/i_eth2_dai';
 | 
			
		||||
export * from '../test/generated-wrappers/i_gas_token';
 | 
			
		||||
export * from '../test/generated-wrappers/i_kyber_network_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/i_m_stable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_mooniswap';
 | 
			
		||||
export * from '../test/generated-wrappers/i_shell';
 | 
			
		||||
export * from '../test/generated-wrappers/i_uniswap_exchange';
 | 
			
		||||
export * from '../test/generated-wrappers/i_uniswap_exchange_factory';
 | 
			
		||||
export * from '../test/generated-wrappers/i_uniswap_v2_router01';
 | 
			
		||||
export * from '../test/generated-wrappers/kyber_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/m_stable_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_asset_proxy_dispatcher';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/mixin_gas_token';
 | 
			
		||||
export * from '../test/generated-wrappers/mooniswap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/multi_asset_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/ownable';
 | 
			
		||||
export * from '../test/generated-wrappers/shell_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/snow_swap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/static_call_proxy';
 | 
			
		||||
export * from '../test/generated-wrappers/sushi_swap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/swerve_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_bancor_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_chai_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_dex_forwarder_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_dydx_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_erc20_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_eth2_dai_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_kyber_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_static_call_target';
 | 
			
		||||
export * from '../test/generated-wrappers/test_uniswap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/test_uniswap_v2_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/uniswap_bridge';
 | 
			
		||||
export * from '../test/generated-wrappers/uniswap_v2_bridge';
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,14 @@
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/BalancerBridge.json",
 | 
			
		||||
        "generated-artifacts/BancorBridge.json",
 | 
			
		||||
        "generated-artifacts/ChaiBridge.json",
 | 
			
		||||
        "generated-artifacts/CreamBridge.json",
 | 
			
		||||
        "generated-artifacts/CryptoComBridge.json",
 | 
			
		||||
        "generated-artifacts/CurveBridge.json",
 | 
			
		||||
        "generated-artifacts/DODOBridge.json",
 | 
			
		||||
        "generated-artifacts/DexForwarderBridge.json",
 | 
			
		||||
        "generated-artifacts/DydxBridge.json",
 | 
			
		||||
        "generated-artifacts/ERC1155Proxy.json",
 | 
			
		||||
        "generated-artifacts/ERC20BridgeProxy.json",
 | 
			
		||||
@@ -14,29 +21,55 @@
 | 
			
		||||
        "generated-artifacts/IAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/IAssetProxyDispatcher.json",
 | 
			
		||||
        "generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/IBalancerPool.json",
 | 
			
		||||
        "generated-artifacts/IBancorNetwork.json",
 | 
			
		||||
        "generated-artifacts/IChai.json",
 | 
			
		||||
        "generated-artifacts/ICurve.json",
 | 
			
		||||
        "generated-artifacts/IDydx.json",
 | 
			
		||||
        "generated-artifacts/IDydxBridge.json",
 | 
			
		||||
        "generated-artifacts/IERC20Bridge.json",
 | 
			
		||||
        "generated-artifacts/IEth2Dai.json",
 | 
			
		||||
        "generated-artifacts/IGasToken.json",
 | 
			
		||||
        "generated-artifacts/IKyberNetworkProxy.json",
 | 
			
		||||
        "generated-artifacts/IMStable.json",
 | 
			
		||||
        "generated-artifacts/IMooniswap.json",
 | 
			
		||||
        "generated-artifacts/IShell.json",
 | 
			
		||||
        "generated-artifacts/IUniswapExchange.json",
 | 
			
		||||
        "generated-artifacts/IUniswapExchangeFactory.json",
 | 
			
		||||
        "generated-artifacts/IUniswapV2Router01.json",
 | 
			
		||||
        "generated-artifacts/KyberBridge.json",
 | 
			
		||||
        "generated-artifacts/MStableBridge.json",
 | 
			
		||||
        "generated-artifacts/MixinAssetProxyDispatcher.json",
 | 
			
		||||
        "generated-artifacts/MixinAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/MixinGasToken.json",
 | 
			
		||||
        "generated-artifacts/MooniswapBridge.json",
 | 
			
		||||
        "generated-artifacts/MultiAssetProxy.json",
 | 
			
		||||
        "generated-artifacts/Ownable.json",
 | 
			
		||||
        "generated-artifacts/ShellBridge.json",
 | 
			
		||||
        "generated-artifacts/SnowSwapBridge.json",
 | 
			
		||||
        "generated-artifacts/StaticCallProxy.json",
 | 
			
		||||
        "generated-artifacts/SushiSwapBridge.json",
 | 
			
		||||
        "generated-artifacts/SwerveBridge.json",
 | 
			
		||||
        "generated-artifacts/TestBancorBridge.json",
 | 
			
		||||
        "generated-artifacts/TestChaiBridge.json",
 | 
			
		||||
        "generated-artifacts/TestDexForwarderBridge.json",
 | 
			
		||||
        "generated-artifacts/TestDydxBridge.json",
 | 
			
		||||
        "generated-artifacts/TestERC20Bridge.json",
 | 
			
		||||
        "generated-artifacts/TestEth2DaiBridge.json",
 | 
			
		||||
        "generated-artifacts/TestKyberBridge.json",
 | 
			
		||||
        "generated-artifacts/TestStaticCallTarget.json",
 | 
			
		||||
        "generated-artifacts/TestUniswapBridge.json",
 | 
			
		||||
        "generated-artifacts/TestUniswapV2Bridge.json",
 | 
			
		||||
        "generated-artifacts/UniswapBridge.json",
 | 
			
		||||
        "generated-artifacts/UniswapV2Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/BalancerBridge.json",
 | 
			
		||||
        "test/generated-artifacts/BancorBridge.json",
 | 
			
		||||
        "test/generated-artifacts/ChaiBridge.json",
 | 
			
		||||
        "test/generated-artifacts/CreamBridge.json",
 | 
			
		||||
        "test/generated-artifacts/CryptoComBridge.json",
 | 
			
		||||
        "test/generated-artifacts/CurveBridge.json",
 | 
			
		||||
        "test/generated-artifacts/DODOBridge.json",
 | 
			
		||||
        "test/generated-artifacts/DexForwarderBridge.json",
 | 
			
		||||
        "test/generated-artifacts/DydxBridge.json",
 | 
			
		||||
        "test/generated-artifacts/ERC1155Proxy.json",
 | 
			
		||||
        "test/generated-artifacts/ERC20BridgeProxy.json",
 | 
			
		||||
@@ -47,28 +80,47 @@
 | 
			
		||||
        "test/generated-artifacts/IAssetProxy.json",
 | 
			
		||||
        "test/generated-artifacts/IAssetProxyDispatcher.json",
 | 
			
		||||
        "test/generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/IBalancerPool.json",
 | 
			
		||||
        "test/generated-artifacts/IBancorNetwork.json",
 | 
			
		||||
        "test/generated-artifacts/IChai.json",
 | 
			
		||||
        "test/generated-artifacts/ICurve.json",
 | 
			
		||||
        "test/generated-artifacts/IDydx.json",
 | 
			
		||||
        "test/generated-artifacts/IDydxBridge.json",
 | 
			
		||||
        "test/generated-artifacts/IERC20Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/IEth2Dai.json",
 | 
			
		||||
        "test/generated-artifacts/IGasToken.json",
 | 
			
		||||
        "test/generated-artifacts/IKyberNetworkProxy.json",
 | 
			
		||||
        "test/generated-artifacts/IMStable.json",
 | 
			
		||||
        "test/generated-artifacts/IMooniswap.json",
 | 
			
		||||
        "test/generated-artifacts/IShell.json",
 | 
			
		||||
        "test/generated-artifacts/IUniswapExchange.json",
 | 
			
		||||
        "test/generated-artifacts/IUniswapExchangeFactory.json",
 | 
			
		||||
        "test/generated-artifacts/IUniswapV2Router01.json",
 | 
			
		||||
        "test/generated-artifacts/KyberBridge.json",
 | 
			
		||||
        "test/generated-artifacts/MStableBridge.json",
 | 
			
		||||
        "test/generated-artifacts/MixinAssetProxyDispatcher.json",
 | 
			
		||||
        "test/generated-artifacts/MixinAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/MixinGasToken.json",
 | 
			
		||||
        "test/generated-artifacts/MooniswapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/MultiAssetProxy.json",
 | 
			
		||||
        "test/generated-artifacts/Ownable.json",
 | 
			
		||||
        "test/generated-artifacts/ShellBridge.json",
 | 
			
		||||
        "test/generated-artifacts/SnowSwapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/StaticCallProxy.json",
 | 
			
		||||
        "test/generated-artifacts/SushiSwapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/SwerveBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestBancorBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestChaiBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestDexForwarderBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestDydxBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestERC20Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestEth2DaiBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestKyberBridge.json",
 | 
			
		||||
        "test/generated-artifacts/TestStaticCallTarget.json",
 | 
			
		||||
        "test/generated-artifacts/TestUniswapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/UniswapBridge.json"
 | 
			
		||||
        "test/generated-artifacts/TestUniswapV2Bridge.json",
 | 
			
		||||
        "test/generated-artifacts/UniswapBridge.json",
 | 
			
		||||
        "test/generated-artifacts/UniswapV2Bridge.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,267 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1617311315,
 | 
			
		||||
        "version": "1.1.27",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1616005394,
 | 
			
		||||
        "version": "1.1.26",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "1.1.25",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1612950500,
 | 
			
		||||
        "version": "1.1.24",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1611648096,
 | 
			
		||||
        "version": "1.1.23",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1610510890,
 | 
			
		||||
        "version": "1.1.22",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1609802516,
 | 
			
		||||
        "version": "1.1.21",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608692071,
 | 
			
		||||
        "version": "1.1.20",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608245516,
 | 
			
		||||
        "version": "1.1.19",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608105788,
 | 
			
		||||
        "version": "1.1.18",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607485227,
 | 
			
		||||
        "version": "1.1.17",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607381756,
 | 
			
		||||
        "version": "1.1.16",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1606961263,
 | 
			
		||||
        "version": "1.1.15",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605763885,
 | 
			
		||||
        "version": "1.1.14",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605302002,
 | 
			
		||||
        "version": "1.1.13",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604385937,
 | 
			
		||||
        "version": "1.1.12",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604376968,
 | 
			
		||||
        "version": "1.1.11",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604355662,
 | 
			
		||||
        "version": "1.1.10",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603851023,
 | 
			
		||||
        "version": "1.1.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603833198,
 | 
			
		||||
        "version": "1.1.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603265572,
 | 
			
		||||
        "version": "1.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1594788383,
 | 
			
		||||
        "version": "1.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Fix broken tests.",
 | 
			
		||||
                "pr": 2591
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1592969527
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1583220306,
 | 
			
		||||
        "version": "1.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582837861,
 | 
			
		||||
        "version": "1.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582677073,
 | 
			
		||||
        "version": "1.1.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582623685,
 | 
			
		||||
        "version": "1.1.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.1.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added decoders for broker data",
 | 
			
		||||
                "pr": 2484
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1581748629
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1581204851,
 | 
			
		||||
        "version": "1.0.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1580988106,
 | 
			
		||||
        "version": "1.0.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,122 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.1.27 - _April 1, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.26 - _March 17, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.25 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.24 - _February 10, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.23 - _January 26, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.22 - _January 13, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.21 - _January 4, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.20 - _December 23, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.19 - _December 17, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.18 - _December 16, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.17 - _December 9, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.16 - _December 7, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.15 - _December 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.14 - _November 19, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.13 - _November 13, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.12 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.11 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.10 - _November 2, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.9 - _October 28, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.8 - _October 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.7 - _October 21, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.6 - _July 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.5 - _June 24, 2020_
 | 
			
		||||
 | 
			
		||||
    * Fix broken tests. (#2591)
 | 
			
		||||
 | 
			
		||||
## v1.1.4 - _March 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.3 - _February 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.2 - _February 26, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.1 - _February 25, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.0 - _February 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Added decoders for broker data (#2484)
 | 
			
		||||
 | 
			
		||||
## v1.0.2 - _February 8, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.0.1 - _February 6, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
    "shouldSaveStandardInput": true,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "istanbul",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-broker",
 | 
			
		||||
    "version": "1.0.1",
 | 
			
		||||
    "version": "1.1.27",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -43,31 +43,31 @@
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo.git"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol.git"
 | 
			
		||||
    },
 | 
			
		||||
    "license": "Apache-2.0",
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo/issues"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.1.2",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.1.3",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.0.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.0.6",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.1.2",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.2.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.6",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.1.3",
 | 
			
		||||
        "@0x/contracts-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.0.6",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.22",
 | 
			
		||||
        "@0x/tslint-config": "^4.0.0",
 | 
			
		||||
        "@0x/types": "^3.1.1",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.0.5",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.9",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.6",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.27",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.28",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.27",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.24",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.6",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
        "@types/node": "12.12.54",
 | 
			
		||||
        "chai": "^4.0.1",
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
@@ -80,17 +80,18 @@
 | 
			
		||||
        "solhint": "^1.4.1",
 | 
			
		||||
        "truffle": "^5.0.32",
 | 
			
		||||
        "tslint": "5.11.0",
 | 
			
		||||
        "typedoc": "^0.15.0",
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
        "typedoc": "~0.16.11",
 | 
			
		||||
        "typescript": "4.2.2"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.1.2",
 | 
			
		||||
        "@0x/order-utils": "^10.1.3",
 | 
			
		||||
        "@0x/typescript-typings": "^5.0.1",
 | 
			
		||||
        "@0x/utils": "^5.3.0",
 | 
			
		||||
        "ethereum-types": "^3.0.0"
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/order-utils": "^10.4.19",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "ethereum-types": "^3.4.0"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    "gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,42 +1,59 @@
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { ERC1155AssetData } from '@0x/types';
 | 
			
		||||
import { AbiEncoder, BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
export const godsUnchainedUtils = {
 | 
			
		||||
    /**
 | 
			
		||||
     * Encodes the given proto and quality into the bytes format expected by the GodsUnchainedValidator.
 | 
			
		||||
     */
 | 
			
		||||
    encodePropertyData(proto: BigNumber, quality: BigNumber): string {
 | 
			
		||||
        return AbiEncoder.create([{ name: 'proto', type: 'uint16' }, { name: 'quality', type: 'uint8' }]).encode({
 | 
			
		||||
            proto,
 | 
			
		||||
            quality,
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Encodes the given proto and quality into ERC1155 asset data to be used as the takerAssetData
 | 
			
		||||
     * of a property-based GodsUnchained order. Must also provide the addresses of the Broker,
 | 
			
		||||
     * GodsUnchained, and GodsUnchainedValidator contracts. The optional bundleSize parameter specifies
 | 
			
		||||
     * how many cards are expected for each "unit" of the takerAssetAmount. For example, If the
 | 
			
		||||
     * takerAssetAmount is 3 and the bundleSize is 2, the taker must provide 2, 4, or 6 cards
 | 
			
		||||
     * with the given proto and quality to fill the order. If an odd number is provided, the fill fails.
 | 
			
		||||
     */
 | 
			
		||||
    encodeBrokerAssetData(
 | 
			
		||||
        brokerAddress: string,
 | 
			
		||||
        godsUnchainedAddress: string,
 | 
			
		||||
        validatorAddress: string,
 | 
			
		||||
        proto: BigNumber,
 | 
			
		||||
        quality: BigNumber,
 | 
			
		||||
        bundleSize: number = 1,
 | 
			
		||||
    ): string {
 | 
			
		||||
        const dataEncoder = AbiEncoder.create([
 | 
			
		||||
            { name: 'godsUnchainedAddress', type: 'address' },
 | 
			
		||||
            { name: 'validatorAddress', type: 'address' },
 | 
			
		||||
            { name: 'propertyData', type: 'bytes' },
 | 
			
		||||
        ]);
 | 
			
		||||
        const propertyData = AbiEncoder.create([
 | 
			
		||||
            { name: 'proto', type: 'uint16' },
 | 
			
		||||
            { name: 'quality', type: 'uint8' },
 | 
			
		||||
        ]).encode({ proto, quality });
 | 
			
		||||
        const data = dataEncoder.encode({ godsUnchainedAddress, validatorAddress, propertyData });
 | 
			
		||||
        return assetDataUtils.encodeERC1155AssetData(brokerAddress, [], [new BigNumber(bundleSize)], data);
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
export interface GodsUnchainedProperties {
 | 
			
		||||
    proto: BigNumber | number;
 | 
			
		||||
    quality: BigNumber | number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const propertyDataEncoder = AbiEncoder.create([{ name: 'proto', type: 'uint16' }, { name: 'quality', type: 'uint8' }]);
 | 
			
		||||
const brokerDataEncoder = AbiEncoder.create([
 | 
			
		||||
    { name: 'godsUnchainedAddress', type: 'address' },
 | 
			
		||||
    { name: 'validatorAddress', type: 'address' },
 | 
			
		||||
    { name: 'propertyData', type: 'bytes' },
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encodes the given proto and quality into the bytes format expected by the GodsUnchainedValidator.
 | 
			
		||||
 */
 | 
			
		||||
export function encodePropertyData(properties: GodsUnchainedProperties): string {
 | 
			
		||||
    return propertyDataEncoder.encode(properties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encodes the given proto and quality into ERC1155 asset data to be used as the takerAssetData
 | 
			
		||||
 * of a property-based GodsUnchained order. Must also provide the addresses of the Broker,
 | 
			
		||||
 * GodsUnchained, and GodsUnchainedValidator contracts. The optional bundleSize parameter specifies
 | 
			
		||||
 * how many cards are expected for each "unit" of the takerAssetAmount. For example, If the
 | 
			
		||||
 * takerAssetAmount is 3 and the bundleSize is 2, the taker must provide 2, 4, or 6 cards
 | 
			
		||||
 * with the given proto and quality to fill the order. If an odd number is provided, the fill fails.
 | 
			
		||||
 */
 | 
			
		||||
export function encodeBrokerAssetData(
 | 
			
		||||
    brokerAddress: string,
 | 
			
		||||
    godsUnchainedAddress: string,
 | 
			
		||||
    validatorAddress: string,
 | 
			
		||||
    properties: GodsUnchainedProperties,
 | 
			
		||||
    bundleSize: number = 1,
 | 
			
		||||
): string {
 | 
			
		||||
    const propertyData = propertyDataEncoder.encode(properties);
 | 
			
		||||
    const brokerData = brokerDataEncoder.encode({ godsUnchainedAddress, validatorAddress, propertyData });
 | 
			
		||||
    return assetDataUtils.encodeERC1155AssetData(brokerAddress, [], [new BigNumber(bundleSize)], brokerData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decodes proto and quality from the bytes format expected by the GodsUnchainedValidator.
 | 
			
		||||
 */
 | 
			
		||||
export function decodePropertyData(propertyData: string): GodsUnchainedProperties {
 | 
			
		||||
    return propertyDataEncoder.decode(propertyData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decodes proto and quality from the ERC1155 takerAssetData of a property-based GodsUnchained order.
 | 
			
		||||
 */
 | 
			
		||||
export function decodeBrokerAssetData(brokerAssetData: string): GodsUnchainedProperties {
 | 
			
		||||
    // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
    const { callbackData: brokerData } = assetDataUtils.decodeAssetDataOrThrow(brokerAssetData) as ERC1155AssetData;
 | 
			
		||||
    const { propertyData } = brokerDataEncoder.decode(brokerData);
 | 
			
		||||
    return decodePropertyData(propertyData);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
export { artifacts } from './artifacts';
 | 
			
		||||
export { BrokerContract, GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
 | 
			
		||||
export { godsUnchainedUtils } from './gods_unchained_utils';
 | 
			
		||||
export * from './gods_unchained_utils';
 | 
			
		||||
export { BrokerRevertErrors } from '@0x/utils';
 | 
			
		||||
export {
 | 
			
		||||
    ContractArtifact,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import { blockchainTests, constants, expect, getRandomInteger } from '@0x/contra
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { godsUnchainedUtils } from '../src/gods_unchained_utils';
 | 
			
		||||
import { encodePropertyData } from '../src/gods_unchained_utils';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { GodsUnchainedValidatorContract, TestGodsUnchainedContract } from './wrappers';
 | 
			
		||||
@@ -33,7 +33,7 @@ blockchainTests.resets('GodsUnchainedValidator unit tests', env => {
 | 
			
		||||
    describe('checkBrokerAsset', () => {
 | 
			
		||||
        const proto = new BigNumber(42);
 | 
			
		||||
        const quality = new BigNumber(7);
 | 
			
		||||
        const propertyData = godsUnchainedUtils.encodePropertyData(proto, quality);
 | 
			
		||||
        const propertyData = encodePropertyData({ proto, quality });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if assetData proto and quality match propertyData', async () => {
 | 
			
		||||
            const tokenId = getRandomInteger(0, constants.MAX_UINT256);
 | 
			
		||||
@@ -44,13 +44,13 @@ blockchainTests.resets('GodsUnchainedValidator unit tests', env => {
 | 
			
		||||
            const tokenId = getRandomInteger(0, constants.MAX_UINT256);
 | 
			
		||||
            await godsUnchained.setTokenProperties(tokenId, proto.plus(1), quality).awaitTransactionSuccessAsync();
 | 
			
		||||
            const tx = validator.checkBrokerAsset(tokenId, propertyData).callAsync();
 | 
			
		||||
            expect(tx).to.revertWith('PROTO_MISMATCH');
 | 
			
		||||
            expect(tx).to.revertWith('GodsUnchainedValidator/PROTO_MISMATCH');
 | 
			
		||||
        });
 | 
			
		||||
        it("reverts if assetData quality doesn't match proeprtyData", async () => {
 | 
			
		||||
            const tokenId = getRandomInteger(0, constants.MAX_UINT256);
 | 
			
		||||
            await godsUnchained.setTokenProperties(tokenId, proto, quality.plus(1)).awaitTransactionSuccessAsync();
 | 
			
		||||
            const tx = validator.checkBrokerAsset(tokenId, propertyData).callAsync();
 | 
			
		||||
            expect(tx).to.revertWith('QUALITY_MISMATCH');
 | 
			
		||||
            expect(tx).to.revertWith('GodsUnchainedValidator/QUALITY_MISMATCH');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,266 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1617311315,
 | 
			
		||||
        "version": "3.1.28",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1616005394,
 | 
			
		||||
        "version": "3.1.27",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.1.26",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1612950500,
 | 
			
		||||
        "version": "3.1.25",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1611648096,
 | 
			
		||||
        "version": "3.1.24",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1610510890,
 | 
			
		||||
        "version": "3.1.23",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1609802516,
 | 
			
		||||
        "version": "3.1.22",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608692071,
 | 
			
		||||
        "version": "3.1.21",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608245516,
 | 
			
		||||
        "version": "3.1.20",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608105788,
 | 
			
		||||
        "version": "3.1.19",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607485227,
 | 
			
		||||
        "version": "3.1.18",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607381756,
 | 
			
		||||
        "version": "3.1.17",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1606961263,
 | 
			
		||||
        "version": "3.1.16",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605763885,
 | 
			
		||||
        "version": "3.1.15",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605302002,
 | 
			
		||||
        "version": "3.1.14",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604385937,
 | 
			
		||||
        "version": "3.1.13",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604376968,
 | 
			
		||||
        "version": "3.1.12",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604355662,
 | 
			
		||||
        "version": "3.1.11",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603851023,
 | 
			
		||||
        "version": "3.1.10",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603833198,
 | 
			
		||||
        "version": "3.1.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603265572,
 | 
			
		||||
        "version": "3.1.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1594788383,
 | 
			
		||||
        "version": "3.1.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1592969527,
 | 
			
		||||
        "version": "3.1.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1583220306,
 | 
			
		||||
        "version": "3.1.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582837861,
 | 
			
		||||
        "version": "3.1.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582677073,
 | 
			
		||||
        "version": "3.1.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582623685,
 | 
			
		||||
        "version": "3.1.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1581748629,
 | 
			
		||||
        "version": "3.1.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.1.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Update tests.",
 | 
			
		||||
                "pr": 2462
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1581204851
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1580988106,
 | 
			
		||||
        "version": "3.0.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,122 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.28 - _April 1, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.27 - _March 17, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.26 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.25 - _February 10, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.24 - _January 26, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.23 - _January 13, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.22 - _January 4, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.21 - _December 23, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.20 - _December 17, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.19 - _December 16, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.18 - _December 9, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.17 - _December 7, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.16 - _December 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.15 - _November 19, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.14 - _November 13, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.13 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.12 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.11 - _November 2, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.10 - _October 28, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.9 - _October 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.8 - _October 21, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.7 - _July 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.6 - _June 24, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.5 - _March 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.4 - _February 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.3 - _February 26, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.2 - _February 25, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.1 - _February 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.0 - _February 8, 2020_
 | 
			
		||||
 | 
			
		||||
    * Update tests. (#2462)
 | 
			
		||||
 | 
			
		||||
## v3.0.6 - _February 6, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "shouldSaveStandardInput": true,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "istanbul",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-coordinator",
 | 
			
		||||
    "version": "3.0.6",
 | 
			
		||||
    "version": "3.1.28",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -44,30 +44,28 @@
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo.git"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol.git"
 | 
			
		||||
    },
 | 
			
		||||
    "license": "Apache-2.0",
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/0x-monorepo/issues"
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.1.2",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.1.3",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.0.6",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.0.6",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.1.2",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.6",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.1.3",
 | 
			
		||||
        "@0x/dev-utils": "^3.1.3",
 | 
			
		||||
        "@0x/order-utils": "^10.1.3",
 | 
			
		||||
        "@0x/sol-compiler": "^4.0.6",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.22",
 | 
			
		||||
        "@0x/tslint-config": "^4.0.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.0.5",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.9",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.26",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.6",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.19",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "*",
 | 
			
		||||
        "@types/node": "12.12.54",
 | 
			
		||||
        "chai": "^4.0.1",
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
@@ -80,22 +78,25 @@
 | 
			
		||||
        "solhint": "^1.4.1",
 | 
			
		||||
        "truffle": "^5.0.32",
 | 
			
		||||
        "tslint": "5.11.0",
 | 
			
		||||
        "typedoc": "^0.15.0",
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
        "typedoc": "~0.16.11",
 | 
			
		||||
        "typescript": "4.2.2"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.5",
 | 
			
		||||
        "@0x/base-contract": "^6.1.2",
 | 
			
		||||
        "@0x/contract-addresses": "^4.4.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.2.1",
 | 
			
		||||
        "@0x/json-schemas": "^5.0.5",
 | 
			
		||||
        "@0x/types": "^3.1.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.0.1",
 | 
			
		||||
        "@0x/utils": "^5.3.0",
 | 
			
		||||
        "ethereum-types": "^3.0.0",
 | 
			
		||||
        "@0x/assert": "^3.0.21",
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contract-addresses": "^6.0.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.28",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.24",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.6",
 | 
			
		||||
        "@0x/json-schemas": "^5.4.1",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "ethereum-types": "^3.4.0",
 | 
			
		||||
        "http-status-codes": "^1.3.2"
 | 
			
		||||
    },
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    "gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,16 +14,12 @@ export class ApprovalFactory {
 | 
			
		||||
        this._verifyingContractAddress = verifyingContract;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async newSignedApprovalAsync(
 | 
			
		||||
    public newSignedApproval(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
        signatureType: SignatureType = SignatureType.EthSign,
 | 
			
		||||
    ): Promise<SignedCoordinatorApproval> {
 | 
			
		||||
        const approvalHashBuff = await hashUtils.getApprovalHashBufferAsync(
 | 
			
		||||
            transaction,
 | 
			
		||||
            this._verifyingContractAddress,
 | 
			
		||||
            txOrigin,
 | 
			
		||||
        );
 | 
			
		||||
    ): SignedCoordinatorApproval {
 | 
			
		||||
        const approvalHashBuff = hashUtils.getApprovalHashBuffer(transaction, this._verifyingContractAddress, txOrigin);
 | 
			
		||||
        const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
 | 
			
		||||
        const signedApproval = {
 | 
			
		||||
            txOrigin,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,27 +3,13 @@ import { SignedZeroExTransaction } from '@0x/types';
 | 
			
		||||
import { hexUtils, signTypedDataUtils } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
export const hashUtils = {
 | 
			
		||||
    async getApprovalHashBufferAsync(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        verifyingContract: string,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
    ): Promise<Buffer> {
 | 
			
		||||
        const typedData = await eip712Utils.createCoordinatorApprovalTypedDataAsync(
 | 
			
		||||
            transaction,
 | 
			
		||||
            verifyingContract,
 | 
			
		||||
            txOrigin,
 | 
			
		||||
        );
 | 
			
		||||
    getApprovalHashBuffer(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): Buffer {
 | 
			
		||||
        const typedData = eip712Utils.createCoordinatorApprovalTypedData(transaction, verifyingContract, txOrigin);
 | 
			
		||||
        const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
 | 
			
		||||
        return hashBuffer;
 | 
			
		||||
    },
 | 
			
		||||
    async getApprovalHashHexAsync(
 | 
			
		||||
        transaction: SignedZeroExTransaction,
 | 
			
		||||
        verifyingContract: string,
 | 
			
		||||
        txOrigin: string,
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        const hashHex = hexUtils.concat(
 | 
			
		||||
            await hashUtils.getApprovalHashBufferAsync(transaction, verifyingContract, txOrigin),
 | 
			
		||||
        );
 | 
			
		||||
    getApprovalHashHex(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): string {
 | 
			
		||||
        const hashHex = hexUtils.toHex(hashUtils.getApprovalHashBuffer(transaction, verifyingContract, txOrigin));
 | 
			
		||||
        return hashHex;
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ export {
 | 
			
		||||
    OutputField,
 | 
			
		||||
    ParamDescription,
 | 
			
		||||
    EvmBytecodeOutput,
 | 
			
		||||
    EvmBytecodeOutputLinkReferences,
 | 
			
		||||
    AbiDefinition,
 | 
			
		||||
    FunctionAbi,
 | 
			
		||||
    EventAbi,
 | 
			
		||||
 
 | 
			
		||||
@@ -44,11 +44,7 @@ blockchainTests.resets('Libs tests', env => {
 | 
			
		||||
                transactionHash: transactionHashUtils.getTransactionHashHex(signedTx),
 | 
			
		||||
                transactionSignature: signedTx.signature,
 | 
			
		||||
            };
 | 
			
		||||
            const expectedApprovalHash = await hashUtils.getApprovalHashHexAsync(
 | 
			
		||||
                signedTx,
 | 
			
		||||
                coordinatorContract.address,
 | 
			
		||||
                txOrigin,
 | 
			
		||||
            );
 | 
			
		||||
            const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, coordinatorContract.address, txOrigin);
 | 
			
		||||
            const approvalHash = await coordinatorContract.getCoordinatorApprovalHash(approval).callAsync();
 | 
			
		||||
            expect(expectedApprovalHash).to.eq(approvalHash);
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -236,7 +236,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -251,7 +251,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [order];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -272,7 +272,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -293,7 +293,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const signature = hexUtils.concat(
 | 
			
		||||
                    hexUtils.slice(approval.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
@@ -314,7 +314,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
@@ -335,7 +335,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -349,7 +349,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                }));
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -371,7 +371,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval.signature,
 | 
			
		||||
@@ -382,8 +382,8 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                await mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
                        approval1.signature,
 | 
			
		||||
@@ -403,7 +403,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
@@ -429,7 +429,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const signature = hexUtils.concat(
 | 
			
		||||
                    hexUtils.slice(approval.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
@@ -450,8 +450,8 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const approvalSignature2 = hexUtils.concat(
 | 
			
		||||
                    hexUtils.slice(approval2.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
@@ -473,7 +473,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
                const approvalSignature2 = hexUtils.concat(
 | 
			
		||||
                    hexUtils.slice(approval2.signature, 0, 2),
 | 
			
		||||
                    '0xFFFFFFFF',
 | 
			
		||||
@@ -494,7 +494,7 @@ blockchainTests.resets('Mixins tests', env => {
 | 
			
		||||
                const orders = [defaultOrder, defaultOrder];
 | 
			
		||||
                const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
 | 
			
		||||
                const transaction = await transactionFactory.newSignedTransactionAsync({ data });
 | 
			
		||||
                const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
 | 
			
		||||
                const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
 | 
			
		||||
 | 
			
		||||
                const tx = mixins
 | 
			
		||||
                    .assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,280 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1617311315,
 | 
			
		||||
        "version": "1.3.26",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1616005394,
 | 
			
		||||
        "version": "1.3.25",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "1.3.24",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1612950500,
 | 
			
		||||
        "version": "1.3.23",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1611648096,
 | 
			
		||||
        "version": "1.3.22",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1610510890,
 | 
			
		||||
        "version": "1.3.21",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1609802516,
 | 
			
		||||
        "version": "1.3.20",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608692071,
 | 
			
		||||
        "version": "1.3.19",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608245516,
 | 
			
		||||
        "version": "1.3.18",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1608105788,
 | 
			
		||||
        "version": "1.3.17",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607485227,
 | 
			
		||||
        "version": "1.3.16",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1607381756,
 | 
			
		||||
        "version": "1.3.15",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1606961263,
 | 
			
		||||
        "version": "1.3.14",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605763885,
 | 
			
		||||
        "version": "1.3.13",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1605302002,
 | 
			
		||||
        "version": "1.3.12",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604385937,
 | 
			
		||||
        "version": "1.3.11",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604376968,
 | 
			
		||||
        "version": "1.3.10",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1604355662,
 | 
			
		||||
        "version": "1.3.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603851023,
 | 
			
		||||
        "version": "1.3.8",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603833198,
 | 
			
		||||
        "version": "1.3.7",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1603265572,
 | 
			
		||||
        "version": "1.3.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1594788383,
 | 
			
		||||
        "version": "1.3.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1592969527,
 | 
			
		||||
        "version": "1.3.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1583220306,
 | 
			
		||||
        "version": "1.3.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582837861,
 | 
			
		||||
        "version": "1.3.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1582677073,
 | 
			
		||||
        "version": "1.3.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.3.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Update `DevUtils` addresses in `DeploymentConstants`",
 | 
			
		||||
                "pr": 2493
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1582623685
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.2.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `DydxBridge` order validation",
 | 
			
		||||
                "pr": 2466
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1581748629,
 | 
			
		||||
        "version": "1.1.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.1.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Refactor mixins into public libraries.",
 | 
			
		||||
                "pr": 2464
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Remove `LibTransactionDecoder` export",
 | 
			
		||||
                "pr": 2464
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1581204851
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1580988106,
 | 
			
		||||
        "version": "1.0.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,127 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.3.26 - _April 1, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.25 - _March 17, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.24 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.23 - _February 10, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.22 - _January 26, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.21 - _January 13, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.20 - _January 4, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.19 - _December 23, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.18 - _December 17, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.17 - _December 16, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.16 - _December 9, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.15 - _December 7, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.14 - _December 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.13 - _November 19, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.12 - _November 13, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.11 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.10 - _November 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.9 - _November 2, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.8 - _October 28, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.7 - _October 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.6 - _October 21, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.5 - _July 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.4 - _June 24, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.3 - _March 3, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.2 - _February 27, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.1 - _February 26, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.0 - _February 25, 2020_
 | 
			
		||||
 | 
			
		||||
    * Update `DevUtils` addresses in `DeploymentConstants` (#2493)
 | 
			
		||||
 | 
			
		||||
## v1.2.0 - _Invalid date_
 | 
			
		||||
 | 
			
		||||
    * Add `DydxBridge` order validation (#2466)
 | 
			
		||||
 | 
			
		||||
## v1.1.1 - _February 15, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.0 - _February 8, 2020_
 | 
			
		||||
 | 
			
		||||
    * Refactor mixins into public libraries. (#2464)
 | 
			
		||||
    * Remove `LibTransactionDecoder` export (#2464)
 | 
			
		||||
 | 
			
		||||
## v1.0.6 - _February 6, 2020_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
    "shouldSaveStandardInput": true,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "istanbul",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								contracts/dev-utils/contracts/src/Addresses.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								contracts/dev-utils/contracts/src/Addresses.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.16;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-empty-blocks
 | 
			
		||||
contract Addresses is
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    address public exchangeAddress;
 | 
			
		||||
    address public erc20ProxyAddress;
 | 
			
		||||
    address public erc721ProxyAddress;
 | 
			
		||||
    address public erc1155ProxyAddress;
 | 
			
		||||
    address public staticCallProxyAddress;
 | 
			
		||||
    address public chaiBridgeAddress;
 | 
			
		||||
    address public dydxBridgeAddress;
 | 
			
		||||
 | 
			
		||||
    constructor (
 | 
			
		||||
        address exchange_,
 | 
			
		||||
        address chaiBridge_,
 | 
			
		||||
        address dydxBridge_
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        exchangeAddress = exchange_;
 | 
			
		||||
        chaiBridgeAddress = chaiBridge_;
 | 
			
		||||
        dydxBridgeAddress = dydxBridge_;
 | 
			
		||||
        erc20ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
 | 
			
		||||
        erc721ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
 | 
			
		||||
        erc1155ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
 | 
			
		||||
        staticCallProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).StaticCall.selector);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										388
									
								
								contracts/dev-utils/contracts/src/AssetBalance.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										388
									
								
								contracts/dev-utils/contracts/src/AssetBalance.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,388 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.16;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
 | 
			
		||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
 | 
			
		||||
import "./Addresses.sol";
 | 
			
		||||
import "./LibDydxBalance.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract AssetBalance is
 | 
			
		||||
    Addresses
 | 
			
		||||
{
 | 
			
		||||
    // 2^256 - 1
 | 
			
		||||
    uint256 constant internal _MAX_UINT256 = uint256(-1);
 | 
			
		||||
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the owner's balance of the assets(s) specified in
 | 
			
		||||
    /// assetData.  When the asset data contains multiple assets (eg in
 | 
			
		||||
    /// ERC1155 or Multi-Asset), the return value indicates how many
 | 
			
		||||
    /// complete "baskets" of those assets are owned by owner.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner.
 | 
			
		||||
    function getBalance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 balance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
            balance = LibERC20Token.balanceOf(tokenAddress, ownerAddress);
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Check if id is owned by ownerAddress
 | 
			
		||||
            bytes memory ownerOfCalldata = abi.encodeWithSelector(
 | 
			
		||||
                IERC721Token(address(0)).ownerOf.selector,
 | 
			
		||||
                tokenId
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
 | 
			
		||||
            address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
 | 
			
		||||
            balance = currentOwnerAddress == ownerAddress ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
 | 
			
		||||
            // Get ERC1155 token address, array of ids, and array of values
 | 
			
		||||
            (, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = LibAssetData.decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = tokenIds.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the token if the corresponding value is 0.
 | 
			
		||||
                if (tokenValues[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Encode data for `balanceOf(ownerAddress, tokenIds[i])
 | 
			
		||||
                bytes memory balanceOfData = abi.encodeWithSelector(
 | 
			
		||||
                    IERC1155(address(0)).balanceOf.selector,
 | 
			
		||||
                    ownerAddress,
 | 
			
		||||
                    tokenIds[i]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                // Query balance
 | 
			
		||||
                (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
 | 
			
		||||
                uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / tokenValues[i];
 | 
			
		||||
                if (scaledBalance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
 | 
			
		||||
            // Encode data for `staticCallProxy.transferFrom(assetData,...)`
 | 
			
		||||
            bytes memory transferFromData = abi.encodeWithSelector(
 | 
			
		||||
                IAssetProxy(address(0)).transferFrom.selector,
 | 
			
		||||
                assetData,
 | 
			
		||||
                address(0),  // `from` address is not used
 | 
			
		||||
                address(0),  // `to` address is not used
 | 
			
		||||
                0            // `amount` is not used
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Check if staticcall would be successful
 | 
			
		||||
            (bool success,) = staticCallProxyAddress.staticcall(transferFromData);
 | 
			
		||||
 | 
			
		||||
            // Success means that the staticcall can be made an unlimited amount of times
 | 
			
		||||
            balance = success ? _MAX_UINT256 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
 | 
			
		||||
            // Get address of ERC20 token and bridge contract
 | 
			
		||||
            (, address tokenAddress, address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(assetData);
 | 
			
		||||
            if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
 | 
			
		||||
                uint256 chaiBalance = LibERC20Token.balanceOf(_getChaiAddress(), ownerAddress);
 | 
			
		||||
                // Calculate Dai balance
 | 
			
		||||
                balance = _convertChaiToDaiAmount(chaiBalance);
 | 
			
		||||
            }
 | 
			
		||||
            // Balance will be 0 if bridge is not supported
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the asset if the corresponding amount is 0.
 | 
			
		||||
                if (assetAmounts[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Query balance of individual assetData
 | 
			
		||||
                uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / assetAmounts[i];
 | 
			
		||||
                if (scaledBalance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Balance will be 0 if assetProxyId is unknown
 | 
			
		||||
        return balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Array of asset balances from getBalance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory balances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        balances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            balances[i] = getBalance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return balances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the number of asset(s) (described by assetData) that
 | 
			
		||||
    /// the corresponding AssetProxy contract is authorized to spend.  When the asset data contains
 | 
			
		||||
    /// multiple assets (eg for Multi-Asset), the return value indicates
 | 
			
		||||
    /// how many complete "baskets" of those assets may be spent by all of the corresponding
 | 
			
		||||
    /// AssetProxy contracts.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory amounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the asset if the corresponding amount is 0.
 | 
			
		||||
                if (amounts[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Query allowance of individual assetData
 | 
			
		||||
                uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total allowance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledAllowance = totalAllowance / amounts[i];
 | 
			
		||||
                if (scaledAllowance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledAllowance < allowance || allowance == 0) {
 | 
			
		||||
                    allowance = scaledAllowance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return allowance;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
            allowance = LibERC20Token.allowance(tokenAddress, ownerAddress, erc20ProxyAddress);
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, erc721ProxyAddress)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                IERC721Token(address(0)).isApprovedForAll.selector,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                erc721ProxyAddress
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
 | 
			
		||||
            // If not approved for all, call `getApproved(tokenId)`
 | 
			
		||||
            if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
 | 
			
		||||
                // Encode data for `getApproved(tokenId)`
 | 
			
		||||
                bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
 | 
			
		||||
                (success, returnData) = tokenAddress.staticcall(getApprovedData);
 | 
			
		||||
 | 
			
		||||
                // Allowance is 1 if successful and the approved address is the ERC721Proxy
 | 
			
		||||
                allowance = success && returnData.length == 32 && returnData.readAddress(12) == erc721ProxyAddress ? 1 : 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                // Allowance is 2^256 - 1 if `isApprovedForAll` returned true
 | 
			
		||||
                allowance = _MAX_UINT256;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
 | 
			
		||||
            // Get ERC1155 token address
 | 
			
		||||
            (, address tokenAddress, , , ) = LibAssetData.decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, erc1155ProxyAddress)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                IERC1155(address(0)).isApprovedForAll.selector,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                erc1155ProxyAddress
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
            allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
 | 
			
		||||
            // The StaticCallProxy does not require any approvals
 | 
			
		||||
            allowance = _MAX_UINT256;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
 | 
			
		||||
            // Get address of ERC20 token and bridge contract
 | 
			
		||||
            (, address tokenAddress, address bridgeAddress,) =
 | 
			
		||||
                LibAssetData.decodeERC20BridgeAssetData(assetData);
 | 
			
		||||
            if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
 | 
			
		||||
                uint256 chaiAllowance = LibERC20Token.allowance(_getChaiAddress(), ownerAddress, chaiBridgeAddress);
 | 
			
		||||
                // Dai allowance is unlimited if Chai allowance is unlimited
 | 
			
		||||
                allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
 | 
			
		||||
            } else if (bridgeAddress == dydxBridgeAddress) {
 | 
			
		||||
                allowance = LibDydxBalance.getDydxMakerAllowance(ownerAddress, bridgeAddress, _getDydxAddress());
 | 
			
		||||
            }
 | 
			
		||||
            // Allowance will be 0 if bridge is not supported
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Allowance will be 0 if the assetProxyId is unknown
 | 
			
		||||
        return allowance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getAssetProxyAllowance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset allowances from getAllowance(), with each
 | 
			
		||||
    /// element corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        allowances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return allowances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() and getAllowance() for assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner, and number
 | 
			
		||||
    /// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getBalanceAndAssetProxyAllowance(
 | 
			
		||||
        address ownerAddress,
 | 
			
		||||
        bytes memory assetData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        balance = getBalance(ownerAddress, assetData);
 | 
			
		||||
        allowance = getAssetProxyAllowance(ownerAddress, assetData);
 | 
			
		||||
        return (balance, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset balances from getBalance(), and an array of
 | 
			
		||||
    /// asset allowances from getAllowance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalancesAndAssetProxyAllowances(
 | 
			
		||||
        address ownerAddress,
 | 
			
		||||
        bytes[] memory assetData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory balances, uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        balances = getBatchBalances(ownerAddress, assetData);
 | 
			
		||||
        allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
 | 
			
		||||
        return (balances, allowances);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Converts an amount of Chai into its equivalent Dai amount.
 | 
			
		||||
    ///      Also accumulates Dai from DSR if called after the last time it was collected.
 | 
			
		||||
    /// @param chaiAmount Amount of Chai to converts.
 | 
			
		||||
    function _convertChaiToDaiAmount(uint256 chaiAmount)
 | 
			
		||||
        internal
 | 
			
		||||
        returns (uint256 daiAmount)
 | 
			
		||||
    {
 | 
			
		||||
        PotLike pot = IChai(_getChaiAddress()).pot();
 | 
			
		||||
        // Accumulate savings if called after last time savings were collected
 | 
			
		||||
        // solhint-disable-next-line not-rely-on-time
 | 
			
		||||
        uint256 chiMultiplier = (now > pot.rho())
 | 
			
		||||
            ? pot.drip()
 | 
			
		||||
            : pot.chi();
 | 
			
		||||
        daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
 | 
			
		||||
        return daiAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns an order MAKER's balance of the assets(s) specified in
 | 
			
		||||
    ///      makerAssetData. Unlike `getBalanceAndAssetProxyAllowance()`, this
 | 
			
		||||
    ///      can handle maker asset types that depend on taker tokens being
 | 
			
		||||
    ///      transferred to the maker first.
 | 
			
		||||
    /// @param order The order.
 | 
			
		||||
    /// @return balance Quantity of assets transferrable from maker to taker.
 | 
			
		||||
    function _getConvertibleMakerBalanceAndAssetProxyAllowance(
 | 
			
		||||
        LibOrder.Order memory order
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        if (order.makerAssetData.length < 4) {
 | 
			
		||||
            return (0, 0);
 | 
			
		||||
        }
 | 
			
		||||
        bytes4 assetProxyId = order.makerAssetData.readBytes4(0);
 | 
			
		||||
        // Handle dydx bridge assets.
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
 | 
			
		||||
            (, , address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(order.makerAssetData);
 | 
			
		||||
            if (bridgeAddress == dydxBridgeAddress) {
 | 
			
		||||
                return (
 | 
			
		||||
                    LibDydxBalance.getDydxMakerBalance(order, _getDydxAddress()),
 | 
			
		||||
                    getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return (
 | 
			
		||||
            getBalance(order.makerAddress, order.makerAssetData),
 | 
			
		||||
            getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.16;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
 | 
			
		||||
@@ -24,27 +24,31 @@ 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 "./Addresses.sol";
 | 
			
		||||
import "./OrderValidationUtils.sol";
 | 
			
		||||
import "./OrderTransferSimulationUtils.sol";
 | 
			
		||||
import "./EthBalanceChecker.sol";
 | 
			
		||||
import "./ExternalFunctions.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// solhint-disable no-empty-blocks
 | 
			
		||||
contract DevUtils is
 | 
			
		||||
    Addresses,
 | 
			
		||||
    OrderValidationUtils,
 | 
			
		||||
    LibEIP712ExchangeDomain,
 | 
			
		||||
    EthBalanceChecker
 | 
			
		||||
    EthBalanceChecker,
 | 
			
		||||
    ExternalFunctions
 | 
			
		||||
{
 | 
			
		||||
    constructor (
 | 
			
		||||
        address _exchange,
 | 
			
		||||
        address _chaiBridge
 | 
			
		||||
        address exchange_,
 | 
			
		||||
        address chaiBridge_,
 | 
			
		||||
        address dydxBridge_
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        OrderValidationUtils(
 | 
			
		||||
            _exchange,
 | 
			
		||||
            _chaiBridge
 | 
			
		||||
        Addresses(
 | 
			
		||||
            exchange_,
 | 
			
		||||
            chaiBridge_,
 | 
			
		||||
            dydxBridge_
 | 
			
		||||
        )
 | 
			
		||||
        OrderTransferSimulationUtils(_exchange)
 | 
			
		||||
        LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.16;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract EthBalanceChecker {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										322
									
								
								contracts/dev-utils/contracts/src/ExternalFunctions.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								contracts/dev-utils/contracts/src/ExternalFunctions.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,322 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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.16;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "./Addresses.sol";
 | 
			
		||||
import "./LibAssetData.sol";
 | 
			
		||||
import "./LibTransactionDecoder.sol";
 | 
			
		||||
import "./LibOrderTransferSimulation.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract ExternalFunctions is
 | 
			
		||||
    Addresses
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// @dev Decodes the call data for an Exchange contract method call.
 | 
			
		||||
    /// @param transactionData ABI-encoded calldata for an Exchange
 | 
			
		||||
    ///     contract method call.
 | 
			
		||||
    /// @return The name of the function called, and the parameters it was
 | 
			
		||||
    ///     given.  For single-order fills and cancels, the arrays will have
 | 
			
		||||
    ///     just one element.
 | 
			
		||||
    function decodeZeroExTransactionData(bytes memory transactionData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns(
 | 
			
		||||
            string memory functionName,
 | 
			
		||||
            LibOrder.Order[] memory orders,
 | 
			
		||||
            uint256[] memory takerAssetFillAmounts,
 | 
			
		||||
            bytes[] memory signatures
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibTransactionDecoder.decodeZeroExTransactionData(transactionData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeAssetProxyId(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the asset.
 | 
			
		||||
    function encodeERC20AssetData(address tokenAddress)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.encodeERC20AssetData(tokenAddress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
 | 
			
		||||
    /// @return The AssetProxy identifier, and the address of the ERC-20
 | 
			
		||||
    /// contract hosting this asset.
 | 
			
		||||
    function decodeERC20AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeERC20AssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded.
 | 
			
		||||
    /// @param tokenId The identifier of the specific asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the asset.
 | 
			
		||||
    function encodeERC721AssetData(address tokenAddress, uint256 tokenId)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.encodeERC721AssetData(tokenAddress, tokenId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset.
 | 
			
		||||
    /// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
 | 
			
		||||
    /// contract hosting this asset, and the identifier of the specific
 | 
			
		||||
    /// asset to be traded.
 | 
			
		||||
    function decodeERC721AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256 tokenId
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeERC721AssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded.
 | 
			
		||||
    /// @param tokenIds The identifiers of the specific assets to be traded.
 | 
			
		||||
    /// @param tokenValues The amounts of each asset to be traded.
 | 
			
		||||
    /// @param callbackData Data to be passed to receiving contracts when a transfer is performed.
 | 
			
		||||
    /// @return AssetProxy-compliant asset data describing the set of assets.
 | 
			
		||||
    function encodeERC1155AssetData(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        uint256[] memory tokenIds,
 | 
			
		||||
        uint256[] memory tokenValues,
 | 
			
		||||
        bytes memory callbackData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.encodeERC1155AssetData(
 | 
			
		||||
            tokenAddress,
 | 
			
		||||
            tokenIds,
 | 
			
		||||
            tokenValues,
 | 
			
		||||
            callbackData
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets.
 | 
			
		||||
    /// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
 | 
			
		||||
    /// contract hosting the assets, an array of the identifiers of the
 | 
			
		||||
    /// assets to be traded, an array of asset amounts to be traded, and
 | 
			
		||||
    /// callback data.  Each element of the arrays corresponds to the
 | 
			
		||||
    /// same-indexed element of the other array.  Return values specified as
 | 
			
		||||
    /// `memory` are returned as pointers to locations within the memory of
 | 
			
		||||
    /// the input parameter `assetData`.
 | 
			
		||||
    function decodeERC1155AssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            uint256[] memory tokenIds,
 | 
			
		||||
            uint256[] memory tokenValues,
 | 
			
		||||
            bytes memory callbackData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeERC1155AssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Encode data for multiple assets, per the AssetProxy contract specification.
 | 
			
		||||
    /// @param amounts The amounts of each asset to be traded.
 | 
			
		||||
    /// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded.
 | 
			
		||||
    /// @return AssetProxy-compliant data describing the set of assets.
 | 
			
		||||
    function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory assetData)
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.encodeMultiAssetData(amounts, nestedAssetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode multi-asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant data describing a multi-asset basket.
 | 
			
		||||
    /// @return The Multi-Asset AssetProxy identifier, an array of the amounts
 | 
			
		||||
    /// of the assets to be traded, and an array of the
 | 
			
		||||
    /// AssetProxy-compliant data describing each asset to be traded.  Each
 | 
			
		||||
    /// element of the arrays corresponds to the same-indexed element of the other array.
 | 
			
		||||
    function decodeMultiAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            uint256[] memory amounts,
 | 
			
		||||
            bytes[] memory nestedAssetData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeMultiAssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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)
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.encodeStaticCallAssetData(
 | 
			
		||||
            staticCallTargetAddress,
 | 
			
		||||
            staticCallData,
 | 
			
		||||
            expectedReturnDataHash
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeStaticCallAssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification.
 | 
			
		||||
    /// @param assetData AssetProxy-compliant asset data describing an ERC20Bridge asset
 | 
			
		||||
    /// @return The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address
 | 
			
		||||
    /// of the bridge contract, and extra data to be passed to the bridge contract.
 | 
			
		||||
    function decodeERC20BridgeAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
        returns (
 | 
			
		||||
            bytes4 assetProxyId,
 | 
			
		||||
            address tokenAddress,
 | 
			
		||||
            address bridgeAddress,
 | 
			
		||||
            bytes memory bridgeData
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.decodeERC20BridgeAssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Reverts if assetData is not of a valid format for its given proxy id.
 | 
			
		||||
    /// @param assetData AssetProxy compliant asset data.
 | 
			
		||||
    function revertIfInvalidAssetData(bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        pure
 | 
			
		||||
    {
 | 
			
		||||
        return LibAssetData.revertIfInvalidAssetData(assetData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer.
 | 
			
		||||
    /// @param order The order to simulate transfers for.
 | 
			
		||||
    /// @param takerAddress The address of the taker that will fill the order.
 | 
			
		||||
    /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
 | 
			
		||||
    /// @return The index of the first failed transfer (or 4 if all transfers are successful).
 | 
			
		||||
    function getSimulatedOrderMakerTransferResults(
 | 
			
		||||
        LibOrder.Order memory order,
 | 
			
		||||
        address takerAddress,
 | 
			
		||||
        uint256 takerAssetFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
 | 
			
		||||
    {
 | 
			
		||||
        return LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
 | 
			
		||||
            exchangeAddress,
 | 
			
		||||
            order,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            takerAssetFillAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer.
 | 
			
		||||
    /// @param order The order to simulate transfers for.
 | 
			
		||||
    /// @param takerAddress The address of the taker that will fill the order.
 | 
			
		||||
    /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
 | 
			
		||||
    /// @return The index of the first failed transfer (or 4 if all transfers are successful).
 | 
			
		||||
    function getSimulatedOrderTransferResults(
 | 
			
		||||
        LibOrder.Order memory order,
 | 
			
		||||
        address takerAddress,
 | 
			
		||||
        uint256 takerAssetFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
 | 
			
		||||
    {
 | 
			
		||||
        return LibOrderTransferSimulation.getSimulatedOrderTransferResults(
 | 
			
		||||
            exchangeAddress,
 | 
			
		||||
            order,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            takerAssetFillAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
 | 
			
		||||
    /// @param orders Array of orders to individually simulate transfers for.
 | 
			
		||||
    /// @param takerAddresses Array of addresses of takers that will fill each order.
 | 
			
		||||
    /// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
 | 
			
		||||
    /// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
 | 
			
		||||
    function getSimulatedOrdersTransferResults(
 | 
			
		||||
        LibOrder.Order[] memory orders,
 | 
			
		||||
        address[] memory takerAddresses,
 | 
			
		||||
        uint256[] memory takerAssetFillAmounts
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (LibOrderTransferSimulation.OrderTransferResults[] memory orderTransferResults)
 | 
			
		||||
    {
 | 
			
		||||
        return LibOrderTransferSimulation.getSimulatedOrdersTransferResults(
 | 
			
		||||
            exchangeAddress,
 | 
			
		||||
            orders,
 | 
			
		||||
            takerAddresses,
 | 
			
		||||
            takerAssetFillAmounts
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16,357 +16,17 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.16;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
 | 
			
		||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
 | 
			
		||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
			
		||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LibAssetData is
 | 
			
		||||
    DeploymentConstants
 | 
			
		||||
{
 | 
			
		||||
    // 2^256 - 1
 | 
			
		||||
    uint256 constant internal _MAX_UINT256 = uint256(-1);
 | 
			
		||||
library LibAssetData {
 | 
			
		||||
 | 
			
		||||
    using LibBytes for bytes;
 | 
			
		||||
 | 
			
		||||
    // solhint-disable var-name-mixedcase
 | 
			
		||||
    IExchange internal _EXCHANGE;
 | 
			
		||||
    address internal _ERC20_PROXY_ADDRESS;
 | 
			
		||||
    address internal _ERC721_PROXY_ADDRESS;
 | 
			
		||||
    address internal _ERC1155_PROXY_ADDRESS;
 | 
			
		||||
    address internal _STATIC_CALL_PROXY_ADDRESS;
 | 
			
		||||
    address internal _CHAI_BRIDGE_ADDRESS;
 | 
			
		||||
    // solhint-enable var-name-mixedcase
 | 
			
		||||
 | 
			
		||||
    constructor (
 | 
			
		||||
        address _exchange,
 | 
			
		||||
        address _chaiBridge
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        _EXCHANGE = IExchange(_exchange);
 | 
			
		||||
        _ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
 | 
			
		||||
        _ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
 | 
			
		||||
        _ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
 | 
			
		||||
        _STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.selector);
 | 
			
		||||
        _CHAI_BRIDGE_ADDRESS = _chaiBridge;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the owner's balance of the assets(s) specified in
 | 
			
		||||
    /// assetData.  When the asset data contains multiple assets (eg in
 | 
			
		||||
    /// ERC1155 or Multi-Asset), the return value indicates how many
 | 
			
		||||
    /// complete "baskets" of those assets are owned by owner.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner.
 | 
			
		||||
    function getBalance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 balance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
            balance = _erc20BalanceOf(tokenAddress, ownerAddress);
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Check if id is owned by ownerAddress
 | 
			
		||||
            bytes memory ownerOfCalldata = abi.encodeWithSelector(
 | 
			
		||||
                IERC721Token(address(0)).ownerOf.selector,
 | 
			
		||||
                tokenId
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
 | 
			
		||||
            address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
 | 
			
		||||
            balance = currentOwnerAddress == ownerAddress ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
 | 
			
		||||
            // Get ERC1155 token address, array of ids, and array of values
 | 
			
		||||
            (, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = tokenIds.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the token if the corresponding value is 0.
 | 
			
		||||
                if (tokenValues[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Encode data for `balanceOf(ownerAddress, tokenIds[i])
 | 
			
		||||
                bytes memory balanceOfData = abi.encodeWithSelector(
 | 
			
		||||
                    IERC1155(address(0)).balanceOf.selector,
 | 
			
		||||
                    ownerAddress,
 | 
			
		||||
                    tokenIds[i]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                // Query balance
 | 
			
		||||
                (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
 | 
			
		||||
                uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / tokenValues[i];
 | 
			
		||||
                if (scaledBalance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
 | 
			
		||||
            // Encode data for `staticCallProxy.transferFrom(assetData,...)`
 | 
			
		||||
            bytes memory transferFromData = abi.encodeWithSelector(
 | 
			
		||||
                IAssetProxy(address(0)).transferFrom.selector,
 | 
			
		||||
                assetData,
 | 
			
		||||
                address(0),  // `from` address is not used
 | 
			
		||||
                address(0),  // `to` address is not used
 | 
			
		||||
                0            // `amount` is not used
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Check if staticcall would be successful
 | 
			
		||||
            (bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
 | 
			
		||||
 | 
			
		||||
            // Success means that the staticcall can be made an unlimited amount of times
 | 
			
		||||
            balance = success ? _MAX_UINT256 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
 | 
			
		||||
            // Get address of ERC20 token and bridge contract
 | 
			
		||||
            (, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
 | 
			
		||||
            if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
 | 
			
		||||
                uint256 chaiBalance = _erc20BalanceOf(_getChaiAddress(), ownerAddress);
 | 
			
		||||
                // Calculate Dai balance
 | 
			
		||||
                balance = _convertChaiToDaiAmount(chaiBalance);
 | 
			
		||||
            }
 | 
			
		||||
            // Balance will be 0 if bridge is not supported
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the asset if the corresponding amount is 0.
 | 
			
		||||
                if (assetAmounts[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Query balance of individual assetData
 | 
			
		||||
                uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total balance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledBalance = totalBalance / assetAmounts[i];
 | 
			
		||||
                if (scaledBalance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledBalance < balance || balance == 0) {
 | 
			
		||||
                    balance = scaledBalance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Balance will be 0 if assetProxyId is unknown
 | 
			
		||||
        return balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Array of asset balances from getBalance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory balances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        balances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            balances[i] = getBalance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return balances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Returns the number of asset(s) (described by assetData) that
 | 
			
		||||
    /// the corresponding AssetProxy contract is authorized to spend.  When the asset data contains
 | 
			
		||||
    /// multiple assets (eg for Multi-Asset), the return value indicates
 | 
			
		||||
    /// how many complete "baskets" of those assets may be spent by all of the corresponding
 | 
			
		||||
    /// AssetProxy contracts.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        // Get id of AssetProxy contract
 | 
			
		||||
        bytes4 assetProxyId = assetData.readBytes4(0);
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
 | 
			
		||||
            // Get array of values and array of assetDatas
 | 
			
		||||
            (, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            uint256 length = nestedAssetData.length;
 | 
			
		||||
            for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
                // Skip over the asset if the corresponding amount is 0.
 | 
			
		||||
                if (amounts[i] == 0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Query allowance of individual assetData
 | 
			
		||||
                uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
 | 
			
		||||
 | 
			
		||||
                // Scale total allowance down by corresponding value in assetData
 | 
			
		||||
                uint256 scaledAllowance = totalAllowance / amounts[i];
 | 
			
		||||
                if (scaledAllowance == 0) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
                if (scaledAllowance < allowance || allowance == 0) {
 | 
			
		||||
                    allowance = scaledAllowance;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return allowance;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
 | 
			
		||||
            // Get ERC20 token address
 | 
			
		||||
            address tokenAddress = assetData.readAddress(16);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory allowanceData = abi.encodeWithSelector(
 | 
			
		||||
                IERC20Token(address(0)).allowance.selector,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC20_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
 | 
			
		||||
            allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
 | 
			
		||||
            // Get ERC721 token address and id
 | 
			
		||||
            (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                IERC721Token(address(0)).isApprovedForAll.selector,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC721_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
 | 
			
		||||
            // If not approved for all, call `getApproved(tokenId)`
 | 
			
		||||
            if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
 | 
			
		||||
                // Encode data for `getApproved(tokenId)`
 | 
			
		||||
                bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
 | 
			
		||||
                (success, returnData) = tokenAddress.staticcall(getApprovedData);
 | 
			
		||||
 | 
			
		||||
                // Allowance is 1 if successful and the approved address is the ERC721Proxy
 | 
			
		||||
                allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                // Allowance is 2^256 - 1 if `isApprovedForAll` returned true
 | 
			
		||||
                allowance = _MAX_UINT256;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
 | 
			
		||||
            // Get ERC1155 token address
 | 
			
		||||
            (, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
 | 
			
		||||
 | 
			
		||||
            // Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
 | 
			
		||||
            bytes memory isApprovedForAllData = abi.encodeWithSelector(
 | 
			
		||||
                IERC1155(address(0)).isApprovedForAll.selector,
 | 
			
		||||
                ownerAddress,
 | 
			
		||||
                _ERC1155_PROXY_ADDRESS
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Query allowance
 | 
			
		||||
            (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
 | 
			
		||||
            allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
 | 
			
		||||
            // The StaticCallProxy does not require any approvals
 | 
			
		||||
            allowance = _MAX_UINT256;
 | 
			
		||||
 | 
			
		||||
        } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
 | 
			
		||||
            // Get address of ERC20 token and bridge contract
 | 
			
		||||
            (, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
 | 
			
		||||
            if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
 | 
			
		||||
                bytes memory allowanceData = abi.encodeWithSelector(
 | 
			
		||||
                    IERC20Token(address(0)).allowance.selector,
 | 
			
		||||
                    ownerAddress,
 | 
			
		||||
                    _CHAI_BRIDGE_ADDRESS
 | 
			
		||||
                );
 | 
			
		||||
                (bool success, bytes memory returnData) = _getChaiAddress().staticcall(allowanceData);
 | 
			
		||||
                uint256 chaiAllowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
                // Dai allowance is unlimited if Chai allowance is unlimited
 | 
			
		||||
                allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
 | 
			
		||||
            }
 | 
			
		||||
            // Allowance will be 0 if bridge is not supported
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Allowance will be 0 if the assetProxyId is unknown
 | 
			
		||||
        return allowance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getAssetProxyAllowance() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset allowances from getAllowance(), with each
 | 
			
		||||
    /// element corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = assetData.length;
 | 
			
		||||
        allowances = new uint256[](length);
 | 
			
		||||
        for (uint256 i = 0; i != length; i++) {
 | 
			
		||||
            allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return allowances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBalance() and getAllowance() for assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Details of asset, encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return Number of assets (or asset baskets) held by owner, and number
 | 
			
		||||
    /// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
 | 
			
		||||
    function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 balance, uint256 allowance)
 | 
			
		||||
    {
 | 
			
		||||
        balance = getBalance(ownerAddress, assetData);
 | 
			
		||||
        allowance = getAssetProxyAllowance(ownerAddress, assetData);
 | 
			
		||||
        return (balance, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
 | 
			
		||||
    /// @param ownerAddress Owner of the assets specified by assetData.
 | 
			
		||||
    /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
 | 
			
		||||
    /// @return An array of asset balances from getBalance(), and an array of
 | 
			
		||||
    /// asset allowances from getAllowance(), with each element
 | 
			
		||||
    /// corresponding to the same-indexed element in the assetData input.
 | 
			
		||||
    function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256[] memory balances, uint256[] memory allowances)
 | 
			
		||||
    {
 | 
			
		||||
        balances = getBatchBalances(ownerAddress, assetData);
 | 
			
		||||
        allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
 | 
			
		||||
        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
 | 
			
		||||
@@ -691,44 +351,4 @@ contract LibAssetData is
 | 
			
		||||
            revert("WRONG_PROXY_ID");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Queries balance of an ERC20 token. Returns 0 if call was unsuccessful.
 | 
			
		||||
    /// @param tokenAddress Address of ERC20 token.
 | 
			
		||||
    /// @param ownerAddress Address of owner of ERC20 token.
 | 
			
		||||
    /// @return balance ERC20 token balance of owner.
 | 
			
		||||
    function _erc20BalanceOf(
 | 
			
		||||
        address tokenAddress,
 | 
			
		||||
        address ownerAddress
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 balance)
 | 
			
		||||
    {
 | 
			
		||||
        // Encode data for `balanceOf(ownerAddress)`
 | 
			
		||||
        bytes memory balanceOfData = abi.encodeWithSelector(
 | 
			
		||||
            IERC20Token(address(0)).balanceOf.selector,
 | 
			
		||||
            ownerAddress
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Query balance
 | 
			
		||||
        (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
 | 
			
		||||
        balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
 | 
			
		||||
        return balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Converts an amount of Chai into its equivalent Dai amount.
 | 
			
		||||
    ///      Also accumulates Dai from DSR if called after the last time it was collected.
 | 
			
		||||
    /// @param chaiAmount Amount of Chai to converts.
 | 
			
		||||
    function _convertChaiToDaiAmount(uint256 chaiAmount)
 | 
			
		||||
        internal
 | 
			
		||||
        returns (uint256 daiAmount)
 | 
			
		||||
    {
 | 
			
		||||
        PotLike pot = IChai(_getChaiAddress()).pot();
 | 
			
		||||
        // Accumulate savings if called after last time savings were collected
 | 
			
		||||
        uint256 chiMultiplier = (now > pot.rho())
 | 
			
		||||
            ? pot.drip()
 | 
			
		||||
            : pot.chi();
 | 
			
		||||
        daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
 | 
			
		||||
        return daiAmount;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user