Compare commits
	
		
			740 Commits
		
	
	
		
			@0x/migrat
			...
			@0x/contra
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ec92cea598 | ||
|  | 0e25f8ba32 | ||
|  | 23602ec6b4 | ||
|  | f4da2a129d | ||
|  | ab6938f614 | ||
|  | 09ec6d637b | ||
|  | 703e8e06a3 | ||
|  | 47f30d097a | ||
|  | 5c18b394a4 | ||
|  | fb5afafbbe | ||
|  | b3f71af850 | ||
|  | 093fb6e68d | ||
|  | a8ae2b7355 | ||
|  | d45f64ab06 | ||
|  | 050343c97a | ||
|  | 64f5aaccd7 | ||
|  | 856472452a | ||
|  | f06e7a511e | ||
|  | f6bd8c939c | ||
|  | d09040d1d3 | ||
|  | 00fcdbd43a | ||
|  | 4dfd91e2df | ||
|  | 50f86dd61b | ||
|  | 9c219159c6 | ||
|  | e1195a3444 | ||
|  | 7fe4a03683 | ||
|  | 803505cacc | ||
|  | e05e118bd2 | ||
|  | c883f5ea41 | ||
|  | 0567b3332b | ||
|  | cc2833b372 | ||
|  | 0165d67dc1 | ||
|  | 1a4489b96a | ||
|  | 1ecc4a14ca | ||
|  | 9eba6d7146 | ||
|  | 3724ac4b67 | ||
|  | d912175a7a | ||
|  | 5f23eee6dc | ||
|  | 5fe607557d | ||
|  | 5d6584b0eb | ||
|  | 7bdb77d93f | ||
|  | 2530d47fde | ||
|  | 2b8226a757 | ||
|  | 92d5adaac4 | ||
|  | 0c9daa693e | ||
|  | 89729e828c | ||
|  | c2113caae1 | ||
|  | e0adb6624d | ||
|  | 022855add0 | ||
|  | 4dd1c48dc8 | ||
|  | cdc2393aa6 | ||
|  | 94f94bdda7 | ||
|  | 3264bd223d | ||
|  | 6292c0703c | ||
|  | 9a28079f2a | ||
|  | c612649f02 | ||
|  | eda44d1ffb | ||
|  | 4c2f77c014 | ||
|  | 6b8bbd3d5f | ||
|  | e914e1b7fa | ||
|  | 3d2ce749a8 | ||
|  | 9892d8d6d2 | ||
|  | 218a7ab810 | ||
|  | 6779e52813 | ||
|  | 5d51b40541 | ||
|  | b12b7069f7 | ||
|  | 10a5d38446 | ||
|  | e39e7a934e | ||
|  | b7127d8506 | ||
|  | a12e07b1a8 | ||
|  | 8ff5c0a603 | ||
|  | c5c8506cc6 | ||
|  | dbef531d66 | ||
|  | 4e9c9ca079 | ||
|  | d7c61fea4c | ||
|  | 08dc5fafa0 | ||
|  | 78493a9d98 | ||
|  | e274d8994a | ||
|  | 2dee887e6f | ||
|  | f7eb20a235 | ||
|  | f3cea0ebd0 | ||
|  | 05e00d278f | ||
|  | 107c7a71f9 | ||
|  | 56698fb09e | ||
|  | 55bb6f89d3 | ||
|  | 47d77cbddd | ||
|  | 2547e0e5b1 | ||
|  | 1a4699ecac | ||
|  | c825643b67 | ||
|  | a425d3a234 | ||
|  | 3041e7459e | ||
|  | 1fb9d54174 | ||
|  | 598607f5a3 | ||
|  | 5c5bb20415 | ||
|  | 6199a17791 | ||
|  | 7dd42ad6aa | ||
|  | c7fd85633d | ||
|  | b3df71bebf | ||
|  | 88d95ebdbc | ||
|  | 140cf4d378 | ||
|  | 451a19117f | ||
|  | aa6ab33b93 | ||
|  | 8ec04271f3 | ||
|  | f583de652f | ||
|  | 96cd9de8a6 | ||
|  | 9a17cb4c92 | ||
|  | 021cba9fad | ||
|  | 47f4321611 | ||
|  | 775a41a789 | ||
|  | f6c61ed79f | ||
|  | 152e057e08 | ||
|  | 8b84ecc593 | ||
|  | 9c10babefd | ||
|  | 67193d9472 | ||
|  | 7d04dd9520 | ||
|  | 93bda7972c | ||
|  | 92c0e34ed2 | ||
|  | c0a471b349 | ||
|  | 2543076d16 | ||
|  | e32bb6fc0f | ||
|  | 7020166473 | ||
|  | 16ae47f2ad | ||
|  | abf1141ad8 | ||
|  | 3790e0a741 | ||
|  | 9e1966b4fe | ||
|  | 38e06e57a3 | ||
|  | 7f2fc90677 | ||
|  | 1f0ab54fc5 | ||
|  | 7f8c11a74c | ||
|  | 7a4d64d90d | ||
|  | 7217bfa35e | ||
|  | 25077affc8 | ||
|  | 7a80583655 | ||
|  | c21fe0cb50 | ||
|  | 3d08e79089 | ||
|  | c43db2d096 | ||
|  | 220856d084 | ||
|  | a01eafa4e7 | ||
|  | f9c2d25352 | ||
|  | d2f77d74e6 | ||
|  | c3b928c1f5 | ||
|  | 9dfa9c194e | ||
|  | 1a3dc6cefc | ||
|  | 1a73daf82a | ||
|  | 6b20c9a542 | ||
|  | 76c996250d | ||
|  | 52e8de9966 | ||
|  | 81ab84b087 | ||
|  | e34755a1ef | ||
|  | 6c11b2ad8a | ||
|  | ede6ecc3aa | ||
|  | 9db69f33e4 | ||
|  | 17d5d4648b | ||
|  | e203b5593a | ||
|  | de9aa063c0 | ||
|  | 077d001b42 | ||
|  | dfd46d68ac | ||
|  | 4dbe137999 | ||
|  | 1ac5cb404f | ||
|  | 43ffa2dd77 | ||
|  | 1efa7935b7 | ||
|  | b0835b005a | ||
|  | 30946ac110 | ||
|  | 9427858755 | ||
|  | 53864d3817 | ||
|  | ab283ddd9b | ||
|  | 7efcf9066c | ||
|  | 219e09d157 | ||
|  | d816551dba | ||
|  | 04c5752b8a | ||
|  | ed12d8b95f | ||
|  | f48852742d | ||
|  | b84d89367a | ||
|  | d8dab6a070 | ||
|  | ac2443690c | ||
|  | 5df0f13eb0 | ||
|  | 24d782fb19 | ||
|  | 01a5472318 | ||
|  | 4b7a2e9d49 | ||
|  | 62936e3502 | ||
|  | d6b3e4fbaa | ||
|  | a5f011f4a4 | ||
|  | c6efaab01d | ||
|  | 0f7282d9a9 | ||
|  | a3b414a986 | ||
|  | 8a6d0b67f1 | ||
|  | f78ff91975 | ||
|  | c8e416f3b1 | ||
|  | d61f67d24a | ||
|  | 258ffdcc94 | ||
|  | 1f93f09864 | ||
|  | 7afddb9309 | ||
|  | 5eb4dbd5d9 | ||
|  | fc39ddfb71 | ||
|  | ba04a8bc0c | ||
|  | 02d4a28402 | ||
|  | ea2bf07ea6 | ||
|  | b5dc734dc4 | ||
|  | 7dd9b0ba66 | ||
|  | 69a5c8a317 | ||
|  | b975ac7c31 | ||
|  | dcede832c8 | ||
|  | f40bbbc238 | ||
|  | 361f5ca5cc | ||
|  | a710ebe5b3 | ||
|  | 2becef23ff | ||
|  | f916d293fa | ||
|  | f312a260cc | ||
|  | fd9b51c7db | ||
|  | 1dac6b6157 | ||
|  | c2ba6b3a0f | ||
|  | 576bd5585f | ||
|  | ae61a87190 | ||
|  | 2e8f2ae769 | ||
|  | b507a308e6 | ||
|  | ad83b17fdf | ||
|  | e452cfcd59 | ||
|  | 6474a4e08c | ||
|  | e78288ddfd | ||
|  | 6e2d0ab13d | ||
|  | bfbc78c95c | ||
|  | 368ae86530 | ||
|  | d8ccc1694d | ||
|  | b4e10b1e06 | ||
|  | 05f76958ac | ||
|  | 1183cf5e6b | ||
|  | bf9eb1413b | ||
|  | 38d48a8f20 | ||
|  | ca222a470d | ||
|  | 49ca8840ea | ||
|  | faaeba78bb | ||
|  | 6c37d47f2f | ||
|  | 185e53149f | ||
|  | 4329a252ee | ||
|  | 8d38d69684 | ||
|  | edb5e50253 | ||
|  | 81ab2e75ca | ||
|  | e0d8398cf7 | ||
|  | 4fd46d1c95 | ||
|  | c217764fe0 | ||
|  | 42124274c7 | ||
|  | 562342ac99 | ||
|  | 14b573ebfd | ||
|  | e3834c2fc0 | ||
|  | c2f3757de7 | ||
|  | 4b0010be63 | ||
|  | 078af36e0e | ||
|  | b17d12fe23 | ||
|  | 294c0b449b | ||
|  | bc3927e973 | ||
|  | a2cfdd2975 | ||
|  | 53b4f48b2e | ||
|  | 635b80440a | ||
|  | f2d95477e6 | ||
|  | 1005e4962a | ||
|  | 487bc1a08b | ||
|  | 0cf768185e | ||
|  | b5558a8cff | ||
|  | af2b8dfde5 | ||
|  | 2bde5f7034 | ||
|  | c38f913a84 | ||
|  | 44b4f91208 | ||
|  | 9c4ad6ac32 | ||
|  | b151c0b701 | ||
|  | d4b6db773f | ||
|  | 7da71c0955 | ||
|  | 32adb35c2a | ||
|  | 2f197d128a | ||
|  | 5415bc4590 | ||
|  | f6086b8054 | ||
|  | c9d77d7fa0 | ||
|  | ab8c457c51 | ||
|  | 5d91ad3656 | ||
|  | 78ffca06ea | ||
|  | 0d71ec93e7 | ||
|  | d4c771dc7d | ||
|  | 68004466bb | ||
|  | 4dd2d1afaf | ||
|  | 4947676434 | ||
|  | ea5e83da03 | ||
|  | 0705276ff9 | ||
|  | 0299abf1b5 | ||
|  | 132394ffbe | ||
|  | 40edcef340 | ||
|  | bf22eba795 | ||
|  | e990272db3 | ||
|  | 401a0eadb1 | ||
|  | 5852e0b476 | ||
|  | 401df5f45d | ||
|  | 7da40fd7bc | ||
|  | 89740dc24c | ||
|  | 4d7ba42f8f | ||
|  | bbd9c4ef67 | ||
|  | de036ae96a | ||
|  | e5985d7c3f | ||
|  | fb54c45d7d | ||
|  | f1b704a91a | ||
|  | b99eab6804 | ||
|  | 82acc26f97 | ||
|  | 569a165c87 | ||
|  | 704adcb03d | ||
|  | 197cdee604 | ||
|  | 3dc5de936e | ||
|  | d88eb6a5c9 | ||
|  | a168f34538 | ||
|  | 7b150bab73 | ||
|  | b0e38f79ea | ||
|  | a68ebc27ed | ||
|  | 25705bd314 | ||
|  | 85c9b7d9c5 | ||
|  | 629c2ecba2 | ||
|  | be0662a41d | ||
|  | 1985fec892 | ||
|  | 2cbdd76aa3 | ||
|  | 73ae0541d8 | ||
|  | 22621b9f76 | ||
|  | c9f214504a | ||
|  | e8a2d1240f | ||
|  | f2e0fe49f7 | ||
|  | 4ce7bf56e7 | ||
|  | 29be232ae9 | ||
|  | 794c0342ee | ||
|  | d5a22829ac | ||
|  | b58d4005d3 | ||
|  | c16d9d85a2 | ||
|  | 92aeca1f30 | ||
|  | b81ed67975 | ||
|  | 2bc6582e6b | ||
|  | b27311da2e | ||
|  | ab8a0da16a | ||
|  | 800e37ed03 | ||
|  | 950e84fe5c | ||
|  | fdbc235fd6 | ||
|  | ffdb5c06f6 | ||
|  | 14f0f89798 | ||
|  | 54b53184b7 | ||
|  | 75b1cdac66 | ||
|  | d21f394531 | ||
|  | 86d90599ca | ||
|  | ec24976789 | ||
|  | 00eaa8bd34 | ||
|  | 5c44163d68 | ||
|  | f73bad5c13 | ||
|  | a063fa6fe0 | ||
|  | 894ad8af21 | ||
|  | c01793599f | ||
|  | 63db393b60 | ||
|  | 5846166c85 | ||
|  | 25e941128a | ||
|  | 22964ff913 | ||
|  | 62a58667ba | ||
|  | c868015989 | ||
|  | 565e5e5770 | ||
|  | 198831d084 | ||
|  | d3be097436 | ||
|  | 1259de5be4 | ||
|  | df6be48638 | ||
|  | 4923fdbb73 | ||
|  | 66964a5a2f | ||
|  | 97e24d0e14 | ||
|  | fe0b75ef26 | ||
|  | 4b76efbc28 | ||
|  | 11cff4d391 | ||
|  | 59211c1c1e | ||
|  | c0ab2e8127 | ||
|  | d39e90bfa1 | ||
|  | 16e55457c8 | ||
|  | ea2a453811 | ||
|  | 7d2a768a0c | ||
|  | 78304c4369 | ||
|  | 85f243e2e0 | ||
|  | 785ca4f5d1 | ||
|  | 730e8ad151 | ||
|  | b3e6e23508 | ||
|  | f09d56cdb9 | ||
|  | b51933c4d9 | ||
|  | 477791a600 | ||
|  | f0d6476f92 | ||
|  | fa4accd0c4 | ||
|  | e64754f554 | ||
|  | 5badb1eb5d | ||
|  | 9c52fd1f2a | ||
|  | 27e01b9249 | ||
|  | 5bf0de5519 | ||
|  | 139a4acb1b | ||
|  | 9d8b2d9e0c | ||
|  | d16a0f1b56 | ||
|  | edb63c0f26 | ||
|  | bd3a80bcde | ||
|  | 9f0da8ec39 | ||
|  | 42ed4e393f | ||
|  | 99ffe6bb2d | ||
|  | 70898be894 | ||
|  | 9f1859575d | ||
|  | 0167689374 | ||
|  | 053c5f0f88 | ||
|  | fa6516d0be | ||
|  | 7fb0e1b39c | ||
|  | 8ba439c263 | ||
|  | 1a1f24146c | ||
|  | 086fa31d04 | ||
|  | b5e02d1b74 | ||
|  | e88aee6ad9 | ||
|  | fb4ead84f5 | ||
|  | 298967e639 | ||
|  | 903a9947a3 | ||
|  | 72beb59d63 | ||
|  | 75dd1be40e | ||
|  | 6a7c2918bb | ||
|  | 9b9ee2415d | ||
|  | f1f38fb8b0 | ||
|  | 1e44bcb7c9 | ||
|  | 11e689156e | ||
|  | 6c792e89f9 | ||
|  | 11026fe36a | ||
|  | 3133dde3a3 | ||
|  | b666ca0271 | ||
|  | de5c6c1ed0 | ||
|  | 34f4cf133b | ||
|  | 1ba54af4e2 | ||
|  | 42e0d608c8 | ||
|  | 2c35d63976 | ||
|  | d1ca1e768f | ||
|  | 2255cc2ebc | ||
|  | 6512c12f40 | ||
|  | fc8d428d1d | ||
|  | e07613818d | ||
|  | de59ae11bd | ||
|  | 026690c837 | ||
|  | c223a72f5b | ||
|  | c66cf83ef1 | ||
|  | 30cf9ac857 | ||
|  | b99b9d5435 | ||
|  | 81b9ab2b6e | ||
|  | 78a60a9973 | ||
|  | fca6f838d5 | ||
|  | 4a39eb7931 | ||
|  | 00ab5f0afb | ||
|  | 34dfd73aab | ||
|  | 9e0e12a468 | ||
|  | 1bdcb4f737 | ||
|  | 5e5ecdcf32 | ||
|  | b316217394 | ||
|  | d96e307e2c | ||
|  | a7944bb3c5 | ||
|  | 2dc3885691 | ||
|  | 027ab98a3e | ||
|  | 1a5736a498 | ||
|  | 73f4c036c6 | ||
|  | 6cbadcf8e9 | ||
|  | 6a38f231b1 | ||
|  | 02d63daba5 | ||
|  | 99074b3c34 | ||
|  | bb33609164 | ||
|  | 27832741e4 | ||
|  | 0cffdc9868 | ||
|  | 6055d44120 | ||
|  | 984305d483 | ||
|  | 7934624afc | ||
|  | e7db5aa4f3 | ||
|  | e922299a55 | ||
|  | 58cbc7a05f | ||
|  | 43648a2382 | ||
|  | c1abaa3293 | ||
|  | 9f77879198 | ||
|  | 79279e5614 | ||
|  | d100897b20 | ||
|  | bfaaefaf0a | ||
|  | 520c6fa426 | ||
|  | d95b520512 | ||
|  | 10f8637802 | ||
|  | b327cc0f52 | ||
|  | 88acdaff90 | ||
|  | d5039809de | ||
|  | 2746b73416 | ||
|  | fdd1d20c5b | ||
|  | e2b4670016 | ||
|  | 336adc6974 | ||
|  | 7c72ac52e1 | ||
|  | d165bb2bb2 | ||
|  | 12dea02fab | ||
|  | 5181ee172b | ||
|  | def0d9307e | ||
|  | 45e572388b | ||
|  | 4898de8d41 | ||
|  | 1aa2270d97 | ||
|  | 5abc9a8066 | ||
|  | a8deb6cc74 | ||
|  | 87bcb46f43 | ||
|  | 3d904aac67 | ||
|  | ace63fe83a | ||
|  | 33320fd758 | ||
|  | be5b4b7702 | ||
|  | 5c55064c0f | ||
|  | 71ad8dcec0 | ||
|  | 09fd8bc521 | ||
|  | ace0150fcb | ||
|  | e627d3ce01 | ||
|  | a65f981f55 | ||
|  | dbebb3818d | ||
|  | 2027b74c5f | ||
|  | 5e921fdd08 | ||
|  | 6eda017719 | ||
|  | 9b9960c7b9 | ||
|  | 9df09e2464 | ||
|  | 5dacc58a4e | ||
|  | fcb18e8d34 | ||
|  | 9af95a9461 | ||
|  | bef662a6e1 | ||
|  | 04f24f32e2 | ||
|  | 65743882bb | ||
|  | 9e82b51eb5 | ||
|  | a20c40ca90 | ||
|  | 745bdda1a3 | ||
|  | 3c7e538202 | ||
|  | 786419fee0 | ||
|  | 739651b917 | ||
|  | e374469818 | ||
|  | 2ecd9672c2 | ||
|  | 68a4ad2e51 | ||
|  | b2e2c27775 | ||
|  | 8e45d5e137 | ||
|  | 1ded7cd4f1 | ||
|  | 8bd2411a89 | ||
|  | 907fba7d0f | ||
|  | bb5afc43b9 | ||
|  | a243c9d685 | ||
|  | 829eeb2374 | ||
|  | 338de4ffa1 | ||
|  | c7fbd6c64c | ||
|  | 95b7ae3146 | ||
|  | ded48fd453 | ||
|  | cbe2cf8a85 | ||
|  | a12dc5c81b | ||
|  | db062154d1 | ||
|  | ac3a6426e8 | ||
|  | f1f5b57254 | ||
|  | 3403e8af9b | ||
|  | 19286db952 | ||
|  | 40234e5b4a | ||
|  | a9f046609c | ||
|  | f2e2672e81 | ||
|  | 784f2674a9 | ||
|  | 93399165e7 | ||
|  | 7422485817 | ||
|  | 2ef19f31db | ||
|  | 8154209eab | ||
|  | d56fb374a7 | ||
|  | 7bad1d2921 | ||
|  | 37dd494abd | ||
|  | a9748e1b52 | ||
|  | cc33101923 | ||
|  | 31fbbb52a8 | ||
|  | d2c5665a30 | ||
|  | 06744ee7fb | ||
|  | 3e1db453ff | ||
|  | ec76186c23 | ||
|  | fcf975a65c | ||
|  | e6d2c7db88 | ||
|  | d012268953 | ||
|  | 70b797cb6d | ||
|  | 28d7cf38c8 | ||
|  | 6094fa7b6d | ||
|  | 8f3b7ee522 | ||
|  | 74f6fb7408 | ||
|  | 4ccb735282 | ||
|  | b94631c84a | ||
|  | 2544e4fd65 | ||
|  | 7454a7a6f3 | ||
|  | 13e262b9cf | ||
|  | b4db9d8b7d | ||
|  | 14ad5ced78 | ||
|  | b2e592bb41 | ||
|  | 1a3281a959 | ||
|  | 6701c58a10 | ||
|  | 80fd0db2eb | ||
|  | 7ca8c5c16d | ||
|  | 3ed7cc5cab | ||
|  | 0987ae05a8 | ||
|  | 3154149d37 | ||
|  | 6f46109617 | ||
|  | b0896408d2 | ||
|  | 243b478b99 | ||
|  | fabbad2b2c | ||
|  | 1948ffe7bd | ||
|  | 67baee60f8 | ||
|  | 8f4c4715e2 | ||
|  | 3e7cbe6015 | ||
|  | 0053bde668 | ||
|  | 363dd31768 | ||
|  | f841737adc | ||
|  | 9adaa7972e | ||
|  | ec387f9bb7 | ||
|  | aa657776fc | ||
|  | f12632a1f2 | ||
|  | 4f8164dc43 | ||
|  | 88303d8855 | ||
|  | 4e8ddafa64 | ||
|  | 1ebe9d2bba | ||
|  | fbae619725 | ||
|  | 8c5f4c3de7 | ||
|  | 154841157f | ||
|  | 6a20d06194 | ||
|  | 245e118016 | ||
|  | fcc9d6749c | ||
|  | 9e091c5015 | ||
|  | 01247319c3 | ||
|  | 1d3d5f7e32 | ||
|  | 49f2cef5ac | ||
|  | 926d165321 | ||
|  | 86218445cd | ||
|  | 6e0f695699 | ||
|  | 7b9ff7776d | ||
|  | e0f3f53d42 | ||
|  | 2e911ee709 | ||
|  | 43afed6654 | ||
|  | 0dda8328af | ||
|  | 48052fc3e4 | ||
|  | 5ac5fed513 | ||
|  | 60521e8167 | ||
|  | 510568d4f1 | ||
|  | 3e3ec3134d | ||
|  | c22374893e | ||
|  | 013eaeeb07 | ||
|  | b97b6867d8 | ||
|  | 87f31ec532 | ||
|  | 9b12695443 | ||
|  | cbb40c1c2b | ||
|  | b0e56fc27b | ||
|  | d15532227d | ||
|  | c3f98e95ad | ||
|  | e92e99d6ea | ||
|  | f6b67f6c98 | ||
|  | 108861b6ca | ||
|  | 80d93e8d75 | ||
|  | 1634cd53be | ||
|  | 577df3749d | ||
|  | 73c53b3da6 | ||
|  | 9af996a907 | ||
|  | bd2e4a8076 | ||
|  | ceaa6a592c | ||
|  | b503fecccb | ||
|  | 4161055cc7 | ||
|  | b0c9a3bbe1 | ||
|  | 436bdde461 | ||
|  | 01853064b0 | ||
|  | c1ccb5af0f | ||
|  | 706f04ee27 | ||
|  | 549e35e972 | ||
|  | 1ed66966a8 | ||
|  | 326539f1f5 | ||
|  | 67322ba39f | ||
|  | 41fcc41bd1 | ||
|  | 7aacff62ca | ||
|  | 4566ddb037 | ||
|  | 957e6b1500 | ||
|  | 5945635d1d | ||
|  | 045fc0914b | ||
|  | 72442871aa | ||
|  | bbd3c03969 | ||
|  | a4405c3d39 | ||
|  | 0fe4f587d8 | ||
|  | d3c714bd17 | ||
|  | c399b7a7d5 | ||
|  | b9234e94fb | ||
|  | 417bb87785 | ||
|  | 0233ae3134 | ||
|  | eed0c5dd59 | ||
|  | 2b3b167095 | ||
|  | 5d91d19808 | ||
|  | 0f374ddee9 | ||
|  | a65a9913cd | ||
|  | 1ead32c666 | ||
|  | d1af9fc780 | ||
|  | 0f06737fb6 | ||
|  | 1676231532 | ||
|  | b1caf697c8 | ||
|  | 51481065fe | ||
|  | e367da710c | ||
|  | f493d6524d | ||
|  | e1b85da2a7 | ||
|  | 22c6548ed1 | ||
|  | afb32c087d | ||
|  | bbc1ed1c64 | ||
|  | 3a46f1a27a | ||
|  | 90cd364780 | ||
|  | 6795e6f078 | ||
|  | cfb3404349 | ||
|  | 0212f3ee78 | ||
|  | 6b2995a4ee | ||
|  | 09e7ac54d4 | ||
|  | f69009d4a8 | ||
|  | 206802ae33 | ||
|  | 91d4138fb8 | ||
|  | cb455f951a | ||
|  | 5f25d20cd0 | ||
|  | 1f0e2cd910 | ||
|  | 1749d02701 | ||
|  | 55ace3179c | ||
|  | 7866d9ccb4 | ||
|  | 51f73d07fa | ||
|  | 63d84674ab | ||
|  | 14066997b2 | ||
|  | 28561e765a | ||
|  | 453fbbdc5d | ||
|  | 1e1e5ec10d | ||
|  | 2088b0e459 | ||
|  | 58400d9e01 | ||
|  | ac9375f1d2 | ||
|  | db061c9355 | ||
|  | d5ce6c464b | ||
|  | b06205bb7f | ||
|  | f528a3e1de | ||
|  | bddfdacfad | ||
|  | d3cdd3f235 | ||
|  | 41ae45ea40 | ||
|  | 657e0895ea | ||
|  | b2592d1cc2 | ||
|  | aa3524c3b2 | ||
|  | 39deb1a05f | ||
|  | 302d08e290 | ||
|  | 05489dd7f1 | ||
|  | 55bd076602 | ||
|  | 7a224fe08f | ||
|  | 3bdeb82097 | ||
|  | f49ab3f919 | ||
|  | 42d5bdd3ab | ||
|  | 7228cbfe92 | ||
|  | 11e2fc5bc4 | ||
|  | 3e88f820b8 | ||
|  | 163750f8c2 | ||
|  | 4aabc5d791 | ||
|  | c9a7b9dcc1 | ||
|  | 98075b5653 | ||
|  | 57ae5be916 | ||
|  | 8caf62997f | ||
|  | f8656ad376 | ||
|  | 29c6c2a2ad | ||
|  | f2db67ef02 | ||
|  | 72b8ef33d9 | 
| @@ -1,25 +1,35 @@ | ||||
| version: 2.1 | ||||
| version: 2 | ||||
|  | ||||
| jobs: | ||||
|     build: | ||||
|         resource_class: xlarge | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         environment: | ||||
|             NODE_OPTIONS: '--max-old-space-size=16384' | ||||
|             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.22.0 | ||||
|                   command: npm install --global yarn@1.17.0 | ||||
|             - run: | ||||
|                   name: yarn | ||||
|                   command: yarn --frozen-lockfile --ignore-engines install || yarn --frozen-lockfile --ignore-engines install | ||||
|             - setup_remote_docker | ||||
|             - run: yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci || yarn build:ci | ||||
|             - run: yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts || yarn build:ts | ||||
|             - run: yarn build:ci | ||||
|             - run: yarn build:ts | ||||
|             - save_cache: | ||||
|                   key: repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   paths: | ||||
| @@ -27,116 +37,255 @@ jobs: | ||||
|             - store_artifacts: | ||||
|                   path: ~/repo/packages/abi-gen/test-cli/output | ||||
|             - store_artifacts: | ||||
|                   path: ~/repo/packages/contract-wrappers/generated_docs | ||||
|     test-exchange-ganache: | ||||
|                   path: ~/repo/packages/abi-gen-wrappers/generated_docs | ||||
|     test-contracts-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-exchange -m --serial -c test:circleci | ||||
|     test-integrations-ganache: | ||||
|         resource_class: medium+ | ||||
|             - run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils | ||||
|     test-contracts-geth: | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|             - image: 0xorg/devnet | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-integrations -m --serial -c test:circleci | ||||
|     test-contracts-staking-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-staking -m --serial -c test:circleci | ||||
|     test-contracts-extra-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-exchange-forwarder -p @0x/contracts-coordinator -m --serial -c test:circleci | ||||
|     test-contracts-rest-ganache: | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-multisig -p @0x/contracts-utils -p @0x/contracts-exchange-libs -p  @0x/contracts-erc20 -p @0x/contracts-erc721 -p @0x/contracts-erc1155 -p @0x/contracts-asset-proxy -p @0x/contracts-broker -p @0x/contracts-zero-ex -m --serial -c test:circleci | ||||
|             # HACK(albrow): we need to sleep 10 seconds to ensure the devnet is | ||||
|             # initialized | ||||
|             - run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils | ||||
|     test-publish: | ||||
|         resource_class: large | ||||
|         environment: | ||||
|             NODE_OPTIONS: '--max-old-space-size=6442' | ||||
|         resource_class: medium+ | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|             - image: 0xorg/verdaccio | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: | ||||
|                   command: yarn test:publish:circleci | ||||
|                   no_output_timeout: 1800 | ||||
|             - store_artifacts: | ||||
|                   path: ~/.npm/_logs | ||||
|             - run: yarn test:publish:circleci | ||||
|     test-doc-generation: | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: | ||||
|                   command: yarn test:generate_docs:circleci | ||||
|                   no_output_timeout: 1200 | ||||
|             - run: yarn test:generate_docs:circleci | ||||
|     test-rest: | ||||
|         docker: | ||||
|             - image: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - run: yarn wsrun -p @0x/contracts-test-utils -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/contract-artifacts -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/contract-wrappers-test -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/migrations -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/order-utils -m --serial -c test:circleci | ||||
|             - run: yarn wsrun -p @0x/asset-swapper -m --serial -c test:circleci | ||||
|             - run: yarn wsrun test:circleci @0x/contracts-test-utils | ||||
|             - run: yarn wsrun test:circleci @0x/abi-gen | ||||
|             - run: yarn wsrun test:circleci @0x/asset-buyer | ||||
|             - run: yarn wsrun test:circleci @0x/contract-artifacts | ||||
|             - run: yarn wsrun test:circleci @0x/assert | ||||
|             - run: yarn wsrun test:circleci @0x/base-contract | ||||
|             - run: yarn wsrun test:circleci @0x/connect | ||||
|             - run: yarn wsrun test:circleci @0x/contract-wrappers | ||||
|             - run: yarn wsrun test:circleci @0x/dev-utils | ||||
|             - run: yarn wsrun test:circleci @0x/json-schemas | ||||
|             - run: yarn wsrun test:circleci @0x/order-utils | ||||
|             - 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-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   paths: | ||||
|                       - ~/repo/packages/contract-wrappers-test/coverage/lcov.info | ||||
|                       - ~/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-buyer-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   paths: | ||||
|                       - ~/repo/packages/asset-buyer/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 | ||||
|             - save_cache: | ||||
|                   key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                   paths: | ||||
|                       - ~/repo/packages/contract-wrappers/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:2.2.2 | ||||
|             - image: 0xorg/launch-kit-backend:74bcc39 | ||||
|               environment: | ||||
|                   RPC_URL: http://localhost:8545 | ||||
|                   NETWORK_ID: 50 | ||||
|                   WHITELIST_ALL_TOKENS: True | ||||
|               command: | | ||||
|                   sh -c "until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done; node_modules/.bin/forever ts/lib/index.js" | ||||
|         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_without_sra_client coverage run setup.py test | ||||
|                       ./build_docs | ||||
|             - 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_wrappers/src/zero_ex/contract_wrappers/*/__init__.py | ||||
|             - 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: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         steps: | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
| @@ -145,9 +294,11 @@ 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: node:12 | ||||
|             - image: nikolaik/python-nodejs:python3.7-nodejs8 | ||||
|         working_directory: ~/repo | ||||
|         steps: | ||||
|             - restore_cache: | ||||
| @@ -155,35 +306,81 @@ jobs: | ||||
|                       - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-contract-wrappers-test-{{ .Environment.CIRCLE_SHA1 }} | ||||
|                       - coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-assert-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-asset-buyer-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-connect-{{ .Environment.CIRCLE_SHA1 }} | ||||
|             - restore_cache: | ||||
|                   keys: | ||||
|                       - coverage-contract-wrappers-{{ .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 | ||||
|             # 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: | ||||
|             - test-contracts-ganache: | ||||
|                   requires: | ||||
|                       - build | ||||
|             # TODO(albrow): Tests always fail on Geth right now because our fork | ||||
|             # is outdated. Uncomment once we have updated our Geth fork. | ||||
|             # - test-contracts-geth: | ||||
|             #       requires: | ||||
|             #           - build | ||||
|             - test-rest: | ||||
|                   requires: | ||||
|                       - build | ||||
| @@ -196,14 +393,15 @@ workflows: | ||||
|             - test-doc-generation: | ||||
|                   requires: | ||||
|                       - build | ||||
|             # 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 | ||||
|             - submit-coverage: | ||||
|                   requires: | ||||
|                       - test-rest | ||||
|                       - test-python | ||||
|             - static-tests-python: | ||||
|                   requires: | ||||
|                       - test-python | ||||
|             - test-python: | ||||
|                   requires: | ||||
|                       - build | ||||
|             # skip python tox run for now, as we don't yet have multiple test environments to support. | ||||
|             #- test-rest-python | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -2,3 +2,7 @@ | ||||
|  | ||||
| # 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 | ||||
|  | ||||
|   | ||||
							
								
								
									
										30
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,7 +1,37 @@ | ||||
| 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-buyer: ['packages/asset-buyer'] | ||||
| @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/abi-gen-wrappers: ['packages/abi-gen-wrappers'] | ||||
| @0x/contract-artifacts: ['packages/contract-artifacts'] | ||||
| @0x/dev-utils: ['packages/dev-utils'] | ||||
| @0x/contract-wrappers: ['packages/contract-wrappers'] | ||||
| @0x/json-schemas: ['packages/json-schemas'] | ||||
| @0x/ethereum-types: ['ethereum-types'] | ||||
| @0x/connect: ['packages/connect'] | ||||
| @0x/fill-scenarios: ['packages/fill-scenarios'] | ||||
| @0x/testnet-faucets: ['packages/testnet-faucets'] | ||||
| @0x/monorepo-scripts: ['packages/monorepo-scripts'] | ||||
|   | ||||
							
								
								
									
										53
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,53 +0,0 @@ | ||||
| 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 | ||||
							
								
								
									
										133
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										133
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -78,104 +78,77 @@ TODO.md | ||||
| # VSCode file | ||||
| .vscode | ||||
|  | ||||
| # generated contract artifacts/ | ||||
| contracts/broker/generated-artifacts/ | ||||
| contracts/broker/test/generated-artifacts/ | ||||
| contracts/erc20-bridge-sampler/generated-artifacts/ | ||||
| contracts/erc20-bridge-sampler/test/generated-artifacts/ | ||||
| contracts/integrations/generated-artifacts/ | ||||
| contracts/integrations/test/generated-artifacts/ | ||||
| contracts/staking/generated-artifacts/ | ||||
| contracts/staking/test/generated-artifacts/ | ||||
| contracts/coordinator/generated-artifacts/ | ||||
| contracts/coordinator/test/generated-artifacts/ | ||||
| contracts/exchange/generated-artifacts/ | ||||
| contracts/exchange/test/generated-artifacts/ | ||||
| contracts/asset-proxy/generated-artifacts/ | ||||
| contracts/asset-proxy/test/generated-artifacts/ | ||||
| contracts/multisig/generated-artifacts/ | ||||
| contracts/multisig/test/generated-artifacts/ | ||||
| contracts/utils/generated-artifacts/ | ||||
| contracts/utils/test/generated-artifacts/ | ||||
| contracts/exchange-libs/generated-artifacts/ | ||||
| contracts/exchange-libs/test/generated-artifacts/ | ||||
| contracts/erc20/generated-artifacts/ | ||||
| contracts/erc20/test/generated-artifacts/ | ||||
| contracts/erc721/generated-artifacts/ | ||||
| contracts/erc721/test/generated-artifacts/ | ||||
| contracts/erc1155/generated-artifacts/ | ||||
| contracts/erc1155/test/generated-artifacts/ | ||||
| contracts/extensions/generated-artifacts/ | ||||
| contracts/extensions/test/generated-artifacts/ | ||||
| contracts/exchange-forwarder/generated-artifacts/ | ||||
| contracts/exchange-forwarder/test/generated-artifacts/ | ||||
| contracts/dev-utils/generated-artifacts/ | ||||
| contracts/dev-utils/test/generated-artifacts/ | ||||
| contracts/zero-ex/generated-artifacts/ | ||||
| contracts/zero-ex/test/generated-artifacts/ | ||||
| contracts/treasury/generated-artifacts/ | ||||
| contracts/treasury/test/generated-artifacts/ | ||||
| # server cli | ||||
| packages/testnet-faucets/server/ | ||||
|  | ||||
| # generated truffle contract artifacts/ | ||||
| contracts/broker/build/ | ||||
| contracts/erc20-bridge-sampler/build/ | ||||
| contracts/staking/build/ | ||||
| contracts/coordinator/build/ | ||||
| contracts/exchange/build/ | ||||
| contracts/asset-proxy/build/ | ||||
| contracts/multisig/build/ | ||||
| contracts/utils/build/ | ||||
| contracts/exchange-libs/build/ | ||||
| contracts/erc20/build/ | ||||
| contracts/erc721/build/ | ||||
| contracts/erc1155/build/ | ||||
| contracts/extensions/build/ | ||||
| contracts/exchange-forwarder/build/ | ||||
| contracts/dev-utils/build/ | ||||
| # generated contract artifacts/ | ||||
| contracts/coordinator/generated-artifacts/ | ||||
| contracts/exchange/generated-artifacts/ | ||||
| contracts/asset-proxy/generated-artifacts/ | ||||
| contracts/multisig/generated-artifacts/ | ||||
| contracts/utils/generated-artifacts/ | ||||
| contracts/exchange-libs/generated-artifacts/ | ||||
| contracts/erc20/generated-artifacts/ | ||||
| contracts/erc721/generated-artifacts/ | ||||
| contracts/erc1155/generated-artifacts/ | ||||
| contracts/extensions/generated-artifacts/ | ||||
| contracts/exchange-forwarder/generated-artifacts/ | ||||
| contracts/dev-utils/generated-artifacts/ | ||||
| packages/sol-tracing-utils/test/fixtures/artifacts/ | ||||
| python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/ | ||||
|  | ||||
| # generated contract wrappers | ||||
| contracts/broker/generated-wrappers/ | ||||
| contracts/broker/test/generated-wrappers/ | ||||
| packages/python-contract-wrappers/generated/ | ||||
| contracts/erc20-bridge-sampler/generated-wrappers/ | ||||
| contracts/erc20-bridge-sampler/test/generated-wrappers/ | ||||
| contracts/integrations/generated-wrappers/ | ||||
| contracts/integrations/test/generated-wrappers/ | ||||
| contracts/staking/generated-wrappers/ | ||||
| contracts/staking/test/generated-wrappers/ | ||||
| contracts/coordinator/generated-wrappers/ | ||||
| contracts/coordinator/test/generated-wrappers/ | ||||
| contracts/exchange/generated-wrappers/ | ||||
| contracts/exchange/test/generated-wrappers/ | ||||
| contracts/asset-proxy/generated-wrappers/ | ||||
| contracts/asset-proxy/test/generated-wrappers/ | ||||
| contracts/multisig/generated-wrappers/ | ||||
| contracts/multisig/test/generated-wrappers/ | ||||
| contracts/utils/generated-wrappers/ | ||||
| contracts/utils/test/generated-wrappers/ | ||||
| contracts/exchange-libs/generated-wrappers/ | ||||
| contracts/exchange-libs/test/generated-wrappers/ | ||||
| contracts/erc20/generated-wrappers/ | ||||
| contracts/erc20/test/generated-wrappers/ | ||||
| contracts/erc721/generated-wrappers/ | ||||
| contracts/erc721/test/generated-wrappers/ | ||||
| contracts/erc1155/generated-wrappers/ | ||||
| contracts/erc1155/test/generated-wrappers/ | ||||
| contracts/extensions/generated-wrappers/ | ||||
| contracts/extensions/test/generated-wrappers/ | ||||
| contracts/exchange-forwarder/generated-wrappers/ | ||||
| contracts/exchange-forwarder/test/generated-wrappers/ | ||||
| contracts/dev-utils/generated-wrappers/ | ||||
| contracts/dev-utils/test/generated-wrappers/ | ||||
| contracts/zero-ex/generated-wrappers/ | ||||
| contracts/zero-ex/test/generated-wrappers/ | ||||
| contracts/treasury/generated-wrappers/ | ||||
| contracts/treasury/test/generated-wrappers/ | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/asset_proxy_owner/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator_registry/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc20_token/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc721_token/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dutch_auction/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/eth_balance_checker/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/forwarder/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_asset_proxy/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_validator/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_wallet/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/multi_asset_proxy/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/order_validator/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/weth9/__init__.py | ||||
| python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_token/__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 | ||||
| python-packages/json_schemas/src/zero_ex/json_schemas/schemas | ||||
|  | ||||
| # Doc README copy | ||||
| packages/*/docs/README.md | ||||
|  | ||||
| .DS_Store | ||||
|  | ||||
| # the snapshot that gets built for migrations sure does have a ton of files | ||||
| packages/migrations/0x_ganache_snapshot* | ||||
|   | ||||
| @@ -1,90 +1,40 @@ | ||||
| lib | ||||
| .nyc_output | ||||
| /contracts/broker/generated-wrappers | ||||
| /contracts/broker/test/generated-wrappers | ||||
| /contracts/broker/generated-artifacts | ||||
| /contracts/broker/test/generated-artifacts | ||||
| /contracts/integrations/generated-wrappers | ||||
| /contracts/integrations/test/generated-wrappers | ||||
| /contracts/integrations/generated-artifacts | ||||
| /contracts/integrations/test/generated-artifacts | ||||
| /contracts/staking/generated-wrappers | ||||
| /contracts/staking/test/generated-wrappers | ||||
| /contracts/staking/generated-artifacts | ||||
| /contracts/staking/test/generated-artifacts | ||||
| /contracts/coordinator/generated-wrappers | ||||
| /contracts/coordinator/test/generated-wrappers | ||||
| /contracts/coordinator/generated-artifacts | ||||
| /contracts/coordinator/test/generated-artifacts | ||||
| /contracts/exchange/generated-wrappers | ||||
| /contracts/exchange/test/generated-wrappers | ||||
| /contracts/exchange/generated-artifacts | ||||
| /contracts/exchange/test/generated-artifacts | ||||
| /contracts/asset-proxy/generated-wrappers | ||||
| /contracts/asset-proxy/test/generated-wrappers | ||||
| /contracts/asset-proxy/generated-artifacts | ||||
| /contracts/asset-proxy/test/generated-artifacts | ||||
| /contracts/multisig/generated-wrappers | ||||
| /contracts/multisig/test/generated-wrappers | ||||
| /contracts/multisig/generated-artifacts | ||||
| /contracts/multisig/test/generated-artifacts | ||||
| /contracts/utils/generated-wrappers | ||||
| /contracts/utils/test/generated-wrappers | ||||
| /contracts/utils/generated-artifacts | ||||
| /contracts/utils/test/generated-artifacts | ||||
| /contracts/exchange-libs/generated-wrappers | ||||
| /contracts/exchange-libs/test/generated-wrappers | ||||
| /contracts/exchange-libs/generated-artifacts | ||||
| /contracts/exchange-libs/test/generated-artifacts | ||||
| /contracts/erc20/generated-wrappers | ||||
| /contracts/erc20/test/generated-wrappers | ||||
| /contracts/erc20/generated-artifacts | ||||
| /contracts/erc20/test/generated-artifacts | ||||
| /contracts/erc721/generated-wrappers | ||||
| /contracts/erc721/test/generated-wrappers | ||||
| /contracts/erc721/generated-artifacts | ||||
| /contracts/erc721/test/generated-artifacts | ||||
| /contracts/erc1155/generated-wrappers | ||||
| /contracts/erc1155/test/generated-wrappers | ||||
| /contracts/erc1155/generated-artifacts | ||||
| /contracts/erc1155/test/generated-artifacts | ||||
| /contracts/extensions/generated-wrappers | ||||
| /contracts/extensions/test/generated-wrappers | ||||
| /contracts/extensions/generated-artifacts | ||||
| /contracts/extensions/test/generated-artifacts | ||||
| /contracts/exchange-forwarder/generated-wrappers | ||||
| /contracts/exchange-forwarder/test/generated-wrappers | ||||
| /contracts/exchange-forwarder/generated-artifacts | ||||
| /contracts/exchange-forwarder/test/generated-artifacts | ||||
| /contracts/dev-utils/generated-wrappers | ||||
| /contracts/dev-utils/test/generated-wrappers | ||||
| /contracts/dev-utils/generated-artifacts | ||||
| /contracts/dev-utils/test/generated-artifacts | ||||
| /contracts/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/ | ||||
| /contracts/asset-proxy/build/ | ||||
| /contracts/multisig/build/ | ||||
| /contracts/utils/build/ | ||||
| /contracts/exchange-libs/build/ | ||||
| /contracts/erc20/build/ | ||||
| /contracts/erc721/build/ | ||||
| /contracts/erc1155/build/ | ||||
| /contracts/extensions/build/ | ||||
| /contracts/exchange-forwarder/build/ | ||||
| /packages/asset-swapper/generated-artifacts | ||||
| /packages/asset-swapper/generated-wrappers | ||||
| /packages/asset-swapper/test/generated-artifacts | ||||
| /packages/asset-swapper/test/generated-wrappers | ||||
| /packages/abi-gen/test-cli/output | ||||
| /packages/json-schemas/schemas | ||||
| /python-packages/json_schemas/src/zero_ex/json_schemas/schemas | ||||
| /packages/sra-spec/public/ | ||||
| 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 | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| { | ||||
|     "printWidth": 120, | ||||
|     "tabWidth": 4, | ||||
|     "singleQuote": true, | ||||
|     "trailingComma": "all", | ||||
|     "bracketSpacing": true, | ||||
|     "arrowParens": "avoid" | ||||
|     "printWidth": 120, | ||||
|     "trailingComma": all, | ||||
|     "singleQuote": true | ||||
| } | ||||
|   | ||||
| @@ -1,23 +0,0 @@ | ||||
| # 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 | ||||
							
								
								
									
										34
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								CODEOWNERS
									
									
									
									
									
								
							| @@ -5,14 +5,34 @@ | ||||
| # https://git-scm.com/docs/gitignore#_pattern_format | ||||
|  | ||||
| # Website | ||||
| packages/asset-swapper/  @BMillman19 @fragosti @dave4506 | ||||
| packages/instant/  @BMillman19 @fragosti @dave4506 | ||||
| packages/asset-buyer/  @BMillman19 @fragosti @steveklebanoff | ||||
| packages/instant/  @BMillman19 @fragosti @steveklebanoff | ||||
|  | ||||
| # Dev tools & setup | ||||
| .circleci/ @dorothy-zbornak | ||||
| packages/contract-addresses/ @abandeali1 | ||||
| packages/contract-artifacts/ @abandeali1 | ||||
| packages/order-utils/ @dorothy-zbornak  | ||||
| .circleci/ @LogvinovLeon | ||||
| packages/abi-gen/ @feuGeneA | ||||
| packages/base-contract/ @xianny | ||||
| packages/connect/ @fragosti  | ||||
| packages/abi-gen-templates/ @feuGeneA @xianny | ||||
| packages/contract-addresses/ @albrow | ||||
| packages/contract-artifacts/ @albrow | ||||
| 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 | ||||
|  | ||||
| # Protocol/smart contracts | ||||
| contracts/ @abandeali1 @hysz @dorothy-zbornak @mzhu25 | ||||
| contracts/ @abandeali1 @hysz | ||||
|   | ||||
| @@ -4,9 +4,9 @@ We welcome contributions from anyone on the internet and are grateful for even t | ||||
|  | ||||
| ### Getting started | ||||
|  | ||||
| 1.  Fork `0xproject/0x-tools` | ||||
| 1.  Fork `0xproject/0x-monorepo` | ||||
| 2.  Clone your fork | ||||
| 3.  Follow the [installation & build steps](https://github.com/0xProject/0x-tools#install-dependencies) in the repo's top-level README. | ||||
| 3.  Follow the [installation & build steps](https://github.com/0xProject/0x-monorepo#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-tools/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-monorepo/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-tools/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-monorepo/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-tools`, but when running the check against your fork the token needs to match your repo's name `your-username/0x-tools`. | ||||
| 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`. | ||||
|  | ||||
| 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-tools, 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-monorepo, 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. | ||||
|   | ||||
| @@ -49,6 +49,7 @@ | ||||
| | Package | Version | | ||||
| | ------: | :------ | | ||||
|  | ||||
|  | ||||
| <!-- For example: | ||||
| |             `0x.js` | 2.0.4   | | ||||
| | `Exchange Contract` | v2      | | ||||
|   | ||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| Copyright 2020 ZeroEx Labs | ||||
| Copyright 2017 ZeroEx Intl. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
|   | ||||
							
								
								
									
										81
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								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/protocool) | ||||
| [](https://circleci.com/gh/0xProject/0x-monorepo) | ||||
| [](https://coveralls.io/github/0xProject/0x-monorepo?branch=development) | ||||
| [](https://discordapp.com/invite/d3FTX3M) | ||||
| [](https://opensource.org/licenses/Apache-2.0) | ||||
| @@ -17,6 +17,17 @@ 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. | ||||
| @@ -36,19 +47,59 @@ These packages are all under development. See [/contracts/README.md](/contracts/ | ||||
| | [`@0x/contracts-utils`](/contracts/utils)                           | [](https://www.npmjs.com/package/@0x/contracts-utils)                           | Generic libraries and utilities used throughout all of the contracts                                                                                                                                                                                  | | ||||
| | [`@0x/contracts-coordinator`](/contracts/coordinator)               | [](https://www.npmjs.com/package/@0x/contracts-coordinator)               | A contract that allows users to execute 0x transactions with permission from a Coordinator                                                                                                                                                            | | ||||
| | [`@0x/contracts-dev-utils`](/contracts/dev-utils)                   | [](https://www.npmjs.com/package/@0x/contracts-dev-utils)                   | A contract contains utility functions for developers (such as validating many orders using a single eth_call)                                                                                                                                         | | ||||
| | [`@0x/contracts-staking`](/contracts/staking)                       | [](https://www.npmjs.com/package/@0x/contracts-staking)                       | Implements the stake-based liquidity incentives defined by [`ZEIP-31`](https://github.com/0xProject/ZEIPs/issues/31)                                                                                                                                  | | ||||
|  | ||||
| ### TypeScript/Javascript Packages | ||||
|  | ||||
| #### 0x-specific packages | ||||
|  | ||||
| | 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                                                        |     | | ||||
| | 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/abi-gen-wrappers`](/packages/abi-gen-wrappers)     | [](https://www.npmjs.com/package/@0x/abi-gen-wrappers)     | Low-level 0x smart contract wrappers generated using `@0x/abi-gen`                                | | ||||
| | [`@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-buyer`](/packages/asset-buyer)               | [](https://www.npmjs.com/package/@0x/asset-buyer)               | Convenience package for discovering and buying assets with Ether                                  | | ||||
| | [`@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                       | | ||||
| | [`@0x/fill-scenarios`](/packages/fill-scenarios)         | [](https://www.npmjs.com/package/@0x/fill-scenarios)         | 0x order fill scenario generator                                | | ||||
|  | ||||
| #### Private Packages | ||||
|  | ||||
| | Package                                            | Description                                                                      | | ||||
| | -------------------------------------------------- | -------------------------------------------------------------------------------- | | ||||
| | [`@0x/instant`](/packages/instant)                 | A free and flexible way to offer simple crypto purchasing in any app or website. | | ||||
| | [`@0x/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether                 | | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| @@ -81,6 +132,8 @@ 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: | ||||
| @@ -92,7 +145,7 @@ yarn build | ||||
| To build a specific package: | ||||
|  | ||||
| ```bash | ||||
| PKG=@0x/contract-wrappers yarn build | ||||
| PKG=@0x/web3-wrapper yarn build | ||||
| ``` | ||||
|  | ||||
| To build all contracts packages: | ||||
| @@ -115,7 +168,7 @@ To watch a specific package and all it's dependent packages: | ||||
| PKG=[NPM_PACKAGE_NAME] yarn watch | ||||
|  | ||||
| e.g | ||||
| PKG=@0x/contract-wrappers yarn watch | ||||
| PKG=@0x/web3-wrapper yarn watch | ||||
| ``` | ||||
|  | ||||
| ### Clean | ||||
| @@ -143,7 +196,7 @@ yarn rebuild | ||||
| To re-build (clean & build) a specific package & it's deps: | ||||
|  | ||||
| ```bash | ||||
| PKG=@0x/contract-wrappers yarn rebuild | ||||
| PKG=0x.js yarn rebuild | ||||
| ``` | ||||
|  | ||||
| ### Lint | ||||
| @@ -157,7 +210,7 @@ yarn lint | ||||
| Lint a specific package: | ||||
|  | ||||
| ```bash | ||||
| PKG=@0x/contract-wrappers yarn lint | ||||
| PKG=0x.js yarn lint | ||||
| ``` | ||||
|  | ||||
| ### Run Tests | ||||
| @@ -171,7 +224,7 @@ yarn test | ||||
| Run a specific package's test: | ||||
|  | ||||
| ```bash | ||||
| PKG=@0x/contract-wrappers yarn test | ||||
| PKG=@0x/web3-wrapper yarn test | ||||
| ``` | ||||
|  | ||||
| Run all contracts packages tests: | ||||
|   | ||||
| @@ -16,7 +16,6 @@ | ||||
|         "quotes": ["error", "double"], | ||||
|         "separate-by-one-line-in-contract": "error", | ||||
|         "space-after-comma": "error", | ||||
|         "statement-indent": "error", | ||||
|         "no-empty-blocks": false | ||||
|         "statement-indent": "error" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -13,4 +13,4 @@ | ||||
|  | ||||
| #### Development | ||||
|  | ||||
| Building solidity files will update the contract artifact in `{package-name}/generated-artifacts/{contract}.json`, but does not automatically update the `contract-artifacts` or `contract-wrappers` packages, which are generated from the artifact JSON. See `contract-artifacts/README.md` for instructions on updating these packages. | ||||
| Building solidity files will update the contract artifact in `{package-name}/generated-artifacts/{contract}.json`, but does not automatically update the `abi-gen-wrappers` package, which are generated from the artifact JSON. To ensure consistency, clean and rebuild `abi-gen-wrappers` after any changes to the artifact JSON. | ||||
|   | ||||
| @@ -1,10 +0,0 @@ | ||||
| # Blacklist all files | ||||
| .* | ||||
| * | ||||
| # Whitelist lib | ||||
| !lib/**/* | ||||
| # Whitelist Solidity contracts | ||||
| !contracts/src/**/* | ||||
| # Blacklist tests in lib | ||||
| /lib/test/* | ||||
| # Package specific ignore | ||||
| @@ -1,2 +0,0 @@ | ||||
| # solhint can't parse `abi.decode` syntax. | ||||
| contracts/src/ERC1155Proxy.sol | ||||
| @@ -1,617 +1,4 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1628225642, | ||||
|         "version": "3.7.17", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1624356181, | ||||
|         "version": "3.7.16", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1623382456, | ||||
|         "version": "3.7.15", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1622609597, | ||||
|         "version": "3.7.14", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1621944788, | ||||
|         "version": "3.7.13", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1621600614, | ||||
|         "version": "3.7.12", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1620214333, | ||||
|         "version": "3.7.11", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1619596077, | ||||
|         "version": "3.7.10", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "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", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1580811564, | ||||
|         "version": "3.1.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1579682890, | ||||
|         "version": "3.1.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "3.1.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Integration tests for DydxBridge with ERC20BridgeProxy.", | ||||
|                 "pr": 2401 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Fix `UniswapBridge` token -> token transfer call.", | ||||
|                 "pr": 2412 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Fix `KyberBridge` incorrect `minConversionRate` calculation.", | ||||
|                 "pr": 2412 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1578272714 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1576540892, | ||||
|         "version": "3.0.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1575931811, | ||||
|         "version": "3.0.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "3.0.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Implement `KyberBridge`.", | ||||
|                 "pr": 2352 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils", | ||||
|                 "pr": 2330 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract", | ||||
|                 "pr": 2034 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable", | ||||
|                 "pr": 2019 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Remove `LibAssetProxyIds` contract", | ||||
|                 "pr": 2055 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Compile and export all contracts, artifacts, and wrappers by default", | ||||
|                 "pr": 2055 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Remove unused dependency on IAuthorizable in IAssetProxy", | ||||
|                 "pr": 1910 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `ERC20BridgeProxy`", | ||||
|                 "pr": 2220 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `Eth2DaiBridge`", | ||||
|                 "pr": 2221 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `UniswapBridge`", | ||||
|                 "pr": 2233 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Replaced `SafeMath` with `LibSafeMath`", | ||||
|                 "pr": 2254 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1575296764 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.3.0-beta.4", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Implement `KyberBridge`.", | ||||
|                 "pr": 2352 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Implement `DydxBridge`.", | ||||
|                 "pr": 2365 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1575290197 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.3.0-beta.3", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1574238768 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.3.0-beta.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils", | ||||
|                 "pr": 2330 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1574030254 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.3.0-beta.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract", | ||||
|                 "pr": 2034 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1573159180 | ||||
|     }, | ||||
|     { | ||||
|         "version": "2.3.0-beta.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable", | ||||
|                 "pr": 2019 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Remove `LibAssetProxyIds` contract", | ||||
|                 "pr": 2055 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Compile and export all contracts, artifacts, and wrappers by default", | ||||
|                 "pr": 2055 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Remove unused dependency on IAuthorizable in IAssetProxy", | ||||
|                 "pr": 1910 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `ERC20BridgeProxy`", | ||||
|                 "pr": 2220 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `Eth2DaiBridge`", | ||||
|                 "pr": 2221 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `UniswapBridge`", | ||||
|                 "pr": 2233 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Replaced `SafeMath` with `LibSafeMath`", | ||||
|                 "pr": 2254 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1570135330 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1568744790, | ||||
|         "version": "2.2.8", | ||||
| @@ -736,18 +123,6 @@ | ||||
|             { | ||||
|                 "note": "Update tests to use contract-built-in `awaitTransactionSuccessAsync`", | ||||
|                 "pr": 1797 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Make `ERC721Wrapper.setApprovalForAll()` take an owner address instead of a token ID", | ||||
|                 "pr": 1819 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Automatically set unlimited proxy allowances in `ERC721.setBalancesAndAllowancesAsync()`", | ||||
|                 "pr": 1819 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add `setProxyAllowanceForAllAsync()` to `ERC1155ProxyWrapper`.", | ||||
|                 "pr": 1819 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1557507213 | ||||
|   | ||||
| @@ -5,242 +5,6 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.7.17 - _August 6, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.16 - _June 22, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.15 - _June 11, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.14 - _June 2, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.13 - _May 25, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.12 - _May 21, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.11 - _May 5, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.10 - _April 28, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## 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 | ||||
|  | ||||
| ## v3.1.2 - _February 4, 2020_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.1.1 - _January 22, 2020_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.1.0 - _January 6, 2020_ | ||||
|  | ||||
|     * Integration tests for DydxBridge with ERC20BridgeProxy. (#2401) | ||||
|     * Fix `UniswapBridge` token -> token transfer call. (#2412) | ||||
|     * Fix `KyberBridge` incorrect `minConversionRate` calculation. (#2412) | ||||
|  | ||||
| ## v3.0.2 - _December 17, 2019_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.0.1 - _December 9, 2019_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.0.0 - _December 2, 2019_ | ||||
|  | ||||
|     * Implement `KyberBridge`. (#2352) | ||||
|     * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330) | ||||
|     * ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract (#2034) | ||||
|     * Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable (#2019) | ||||
|     * Remove `LibAssetProxyIds` contract (#2055) | ||||
|     * Compile and export all contracts, artifacts, and wrappers by default (#2055) | ||||
|     * Remove unused dependency on IAuthorizable in IAssetProxy (#1910) | ||||
|     * Add `ERC20BridgeProxy` (#2220) | ||||
|     * Add `Eth2DaiBridge` (#2221) | ||||
|     * Add `UniswapBridge` (#2233) | ||||
|     * Replaced `SafeMath` with `LibSafeMath` (#2254) | ||||
|  | ||||
| ## v2.3.0-beta.4 - _December 2, 2019_ | ||||
|  | ||||
|     * Implement `KyberBridge`. (#2352) | ||||
|     * Implement `DydxBridge`. (#2365) | ||||
|  | ||||
| ## v2.3.0-beta.3 - _November 20, 2019_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.3.0-beta.2 - _November 17, 2019_ | ||||
|  | ||||
|     * Drastically reduced bundle size by adding .npmignore, only exporting specific artifacts/wrappers/utils (#2330) | ||||
|  | ||||
| ## v2.3.0-beta.1 - _November 7, 2019_ | ||||
|  | ||||
|     * ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract (#2034) | ||||
|  | ||||
| ## v2.3.0-beta.0 - _October 3, 2019_ | ||||
|  | ||||
|     * Disallow the zero address from being made an authorized address in MixinAuthorizable, and created an archive directory that includes an old version of Ownable (#2019) | ||||
|     * Remove `LibAssetProxyIds` contract (#2055) | ||||
|     * Compile and export all contracts, artifacts, and wrappers by default (#2055) | ||||
|     * Remove unused dependency on IAuthorizable in IAssetProxy (#1910) | ||||
|     * Add `ERC20BridgeProxy` (#2220) | ||||
|     * Add `Eth2DaiBridge` (#2221) | ||||
|     * Add `UniswapBridge` (#2233) | ||||
|     * Replaced `SafeMath` with `LibSafeMath` (#2254) | ||||
|  | ||||
| ## v2.2.8 - _September 17, 2019_ | ||||
|  | ||||
|     * Dependencies updated | ||||
| @@ -294,9 +58,6 @@ CHANGELOG | ||||
| ## v2.1.2 - _May 10, 2019_ | ||||
|  | ||||
|     * Update tests to use contract-built-in `awaitTransactionSuccessAsync` (#1797) | ||||
|     * Make `ERC721Wrapper.setApprovalForAll()` take an owner address instead of a token ID (#1819) | ||||
|     * Automatically set unlimited proxy allowances in `ERC721.setBalancesAndAllowancesAsync()` (#1819) | ||||
|     * Add `setProxyAllowanceForAllAsync()` to `ERC1155ProxyWrapper`. (#1819) | ||||
|  | ||||
| ## v2.1.1 - _April 11, 2019_ | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| { | ||||
|     "artifactsDir": "./test/generated-artifacts", | ||||
|     "artifactsDir": "./generated-artifacts", | ||||
|     "contractsDir": "./contracts", | ||||
|     "useDockerisedSolc": false, | ||||
|     "isOfflineMode": false, | ||||
|     "shouldSaveStandardInput": true, | ||||
|     "compilerSettings": { | ||||
|         "evmVersion": "istanbul", | ||||
|         "evmVersion": "constantinople", | ||||
|         "optimizer": { | ||||
|             "enabled": true, | ||||
|             "runs": 1000000, | ||||
| @@ -23,5 +22,17 @@ | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     }, | ||||
|     "contracts": [ | ||||
|         "src/ERC1155Proxy.sol", | ||||
|         "src/ERC20Proxy.sol", | ||||
|         "src/ERC721Proxy.sol", | ||||
|         "src/MixinAuthorizable.sol", | ||||
|         "src/MultiAssetProxy.sol", | ||||
|         "src/StaticCallProxy.sol", | ||||
|         "src/interfaces/IAssetData.sol", | ||||
|         "src/interfaces/IAssetProxy.sol", | ||||
|         "src/interfaces/IAuthorizable.sol", | ||||
|         "test/TestStaticCallTarget.sol" | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol"; | ||||
|  | ||||
|  | ||||
| contract Ownable is | ||||
|     IOwnable | ||||
| { | ||||
|     address public owner; | ||||
|  | ||||
|     constructor () | ||||
|         public | ||||
|     { | ||||
|         owner = msg.sender; | ||||
|     } | ||||
|  | ||||
|     modifier onlyOwner() { | ||||
|         require( | ||||
|             msg.sender == owner, | ||||
|             "ONLY_CONTRACT_OWNER" | ||||
|         ); | ||||
|         _; | ||||
|     } | ||||
|  | ||||
|     function transferOwnership(address newOwner) | ||||
|         public | ||||
|         onlyOwner | ||||
|     { | ||||
|         if (newOwner != address(0)) { | ||||
|             owner = newOwner; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -19,18 +19,18 @@ | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/LibBytes.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/SafeMath.sol"; | ||||
| import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol"; | ||||
| import "../archive/MixinAuthorizable.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
| import "./interfaces/IAssetProxy.sol"; | ||||
|  | ||||
|  | ||||
| contract ERC1155Proxy is | ||||
|     MixinAuthorizable, | ||||
|     SafeMath, | ||||
|     IAssetProxy | ||||
| { | ||||
|     using LibBytes for bytes; | ||||
|     using LibSafeMath for uint256; | ||||
|  | ||||
|     // Id of this proxy. | ||||
|     bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)")); | ||||
| @@ -69,9 +69,9 @@ contract ERC1155Proxy is | ||||
|         for (uint256 i = 0; i != length; i++) { | ||||
|             // We write the scaled values to an unused location in memory in order | ||||
|             // to avoid copying over `ids` or `data`. This is possible if they are | ||||
|             // identical to `values` and the offsets for each are pointing to the | ||||
|             // identical to `values` and the offsets for each are pointing to the  | ||||
|             // same location in the ABI encoded calldata. | ||||
|             scaledValues[i] = values[i].safeMul(amount); | ||||
|             scaledValues[i] = safeMul(values[i], amount); | ||||
|         } | ||||
|  | ||||
|         // Execute `safeBatchTransferFrom` call | ||||
|   | ||||
| @@ -1,126 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/LibBytes.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/Authorizable.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "./interfaces/IAssetProxy.sol"; | ||||
| import "./interfaces/IERC20Bridge.sol"; | ||||
|  | ||||
|  | ||||
| contract ERC20BridgeProxy is | ||||
|     IAssetProxy, | ||||
|     Authorizable | ||||
| { | ||||
|     using LibBytes for bytes; | ||||
|     using LibSafeMath for uint256; | ||||
|  | ||||
|     // @dev Id of this proxy. Also the result of a successful bridge call. | ||||
|     //      bytes4(keccak256("ERC20Bridge(address,address,bytes)")) | ||||
|     bytes4 constant private PROXY_ID = 0xdc1600f3; | ||||
|  | ||||
|     /// @dev Calls a bridge contract to transfer `amount` of ERC20 from `from` | ||||
|     ///      to `to`. Asserts that the balance of `to` has increased by `amount`. | ||||
|     /// @param assetData Abi-encoded data for this asset proxy encoded as: | ||||
|     ///          abi.encodeWithSelector( | ||||
|     ///             bytes4 PROXY_ID, | ||||
|     ///             address tokenAddress, | ||||
|     ///             address bridgeAddress, | ||||
|     ///             bytes bridgeData | ||||
|     ///          ) | ||||
|     /// @param from Address to transfer asset from. | ||||
|     /// @param to Address to transfer asset to. | ||||
|     /// @param amount Amount of asset to transfer. | ||||
|     function transferFrom( | ||||
|         bytes calldata assetData, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|         onlyAuthorized | ||||
|     { | ||||
|         // Extract asset data fields. | ||||
|         ( | ||||
|             address tokenAddress, | ||||
|             address bridgeAddress, | ||||
|             bytes memory bridgeData | ||||
|         ) = abi.decode( | ||||
|             assetData.sliceDestructive(4, assetData.length), | ||||
|             (address, address, bytes) | ||||
|         ); | ||||
|  | ||||
|         // Remember the balance of `to` before calling the bridge. | ||||
|         uint256 balanceBefore = balanceOf(tokenAddress, to); | ||||
|         // Call the bridge, who should transfer `amount` of `tokenAddress` to | ||||
|         // `to`. | ||||
|         bytes4 success = IERC20Bridge(bridgeAddress).bridgeTransferFrom( | ||||
|             tokenAddress, | ||||
|             from, | ||||
|             to, | ||||
|             amount, | ||||
|             bridgeData | ||||
|         ); | ||||
|         // Bridge must return the proxy ID to indicate success. | ||||
|         require(success == PROXY_ID, "BRIDGE_FAILED"); | ||||
|         // Ensure that the balance of `to` has increased by at least `amount`. | ||||
|         require( | ||||
|             balanceBefore.safeAdd(amount) <= balanceOf(tokenAddress, to), | ||||
|             "BRIDGE_UNDERPAY" | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Gets the proxy id associated with this asset proxy. | ||||
|     /// @return proxyId The proxy id. | ||||
|     function getProxyId() | ||||
|         external | ||||
|         pure | ||||
|         returns (bytes4 proxyId) | ||||
|     { | ||||
|         return PROXY_ID; | ||||
|     } | ||||
|  | ||||
|     /// @dev Retrieves the balance of `owner` for this asset. | ||||
|     /// @return balance The balance of the ERC20 token being transferred by this | ||||
|     ///         asset proxy. | ||||
|     function balanceOf(bytes calldata assetData, address owner) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 balance) | ||||
|     { | ||||
|         (address tokenAddress) = abi.decode( | ||||
|             assetData.sliceDestructive(4, assetData.length), | ||||
|             (address) | ||||
|         ); | ||||
|         return balanceOf(tokenAddress, owner); | ||||
|     } | ||||
|  | ||||
|     /// @dev Retrieves the balance of `owner` given an ERC20 address. | ||||
|     /// @return balance The balance of the ERC20 token for `owner`. | ||||
|     function balanceOf(address tokenAddress, address owner) | ||||
|         private | ||||
|         view | ||||
|         returns (uint256 balance) | ||||
|     { | ||||
|         return IERC20Token(tokenAddress).balanceOf(owner); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,9 +16,9 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "../archive/MixinAuthorizable.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| contract ERC20Proxy is | ||||
| @@ -26,9 +26,9 @@ contract ERC20Proxy is | ||||
| { | ||||
|     // Id of this proxy. | ||||
|     bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC20Token(address)")); | ||||
|  | ||||
|      | ||||
|     // solhint-disable-next-line payable-fallback | ||||
|     function () | ||||
|     function ()  | ||||
|         external | ||||
|     { | ||||
|         assembly { | ||||
| @@ -117,13 +117,13 @@ contract ERC20Proxy is | ||||
|                 // * The "token address" is offset 32+4=36 bytes into "assetData" (tables 1 & 2). | ||||
|                 //   [tokenOffset = assetDataOffsetFromHeader + 36 = calldataload(4) + 4 + 36] | ||||
|                 let token := calldataload(add(calldataload(4), 40)) | ||||
|  | ||||
|                  | ||||
|                 /////// Setup Header Area /////// | ||||
|                 // This area holds the 4-byte `transferFrom` selector. | ||||
|                 // Any trailing data in transferFromSelector will be | ||||
|                 // overwritten in the next `mstore` call. | ||||
|                 mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000) | ||||
|  | ||||
|                  | ||||
|                 /////// Setup Params Area /////// | ||||
|                 // We copy the fields `from`, `to` and `amount` in bulk | ||||
|                 // from our own calldata to the new calldata. | ||||
| @@ -147,7 +147,7 @@ contract ERC20Proxy is | ||||
|                 // If the token does return data, we require that it is a single | ||||
|                 // nonzero 32 bytes value. | ||||
|                 // So the transfer succeeded if the call succeeded and either | ||||
|                 // returned nothing, or returned a non-zero 32 byte value. | ||||
|                 // returned nothing, or returned a non-zero 32 byte value.  | ||||
|                 success := and(success, or( | ||||
|                     iszero(returndatasize), | ||||
|                     and( | ||||
| @@ -158,7 +158,7 @@ contract ERC20Proxy is | ||||
|                 if success { | ||||
|                     return(0, 0) | ||||
|                 } | ||||
|  | ||||
|                  | ||||
|                 // Revert with `Error("TRANSFER_FAILED")` | ||||
|                 mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,9 +16,9 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "../archive/MixinAuthorizable.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| contract ERC721Proxy is | ||||
| @@ -28,7 +28,7 @@ contract ERC721Proxy is | ||||
|     bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256)")); | ||||
|  | ||||
|     // solhint-disable-next-line payable-fallback | ||||
|     function () | ||||
|     function ()  | ||||
|         external | ||||
|     { | ||||
|         assembly { | ||||
| @@ -93,10 +93,10 @@ contract ERC721Proxy is | ||||
|                 // | Params   |        | 2 * 32  | function parameters:                | | ||||
|                 // |          | 4      | 12 + 20 |   1. token address                  | | ||||
|                 // |          | 36     |         |   2. tokenId                        | | ||||
|  | ||||
|                  | ||||
|                 // We construct calldata for the `token.transferFrom` ABI. | ||||
|                 // The layout of this calldata is in the table below. | ||||
|                 // | ||||
|                 //  | ||||
|                 // | Area     | Offset | Length  | Contents                            | | ||||
|                 // |----------|--------|---------|-------------------------------------| | ||||
|                 // | Header   | 0      | 4       | function selector                   | | ||||
| @@ -121,7 +121,7 @@ contract ERC721Proxy is | ||||
|                 // Any trailing data in transferFromSelector will be | ||||
|                 // overwritten in the next `mstore` call. | ||||
|                 mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000) | ||||
|  | ||||
|                  | ||||
|                 /////// Setup Params Area /////// | ||||
|                 // We copy the fields `from` and `to` in bulk | ||||
|                 // from our own calldata to the new calldata. | ||||
| @@ -145,7 +145,7 @@ contract ERC721Proxy is | ||||
|                 if success { | ||||
|                     return(0, 0) | ||||
|                 } | ||||
|  | ||||
|                  | ||||
|                 // Revert with `Error("TRANSFER_FAILED")` | ||||
|                 mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000) | ||||
|                 mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
| 
 | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
| 
 | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,16 +16,16 @@ | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
| 
 | ||||
| import "../archive/Ownable.sol"; | ||||
| import "../src/interfaces/IAssetProxy.sol"; | ||||
| import "../src/interfaces/IAssetProxyDispatcher.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/Ownable.sol"; | ||||
| import "./mixins/MAssetProxyDispatcher.sol"; | ||||
| import "./interfaces/IAssetProxy.sol"; | ||||
| 
 | ||||
| 
 | ||||
| contract MixinAssetProxyDispatcher is | ||||
|     Ownable, | ||||
|     IAssetProxyDispatcher | ||||
|     MAssetProxyDispatcher | ||||
| { | ||||
|     // Mapping from Asset Proxy Id's to their respective Asset Proxy | ||||
|     mapping (bytes4 => address) public assetProxies; | ||||
| @@ -69,7 +69,7 @@ contract MixinAssetProxyDispatcher is | ||||
|     /// @param from Address to transfer token from. | ||||
|     /// @param to Address to transfer token to. | ||||
|     /// @param amount Amount of token to transfer. | ||||
|     function _dispatchTransferFrom( | ||||
|     function dispatchTransferFrom( | ||||
|         bytes memory assetData, | ||||
|         address from, | ||||
|         address to, | ||||
| @@ -84,7 +84,7 @@ contract MixinAssetProxyDispatcher is | ||||
|                 assetData.length > 3, | ||||
|                 "LENGTH_GREATER_THAN_3_REQUIRED" | ||||
|             ); | ||||
| 
 | ||||
|              | ||||
|             // Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons. | ||||
|             bytes4 assetProxyId; | ||||
|             assembly { | ||||
| @@ -100,10 +100,10 @@ contract MixinAssetProxyDispatcher is | ||||
|                 assetProxy != address(0), | ||||
|                 "ASSET_PROXY_DOES_NOT_EXIST" | ||||
|             ); | ||||
| 
 | ||||
|              | ||||
|             // We construct calldata for the `assetProxy.transferFrom` ABI. | ||||
|             // The layout of this calldata is in the table below. | ||||
|             // | ||||
|             //  | ||||
|             // | Area     | Offset | Length  | Contents                                    | | ||||
|             // | -------- |--------|---------|-------------------------------------------- | | ||||
|             // | Header   | 0      | 4       | function selector                           | | ||||
| @@ -127,12 +127,12 @@ contract MixinAssetProxyDispatcher is | ||||
|                 // `cdEnd` is the end of the calldata for `assetProxy.transferFrom`. | ||||
|                 let cdEnd := add(cdStart, add(132, dataAreaLength)) | ||||
| 
 | ||||
| 
 | ||||
|                  | ||||
|                 /////// Setup Header Area /////// | ||||
|                 // This area holds the 4-byte `transferFromSelector`. | ||||
|                 // bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4 | ||||
|                 mstore(cdStart, 0xa85e59e400000000000000000000000000000000000000000000000000000000) | ||||
| 
 | ||||
|                  | ||||
|                 /////// Setup Params Area /////// | ||||
|                 // Each parameter is padded to 32-bytes. The entire Params Area is 128 bytes. | ||||
|                 // Notes: | ||||
| @@ -142,7 +142,7 @@ contract MixinAssetProxyDispatcher is | ||||
|                 mstore(add(cdStart, 36), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) | ||||
|                 mstore(add(cdStart, 68), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) | ||||
|                 mstore(add(cdStart, 100), amount) | ||||
| 
 | ||||
|                  | ||||
|                 /////// Setup Data Area /////// | ||||
|                 // This area holds `assetData`. | ||||
|                 let dataArea := add(cdStart, 132) | ||||
| @@ -159,7 +159,7 @@ contract MixinAssetProxyDispatcher is | ||||
|                     assetProxy,             // call address of asset proxy | ||||
|                     0,                      // don't send any ETH | ||||
|                     cdStart,                // pointer to start of input | ||||
|                     sub(cdEnd, cdStart),    // length of input | ||||
|                     sub(cdEnd, cdStart),    // length of input   | ||||
|                     cdStart,                // write output over input | ||||
|                     512                     // reserve 512 bytes for output | ||||
|                 ) | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
| 
 | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
| 
 | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,15 +16,15 @@ | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
| 
 | ||||
| import "../archive/Ownable.sol"; | ||||
| import "../src/interfaces/IAuthorizable.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/Ownable.sol"; | ||||
| import "./mixins/MAuthorizable.sol"; | ||||
| 
 | ||||
| 
 | ||||
| contract MixinAuthorizable is | ||||
|     Ownable, | ||||
|     IAuthorizable | ||||
|     MAuthorizable | ||||
| { | ||||
|     /// @dev Only authorized addresses can invoke functions with this modifier. | ||||
|     modifier onlyAuthorized { | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,10 +16,10 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "../archive/MixinAssetProxyDispatcher.sol"; | ||||
| import "../archive/MixinAuthorizable.sol"; | ||||
| import "./MixinAssetProxyDispatcher.sol"; | ||||
| import "./MixinAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| contract MultiAssetProxy is | ||||
| @@ -105,7 +105,7 @@ contract MultiAssetProxy is | ||||
|                 // |          | 36          |         |   2. offset to nestedAssetData (*)  | | ||||
|                 // | Data     |             |         | amounts:                            | | ||||
|                 // |          | 68          | 32      | amounts Length                      | | ||||
|                 // |          | 100         | a       | amounts Contents                    | | ||||
|                 // |          | 100         | a       | amounts Contents                    |  | ||||
|                 // |          |             |         | nestedAssetData:                    | | ||||
|                 // |          | 100 + a     | 32      | nestedAssetData Length              | | ||||
|                 // |          | 132 + a     | b       | nestedAssetData Contents (offsets)  | | ||||
| @@ -149,8 +149,8 @@ contract MultiAssetProxy is | ||||
|                 // + 32 (amounts offset) | ||||
|                 let nestedAssetDataOffset := calldataload(add(assetDataOffset, 68)) | ||||
|  | ||||
|                 // In order to find the start of the `amounts` contents, we must add: | ||||
|                 // assetDataOffset | ||||
|                 // In order to find the start of the `amounts` contents, we must add:  | ||||
|                 // assetDataOffset  | ||||
|                 // + 32 (assetData len) | ||||
|                 // + 4 (assetProxyId) | ||||
|                 // + amountsOffset | ||||
| @@ -160,8 +160,8 @@ contract MultiAssetProxy is | ||||
|                 // Load number of elements in `amounts` | ||||
|                 let amountsLen := calldataload(sub(amountsContentsStart, 32)) | ||||
|  | ||||
|                 // In order to find the start of the `nestedAssetData` contents, we must add: | ||||
|                 // assetDataOffset | ||||
|                 // In order to find the start of the `nestedAssetData` contents, we must add:  | ||||
|                 // assetDataOffset  | ||||
|                 // + 32 (assetData len) | ||||
|                 // + 4 (assetProxyId) | ||||
|                 // + nestedAssetDataOffset | ||||
| @@ -190,10 +190,10 @@ contract MultiAssetProxy is | ||||
|  | ||||
|                 // Overwrite existing offset to `assetData` with our own | ||||
|                 mstore(4, 128) | ||||
|  | ||||
|                  | ||||
|                 // Load `amount` | ||||
|                 let amount := calldataload(100) | ||||
|  | ||||
|          | ||||
|                 // Calculate number of bytes in `amounts` contents | ||||
|                 let amountsByteLen := mul(amountsLen, 32) | ||||
|  | ||||
| @@ -208,7 +208,7 @@ contract MultiAssetProxy is | ||||
|                     let amountsElement := calldataload(add(amountsContentsStart, i)) | ||||
|                     let totalAmount := mul(amountsElement, amount) | ||||
|  | ||||
|                     // Revert if `amount` != 0 and multiplication resulted in an overflow | ||||
|                     // Revert if `amount` != 0 and multiplication resulted in an overflow  | ||||
|                     if iszero(or( | ||||
|                         iszero(amount), | ||||
|                         eq(div(totalAmount, amount), amountsElement) | ||||
| @@ -228,7 +228,7 @@ contract MultiAssetProxy is | ||||
|                     let nestedAssetDataElementOffset := calldataload(add(nestedAssetDataContentsStart, i)) | ||||
|  | ||||
|                     // In order to find the start of the `nestedAssetData[i]` contents, we must add: | ||||
|                     // assetDataOffset | ||||
|                     // assetDataOffset  | ||||
|                     // + 32 (assetData len) | ||||
|                     // + 4 (assetProxyId) | ||||
|                     // + nestedAssetDataOffset | ||||
| @@ -274,7 +274,7 @@ contract MultiAssetProxy is | ||||
|                         mstore(164, assetProxies_slot) | ||||
|                         assetProxy := sload(keccak256(132, 64)) | ||||
|                     } | ||||
|  | ||||
|                      | ||||
|                     // Revert if AssetProxy with given id does not exist | ||||
|                     if iszero(assetProxy) { | ||||
|                         // Revert with `Error("ASSET_PROXY_DOES_NOT_EXIST")` | ||||
| @@ -284,7 +284,7 @@ contract MultiAssetProxy is | ||||
|                         mstore(96, 0) | ||||
|                         revert(0, 100) | ||||
|                     } | ||||
|  | ||||
|      | ||||
|                     // Copy `nestedAssetData[i]` from calldata to memory | ||||
|                     calldatacopy( | ||||
|                         132,                                // memory slot after `amounts[i]` | ||||
| @@ -298,7 +298,7 @@ contract MultiAssetProxy is | ||||
|                         assetProxy,                             // call address of asset proxy | ||||
|                         0,                                      // don't send any ETH | ||||
|                         0,                                      // pointer to start of input | ||||
|                         add(164, nestedAssetDataElementLen),    // length of input | ||||
|                         add(164, nestedAssetDataElementLen),    // length of input   | ||||
|                         0,                                      // write output over memory that won't be reused | ||||
|                         0                                       // don't copy output to memory | ||||
|                     ) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   | ||||
| @@ -1,103 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,144 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,75 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
| import "../interfaces/IChai.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| contract ChaiBridge is | ||||
|     IERC20Bridge, | ||||
|     DeploymentConstants | ||||
| { | ||||
|     /// @dev Withdraws `amount` of `from` address's Dai from the Chai contract. | ||||
|     ///      Transfers `amount` of Dai to `to` address. | ||||
|     /// @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 `0xdc1600f3` if successful. | ||||
|     function bridgeTransferFrom( | ||||
|         address /* tokenAddress */, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes calldata /* bridgeData */ | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         // Ensure that only the `ERC20BridgeProxy` can call this function. | ||||
|         require( | ||||
|             msg.sender == _getERC20BridgeProxyAddress(), | ||||
|             "ChaiBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY" | ||||
|         ); | ||||
|  | ||||
|         // Withdraw `from` address's Dai. | ||||
|         // NOTE: This contract must be approved to spend Chai on behalf of `from`. | ||||
|         bytes memory drawCalldata = abi.encodeWithSelector( | ||||
|             IChai(address(0)).draw.selector, | ||||
|             from, | ||||
|             amount | ||||
|         ); | ||||
|  | ||||
|         (bool success,) = _getChaiAddress().call(drawCalldata); | ||||
|         require( | ||||
|             success, | ||||
|             "ChaiBridge/DRAW_DAI_FAILED" | ||||
|         ); | ||||
|  | ||||
|         // Transfer Dai to `to` | ||||
|         // This will never fail if the `draw` call was successful | ||||
|         IERC20Token(_getDaiAddress()).transfer(to, amount); | ||||
|  | ||||
|         return BRIDGE_SUCCESS; | ||||
|     } | ||||
| } | ||||
| @@ -1,103 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,136 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,119 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
|     } | ||||
| } | ||||
| @@ -1,147 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,200 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,242 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; | ||||
| import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
| import "../interfaces/IDydxBridge.sol"; | ||||
| import "../interfaces/IDydx.sol"; | ||||
|  | ||||
|  | ||||
| contract DydxBridge is | ||||
|     IERC20Bridge, | ||||
|     IDydxBridge, | ||||
|     DeploymentConstants | ||||
| { | ||||
|  | ||||
|     using LibSafeMath for uint256; | ||||
|  | ||||
|     /// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account. | ||||
|     ///      Notes: | ||||
|     ///         1. This bridge must be set as an operator of the input dydx account. | ||||
|     ///         2. This function may only be called in the context of the 0x Exchange. | ||||
|     ///         3. The maker or taker of the 0x order must be the dydx account owner. | ||||
|     ///         4. Deposits into dydx are made from the `from` address. | ||||
|     ///         5. Withdrawals from dydx are made to the `to` address. | ||||
|     ///         6. Calling this function must always withdraw at least `amount`, | ||||
|     ///            otherwise the `ERC20Bridge` will revert. | ||||
|     /// @param from The sender of the tokens and owner of the dydx account. | ||||
|     /// @param to The recipient of the tokens. | ||||
|     /// @param amount Minimum amount of `toTokenAddress` tokens to deposit or withdraw. | ||||
|     /// @param encodedBridgeData An abi-encoded `BridgeData` struct. | ||||
|     /// @return success The magic bytes if successful. | ||||
|     function bridgeTransferFrom( | ||||
|         address, /* toTokenAddress */ | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes calldata encodedBridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         // Ensure that only the `ERC20BridgeProxy` can call this function. | ||||
|         require( | ||||
|             msg.sender == _getERC20BridgeProxyAddress(), | ||||
|             "DydxBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY" | ||||
|         ); | ||||
|  | ||||
|         // Decode bridge data. | ||||
|         (BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData)); | ||||
|  | ||||
|         // The dydx accounts are owned by the `from` address. | ||||
|         IDydx.AccountInfo[] memory accounts = _createAccounts(from, bridgeData); | ||||
|  | ||||
|         // Create dydx actions to run on the dydx accounts. | ||||
|         IDydx.ActionArgs[] memory actions = _createActions( | ||||
|             from, | ||||
|             to, | ||||
|             amount, | ||||
|             bridgeData | ||||
|         ); | ||||
|  | ||||
|         // Run operation. This will revert on failure. | ||||
|         IDydx(_getDydxAddress()).operate(accounts, actions); | ||||
|  | ||||
|         return BRIDGE_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /// @dev Creates an array of accounts for dydx to operate on. | ||||
|     ///      All accounts must belong to the same owner. | ||||
|     /// @param accountOwner Owner of the dydx account. | ||||
|     /// @param bridgeData A `BridgeData` struct. | ||||
|     function _createAccounts( | ||||
|         address accountOwner, | ||||
|         BridgeData memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (IDydx.AccountInfo[] memory accounts) | ||||
|     { | ||||
|         uint256[] memory accountNumbers = bridgeData.accountNumbers; | ||||
|         uint256 nAccounts = accountNumbers.length; | ||||
|         accounts = new IDydx.AccountInfo[](nAccounts); | ||||
|         for (uint256 i = 0; i < nAccounts; ++i) { | ||||
|             accounts[i] = IDydx.AccountInfo({ | ||||
|                 owner: accountOwner, | ||||
|                 number: accountNumbers[i] | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Creates an array of actions to carry out on dydx. | ||||
|     /// @param depositFrom Deposit value from this address (owner of the dydx account). | ||||
|     /// @param withdrawTo Withdraw value to this address. | ||||
|     /// @param amount The amount of value available to operate on. | ||||
|     /// @param bridgeData A `BridgeData` struct. | ||||
|     function _createActions( | ||||
|         address depositFrom, | ||||
|         address withdrawTo, | ||||
|         uint256 amount, | ||||
|         BridgeData memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (IDydx.ActionArgs[] memory actions) | ||||
|     { | ||||
|         BridgeAction[] memory bridgeActions = bridgeData.actions; | ||||
|         uint256 nBridgeActions = bridgeActions.length; | ||||
|         actions = new IDydx.ActionArgs[](nBridgeActions); | ||||
|         for (uint256 i = 0; i < nBridgeActions; ++i) { | ||||
|             // Cache current bridge action. | ||||
|             BridgeAction memory bridgeAction = bridgeActions[i]; | ||||
|  | ||||
|             // Scale amount, if conversion rate is set. | ||||
|             uint256 scaledAmount; | ||||
|             if (bridgeAction.conversionRateDenominator > 0) { | ||||
|                 scaledAmount = LibMath.safeGetPartialAmountFloor( | ||||
|                     bridgeAction.conversionRateNumerator, | ||||
|                     bridgeAction.conversionRateDenominator, | ||||
|                     amount | ||||
|                 ); | ||||
|             } else { | ||||
|                 scaledAmount = amount; | ||||
|             } | ||||
|  | ||||
|             // Construct dydx action. | ||||
|             if (bridgeAction.actionType == BridgeActionType.Deposit) { | ||||
|                 // Deposit tokens from the account owner into their dydx account. | ||||
|                 actions[i] = _createDepositAction( | ||||
|                     depositFrom, | ||||
|                     scaledAmount, | ||||
|                     bridgeAction | ||||
|                 ); | ||||
|             } else if (bridgeAction.actionType == BridgeActionType.Withdraw) { | ||||
|                 // Withdraw tokens from dydx to the `otherAccount`. | ||||
|                 actions[i] = _createWithdrawAction( | ||||
|                     withdrawTo, | ||||
|                     scaledAmount, | ||||
|                     bridgeAction | ||||
|                 ); | ||||
|             } else { | ||||
|                 // If all values in the `Action` enum are handled then this | ||||
|                 // revert is unreachable: Solidity will revert when casting | ||||
|                 // from `uint8` to `Action`. | ||||
|                 revert("DydxBridge/UNRECOGNIZED_BRIDGE_ACTION"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns a dydx `DepositAction`. | ||||
|     /// @param depositFrom Deposit tokens from this address who is also the account owner. | ||||
|     /// @param amount of tokens to deposit. | ||||
|     /// @param bridgeAction A `BridgeAction` struct. | ||||
|     /// @return depositAction The encoded dydx action. | ||||
|     function _createDepositAction( | ||||
|         address depositFrom, | ||||
|         uint256 amount, | ||||
|         BridgeAction memory bridgeAction | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns ( | ||||
|             IDydx.ActionArgs memory depositAction | ||||
|         ) | ||||
|     { | ||||
|         // Create dydx amount. | ||||
|         IDydx.AssetAmount memory dydxAmount = IDydx.AssetAmount({ | ||||
|             sign: true,                                 // true if positive. | ||||
|             denomination: IDydx.AssetDenomination.Wei,  // Wei => actual token amount held in account. | ||||
|             ref: IDydx.AssetReference.Delta,                // Delta => a relative amount. | ||||
|             value: amount                               // amount to deposit. | ||||
|         }); | ||||
|  | ||||
|         // Create dydx deposit action. | ||||
|         depositAction = IDydx.ActionArgs({ | ||||
|             actionType: IDydx.ActionType.Deposit,           // deposit tokens. | ||||
|             amount: dydxAmount,                             // amount to deposit. | ||||
|             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, | ||||
|             otherAccountIdx: 0, | ||||
|             data: hex'' | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns a dydx `WithdrawAction`. | ||||
|     /// @param withdrawTo Withdraw tokens to this address. | ||||
|     /// @param amount of tokens to withdraw. | ||||
|     /// @param bridgeAction A `BridgeAction` struct. | ||||
|     /// @return withdrawAction The encoded dydx action. | ||||
|     function _createWithdrawAction( | ||||
|         address withdrawTo, | ||||
|         uint256 amount, | ||||
|         BridgeAction memory bridgeAction | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns ( | ||||
|             IDydx.ActionArgs memory withdrawAction | ||||
|         ) | ||||
|     { | ||||
|         // Create dydx amount. | ||||
|         IDydx.AssetAmount memory amountToWithdraw = IDydx.AssetAmount({ | ||||
|             sign: false,                                    // false if negative. | ||||
|             denomination: IDydx.AssetDenomination.Wei,      // Wei => actual token amount held in account. | ||||
|             ref: IDydx.AssetReference.Delta,                // Delta => a relative amount. | ||||
|             value: amount                                   // amount to withdraw. | ||||
|         }); | ||||
|  | ||||
|         // Create withdraw action. | ||||
|         withdrawAction = IDydx.ActionArgs({ | ||||
|             actionType: IDydx.ActionType.Withdraw,          // withdraw tokens. | ||||
|             amount: amountToWithdraw,                       // amount to withdraw. | ||||
|             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, | ||||
|             otherAccountIdx: 0, | ||||
|             data: hex'' | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @@ -1,98 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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/IEth2Dai.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| contract Eth2DaiBridge is | ||||
|     IERC20Bridge, | ||||
|     IWallet, | ||||
|     DeploymentConstants | ||||
| { | ||||
|     /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of | ||||
|     ///      `toTokenAddress` tokens by selling the entirety of the opposing asset | ||||
|     ///      (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 to, | ||||
|         uint256 amount, | ||||
|         bytes calldata bridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         // Decode the bridge data to get the `fromTokenAddress`. | ||||
|         (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.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance); | ||||
|  | ||||
|         // Try to sell all of this contract's `fromTokenAddress` token balance. | ||||
|         uint256 boughtAmount = exchange.sellAllAmount( | ||||
|             fromTokenAddress, | ||||
|             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; | ||||
|     } | ||||
|  | ||||
|     /// @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; | ||||
|     } | ||||
| } | ||||
| @@ -1,169 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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 "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
| import "../interfaces/IKyberNetworkProxy.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| contract KyberBridge is | ||||
|     IERC20Bridge, | ||||
|     IWallet, | ||||
|     DeploymentConstants | ||||
| { | ||||
|     using LibSafeMath for uint256; | ||||
|  | ||||
|     // @dev Structure used internally to get around stack limits. | ||||
|     struct TradeState { | ||||
|         IKyberNetworkProxy kyber; | ||||
|         IEtherToken weth; | ||||
|         address fromTokenAddress; | ||||
|         uint256 fromTokenBalance; | ||||
|         uint256 payableAmount; | ||||
|         uint256 conversionRate; | ||||
|         bytes hint; | ||||
|     } | ||||
|  | ||||
|     /// @dev Kyber ETH pseudo-address. | ||||
|     address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||||
|     /// @dev `bridgeTransferFrom()` failure result. | ||||
|     bytes4 constant private BRIDGE_FAILED = 0x0; | ||||
|     /// @dev Precision of Kyber rates. | ||||
|     uint256 constant private KYBER_RATE_BASE = 10 ** 18; | ||||
|  | ||||
|     // solhint-disable no-empty-blocks | ||||
|     /// @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 to, | ||||
|         uint256 amount, | ||||
|         bytes calldata bridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         TradeState memory state; | ||||
|         state.kyber = IKyberNetworkProxy(_getKyberNetworkProxyAddress()); | ||||
|         state.weth = IEtherToken(_getWethAddress()); | ||||
|         // Decode the bridge data to get the `fromTokenAddress`. | ||||
|         (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; | ||||
|         } | ||||
|         if (state.fromTokenAddress == toTokenAddress) { | ||||
|             // Just transfer the tokens if they're the same. | ||||
|             LibERC20Token.transfer(state.fromTokenAddress, to, state.fromTokenBalance); | ||||
|             return BRIDGE_SUCCESS; | ||||
|         } | ||||
|         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.tradeWithHint.value(state.payableAmount)( | ||||
|             // Input token. | ||||
|             state.fromTokenAddress, | ||||
|             // Sell amount. | ||||
|             state.fromTokenBalance, | ||||
|             // Output token. | ||||
|             isToTokenWeth ? KYBER_ETH_ADDRESS : toTokenAddress, | ||||
|             // Transfer to this contract if converting to ETH, otherwise | ||||
|             // transfer directly to the recipient. | ||||
|             isToTokenWeth ? address(uint160(address(this))) : address(uint160(to)), | ||||
|             // Buy as much as possible. | ||||
|             uint256(-1), | ||||
|             // The minimum conversion rate | ||||
|             1, | ||||
|             // No affiliate address. | ||||
|             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; | ||||
|     } | ||||
|  | ||||
|     /// @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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,94 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
|     } | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,148 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,95 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
|     } | ||||
| } | ||||
| @@ -1,119 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
|     } | ||||
| } | ||||
| @@ -1,136 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,119 +0,0 @@ | ||||
|  | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
|     } | ||||
| } | ||||
| @@ -1,220 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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/IUniswapExchangeFactory.sol"; | ||||
| import "../interfaces/IUniswapExchange.sol"; | ||||
| import "../interfaces/IERC20Bridge.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| // solhint-disable not-rely-on-time | ||||
| contract UniswapBridge is | ||||
|     IERC20Bridge, | ||||
|     IWallet, | ||||
|     DeploymentConstants | ||||
| { | ||||
|     // Struct to hold `bridgeTransferFrom()` local variables in memory and to avoid | ||||
|     // stack overflows. | ||||
|     struct TransferState { | ||||
|         IUniswapExchange exchange; | ||||
|         uint256 fromTokenBalance; | ||||
|         IEtherToken weth; | ||||
|         uint256 boughtAmount; | ||||
|     } | ||||
|  | ||||
|     // 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 "from" token address. | ||||
|     /// @return success The magic bytes if successful. | ||||
|     function bridgeTransferFrom( | ||||
|         address toTokenAddress, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes calldata bridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         // State memory object to avoid stack overflows. | ||||
|         TransferState memory state; | ||||
|         // Decode the bridge data to get the `fromTokenAddress`. | ||||
|         (address fromTokenAddress) = abi.decode(bridgeData, (address)); | ||||
|  | ||||
|         // Just transfer the tokens if they're the same. | ||||
|         if (fromTokenAddress == toTokenAddress) { | ||||
|             LibERC20Token.transfer(fromTokenAddress, to, amount); | ||||
|             return BRIDGE_SUCCESS; | ||||
|         } | ||||
|  | ||||
|         // Get the exchange for the token pair. | ||||
|         state.exchange = _getUniswapExchangeForTokenPair( | ||||
|             fromTokenAddress, | ||||
|             toTokenAddress | ||||
|         ); | ||||
|         // Get our balance of `fromTokenAddress` token. | ||||
|         state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); | ||||
|         // Get the weth contract. | ||||
|         state.weth = IEtherToken(_getWethAddress()); | ||||
|  | ||||
|         // Convert from WETH to a token. | ||||
|         if (fromTokenAddress == address(state.weth)) { | ||||
|             // Unwrap the WETH. | ||||
|             state.weth.withdraw(state.fromTokenBalance); | ||||
|             // Buy as much of `toTokenAddress` token with ETH as possible and | ||||
|             // transfer it to `to`. | ||||
|             state.boughtAmount = state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)( | ||||
|                 // Minimum buy amount. | ||||
|                 amount, | ||||
|                 // Expires after this block. | ||||
|                 block.timestamp, | ||||
|                 // Recipient is `to`. | ||||
|                 to | ||||
|             ); | ||||
|  | ||||
|         // Convert from a token to WETH. | ||||
|         } else if (toTokenAddress == address(state.weth)) { | ||||
|             // Grant the exchange an allowance. | ||||
|             _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance); | ||||
|             // Buy as much ETH with `fromTokenAddress` token as possible. | ||||
|             state.boughtAmount = state.exchange.tokenToEthSwapInput( | ||||
|                 // Sell all tokens we hold. | ||||
|                 state.fromTokenBalance, | ||||
|                 // Minimum buy amount. | ||||
|                 amount, | ||||
|                 // Expires after this block. | ||||
|                 block.timestamp | ||||
|             ); | ||||
|             // Wrap the ETH. | ||||
|             state.weth.deposit.value(state.boughtAmount)(); | ||||
|             // Transfer the WETH to `to`. | ||||
|             IEtherToken(toTokenAddress).transfer(to, state.boughtAmount); | ||||
|  | ||||
|         // Convert from one token to another. | ||||
|         } else { | ||||
|             // Grant the exchange an allowance. | ||||
|             _grantExchangeAllowance(state.exchange, fromTokenAddress, state.fromTokenBalance); | ||||
|             // Buy as much `toTokenAddress` token with `fromTokenAddress` token | ||||
|             // and transfer it to `to`. | ||||
|             state.boughtAmount = state.exchange.tokenToTokenTransferInput( | ||||
|                 // Sell all tokens we hold. | ||||
|                 state.fromTokenBalance, | ||||
|                 // Minimum buy amount. | ||||
|                 amount, | ||||
|                 // Must buy at least 1 intermediate ETH. | ||||
|                 1, | ||||
|                 // Expires after this block. | ||||
|                 block.timestamp, | ||||
|                 // Recipient is `to`. | ||||
|                 to, | ||||
|                 // Convert to `toTokenAddress`. | ||||
|                 toTokenAddress | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         emit ERC20BridgeTransfer( | ||||
|             fromTokenAddress, | ||||
|             toTokenAddress, | ||||
|             state.fromTokenBalance, | ||||
|             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; | ||||
|     } | ||||
|  | ||||
|     /// @dev Grants an unlimited allowance to the exchange for its token | ||||
|     ///      on behalf of this contract. | ||||
|     /// @param exchange The Uniswap token exchange. | ||||
|     /// @param tokenAddress The token address for the exchange. | ||||
|     /// @param minimumAllowance The minimum necessary allowance. | ||||
|     function _grantExchangeAllowance( | ||||
|         IUniswapExchange exchange, | ||||
|         address tokenAddress, | ||||
|         uint256 minimumAllowance | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         LibERC20Token.approveIfBelow( | ||||
|             tokenAddress, | ||||
|             address(exchange), | ||||
|             minimumAllowance | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Retrieves the uniswap exchange for a given token pair. | ||||
|     ///      In the case of a WETH-token exchange, this will be the non-WETH token. | ||||
|     ///      In th ecase of a token-token exchange, this will be the first token. | ||||
|     /// @param fromTokenAddress The address of the token we are converting from. | ||||
|     /// @param toTokenAddress The address of the token we are converting to. | ||||
|     /// @return exchange The uniswap exchange. | ||||
|     function _getUniswapExchangeForTokenPair( | ||||
|         address fromTokenAddress, | ||||
|         address toTokenAddress | ||||
|     ) | ||||
|         private | ||||
|         view | ||||
|         returns (IUniswapExchange exchange) | ||||
|     { | ||||
|         address exchangeTokenAddress = fromTokenAddress; | ||||
|         // Whichever isn't WETH is the exchange token. | ||||
|         if (fromTokenAddress == _getWethAddress()) { | ||||
|             exchangeTokenAddress = toTokenAddress; | ||||
|         } | ||||
|         exchange = IUniswapExchange( | ||||
|             IUniswapExchangeFactory(_getUniswapExchangeFactoryAddress()) | ||||
|             .getExchange(exchangeTokenAddress) | ||||
|         ); | ||||
|         require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); | ||||
|         return exchange; | ||||
|     } | ||||
| } | ||||
| @@ -1,135 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -17,7 +17,7 @@ | ||||
| */ | ||||
|  | ||||
| // solhint-disable | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
|  | ||||
| @@ -26,63 +26,33 @@ pragma experimental ABIEncoderV2; | ||||
| // This argument is ABI encoded as one of the methods of this interface. | ||||
| interface IAssetData { | ||||
|  | ||||
|     /// @dev Function signature for encoding ERC20 assetData. | ||||
|     /// @param tokenAddress Address of ERC20Token contract. | ||||
|     function ERC20Token(address tokenAddress) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Function signature for encoding ERC721 assetData. | ||||
|     /// @param tokenAddress Address of ERC721 token contract. | ||||
|     /// @param tokenId Id of ERC721 token to be transferred. | ||||
|      | ||||
|     function ERC721Token( | ||||
|         address tokenAddress, | ||||
|         uint256 tokenId | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Function signature for encoding ERC1155 assetData. | ||||
|     /// @param tokenAddress Address of ERC1155 token contract. | ||||
|     /// @param tokenIds Array of ids of tokens to be transferred. | ||||
|     /// @param values Array of values that correspond to each token id to be transferred. | ||||
|     ///        Note that each value will be multiplied by the amount being filled in the order before transferring. | ||||
|     /// @param callbackData Extra data to be passed to receiver's `onERC1155Received` callback function. | ||||
|     function ERC1155Assets( | ||||
|         address tokenAddress, | ||||
|         uint256[] calldata tokenIds, | ||||
|         uint256[] calldata values, | ||||
|         uint256[] calldata tokenValues, | ||||
|         bytes calldata callbackData | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Function signature for encoding MultiAsset assetData. | ||||
|     /// @param values Array of amounts that correspond to each asset to be transferred. | ||||
|     ///        Note that each value will be multiplied by the amount being filled in the order before transferring. | ||||
|     /// @param nestedAssetData Array of assetData fields that will be be dispatched to their correspnding AssetProxy contract. | ||||
|     function MultiAsset( | ||||
|         uint256[] calldata values, | ||||
|         uint256[] calldata amounts, | ||||
|         bytes[] calldata nestedAssetData | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Function signature for encoding StaticCall assetData. | ||||
|     /// @param staticCallTargetAddress Address that will execute the staticcall. | ||||
|     /// @param staticCallData Data that will be executed via staticcall on the staticCallTargetAddress. | ||||
|     /// @param expectedReturnDataHash Keccak-256 hash of the expected staticcall return data. | ||||
|     function StaticCall( | ||||
|         address staticCallTargetAddress, | ||||
|         address callTarget, | ||||
|         bytes calldata staticCallData, | ||||
|         bytes32 expectedReturnDataHash | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Function signature for encoding ERC20Bridge assetData. | ||||
|     /// @param tokenAddress Address of token to transfer. | ||||
|     /// @param bridgeAddress Address of the bridge contract. | ||||
|     /// @param bridgeData Arbitrary data to be passed to the bridge contract. | ||||
|     function ERC20Bridge( | ||||
|         address tokenAddress, | ||||
|         address bridgeAddress, | ||||
|         bytes calldata bridgeData | ||||
|         bytes32 callResultHash | ||||
|     ) | ||||
|         external; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,7 +16,9 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "./IAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| contract IAssetProxy { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,17 +16,11 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
|  | ||||
| contract IAssetProxyDispatcher { | ||||
|  | ||||
|     // Logs registration of new asset proxy | ||||
|     event AssetProxyRegistered( | ||||
|         bytes4 id,              // Id of new registered AssetProxy. | ||||
|         address assetProxy      // Address of new registered AssetProxy. | ||||
|     ); | ||||
|  | ||||
|     /// @dev Registers an asset proxy to its asset proxy id. | ||||
|     ///      Once an asset proxy is registered, it cannot be unregistered. | ||||
|     /// @param assetProxy Address of new asset proxy to register. | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -16,7 +16,7 @@ | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol"; | ||||
|  | ||||
| @@ -24,18 +24,6 @@ import "@0x/contracts-utils/contracts/src/interfaces/IOwnable.sol"; | ||||
| contract IAuthorizable is | ||||
|     IOwnable | ||||
| { | ||||
|     // Event logged when a new address is authorized. | ||||
|     event AuthorizedAddressAdded( | ||||
|         address indexed target, | ||||
|         address indexed caller | ||||
|     ); | ||||
|  | ||||
|     // Event logged when a currently authorized address is unauthorized. | ||||
|     event AuthorizedAddressRemoved( | ||||
|         address indexed target, | ||||
|         address indexed caller | ||||
|     ); | ||||
|  | ||||
|     /// @dev Authorizes an address. | ||||
|     /// @param target Address to authorize. | ||||
|     function addAuthorizedAddress(address target) | ||||
| @@ -54,7 +42,7 @@ contract IAuthorizable is | ||||
|         uint256 index | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|      | ||||
|     /// @dev Gets all authorized addresses. | ||||
|     /// @return Array of authorized addresses. | ||||
|     function getAuthorizedAddresses() | ||||
|   | ||||
| @@ -1,39 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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); | ||||
| } | ||||
| @@ -1,38 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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); | ||||
| } | ||||
| @@ -1,66 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
|  | ||||
|  | ||||
| contract PotLike { | ||||
|     function chi() external returns (uint256); | ||||
|     function rho() external returns (uint256); | ||||
|     function drip() external returns (uint256); | ||||
|     function join(uint256) external; | ||||
|     function exit(uint256) external; | ||||
| } | ||||
|  | ||||
|  | ||||
| // The actual Chai contract can be found here: https://github.com/dapphub/chai | ||||
| contract IChai is | ||||
|     IERC20Token | ||||
| { | ||||
|     /// @dev Withdraws Dai owned by `src` | ||||
|     /// @param src Address that owns Dai. | ||||
|     /// @param wad Amount of Dai to withdraw. | ||||
|     function draw( | ||||
|         address src, | ||||
|         uint256 wad | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Queries Dai balance of Chai holder. | ||||
|     /// @param usr Address of Chai holder. | ||||
|     /// @return Dai balance. | ||||
|     function dai(address usr) | ||||
|         external | ||||
|         returns (uint256); | ||||
|  | ||||
|     /// @dev Queries the Pot contract used by the Chai contract. | ||||
|     function pot() | ||||
|         external | ||||
|         returns (PotLike); | ||||
|  | ||||
|     /// @dev Deposits Dai in exchange for Chai | ||||
|     /// @param dst Address to receive Chai. | ||||
|     /// @param wad Amount of Dai to deposit. | ||||
|     function join( | ||||
|         address dst, | ||||
|         uint256 wad | ||||
|     ) | ||||
|         external; | ||||
| } | ||||
| @@ -1,70 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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); | ||||
| } | ||||
| @@ -1,192 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
|  | ||||
| interface IDydx { | ||||
|  | ||||
|     /// @dev Represents the unique key that specifies an account | ||||
|     struct AccountInfo { | ||||
|         address owner;  // The address that owns the account | ||||
|         uint256 number; // A nonce that allows a single address to control many accounts | ||||
|     } | ||||
|  | ||||
|     enum ActionType { | ||||
|         Deposit,   // supply tokens | ||||
|         Withdraw,  // borrow tokens | ||||
|         Transfer,  // transfer balance between accounts | ||||
|         Buy,       // buy an amount of some token (externally) | ||||
|         Sell,      // sell an amount of some token (externally) | ||||
|         Trade,     // trade tokens against another account | ||||
|         Liquidate, // liquidate an undercollateralized or expiring account | ||||
|         Vaporize,  // use excess tokens to zero-out a completely negative account | ||||
|         Call       // send arbitrary data to an address | ||||
|     } | ||||
|  | ||||
|     /// @dev Arguments that are passed to Solo in an ordered list as part of a single operation. | ||||
|     /// Each ActionArgs has an actionType which specifies which action struct that this data will be | ||||
|     /// parsed into before being processed. | ||||
|     struct ActionArgs { | ||||
|         ActionType actionType; | ||||
|         uint256 accountIdx; | ||||
|         AssetAmount amount; | ||||
|         uint256 primaryMarketId; | ||||
|         uint256 secondaryMarketId; | ||||
|         address otherAddress; | ||||
|         uint256 otherAccountIdx; | ||||
|         bytes data; | ||||
|     } | ||||
|  | ||||
|     enum AssetDenomination { | ||||
|         Wei, // the amount is denominated in wei | ||||
|         Par  // the amount is denominated in par | ||||
|     } | ||||
|  | ||||
|     enum AssetReference { | ||||
|         Delta, // the amount is given as a delta from the current value | ||||
|         Target // the amount is given as an exact number to end up at | ||||
|     } | ||||
|  | ||||
|     struct AssetAmount { | ||||
|         bool sign; // true if positive | ||||
|         AssetDenomination denomination; | ||||
|         AssetReference ref; | ||||
|         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. | ||||
|     ///      One call to operate() is considered a singular "operation". Account collateralization is | ||||
|     ///      ensured only after the completion of the entire operation. | ||||
|     /// @param  accounts  A list of all accounts that will be used in this operation. Cannot contain | ||||
|     ///                   duplicates. In each action, the relevant account will be referred-to by its | ||||
|     ///                   index in the list. | ||||
|     /// @param  actions   An ordered list of all actions that will be taken in this operation. The | ||||
|     ///                   actions will be processed in order. | ||||
|     function operate( | ||||
|         AccountInfo[] calldata accounts, | ||||
|         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); | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
|  | ||||
| interface IDydxBridge { | ||||
|  | ||||
|     /// @dev This is the subset of `IDydx.ActionType` that are supported by the bridge. | ||||
|     enum BridgeActionType { | ||||
|         Deposit,                    // Deposit tokens into dydx account. | ||||
|         Withdraw                    // Withdraw tokens from dydx account. | ||||
|     } | ||||
|  | ||||
|     struct BridgeAction { | ||||
|         BridgeActionType actionType;            // Action to run on dydx account. | ||||
|         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). | ||||
|     } | ||||
|  | ||||
|     struct BridgeData { | ||||
|         uint256[] accountNumbers;               // Account number used to identify the owner's specific account. | ||||
|         BridgeAction[] actions;                 // Actions to carry out on the owner's accounts. | ||||
|     } | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
|  | ||||
| contract IERC20Bridge { | ||||
|  | ||||
|     /// @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 `0xdc1600f3` if successful. | ||||
|     function bridgeTransferFrom( | ||||
|         address tokenAddress, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes calldata bridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4 success); | ||||
| } | ||||
| @@ -1,38 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
|  | ||||
| interface IEth2Dai { | ||||
|  | ||||
|     /// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token. | ||||
|     /// @param fromToken The token being sold. | ||||
|     /// @param sellAmount The amount of `fromToken` token being sold. | ||||
|     /// @param toToken The token being bought. | ||||
|     /// @param minFillAmount Minimum amount of `toToken` token to buy. | ||||
|     /// @return fillAmount Amount of `toToken` bought. | ||||
|     function sellAllAmount( | ||||
|         address fromToken, | ||||
|         uint256 sellAmount, | ||||
|         address toToken, | ||||
|         uint256 minFillAmount | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 fillAmount); | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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; | ||||
| } | ||||
| @@ -1,72 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
|  | ||||
| interface IKyberNetworkProxy { | ||||
|  | ||||
|     /// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens. | ||||
|     /// @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 | ||||
|     /// @return boughtAmount Amount of tokens bought. | ||||
|     function trade( | ||||
|         address sellTokenAddress, | ||||
|         uint256 sellAmount, | ||||
|         address buyTokenAddress, | ||||
|         address payable recipientAddress, | ||||
|         uint256 maxBuyTokenAmount, | ||||
|         uint256 minConversionRate, | ||||
|         address walletId | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         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,32 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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 IMStable { | ||||
|  | ||||
|     function swap( | ||||
|         address _input, | ||||
|         address _output, | ||||
|         uint256 _quantity, | ||||
|         address _recipient | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 output); | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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); | ||||
| } | ||||
| @@ -1,34 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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); | ||||
| } | ||||
|  | ||||
| @@ -1,70 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
|  | ||||
| interface IUniswapExchange { | ||||
|  | ||||
|     /// @dev Buys at least `minTokensBought` tokens with ETH and transfer them | ||||
|     ///      to `recipient`. | ||||
|     /// @param minTokensBought The minimum number of tokens to buy. | ||||
|     /// @param deadline Time when this order expires. | ||||
|     /// @param recipient Who to transfer the tokens to. | ||||
|     /// @return tokensBought Amount of tokens bought. | ||||
|     function ethToTokenTransferInput( | ||||
|         uint256 minTokensBought, | ||||
|         uint256 deadline, | ||||
|         address recipient | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns (uint256 tokensBought); | ||||
|  | ||||
|     /// @dev Buys at least `minEthBought` ETH with tokens. | ||||
|     /// @param tokensSold Amount of tokens to sell. | ||||
|     /// @param minEthBought The minimum amount of ETH to buy. | ||||
|     /// @param deadline Time when this order expires. | ||||
|     /// @return ethBought Amount of tokens bought. | ||||
|     function tokenToEthSwapInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 ethBought); | ||||
|  | ||||
|     /// @dev Buys at least `minTokensBought` tokens with the exchange token | ||||
|     ///      and transfer them to `recipient`. | ||||
|     /// @param minTokensBought The minimum number of tokens to buy. | ||||
|     /// @param minEthBought The minimum amount of intermediate ETH to buy. | ||||
|     /// @param deadline Time when this order expires. | ||||
|     /// @param recipient Who to transfer the tokens to. | ||||
|     /// @param toTokenAddress The token being bought. | ||||
|     /// @return tokensBought Amount of tokens bought. | ||||
|     function tokenToTokenTransferInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minTokensBought, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline, | ||||
|         address recipient, | ||||
|         address toTokenAddress | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 tokensBought); | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
|  | ||||
| import "./IUniswapExchange.sol"; | ||||
|  | ||||
|  | ||||
| interface IUniswapExchangeFactory { | ||||
|  | ||||
|     /// @dev Get the exchange for a token. | ||||
|     /// @param tokenAddress The address of the token contract. | ||||
|     function getExchange(address tokenAddress) | ||||
|         external | ||||
|         view | ||||
|         returns (address); | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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); | ||||
| } | ||||
| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
|  | ||||
| contract LibAssetProxyIds { | ||||
|  | ||||
|     // AssetProxy Ids are equiavalent the first 4 bytes of the keccak256 hash of the function signature assigned to each AssetProxy. | ||||
|  | ||||
|     // ERC20Token(address) | ||||
|     bytes4 constant public ERC20_PROXY_ID = 0xf47261b0; | ||||
|  | ||||
|     // ERC721Token(address,uint256) | ||||
|     bytes4 constant public ERC721_PROXY_ID = 0x02571792; | ||||
|  | ||||
|     // ERC1155Assets(address,uint256[],uint256[],bytes) | ||||
|     bytes4 constant public ERC1155_PROXY_ID = 0xa7cb5fb7; | ||||
|  | ||||
|     // MultiAsset(uint256[],bytes[]) | ||||
|     bytes4 constant public MULTI_ASSET_PROXY_ID = 0x94cfcdd7; | ||||
|  | ||||
|     // StaticCall(address,bytes,bytes32) | ||||
|     bytes4 constant public STATIC_CALL_PROXY_ID = 0xc339d10a; | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "../interfaces/IAssetProxyDispatcher.sol"; | ||||
|  | ||||
|  | ||||
| contract MAssetProxyDispatcher is | ||||
|     IAssetProxyDispatcher | ||||
| { | ||||
|     // Logs registration of new asset proxy | ||||
|     event AssetProxyRegistered( | ||||
|         bytes4 id,              // Id of new registered AssetProxy. | ||||
|         address assetProxy      // Address of new registered AssetProxy. | ||||
|     ); | ||||
|  | ||||
|     /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws. | ||||
|     /// @param assetData Byte array encoded for the asset. | ||||
|     /// @param from Address to transfer token from. | ||||
|     /// @param to Address to transfer token to. | ||||
|     /// @param amount Amount of token to transfer. | ||||
|     function dispatchTransferFrom( | ||||
|         bytes memory assetData, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         internal; | ||||
| } | ||||
							
								
								
									
										41
									
								
								contracts/asset-proxy/contracts/src/mixins/MAuthorizable.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								contracts/asset-proxy/contracts/src/mixins/MAuthorizable.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.5; | ||||
|  | ||||
| import "../interfaces/IAuthorizable.sol"; | ||||
|  | ||||
|  | ||||
| contract MAuthorizable is | ||||
|     IAuthorizable | ||||
| { | ||||
|     // Event logged when a new address is authorized. | ||||
|     event AuthorizedAddressAdded( | ||||
|         address indexed target, | ||||
|         address indexed caller | ||||
|     ); | ||||
|  | ||||
|     // Event logged when a currently authorized address is unauthorized. | ||||
|     event AuthorizedAddressRemoved( | ||||
|         address indexed target, | ||||
|         address indexed caller | ||||
|     ); | ||||
|  | ||||
|     /// @dev Only authorized addresses can invoke functions with this modifier. | ||||
|     modifier onlyAuthorized { revert(); _; } | ||||
| } | ||||
| @@ -1,247 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,80 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../src/bridges/ChaiBridge.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/ERC20Token.sol"; | ||||
|  | ||||
|  | ||||
| contract TestChaiDai is | ||||
|     ERC20Token | ||||
| { | ||||
|     address private constant ALWAYS_REVERT_ADDRESS = address(1); | ||||
|  | ||||
|     function draw( | ||||
|         address from, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         if (from == ALWAYS_REVERT_ADDRESS) { | ||||
|             revert(); | ||||
|         } | ||||
|         balances[msg.sender] += amount; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestChaiBridge is | ||||
|     ChaiBridge | ||||
| { | ||||
|     address public testChaiDai; | ||||
|     address private constant ALWAYS_REVERT_ADDRESS = address(1); | ||||
|  | ||||
|     constructor() | ||||
|         public | ||||
|     { | ||||
|         testChaiDai = address(new TestChaiDai()); | ||||
|     } | ||||
|  | ||||
|     function _getDaiAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return testChaiDai; | ||||
|     } | ||||
|  | ||||
|     function _getChaiAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return testChaiDai; | ||||
|     } | ||||
|  | ||||
|     function _getERC20BridgeProxyAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender; | ||||
|     } | ||||
| } | ||||
| @@ -1,244 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   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; | ||||
|     } | ||||
| } | ||||
| @@ -1,246 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| 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 | ||||
|     mapping (address => uint256) private _balances; | ||||
|  | ||||
|     /// @dev Sets initial balance of token holders. | ||||
|     constructor(address[] memory holders) | ||||
|         public | ||||
|     { | ||||
|         for (uint256 i = 0; i != holders.length; ++i) { | ||||
|             _balances[holders[i]] = INIT_HOLDER_BALANCE; | ||||
|         } | ||||
|         _balances[msg.sender] = INIT_HOLDER_BALANCE; | ||||
|     } | ||||
|  | ||||
|     /// @dev Basic transferFrom implementation. | ||||
|     function transferFrom(address from, address to, uint256 amount) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         if (_balances[from] < amount || _balances[to] + amount < _balances[to]) { | ||||
|             return false; | ||||
|         } | ||||
|         _balances[from] -= amount; | ||||
|         _balances[to] += amount; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns balance of `holder`. | ||||
|     function balanceOf(address holder) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256) | ||||
|     { | ||||
|         return _balances[holder]; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| // solhint-disable space-after-comma | ||||
| contract TestDydxBridge is | ||||
|     IDydx, | ||||
|     DydxBridge | ||||
| { | ||||
|  | ||||
|     address private constant ALWAYS_REVERT_ADDRESS = address(1); | ||||
|     address private _testTokenAddress; | ||||
|     bool private _shouldRevertOnOperate; | ||||
|  | ||||
|     event OperateAccount( | ||||
|         address owner, | ||||
|         uint256 number | ||||
|     ); | ||||
|  | ||||
|     event OperateAction( | ||||
|         ActionType actionType, | ||||
|         uint256 accountIdx, | ||||
|         bool amountSign, | ||||
|         AssetDenomination amountDenomination, | ||||
|         AssetReference amountRef, | ||||
|         uint256 amountValue, | ||||
|         uint256 primaryMarketId, | ||||
|         uint256 secondaryMarketId, | ||||
|         address otherAddress, | ||||
|         uint256 otherAccountId, | ||||
|         bytes data | ||||
|     ); | ||||
|  | ||||
|     constructor(address[] memory holders) | ||||
|         public | ||||
|     { | ||||
|         // Deploy a test token. This represents the asset being deposited/withdrawn from dydx. | ||||
|         _testTokenAddress = address(new TestDydxBridgeToken(holders)); | ||||
|     } | ||||
|  | ||||
|     /// @dev Simulates `operate` in dydx contract. | ||||
|     ///      Emits events so that arguments can be validated client-side. | ||||
|     function operate( | ||||
|         AccountInfo[] calldata accounts, | ||||
|         ActionArgs[] calldata actions | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         if (_shouldRevertOnOperate) { | ||||
|             revert("TestDydxBridge/SHOULD_REVERT_ON_OPERATE"); | ||||
|         } | ||||
|  | ||||
|         for (uint i = 0; i < accounts.length; ++i) { | ||||
|             emit OperateAccount( | ||||
|                 accounts[i].owner, | ||||
|                 accounts[i].number | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         for (uint i = 0; i < actions.length; ++i) { | ||||
|             emit OperateAction( | ||||
|                 actions[i].actionType, | ||||
|                 actions[i].accountIdx, | ||||
|                 actions[i].amount.sign, | ||||
|                 actions[i].amount.denomination, | ||||
|                 actions[i].amount.ref, | ||||
|                 actions[i].amount.value, | ||||
|                 actions[i].primaryMarketId, | ||||
|                 actions[i].secondaryMarketId, | ||||
|                 actions[i].otherAddress, | ||||
|                 actions[i].otherAccountIdx, | ||||
|                 actions[i].data | ||||
|             ); | ||||
|  | ||||
|             if (actions[i].actionType == IDydx.ActionType.Withdraw) { | ||||
|                 require( | ||||
|                     IERC20Token(_testTokenAddress).transferFrom( | ||||
|                         address(this), | ||||
|                         actions[i].otherAddress, | ||||
|                         actions[i].amount.value | ||||
|                     ), | ||||
|                     "TestDydxBridge/WITHDRAW_FAILED" | ||||
|                 ); | ||||
|             } else if (actions[i].actionType == IDydx.ActionType.Deposit) { | ||||
|                 require( | ||||
|                     IERC20Token(_testTokenAddress).transferFrom( | ||||
|                         actions[i].otherAddress, | ||||
|                         address(this), | ||||
|                         actions[i].amount.value | ||||
|                     ), | ||||
|                     "TestDydxBridge/DEPOSIT_FAILED" | ||||
|                 ); | ||||
|             } else { | ||||
|                 revert("TestDydxBridge/UNSUPPORTED_ACTION"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev If `true` then subsequent calls to `operate` will revert. | ||||
|     function setRevertOnOperate(bool shouldRevert) | ||||
|         external | ||||
|     { | ||||
|         _shouldRevertOnOperate = shouldRevert; | ||||
|     } | ||||
|  | ||||
|     /// @dev Returns test token. | ||||
|     function getTestToken() | ||||
|         external | ||||
|         returns (address) | ||||
|     { | ||||
|         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 | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(this); | ||||
|     } | ||||
|  | ||||
|     /// @dev overrides `_getERC20BridgeProxyAddress()` from `DeploymentConstants` for testing. | ||||
|     function _getERC20BridgeProxyAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return msg.sender == ALWAYS_REVERT_ADDRESS ? address(0) : msg.sender; | ||||
|     } | ||||
| } | ||||
| @@ -1,108 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../src/interfaces/IERC20Bridge.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Test bridge token | ||||
| contract TestERC20BridgeToken { | ||||
|     mapping (address => uint256) private _balances; | ||||
|  | ||||
|     function addBalance(address owner, int256 amount) | ||||
|         external | ||||
|     { | ||||
|         setBalance(owner, uint256(int256(balanceOf(owner)) + amount)); | ||||
|     } | ||||
|  | ||||
|     function setBalance(address owner, uint256 balance) | ||||
|         public | ||||
|     { | ||||
|         _balances[owner] = balance; | ||||
|     } | ||||
|  | ||||
|     function balanceOf(address owner) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256) | ||||
|     { | ||||
|         return _balances[owner]; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev Test bridge contract. | ||||
| contract TestERC20Bridge is | ||||
|     IERC20Bridge | ||||
| { | ||||
|     TestERC20BridgeToken public testToken; | ||||
|  | ||||
|     event BridgeWithdrawTo( | ||||
|         address tokenAddress, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes bridgeData | ||||
|     ); | ||||
|  | ||||
|     constructor() public { | ||||
|         testToken = new TestERC20BridgeToken(); | ||||
|     } | ||||
|  | ||||
|     function setTestTokenBalance(address owner, uint256 balance) | ||||
|         external | ||||
|     { | ||||
|         testToken.setBalance(owner, balance); | ||||
|     } | ||||
|  | ||||
|     function bridgeTransferFrom( | ||||
|         address tokenAddress, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes calldata bridgeData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes4) | ||||
|     { | ||||
|         emit BridgeWithdrawTo( | ||||
|             tokenAddress, | ||||
|             from, | ||||
|             to, | ||||
|             amount, | ||||
|             bridgeData | ||||
|         ); | ||||
|         // Unpack the bridgeData. | ||||
|         ( | ||||
|             int256 transferAmount, | ||||
|             bytes memory revertData, | ||||
|             bytes memory returnData | ||||
|         ) = abi.decode(bridgeData, (int256, bytes, bytes)); | ||||
|  | ||||
|         // If `revertData` is set, revert. | ||||
|         if (revertData.length != 0) { | ||||
|             assembly { revert(add(revertData, 0x20), mload(revertData)) } | ||||
|         } | ||||
|         // Increase `to`'s balance by `transferAmount`. | ||||
|         TestERC20BridgeToken(tokenAddress).addBalance(to, transferAmount); | ||||
|         // Return `returnData`. | ||||
|         assembly { return(add(returnData, 0x20), mload(returnData)) } | ||||
|     } | ||||
| } | ||||
| @@ -1,206 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "../src/bridges/Eth2DaiBridge.sol"; | ||||
| import "../src/interfaces/IEth2Dai.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable no-simple-event-func-name | ||||
| contract TestEvents { | ||||
|  | ||||
|     event TokenTransfer( | ||||
|         address token, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event TokenApprove( | ||||
|         address token, | ||||
|         address spender, | ||||
|         uint256 allowance | ||||
|     ); | ||||
|  | ||||
|     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(msg.sender, spender, allowance); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev A minimalist ERC20 token. | ||||
| contract TestToken { | ||||
|  | ||||
|     mapping (address => uint256) public balances; | ||||
|     string private _nextTransferRevertReason; | ||||
|     bytes private _nextTransferReturnData; | ||||
|  | ||||
|     /// @dev Just calls `raiseTokenTransfer()` on the caller. | ||||
|     function transfer(address to, uint256 amount) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         TestEvents(msg.sender).raiseTokenTransfer(msg.sender, to, amount); | ||||
|         if (bytes(_nextTransferRevertReason).length != 0) { | ||||
|             revert(_nextTransferRevertReason); | ||||
|         } | ||||
|         bytes memory returnData = _nextTransferReturnData; | ||||
|         assembly { return(add(returnData, 0x20), mload(returnData)) } | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the balance for `owner`. | ||||
|     function setBalance(address owner, uint256 balance) | ||||
|         external | ||||
|     { | ||||
|         balances[owner] = balance; | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the behavior of the `transfer()` call. | ||||
|     function setTransferBehavior( | ||||
|         string calldata revertReason, | ||||
|         bytes calldata returnData | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         _nextTransferRevertReason = revertReason; | ||||
|         _nextTransferReturnData = returnData; | ||||
|     } | ||||
|  | ||||
|     /// @dev Just calls `raiseTokenApprove()` on the caller. | ||||
|     function approve(address spender, uint256 allowance) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         TestEvents(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 Eth2DaiBridge overridden to mock tokens and | ||||
| ///      implement IEth2Dai. | ||||
| contract TestEth2DaiBridge is | ||||
|     TestEvents, | ||||
|     IEth2Dai, | ||||
|     Eth2DaiBridge | ||||
| { | ||||
|     event SellAllAmount( | ||||
|         address sellToken, | ||||
|         uint256 sellTokenAmount, | ||||
|         address buyToken, | ||||
|         uint256 minimumFillAmount | ||||
|     ); | ||||
|  | ||||
|     mapping (address => TestToken)  public testTokens; | ||||
|     string private _nextRevertReason; | ||||
|     uint256 private _nextFillAmount; | ||||
|  | ||||
|     /// @dev Create a token and set this contract's balance. | ||||
|     function createToken(uint256 balance) | ||||
|         external | ||||
|         returns (address tokenAddress) | ||||
|     { | ||||
|         TestToken token = new TestToken(); | ||||
|         testTokens[address(token)] = token; | ||||
|         token.setBalance(address(this), balance); | ||||
|         return address(token); | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the behavior for `IEth2Dai.sellAllAmount()`. | ||||
|     function setFillBehavior(string calldata revertReason, uint256 fillAmount) | ||||
|         external | ||||
|     { | ||||
|         _nextRevertReason = revertReason; | ||||
|         _nextFillAmount = fillAmount; | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the behavior of a token's `transfer()`. | ||||
|     function setTransferBehavior( | ||||
|         address tokenAddress, | ||||
|         string calldata revertReason, | ||||
|         bytes calldata returnData | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         testTokens[tokenAddress].setTransferBehavior(revertReason, returnData); | ||||
|     } | ||||
|  | ||||
|     /// @dev Implementation of `IEth2Dai.sellAllAmount()` | ||||
|     function sellAllAmount( | ||||
|         address sellTokenAddress, | ||||
|         uint256 sellTokenAmount, | ||||
|         address buyTokenAddress, | ||||
|         uint256 minimumFillAmount | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 fillAmount) | ||||
|     { | ||||
|         emit SellAllAmount( | ||||
|             sellTokenAddress, | ||||
|             sellTokenAmount, | ||||
|             buyTokenAddress, | ||||
|             minimumFillAmount | ||||
|         ); | ||||
|         if (bytes(_nextRevertReason).length != 0) { | ||||
|             revert(_nextRevertReason); | ||||
|         } | ||||
|         return _nextFillAmount; | ||||
|     } | ||||
|  | ||||
|     // @dev This contract will double as the Eth2Dai contract. | ||||
|     function _getEth2DaiAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(this); | ||||
|     } | ||||
| } | ||||
| @@ -1,355 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "../src/bridges/KyberBridge.sol"; | ||||
| import "../src/interfaces/IKyberNetworkProxy.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable no-simple-event-func-name | ||||
| interface ITestContract { | ||||
|  | ||||
|     function wethWithdraw( | ||||
|         address payable ownerAddress, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     function wethDeposit( | ||||
|         address ownerAddress | ||||
|     ) | ||||
|         external | ||||
|         payable; | ||||
|  | ||||
|     function tokenTransfer( | ||||
|         address ownerAddress, | ||||
|         address recipientAddress, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|         returns (bool success); | ||||
|  | ||||
|     function tokenApprove( | ||||
|         address ownerAddress, | ||||
|         address spenderAddress, | ||||
|         uint256 allowance | ||||
|     ) | ||||
|         external | ||||
|         returns (bool success); | ||||
|  | ||||
|     function tokenBalanceOf( | ||||
|         address ownerAddress | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 balance); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev A minimalist ERC20/WETH token. | ||||
| contract TestToken { | ||||
|  | ||||
|     uint8 public decimals; | ||||
|     ITestContract private _testContract; | ||||
|  | ||||
|     constructor(uint8 decimals_) public { | ||||
|         decimals = decimals_; | ||||
|         _testContract = ITestContract(msg.sender); | ||||
|     } | ||||
|  | ||||
|     function approve(address spender, uint256 allowance) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         return _testContract.tokenApprove( | ||||
|             msg.sender, | ||||
|             spender, | ||||
|             allowance | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function transfer(address recipient, uint256 amount) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         return _testContract.tokenTransfer( | ||||
|             msg.sender, | ||||
|             recipient, | ||||
|             amount | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function withdraw(uint256 amount) | ||||
|         external | ||||
|     { | ||||
|         return _testContract.wethWithdraw(msg.sender, amount); | ||||
|     } | ||||
|  | ||||
|     function deposit() | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         return _testContract.wethDeposit.value(msg.value)(msg.sender); | ||||
|     } | ||||
|  | ||||
|     function allowance(address, address) external view returns (uint256) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     function balanceOf(address owner) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256) | ||||
|     { | ||||
|         return _testContract.tokenBalanceOf(owner); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev KyberBridge overridden to mock tokens and implement IKyberBridge. | ||||
| contract TestKyberBridge is | ||||
|     KyberBridge, | ||||
|     ITestContract, | ||||
|     IKyberNetworkProxy | ||||
| { | ||||
|     event KyberBridgeTrade( | ||||
|         uint256 msgValue, | ||||
|         address sellTokenAddress, | ||||
|         uint256 sellAmount, | ||||
|         address buyTokenAddress, | ||||
|         address payable recipientAddress, | ||||
|         uint256 maxBuyTokenAmount, | ||||
|         uint256 minConversionRate, | ||||
|         address walletId | ||||
|     ); | ||||
|  | ||||
|     event KyberBridgeWethWithdraw( | ||||
|         address ownerAddress, | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event KyberBridgeWethDeposit( | ||||
|         uint256 msgValue, | ||||
|         address ownerAddress, | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event KyberBridgeTokenApprove( | ||||
|         address tokenAddress, | ||||
|         address ownerAddress, | ||||
|         address spenderAddress, | ||||
|         uint256 allowance | ||||
|     ); | ||||
|  | ||||
|     event KyberBridgeTokenTransfer( | ||||
|         address tokenAddress, | ||||
|         address ownerAddress, | ||||
|         address recipientAddress, | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     IEtherToken public weth; | ||||
|     mapping (address => mapping (address => uint256)) private _tokenBalances; | ||||
|     uint256 private _nextFillAmount; | ||||
|  | ||||
|     constructor() public { | ||||
|         weth = IEtherToken(address(new TestToken(18))); | ||||
|     } | ||||
|  | ||||
|     /// @dev Implementation of `IKyberNetworkProxy.trade()` | ||||
|     function trade( | ||||
|         address sellTokenAddress, | ||||
|         uint256 sellAmount, | ||||
|         address buyTokenAddress, | ||||
|         address payable recipientAddress, | ||||
|         uint256 maxBuyTokenAmount, | ||||
|         uint256 minConversionRate, | ||||
|         address walletId | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns(uint256 boughtAmount) | ||||
|     { | ||||
|         emit KyberBridgeTrade( | ||||
|             msg.value, | ||||
|             sellTokenAddress, | ||||
|             sellAmount, | ||||
|             buyTokenAddress, | ||||
|             recipientAddress, | ||||
|             maxBuyTokenAmount, | ||||
|             minConversionRate, | ||||
|             walletId | ||||
|         ); | ||||
|         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) | ||||
|     { | ||||
|         return address(new TestToken(decimals)); | ||||
|     } | ||||
|  | ||||
|     function setNextFillAmount(uint256 amount) | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         if (msg.value != 0) { | ||||
|             require(amount == msg.value, "VALUE_AMOUNT_MISMATCH"); | ||||
|             grantTokensTo(address(weth), address(this), msg.value); | ||||
|         } | ||||
|         _nextFillAmount = amount; | ||||
|     } | ||||
|  | ||||
|     function wethDeposit( | ||||
|         address ownerAddress | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         require(msg.sender == address(weth), "ONLY_WETH"); | ||||
|         grantTokensTo(address(weth), ownerAddress, msg.value); | ||||
|         emit KyberBridgeWethDeposit( | ||||
|             msg.value, | ||||
|             ownerAddress, | ||||
|             msg.value | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function wethWithdraw( | ||||
|         address payable ownerAddress, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         require(msg.sender == address(weth), "ONLY_WETH"); | ||||
|         _tokenBalances[address(weth)][ownerAddress] -= amount; | ||||
|         ownerAddress.transfer(amount); | ||||
|         emit KyberBridgeWethWithdraw( | ||||
|             ownerAddress, | ||||
|             amount | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function tokenApprove( | ||||
|         address ownerAddress, | ||||
|         address spenderAddress, | ||||
|         uint256 allowance | ||||
|     ) | ||||
|         external | ||||
|         returns (bool success) | ||||
|     { | ||||
|         emit KyberBridgeTokenApprove( | ||||
|             msg.sender, | ||||
|             ownerAddress, | ||||
|             spenderAddress, | ||||
|             allowance | ||||
|         ); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     function tokenTransfer( | ||||
|         address ownerAddress, | ||||
|         address recipientAddress, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|         returns (bool success) | ||||
|     { | ||||
|         _tokenBalances[msg.sender][ownerAddress] -= amount; | ||||
|         _tokenBalances[msg.sender][recipientAddress] += amount; | ||||
|         emit KyberBridgeTokenTransfer( | ||||
|             msg.sender, | ||||
|             ownerAddress, | ||||
|             recipientAddress, | ||||
|             amount | ||||
|         ); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     function tokenBalanceOf( | ||||
|         address ownerAddress | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (uint256 balance) | ||||
|     { | ||||
|         return _tokenBalances[msg.sender][ownerAddress]; | ||||
|     } | ||||
|  | ||||
|     function grantTokensTo(address tokenAddress, address ownerAddress, uint256 amount) | ||||
|         public | ||||
|         payable | ||||
|     { | ||||
|         _tokenBalances[tokenAddress][ownerAddress] += amount; | ||||
|         if (tokenAddress != address(weth)) { | ||||
|             // Send back ether if not WETH. | ||||
|             msg.sender.transfer(msg.value); | ||||
|         } else { | ||||
|             require(msg.value == amount, "VALUE_AMOUNT_MISMATCH"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // @dev overridden to point to this contract. | ||||
|     function _getKyberNetworkProxyAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(this); | ||||
|     } | ||||
|  | ||||
|     // @dev overridden to point to test WETH. | ||||
|     function _getWethAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(weth); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|   Copyright 2018 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   | ||||
| @@ -1,436 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.9; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; | ||||
| import "../src/bridges/UniswapBridge.sol"; | ||||
| import "../src/interfaces/IUniswapExchangeFactory.sol"; | ||||
| import "../src/interfaces/IUniswapExchange.sol"; | ||||
|  | ||||
|  | ||||
| // solhint-disable no-simple-event-func-name | ||||
| contract TestEventsRaiser { | ||||
|  | ||||
|     event TokenTransfer( | ||||
|         address token, | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event TokenApprove( | ||||
|         address spender, | ||||
|         uint256 allowance | ||||
|     ); | ||||
|  | ||||
|     event WethDeposit( | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event WethWithdraw( | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     event EthToTokenTransferInput( | ||||
|         address exchange, | ||||
|         uint256 minTokensBought, | ||||
|         uint256 deadline, | ||||
|         address recipient | ||||
|     ); | ||||
|  | ||||
|     event TokenToEthSwapInput( | ||||
|         address exchange, | ||||
|         uint256 tokensSold, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline | ||||
|     ); | ||||
|  | ||||
|     event TokenToTokenTransferInput( | ||||
|         address exchange, | ||||
|         uint256 tokensSold, | ||||
|         uint256 minTokensBought, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline, | ||||
|         address recipient, | ||||
|         address toTokenAddress | ||||
|     ); | ||||
|  | ||||
|     function raiseEthToTokenTransferInput( | ||||
|         uint256 minTokensBought, | ||||
|         uint256 deadline, | ||||
|         address recipient | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         emit EthToTokenTransferInput( | ||||
|             msg.sender, | ||||
|             minTokensBought, | ||||
|             deadline, | ||||
|             recipient | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function raiseTokenToEthSwapInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         emit TokenToEthSwapInput( | ||||
|             msg.sender, | ||||
|             tokensSold, | ||||
|             minEthBought, | ||||
|             deadline | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function raiseTokenToTokenTransferInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minTokensBought, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline, | ||||
|         address recipient, | ||||
|         address toTokenAddress | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         emit TokenToTokenTransferInput( | ||||
|             msg.sender, | ||||
|             tokensSold, | ||||
|             minTokensBought, | ||||
|             minEthBought, | ||||
|             deadline, | ||||
|             recipient, | ||||
|             toTokenAddress | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function raiseTokenTransfer( | ||||
|         address from, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         emit TokenTransfer( | ||||
|             msg.sender, | ||||
|             from, | ||||
|             to, | ||||
|             amount | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function raiseTokenApprove(address spender, uint256 allowance) | ||||
|         external | ||||
|     { | ||||
|         emit TokenApprove(spender, allowance); | ||||
|     } | ||||
|  | ||||
|     function raiseWethDeposit(uint256 amount) | ||||
|         external | ||||
|     { | ||||
|         emit WethDeposit(amount); | ||||
|     } | ||||
|  | ||||
|     function raiseWethWithdraw(uint256 amount) | ||||
|         external | ||||
|     { | ||||
|         emit WethWithdraw(amount); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev A minimalist ERC20/WETH token. | ||||
| contract TestToken { | ||||
|  | ||||
|     using LibSafeMath for uint256; | ||||
|  | ||||
|     mapping (address => uint256) public balances; | ||||
|     string private _nextRevertReason; | ||||
|  | ||||
|     /// @dev Set the balance for `owner`. | ||||
|     function setBalance(address owner) | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         balances[owner] = msg.value; | ||||
|     } | ||||
|  | ||||
|     /// @dev Set the revert reason for `transfer()`, | ||||
|     ///      `deposit()`, and `withdraw()`. | ||||
|     function setRevertReason(string calldata reason) | ||||
|         external | ||||
|     { | ||||
|         _nextRevertReason = reason; | ||||
|     } | ||||
|  | ||||
|     /// @dev Just calls `raiseTokenTransfer()` on the caller. | ||||
|     function transfer(address to, uint256 amount) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         _revertIfReasonExists(); | ||||
|         TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /// @dev Just calls `raiseTokenApprove()` on the caller. | ||||
|     function approve(address spender, uint256 allowance) | ||||
|         external | ||||
|         returns (bool) | ||||
|     { | ||||
|         TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /// @dev `IWETH.deposit()` that increases balances and calls | ||||
|     ///     `raiseWethDeposit()` on the caller. | ||||
|     function deposit() | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         _revertIfReasonExists(); | ||||
|         balances[msg.sender] += balances[msg.sender].safeAdd(msg.value); | ||||
|         TestEventsRaiser(msg.sender).raiseWethDeposit(msg.value); | ||||
|     } | ||||
|  | ||||
|     /// @dev `IWETH.withdraw()` that just reduces balances and calls | ||||
|     ///       `raiseWethWithdraw()` on the caller. | ||||
|     function withdraw(uint256 amount) | ||||
|         external | ||||
|     { | ||||
|         _revertIfReasonExists(); | ||||
|         balances[msg.sender] = balances[msg.sender].safeSub(amount); | ||||
|         msg.sender.transfer(amount); | ||||
|         TestEventsRaiser(msg.sender).raiseWethWithdraw(amount); | ||||
|     } | ||||
|  | ||||
|     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]; | ||||
|     } | ||||
|  | ||||
|     function _revertIfReasonExists() | ||||
|         private | ||||
|         view | ||||
|     { | ||||
|         if (bytes(_nextRevertReason).length != 0) { | ||||
|             revert(_nextRevertReason); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| contract TestExchange is | ||||
|     IUniswapExchange | ||||
| { | ||||
|     address public tokenAddress; | ||||
|     string private _nextRevertReason; | ||||
|  | ||||
|     constructor(address _tokenAddress) public { | ||||
|         tokenAddress = _tokenAddress; | ||||
|     } | ||||
|  | ||||
|     function setFillBehavior( | ||||
|         string calldata revertReason | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         _nextRevertReason = revertReason; | ||||
|     } | ||||
|  | ||||
|     function ethToTokenTransferInput( | ||||
|         uint256 minTokensBought, | ||||
|         uint256 deadline, | ||||
|         address recipient | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns (uint256 tokensBought) | ||||
|     { | ||||
|         TestEventsRaiser(msg.sender).raiseEthToTokenTransferInput( | ||||
|             minTokensBought, | ||||
|             deadline, | ||||
|             recipient | ||||
|         ); | ||||
|         _revertIfReasonExists(); | ||||
|         return address(this).balance; | ||||
|     } | ||||
|  | ||||
|     function tokenToEthSwapInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 ethBought) | ||||
|     { | ||||
|         TestEventsRaiser(msg.sender).raiseTokenToEthSwapInput( | ||||
|             tokensSold, | ||||
|             minEthBought, | ||||
|             deadline | ||||
|         ); | ||||
|         _revertIfReasonExists(); | ||||
|         uint256 fillAmount = address(this).balance; | ||||
|         msg.sender.transfer(fillAmount); | ||||
|         return fillAmount; | ||||
|     } | ||||
|  | ||||
|     function tokenToTokenTransferInput( | ||||
|         uint256 tokensSold, | ||||
|         uint256 minTokensBought, | ||||
|         uint256 minEthBought, | ||||
|         uint256 deadline, | ||||
|         address recipient, | ||||
|         address toTokenAddress | ||||
|     ) | ||||
|         external | ||||
|         returns (uint256 tokensBought) | ||||
|     { | ||||
|         TestEventsRaiser(msg.sender).raiseTokenToTokenTransferInput( | ||||
|             tokensSold, | ||||
|             minTokensBought, | ||||
|             minEthBought, | ||||
|             deadline, | ||||
|             recipient, | ||||
|             toTokenAddress | ||||
|         ); | ||||
|         _revertIfReasonExists(); | ||||
|         return address(this).balance; | ||||
|     } | ||||
|  | ||||
|     function toTokenAddress() | ||||
|         external | ||||
|         view | ||||
|         returns (address _tokenAddress) | ||||
|     { | ||||
|         return tokenAddress; | ||||
|     } | ||||
|  | ||||
|     function _revertIfReasonExists() | ||||
|         private | ||||
|         view | ||||
|     { | ||||
|         if (bytes(_nextRevertReason).length != 0) { | ||||
|             revert(_nextRevertReason); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /// @dev UniswapBridge overridden to mock tokens and implement IUniswapExchangeFactory. | ||||
| contract TestUniswapBridge is | ||||
|     IUniswapExchangeFactory, | ||||
|     TestEventsRaiser, | ||||
|     UniswapBridge | ||||
| { | ||||
|     TestToken public wethToken; | ||||
|     // Token address to TestToken instance. | ||||
|     mapping (address => TestToken) private _testTokens; | ||||
|     // Token address to TestExchange instance. | ||||
|     mapping (address => TestExchange) private _testExchanges; | ||||
|  | ||||
|     constructor() public { | ||||
|         wethToken = new TestToken(); | ||||
|         _testTokens[address(wethToken)] = wethToken; | ||||
|     } | ||||
|  | ||||
|     /// @dev Sets the balance of this contract for an existing token. | ||||
|     ///      The wei attached will be the balance. | ||||
|     function setTokenBalance(address tokenAddress) | ||||
|         external | ||||
|         payable | ||||
|     { | ||||
|         TestToken token = _testTokens[tokenAddress]; | ||||
|         token.deposit.value(msg.value)(); | ||||
|     } | ||||
|  | ||||
|     /// @dev Sets the revert reason for an existing token. | ||||
|     function setTokenRevertReason(address tokenAddress, string calldata revertReason) | ||||
|         external | ||||
|     { | ||||
|         TestToken token = _testTokens[tokenAddress]; | ||||
|         token.setRevertReason(revertReason); | ||||
|     } | ||||
|  | ||||
|     /// @dev Create a token and exchange (if they don't exist) for a new token | ||||
|     ///      and sets the exchange revert and fill behavior. The wei attached | ||||
|     ///      will be the fill amount for the exchange. | ||||
|     /// @param tokenAddress The token address. If zero, one will be created. | ||||
|     /// @param revertReason The revert reason for exchange operations. | ||||
|     function createTokenAndExchange( | ||||
|         address tokenAddress, | ||||
|         string calldata revertReason | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns (TestToken token, TestExchange exchange) | ||||
|     { | ||||
|         token = TestToken(tokenAddress); | ||||
|         if (tokenAddress == address(0)) { | ||||
|             token = new TestToken(); | ||||
|         } | ||||
|         _testTokens[address(token)] = token; | ||||
|         exchange = _testExchanges[address(token)]; | ||||
|         if (address(exchange) == address(0)) { | ||||
|             _testExchanges[address(token)] = exchange = new TestExchange(address(token)); | ||||
|         } | ||||
|         exchange.setFillBehavior.value(msg.value)(revertReason); | ||||
|         return (token, exchange); | ||||
|     } | ||||
|  | ||||
|     /// @dev `IUniswapExchangeFactory.getExchange` | ||||
|     function getExchange(address tokenAddress) | ||||
|         external | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(_testExchanges[tokenAddress]); | ||||
|     } | ||||
|  | ||||
|     // @dev Use `wethToken`. | ||||
|     function _getWethAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(wethToken); | ||||
|     } | ||||
|  | ||||
|     // @dev This contract will double as the Uniswap contract. | ||||
|     function _getUniswapExchangeFactoryAddress() | ||||
|         internal | ||||
|         view | ||||
|         returns (address) | ||||
|     { | ||||
|         return address(this); | ||||
|     } | ||||
| } | ||||
| @@ -1,253 +0,0 @@ | ||||
| /* | ||||
|  | ||||
|   Copyright 2019 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|   See the License for the specific language governing permissions and | ||||
|   limitations under the License. | ||||
|  | ||||
| */ | ||||
|  | ||||
| pragma solidity ^0.5.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.7.17", | ||||
|     "version": "2.2.8", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -12,7 +12,7 @@ | ||||
|     "scripts": { | ||||
|         "build": "yarn pre_build && tsc -b", | ||||
|         "build:ci": "yarn build", | ||||
|         "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy", | ||||
|         "pre_build": "run-s compile generate_contract_wrappers", | ||||
|         "test": "yarn run_mocha", | ||||
|         "rebuild_and_test": "run-s build test", | ||||
|         "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", | ||||
| @@ -21,79 +21,69 @@ | ||||
|         "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", | ||||
|         "compile": "sol-compiler", | ||||
|         "watch": "sol-compiler -w", | ||||
|         "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers", | ||||
|         "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers", | ||||
|         "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", | ||||
|         "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", | ||||
|         "clean": "shx rm -rf lib generated-artifacts generated-wrappers", | ||||
|         "generate_contract_wrappers": "abi-gen --abis  ${npm_package_config_abis} --output generated-wrappers --backend ethers", | ||||
|         "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", | ||||
|         "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", | ||||
|         "coverage:report:text": "istanbul report text", | ||||
|         "coverage:report:html": "istanbul report html && open coverage/index.html", | ||||
|         "profiler:report:html": "istanbul report html && open coverage/index.html", | ||||
|         "coverage:report:lcov": "istanbul report lcov", | ||||
|         "test:circleci": "yarn test", | ||||
|         "contracts:gen": "contracts-gen generate", | ||||
|         "contracts:copy": "contracts-gen copy", | ||||
|         "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol", | ||||
|         "compile:truffle": "truffle compile", | ||||
|         "docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" | ||||
|         "contracts:gen": "contracts-gen", | ||||
|         "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" | ||||
|     }, | ||||
|     "config": { | ||||
|         "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": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy|StaticCallProxy|TestStaticCallTarget).json", | ||||
|         "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." | ||||
|     }, | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "https://github.com/0xProject/protocol.git" | ||||
|         "url": "https://github.com/0xProject/0x-monorepo.git" | ||||
|     }, | ||||
|     "license": "Apache-2.0", | ||||
|     "bugs": { | ||||
|         "url": "https://github.com/0xProject/protocol/issues" | ||||
|         "url": "https://github.com/0xProject/0x-monorepo/issues" | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol", | ||||
|     "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.6.0", | ||||
|         "@0x/contract-wrappers": "^13.17.3", | ||||
|         "@0x/contracts-gen": "^2.0.38", | ||||
|         "@0x/contracts-test-utils": "^5.4.6", | ||||
|         "@0x/contracts-utils": "^4.7.14", | ||||
|         "@0x/dev-utils": "^4.2.7", | ||||
|         "@0x/sol-compiler": "^4.7.3", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
|         "@0x/abi-gen": "^4.2.1", | ||||
|         "@0x/contracts-gen": "^1.0.15", | ||||
|         "@0x/contracts-test-utils": "^3.1.16", | ||||
|         "@0x/dev-utils": "^2.3.3", | ||||
|         "@0x/sol-compiler": "^3.1.15", | ||||
|         "@0x/tslint-config": "^3.0.1", | ||||
|         "@types/lodash": "4.14.104", | ||||
|         "@types/mocha": "^5.2.7", | ||||
|         "@types/node": "12.12.54", | ||||
|         "@types/node": "*", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
|         "chai-bignumber": "^3.0.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "ethereumjs-util": "^7.0.10", | ||||
|         "make-promises-safe": "^1.1.0", | ||||
|         "mocha": "^6.2.0", | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "shx": "^0.2.2", | ||||
|         "solhint": "^1.4.1", | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.4.0", | ||||
|         "@0x/contracts-erc1155": "^2.1.35", | ||||
|         "@0x/contracts-erc20": "^3.3.14", | ||||
|         "@0x/contracts-erc721": "^3.1.35", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.35", | ||||
|         "@0x/order-utils": "^10.4.27", | ||||
|         "@0x/types": "^3.3.3", | ||||
|         "@0x/typescript-typings": "^5.2.0", | ||||
|         "@0x/utils": "^6.4.3", | ||||
|         "@0x/web3-wrapper": "^7.5.3", | ||||
|         "ethereum-types": "^3.5.0", | ||||
|         "@0x/base-contract": "^5.4.0", | ||||
|         "@0x/contracts-erc1155": "^1.1.15", | ||||
|         "@0x/contracts-erc20": "^2.2.14", | ||||
|         "@0x/contracts-erc721": "^2.1.15", | ||||
|         "@0x/contracts-utils": "^3.2.4", | ||||
|         "@0x/order-utils": "^8.4.0", | ||||
|         "@0x/types": "^2.4.3", | ||||
|         "@0x/typescript-typings": "^4.3.0", | ||||
|         "@0x/utils": "^4.5.2", | ||||
|         "@0x/web3-wrapper": "^6.0.13", | ||||
|         "ethereum-types": "^2.1.6", | ||||
|         "ethereumjs-util": "^5.1.1", | ||||
|         "lodash": "^4.17.11" | ||||
|     }, | ||||
|     "publishConfig": { | ||||
|         "access": "public" | ||||
|     }, | ||||
|     "gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,123 +5,25 @@ | ||||
|  */ | ||||
| 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'; | ||||
| import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json'; | ||||
| import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json'; | ||||
| import * as Eth2DaiBridge from '../generated-artifacts/Eth2DaiBridge.json'; | ||||
| import * as IAssetData from '../generated-artifacts/IAssetData.json'; | ||||
| import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json'; | ||||
| import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json'; | ||||
| import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json'; | ||||
| import * as 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, | ||||
|     Ownable: Ownable as ContractArtifact, | ||||
|     ERC1155Proxy: ERC1155Proxy as ContractArtifact, | ||||
|     ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact, | ||||
|     ERC20Proxy: ERC20Proxy as ContractArtifact, | ||||
|     ERC721Proxy: ERC721Proxy as ContractArtifact, | ||||
|     MixinAuthorizable: MixinAuthorizable 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,112 +0,0 @@ | ||||
| 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(); | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| 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' }, | ||||
|         ], | ||||
|     }, | ||||
| ]); | ||||
| @@ -1,40 +0,0 @@ | ||||
| import { AbiEncoder, BigNumber } from '@0x/utils'; | ||||
|  | ||||
| export enum DydxBridgeActionType { | ||||
|     Deposit, | ||||
|     Withdraw, | ||||
| } | ||||
|  | ||||
| export interface DydxBridgeAction { | ||||
|     actionType: DydxBridgeActionType; | ||||
|     accountIdx: BigNumber; | ||||
|     marketId: BigNumber; | ||||
|     conversionRateNumerator: BigNumber; | ||||
|     conversionRateDenominator: BigNumber; | ||||
| } | ||||
|  | ||||
| export interface DydxBridgeData { | ||||
|     accountNumbers: BigNumber[]; | ||||
|     actions: DydxBridgeAction[]; | ||||
| } | ||||
|  | ||||
| export const dydxBridgeDataEncoder = AbiEncoder.create([ | ||||
|     { | ||||
|         name: 'bridgeData', | ||||
|         type: 'tuple', | ||||
|         components: [ | ||||
|             { name: 'accountNumbers', type: 'uint256[]' }, | ||||
|             { | ||||
|                 name: 'actions', | ||||
|                 type: 'tuple[]', | ||||
|                 components: [ | ||||
|                     { name: 'actionType', type: 'uint8' }, | ||||
|                     { name: 'accountIdx', type: 'uint256' }, | ||||
|                     { name: 'marketId', type: 'uint256' }, | ||||
|                     { name: 'conversionRateNumerator', type: 'uint256' }, | ||||
|                     { name: 'conversionRateDenominator', type: 'uint256' }, | ||||
|                 ], | ||||
|             }, | ||||
|         ], | ||||
|     }, | ||||
| ]); | ||||
| @@ -1,93 +1,3 @@ | ||||
| export { artifacts } from './artifacts'; | ||||
| export { | ||||
|     BalancerBridgeContract, | ||||
|     ChaiBridgeContract, | ||||
|     ERC1155ProxyContract, | ||||
|     ERC20BridgeProxyContract, | ||||
|     ERC20ProxyContract, | ||||
|     ERC721ProxyContract, | ||||
|     Eth2DaiBridgeContract, | ||||
|     DydxBridgeContract, | ||||
|     IAssetDataContract, | ||||
|     IAssetProxyContract, | ||||
|     IChaiContract, | ||||
|     IDydxContract, | ||||
|     KyberBridgeContract, | ||||
|     MultiAssetProxyContract, | ||||
|     StaticCallProxyContract, | ||||
|     TestDydxBridgeContract, | ||||
|     TestStaticCallTargetContract, | ||||
|     UniswapBridgeContract, | ||||
|     DexForwarderBridgeContract, | ||||
| } from './wrappers'; | ||||
|  | ||||
| export { ERC20Wrapper } from './erc20_wrapper'; | ||||
| export { ERC721Wrapper } from './erc721_wrapper'; | ||||
| 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, | ||||
|     ERC721TokenIdsByOwner, | ||||
|     ERC1155FungibleHoldingsByOwner, | ||||
|     ERC1155NonFungibleHoldingsByOwner, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| export { | ||||
|     TransactionReceiptWithDecodedLogs, | ||||
|     Provider, | ||||
|     ZeroExProvider, | ||||
|     JSONRPCRequestPayload, | ||||
|     JSONRPCErrorCallback, | ||||
|     TransactionReceiptStatus, | ||||
|     JSONRPCResponsePayload, | ||||
|     JSONRPCResponseError, | ||||
|     ContractArtifact, | ||||
|     ContractChains, | ||||
|     CompilerOpts, | ||||
|     StandardContractOutput, | ||||
|     CompilerSettings, | ||||
|     ContractChainData, | ||||
|     ContractAbi, | ||||
|     DevdocOutput, | ||||
|     EvmOutput, | ||||
|     CompilerSettingsMetadata, | ||||
|     OptimizerSettings, | ||||
|     OutputField, | ||||
|     ParamDescription, | ||||
|     EvmBytecodeOutput, | ||||
|     EvmBytecodeOutputLinkReferences, | ||||
|     AbiDefinition, | ||||
|     FunctionAbi, | ||||
|     EventAbi, | ||||
|     RevertErrorAbi, | ||||
|     EventParameter, | ||||
|     DataItem, | ||||
|     MethodAbi, | ||||
|     ConstructorAbi, | ||||
|     FallbackAbi, | ||||
|     ConstructorStateMutability, | ||||
|     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'; | ||||
| export * from './artifacts'; | ||||
| export * from './wrappers'; | ||||
| export * from '../test/utils'; | ||||
|   | ||||
| @@ -3,62 +3,13 @@ | ||||
|  * 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'; | ||||
| export * from '../generated-wrappers/erc20_proxy'; | ||||
| export * from '../generated-wrappers/erc721_proxy'; | ||||
| export * from '../generated-wrappers/eth2_dai_bridge'; | ||||
| export * from '../generated-wrappers/i_asset_data'; | ||||
| export * from '../generated-wrappers/i_asset_proxy'; | ||||
| export * from '../generated-wrappers/i_asset_proxy_dispatcher'; | ||||
| export * from '../generated-wrappers/i_authorizable'; | ||||
| export * from '../generated-wrappers/i_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'; | ||||
|   | ||||
| @@ -1,127 +0,0 @@ | ||||
| /* | ||||
|  * ----------------------------------------------------------------------------- | ||||
|  * Warning: This file is auto-generated by contracts-gen. Don't edit manually. | ||||
|  * ----------------------------------------------------------------------------- | ||||
|  */ | ||||
| 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'; | ||||
| import * as ERC20Proxy from '../test/generated-artifacts/ERC20Proxy.json'; | ||||
| import * as ERC721Proxy from '../test/generated-artifacts/ERC721Proxy.json'; | ||||
| import * as Eth2DaiBridge from '../test/generated-artifacts/Eth2DaiBridge.json'; | ||||
| import * as IAssetData from '../test/generated-artifacts/IAssetData.json'; | ||||
| import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json'; | ||||
| import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json'; | ||||
| import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json'; | ||||
| import * as 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, | ||||
|     Ownable: Ownable as ContractArtifact, | ||||
|     ERC1155Proxy: ERC1155Proxy as ContractArtifact, | ||||
|     ERC20BridgeProxy: ERC20BridgeProxy as ContractArtifact, | ||||
|     ERC20Proxy: ERC20Proxy as ContractArtifact, | ||||
|     ERC721Proxy: ERC721Proxy as ContractArtifact, | ||||
|     MultiAssetProxy: MultiAssetProxy as ContractArtifact, | ||||
|     StaticCallProxy: StaticCallProxy as ContractArtifact, | ||||
|     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,20 +1,38 @@ | ||||
| import { blockchainTests, expect, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; | ||||
| import { | ||||
|     chaiSetup, | ||||
|     constants, | ||||
|     expectTransactionFailedAsync, | ||||
|     provider, | ||||
|     txDefaults, | ||||
|     web3Wrapper, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { BlockchainLifecycle } from '@0x/dev-utils'; | ||||
| import { RevertReason } from '@0x/types'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
| import { artifacts, MixinAuthorizableContract } from '../src'; | ||||
|  | ||||
| import { MixinAuthorizableContract } from './wrappers'; | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); | ||||
|  | ||||
| blockchainTests.resets('Authorizable', () => { | ||||
| describe('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] = accounts.slice(0, 3); | ||||
|         [owner, address, notOwner] = _.slice(accounts, 0, 3); | ||||
|         authorizable = await MixinAuthorizableContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.MixinAuthorizable, | ||||
|             provider, | ||||
| @@ -22,106 +40,176 @@ blockchainTests.resets('Authorizable', () => { | ||||
|             artifacts, | ||||
|         ); | ||||
|     }); | ||||
|  | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('addAuthorizedAddress', () => { | ||||
|         it('should revert if not called by owner', async () => { | ||||
|             const tx = authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.OnlyContractOwner); | ||||
|         it('should throw if not called by owner', async () => { | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner }), | ||||
|                 RevertReason.OnlyContractOwner, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should allow owner to add an authorized address', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const isAuthorized = await authorizable.authorized(address).callAsync(); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const isAuthorized = await authorizable.authorized.callAsync(address); | ||||
|             expect(isAuthorized).to.be.true(); | ||||
|         }); | ||||
|  | ||||
|         it('should revert if owner attempts to authorize a duplicate address', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const tx = authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.TargetAlreadyAuthorized); | ||||
|         it('should throw if owner attempts to authorize a duplicate address', async () => { | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), | ||||
|                 RevertReason.TargetAlreadyAuthorized, | ||||
|             ); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('removeAuthorizedAddress', () => { | ||||
|         it('should revert if not called by owner', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.OnlyContractOwner); | ||||
|         it('should throw if not called by owner', async () => { | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { | ||||
|                     from: notOwner, | ||||
|                 }), | ||||
|                 RevertReason.OnlyContractOwner, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should allow owner to remove an authorized address', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const isAuthorized = await authorizable.authorized(address).callAsync(); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const isAuthorized = await authorizable.authorized.callAsync(address); | ||||
|             expect(isAuthorized).to.be.false(); | ||||
|         }); | ||||
|  | ||||
|         it('should revert if owner attempts to remove an address that is not authorized', async () => { | ||||
|             const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: owner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized); | ||||
|         it('should throw if owner attempts to remove an address that is not authorized', async () => { | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { | ||||
|                     from: owner, | ||||
|                 }), | ||||
|                 RevertReason.TargetNotAuthorized, | ||||
|             ); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('removeAuthorizedAddressAtIndex', () => { | ||||
|         it('should revert if not called by owner', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|         it('should throw if not called by owner', async () => { | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const index = new BigNumber(0); | ||||
|             const tx = authorizable | ||||
|                 .removeAuthorizedAddressAtIndex(address, index) | ||||
|                 .sendTransactionAsync({ from: notOwner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.OnlyContractOwner); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { | ||||
|                     from: notOwner, | ||||
|                 }), | ||||
|                 RevertReason.OnlyContractOwner, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should revert if index is >= authorities.length', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|         it('should throw if index is >= authorities.length', async () => { | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const index = new BigNumber(1); | ||||
|             const tx = authorizable | ||||
|                 .removeAuthorizedAddressAtIndex(address, index) | ||||
|                 .sendTransactionAsync({ from: owner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.IndexOutOfBounds); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { | ||||
|                     from: owner, | ||||
|                 }), | ||||
|                 RevertReason.IndexOutOfBounds, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should revert if owner attempts to remove an address that is not authorized', async () => { | ||||
|         it('should throw if owner attempts to remove an address that is not authorized', async () => { | ||||
|             const index = new BigNumber(0); | ||||
|             const tx = authorizable | ||||
|                 .removeAuthorizedAddressAtIndex(address, index) | ||||
|                 .sendTransactionAsync({ from: owner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { | ||||
|                     from: owner, | ||||
|                 }), | ||||
|                 RevertReason.TargetNotAuthorized, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should revert if address at index does not match target', async () => { | ||||
|         it('should throw if address at index does not match target', async () => { | ||||
|             const address1 = address; | ||||
|             const address2 = notOwner; | ||||
|             await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address1, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address2, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const address1Index = new BigNumber(0); | ||||
|             const tx = authorizable | ||||
|                 .removeAuthorizedAddressAtIndex(address2, address1Index) | ||||
|                 .sendTransactionAsync({ from: owner }); | ||||
|             return expect(tx).to.revertWith(RevertReason.AuthorizedAddressMismatch); | ||||
|             return expectTransactionFailedAsync( | ||||
|                 authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address2, address1Index, { | ||||
|                     from: owner, | ||||
|                 }), | ||||
|                 RevertReason.AuthorizedAddressMismatch, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should allow owner to remove an authorized address', async () => { | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const index = new BigNumber(0); | ||||
|             await authorizable.removeAuthorizedAddressAtIndex(address, index).awaitTransactionSuccessAsync({ | ||||
|                 from: owner, | ||||
|             }); | ||||
|             const isAuthorized = await authorizable.authorized(address).callAsync(); | ||||
|             await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 index, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const isAuthorized = await authorizable.authorized.callAsync(address); | ||||
|             expect(isAuthorized).to.be.false(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('getAuthorizedAddresses', () => { | ||||
|         it('should return all authorized addresses', async () => { | ||||
|             const initial = await authorizable.getAuthorizedAddresses().callAsync(); | ||||
|             const initial = await authorizable.getAuthorizedAddresses.callAsync(); | ||||
|             expect(initial).to.have.length(0); | ||||
|             await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const afterAdd = await authorizable.getAuthorizedAddresses().callAsync(); | ||||
|             await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const afterAdd = await authorizable.getAuthorizedAddresses.callAsync(); | ||||
|             expect(afterAdd).to.have.length(1); | ||||
|             expect(afterAdd).to.include(address); | ||||
|             await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|             const afterRemove = await authorizable.getAuthorizedAddresses().callAsync(); | ||||
|             await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|                 address, | ||||
|                 { from: owner }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             const afterRemove = await authorizable.getAuthorizedAddresses.callAsync(); | ||||
|             expect(afterRemove).to.have.length(0); | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -1,185 +0,0 @@ | ||||
| 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)); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,60 +0,0 @@ | ||||
| import { ERC20TokenContract } from '@0x/contracts-erc20'; | ||||
| import { blockchainTests, constants, expect, randomAddress } from '@0x/contracts-test-utils'; | ||||
| import { AssetProxyId, RevertReason } from '@0x/types'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
| import { TestChaiBridgeContract } from './wrappers'; | ||||
|  | ||||
| blockchainTests.resets('ChaiBridge unit tests', env => { | ||||
|     let chaiBridgeContract: TestChaiBridgeContract; | ||||
|     let testDaiContract: ERC20TokenContract; | ||||
|     let fromAddress: string; | ||||
|     let toAddress: string; | ||||
|  | ||||
|     const alwaysRevertAddress = '0x0000000000000000000000000000000000000001'; | ||||
|     const amount = new BigNumber(1); | ||||
|  | ||||
|     before(async () => { | ||||
|         [fromAddress, toAddress] = await env.getAccountAddressesAsync(); | ||||
|         chaiBridgeContract = await TestChaiBridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestChaiBridge, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         const testChaiDaiAddress = await chaiBridgeContract.testChaiDai().callAsync(); | ||||
|         testDaiContract = new ERC20TokenContract(testChaiDaiAddress, env.provider, env.txDefaults); | ||||
|     }); | ||||
|  | ||||
|     describe('bridgeTransferFrom()', () => { | ||||
|         it('fails if not called by ERC20BridgeProxy', async () => { | ||||
|             return expect( | ||||
|                 chaiBridgeContract | ||||
|                     .bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES) | ||||
|                     .awaitTransactionSuccessAsync({ from: alwaysRevertAddress }), | ||||
|             ).to.revertWith(RevertReason.ChaiBridgeOnlyCallableByErc20BridgeProxy); | ||||
|         }); | ||||
|         it('returns magic bytes upon success', async () => { | ||||
|             const magicBytes = await chaiBridgeContract | ||||
|                 .bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES) | ||||
|                 .callAsync(); | ||||
|             expect(magicBytes).to.eq(AssetProxyId.ERC20Bridge); | ||||
|         }); | ||||
|         it('should increase the Dai balance of `toAddress` by `amount` if successful', async () => { | ||||
|             const initialBalance = await testDaiContract.balanceOf(toAddress).callAsync(); | ||||
|             await chaiBridgeContract | ||||
|                 .bridgeTransferFrom(randomAddress(), fromAddress, toAddress, amount, constants.NULL_BYTES) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const endBalance = await testDaiContract.balanceOf(toAddress).callAsync(); | ||||
|             expect(endBalance).to.bignumber.eq(initialBalance.plus(amount)); | ||||
|         }); | ||||
|         it('fails if the `chai.draw` call fails', async () => { | ||||
|             return expect( | ||||
|                 chaiBridgeContract | ||||
|                     .bridgeTransferFrom(randomAddress(), alwaysRevertAddress, toAddress, amount, constants.NULL_BYTES) | ||||
|                     .awaitTransactionSuccessAsync(), | ||||
|             ).to.revertWith(RevertReason.ChaiBridgeDrawDaiFailed); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,399 +0,0 @@ | ||||
| import { LibMathRevertErrors } from '@0x/contracts-exchange-libs'; | ||||
| import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils'; | ||||
| import { AssetProxyId, RevertReason } from '@0x/types'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { DydxBridgeActionType, DydxBridgeData, dydxBridgeDataEncoder } from '../src/dydx_bridge_encoder'; | ||||
| import { ERC20BridgeProxyContract, IAssetDataContract } from '../src/wrappers'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
| import { TestDydxBridgeContract, TestDydxBridgeEvents } from './wrappers'; | ||||
|  | ||||
| blockchainTests.resets('DydxBridge unit tests', env => { | ||||
|     const defaultAccountNumber = new BigNumber(1); | ||||
|     const marketId = new BigNumber(2); | ||||
|     const defaultAmount = new BigNumber(4); | ||||
|     const notAuthorized = '0x0000000000000000000000000000000000000001'; | ||||
|     const defaultDepositAction = { | ||||
|         actionType: DydxBridgeActionType.Deposit, | ||||
|         accountIdx: constants.ZERO_AMOUNT, | ||||
|         marketId, | ||||
|         conversionRateNumerator: constants.ZERO_AMOUNT, | ||||
|         conversionRateDenominator: constants.ZERO_AMOUNT, | ||||
|     }; | ||||
|     const defaultWithdrawAction = { | ||||
|         actionType: DydxBridgeActionType.Withdraw, | ||||
|         accountIdx: constants.ZERO_AMOUNT, | ||||
|         marketId, | ||||
|         conversionRateNumerator: constants.ZERO_AMOUNT, | ||||
|         conversionRateDenominator: constants.ZERO_AMOUNT, | ||||
|     }; | ||||
|     let testContract: TestDydxBridgeContract; | ||||
|     let testProxyContract: ERC20BridgeProxyContract; | ||||
|     let assetDataEncoder: IAssetDataContract; | ||||
|     let owner: string; | ||||
|     let authorized: string; | ||||
|     let accountOwner: string; | ||||
|     let receiver: string; | ||||
|  | ||||
|     before(async () => { | ||||
|         // Get accounts | ||||
|         const accounts = await env.web3Wrapper.getAvailableAddressesAsync(); | ||||
|         [owner, authorized, accountOwner, receiver] = accounts; | ||||
|  | ||||
|         // Deploy dydx bridge | ||||
|         testContract = await TestDydxBridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestDydxBridge, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|             [accountOwner, receiver], | ||||
|         ); | ||||
|  | ||||
|         // Deploy test erc20 bridge proxy | ||||
|         testProxyContract = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.ERC20BridgeProxy, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         await testProxyContract.addAuthorizedAddress(authorized).awaitTransactionSuccessAsync({ from: owner }); | ||||
|  | ||||
|         // Setup asset data encoder | ||||
|         assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, env.provider); | ||||
|     }); | ||||
|  | ||||
|     describe('bridgeTransferFrom()', () => { | ||||
|         const callBridgeTransferFrom = async ( | ||||
|             from: string, | ||||
|             to: string, | ||||
|             amount: BigNumber, | ||||
|             bridgeData: DydxBridgeData, | ||||
|             sender: string, | ||||
|         ): Promise<string> => { | ||||
|             const returnValue = await testContract | ||||
|                 .bridgeTransferFrom( | ||||
|                     constants.NULL_ADDRESS, | ||||
|                     from, | ||||
|                     to, | ||||
|                     amount, | ||||
|                     dydxBridgeDataEncoder.encode({ bridgeData }), | ||||
|                 ) | ||||
|                 .callAsync({ from: sender }); | ||||
|             return returnValue; | ||||
|         }; | ||||
|         const executeBridgeTransferFromAndVerifyEvents = async ( | ||||
|             from: string, | ||||
|             to: string, | ||||
|             amount: BigNumber, | ||||
|             bridgeData: DydxBridgeData, | ||||
|             sender: string, | ||||
|         ): Promise<void> => { | ||||
|             // Execute transaction. | ||||
|             const txReceipt = await testContract | ||||
|                 .bridgeTransferFrom( | ||||
|                     constants.NULL_ADDRESS, | ||||
|                     from, | ||||
|                     to, | ||||
|                     amount, | ||||
|                     dydxBridgeDataEncoder.encode({ bridgeData }), | ||||
|                 ) | ||||
|                 .awaitTransactionSuccessAsync({ from: sender }); | ||||
|  | ||||
|             // Verify `OperateAccount` event. | ||||
|             const expectedOperateAccountEvents = []; | ||||
|             for (const accountNumber of bridgeData.accountNumbers) { | ||||
|                 expectedOperateAccountEvents.push({ | ||||
|                     owner: accountOwner, | ||||
|                     number: accountNumber, | ||||
|                 }); | ||||
|             } | ||||
|             verifyEventsFromLogs(txReceipt.logs, expectedOperateAccountEvents, TestDydxBridgeEvents.OperateAccount); | ||||
|  | ||||
|             // Verify `OperateAction` event. | ||||
|             const weiDenomination = 0; | ||||
|             const deltaAmountRef = 0; | ||||
|             const expectedOperateActionEvents = []; | ||||
|             for (const action of bridgeData.actions) { | ||||
|                 expectedOperateActionEvents.push({ | ||||
|                     actionType: action.actionType as number, | ||||
|                     accountIdx: action.accountIdx, | ||||
|                     amountSign: action.actionType === DydxBridgeActionType.Deposit ? true : false, | ||||
|                     amountDenomination: weiDenomination, | ||||
|                     amountRef: deltaAmountRef, | ||||
|                     amountValue: action.conversionRateDenominator.gt(0) | ||||
|                         ? amount | ||||
|                               .times(action.conversionRateNumerator) | ||||
|                               .dividedToIntegerBy(action.conversionRateDenominator) | ||||
|                         : amount, | ||||
|                     primaryMarketId: marketId, | ||||
|                     secondaryMarketId: constants.ZERO_AMOUNT, | ||||
|                     otherAddress: action.actionType === DydxBridgeActionType.Deposit ? from : to, | ||||
|                     otherAccountId: constants.ZERO_AMOUNT, | ||||
|                     data: '0x', | ||||
|                 }); | ||||
|             } | ||||
|             verifyEventsFromLogs(txReceipt.logs, expectedOperateActionEvents, TestDydxBridgeEvents.OperateAction); | ||||
|         }; | ||||
|         it('succeeds when calling with zero amount', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 constants.ZERO_AMOUNT, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling with no accounts', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling with no actions', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with the `deposit` action and a single account', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with the `withdraw` action and a single account', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultWithdrawAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with the `withdraw` action and multiple accounts', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)], | ||||
|                 actions: [defaultWithdrawAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)], | ||||
|                 actions: [defaultWithdrawAction, defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when calling `operate` with multiple actions under a single account', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultWithdrawAction, defaultDepositAction], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when scaling the `amount` to deposit', async () => { | ||||
|             const conversionRateNumerator = new BigNumber(1); | ||||
|             const conversionRateDenominator = new BigNumber(2); | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [ | ||||
|                     defaultWithdrawAction, | ||||
|                     { | ||||
|                         ...defaultDepositAction, | ||||
|                         conversionRateNumerator, | ||||
|                         conversionRateDenominator, | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('succeeds when scaling the `amount` to withdraw', async () => { | ||||
|             const conversionRateNumerator = new BigNumber(1); | ||||
|             const conversionRateDenominator = new BigNumber(2); | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [ | ||||
|                     defaultDepositAction, | ||||
|                     { | ||||
|                         ...defaultWithdrawAction, | ||||
|                         conversionRateNumerator, | ||||
|                         conversionRateDenominator, | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|             await executeBridgeTransferFromAndVerifyEvents( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|         }); | ||||
|         it('reverts if not called by the ERC20 Bridge Proxy', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             const callBridgeTransferFromPromise = callBridgeTransferFrom( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 notAuthorized, | ||||
|             ); | ||||
|             const expectedError = RevertReason.DydxBridgeOnlyCallableByErc20BridgeProxy; | ||||
|             return expect(callBridgeTransferFromPromise).to.revertWith(expectedError); | ||||
|         }); | ||||
|         it('should return magic bytes if call succeeds', async () => { | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             const returnValue = await callBridgeTransferFrom( | ||||
|                 accountOwner, | ||||
|                 receiver, | ||||
|                 defaultAmount, | ||||
|                 bridgeData, | ||||
|                 authorized, | ||||
|             ); | ||||
|             expect(returnValue).to.equal(AssetProxyId.ERC20Bridge); | ||||
|         }); | ||||
|         it('should revert when `Operate` reverts', async () => { | ||||
|             // Set revert flag. | ||||
|             await testContract.setRevertOnOperate(true).awaitTransactionSuccessAsync(); | ||||
|  | ||||
|             // Execute transfer. | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [defaultDepositAction], | ||||
|             }; | ||||
|             const tx = callBridgeTransferFrom(accountOwner, receiver, defaultAmount, bridgeData, authorized); | ||||
|             const expectedError = 'TestDydxBridge/SHOULD_REVERT_ON_OPERATE'; | ||||
|             return expect(tx).to.revertWith(expectedError); | ||||
|         }); | ||||
|         it('should revert when there is a rounding error', async () => { | ||||
|             // Setup a rounding error | ||||
|             const conversionRateNumerator = new BigNumber(5318); | ||||
|             const conversionRateDenominator = new BigNumber(47958); | ||||
|             const amount = new BigNumber(9000); | ||||
|             const bridgeData = { | ||||
|                 accountNumbers: [defaultAccountNumber], | ||||
|                 actions: [ | ||||
|                     defaultDepositAction, | ||||
|                     { | ||||
|                         ...defaultWithdrawAction, | ||||
|                         conversionRateNumerator, | ||||
|                         conversionRateDenominator, | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|  | ||||
|             // Execute transfer and assert error. | ||||
|             const tx = callBridgeTransferFrom(accountOwner, receiver, amount, bridgeData, authorized); | ||||
|             const expectedError = new LibMathRevertErrors.RoundingError( | ||||
|                 conversionRateNumerator, | ||||
|                 conversionRateDenominator, | ||||
|                 amount, | ||||
|             ); | ||||
|             return expect(tx).to.revertWith(expectedError); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('ERC20BridgeProxy.transferFrom()', () => { | ||||
|         const bridgeData = { | ||||
|             accountNumbers: [defaultAccountNumber], | ||||
|             actions: [defaultWithdrawAction], | ||||
|         }; | ||||
|         let assetData: string; | ||||
|  | ||||
|         before(async () => { | ||||
|             const testTokenAddress = await testContract.getTestToken().callAsync(); | ||||
|             assetData = assetDataEncoder | ||||
|                 .ERC20Bridge(testTokenAddress, testContract.address, dydxBridgeDataEncoder.encode({ bridgeData })) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|         }); | ||||
|  | ||||
|         it('should succeed if `bridgeTransferFrom` succeeds', async () => { | ||||
|             await testProxyContract | ||||
|                 .transferFrom(assetData, accountOwner, receiver, defaultAmount) | ||||
|                 .awaitTransactionSuccessAsync({ from: authorized }); | ||||
|         }); | ||||
|         it('should revert if `bridgeTransferFrom` reverts', async () => { | ||||
|             // Set revert flag. | ||||
|             await testContract.setRevertOnOperate(true).awaitTransactionSuccessAsync(); | ||||
|             const tx = testProxyContract | ||||
|                 .transferFrom(assetData, accountOwner, receiver, defaultAmount) | ||||
|                 .awaitTransactionSuccessAsync({ from: authorized }); | ||||
|             const expectedError = 'TestDydxBridge/SHOULD_REVERT_ON_OPERATE'; | ||||
|             return expect(tx).to.revertWith(expectedError); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -14,8 +14,8 @@ import { | ||||
|     txDefaults, | ||||
|     web3Wrapper, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { SafeMathRevertErrors } from '@0x/contracts-utils'; | ||||
| import { BlockchainLifecycle } from '@0x/dev-utils'; | ||||
| import { assetDataUtils } from '@0x/order-utils'; | ||||
| import { AssetProxyId, RevertReason } from '@0x/types'; | ||||
| import { BigNumber } from '@0x/utils'; | ||||
| import * as chai from 'chai'; | ||||
| @@ -23,10 +23,7 @@ import { LogWithDecodedArgs } from 'ethereum-types'; | ||||
| import * as ethUtil from 'ethereumjs-util'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper'; | ||||
| import { ERC1155ProxyContract, IAssetDataContract } from '../src/wrappers'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
| import { artifacts, ERC1155ProxyContract, ERC1155ProxyWrapper } from '../src'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| @@ -62,8 +59,6 @@ describe('ERC1155Proxy', () => { | ||||
|     // tokens | ||||
|     let fungibleTokens: BigNumber[]; | ||||
|     let nonFungibleTokensOwnedBySpender: BigNumber[]; | ||||
|     // IAssetData for encoding and decoding assetData | ||||
|     let assetDataContract: IAssetDataContract; | ||||
|     // tests | ||||
|     before(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
| @@ -77,8 +72,16 @@ describe('ERC1155Proxy', () => { | ||||
|         const usedAddresses = ([owner, notAuthorized, authorized, spender, receiver] = _.slice(accounts, 0, 5)); | ||||
|         erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); | ||||
|         erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); | ||||
|         await erc1155Proxy.addAuthorizedAddress(authorized).awaitTransactionSuccessAsync({ from: owner }); | ||||
|         await erc1155Proxy.addAuthorizedAddress(erc1155Proxy.address).awaitTransactionSuccessAsync({ from: owner }); | ||||
|         await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|             authorized, | ||||
|             { from: owner }, | ||||
|             constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|         ); | ||||
|         await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( | ||||
|             erc1155Proxy.address, | ||||
|             { from: owner }, | ||||
|             constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|         ); | ||||
|         // deploy & configure ERC1155 tokens and receiver | ||||
|         [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync(); | ||||
|         erc1155Contract = erc1155Wrapper.getContract(); | ||||
| @@ -100,8 +103,6 @@ describe('ERC1155Proxy', () => { | ||||
|                 tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0]; | ||||
|             nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender); | ||||
|         }); | ||||
|         // set up assetDataContract | ||||
|         assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider, { from: owner }); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
| @@ -122,7 +123,7 @@ describe('ERC1155Proxy', () => { | ||||
|             ); | ||||
|         }); | ||||
|         it('should have an id of 0xa7cb5fb7', async () => { | ||||
|             const proxyId = await erc1155Proxy.getProxyId().callAsync(); | ||||
|             const proxyId = await erc1155Proxy.getProxyId.callAsync(); | ||||
|             const expectedProxyId = AssetProxyId.ERC1155; | ||||
|             expect(proxyId).to.equal(expectedProxyId); | ||||
|         }); | ||||
| @@ -637,9 +638,12 @@ describe('ERC1155Proxy', () => { | ||||
|                 return value.times(valueMultiplier); | ||||
|             }); | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             const extraData = '0102030405060708091001020304050607080910010203040506070809100102'; | ||||
|             const assetDataWithExtraData = `${assetData}${extraData}`; | ||||
|             // check balances before transfer | ||||
| @@ -692,20 +696,25 @@ describe('ERC1155Proxy', () => { | ||||
|             const tokenUri = ''; | ||||
|             for (const tokenToCreate of tokensToCreate) { | ||||
|                 // create token | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .createWithType(tokenToCreate, tokenUri) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     tokenUri, | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|  | ||||
|                 // mint balance for spender | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .mintFungible(tokenToCreate, [spender], [spenderInitialBalance]) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     [spender], | ||||
|                     [spenderInitialBalance], | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|             } | ||||
|             ///// Step 2/5 ///// | ||||
|             // Check balances before transfer | ||||
| @@ -738,15 +747,18 @@ describe('ERC1155Proxy', () => { | ||||
|             const tokensToTransfer = [new BigNumber(1), new BigNumber(2)]; | ||||
|             const valuesToTransfer = tokensToTransfer; | ||||
|             const valueMultiplier = new BigNumber(2); | ||||
|  | ||||
|             // hand encode optimized assetData because our tooling (based on LibAssetData.sol/ERC1155Assets) does not use optimized encoding | ||||
|             const selector = assetDataContract.getSelector('ERC1155Assets'); | ||||
|             const assetDataWithoutContractAddress = | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // remove the function selector and contract address from check, as these change on each test | ||||
|             const offsetToTokenIds = 74; | ||||
|             const assetDataWithoutContractAddress = assetData.substr(offsetToTokenIds); | ||||
|             const expectedAssetDataWithoutContractAddress = | ||||
|                 '0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000'; | ||||
|             const assetData = `${selector}000000000000000000000000${erc1155ContractAddress.substr( | ||||
|                 2, | ||||
|             )}${assetDataWithoutContractAddress}`; | ||||
|  | ||||
|             expect(assetDataWithoutContractAddress).to.be.equal(expectedAssetDataWithoutContractAddress); | ||||
|             ///// Step 4/5 ///// | ||||
|             // Transfer token IDs [1, 2] and amounts [1, 2] with a multiplier of 2; | ||||
|             // the expected trade will be token IDs [1, 2] and amounts [2, 4] | ||||
| @@ -793,20 +805,25 @@ describe('ERC1155Proxy', () => { | ||||
|             const tokenUri = ''; | ||||
|             for (const tokenToCreate of tokensToCreate) { | ||||
|                 // create token | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .createWithType(tokenToCreate, tokenUri) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     tokenUri, | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|  | ||||
|                 // mint balance for spender | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .mintFungible(tokenToCreate, [spender], [spenderInitialBalance]) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     [spender], | ||||
|                     [spenderInitialBalance], | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|             } | ||||
|             ///// Step 2/5 ///// | ||||
|             // Check balances before transfer | ||||
| @@ -850,9 +867,12 @@ 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 = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const generatedAssetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // remove the function selector and contract address from check, as these change on each test | ||||
|             const offsetToTokenIds = 74; | ||||
|             const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds); | ||||
| @@ -917,20 +937,25 @@ describe('ERC1155Proxy', () => { | ||||
|             const tokenUri = ''; | ||||
|             for (const tokenToCreate of tokensToCreate) { | ||||
|                 // create token | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .createWithType(tokenToCreate, tokenUri) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     tokenUri, | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|  | ||||
|                 // mint balance for spender | ||||
|                 await erc1155Wrapper | ||||
|                     .getContract() | ||||
|                     .mintFungible(tokenToCreate, [spender], [spenderInitialBalance]) | ||||
|                     .awaitTransactionSuccessAsync({ | ||||
|                 await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( | ||||
|                     tokenToCreate, | ||||
|                     [spender], | ||||
|                     [spenderInitialBalance], | ||||
|                     { | ||||
|                         from: owner, | ||||
|                     }); | ||||
|                     }, | ||||
|                     constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|                 ); | ||||
|             } | ||||
|             ///// Step 2/5 ///// | ||||
|             // Check balances before transfer | ||||
| @@ -971,9 +996,12 @@ 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 = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const generatedAssetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // remove the function selector and contract address from check, as these change on each test | ||||
|             const offsetToTokenIds = 74; | ||||
|             const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds); | ||||
| @@ -1031,9 +1059,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1075,9 +1106,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1123,9 +1157,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1171,9 +1208,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1219,9 +1259,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1268,9 +1311,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1312,9 +1358,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1360,9 +1409,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1404,9 +1456,12 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             // The asset data we just generated will look like this: | ||||
|             // a7cb5fb7 | ||||
|             // 0x         0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082 | ||||
| @@ -1452,10 +1507,13 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync( | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData( | ||||
|                 spender, | ||||
|                 receiverContract, | ||||
|                 erc1155Contract.address, | ||||
| @@ -1480,10 +1538,13 @@ describe('ERC1155Proxy', () => { | ||||
|             const valuesToTransfer = [fungibleValueToTransferLarge]; | ||||
|             const valueMultiplier = valueMultiplierSmall; | ||||
|             const erc1155ContractAddress = erc1155Wrapper.getContract().address; | ||||
|             const assetData = assetDataContract | ||||
|                 .ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync( | ||||
|             const assetData = assetDataUtils.encodeERC1155AssetData( | ||||
|                 erc1155ContractAddress, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 receiverCallbackData, | ||||
|             ); | ||||
|             const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData( | ||||
|                 spender, | ||||
|                 receiverContract, | ||||
|                 erc1155Contract.address, | ||||
| @@ -1606,9 +1667,13 @@ describe('ERC1155Proxy', () => { | ||||
|         it('should propagate revert reason from erc1155 contract failure', async () => { | ||||
|             // disable transfers | ||||
|             const shouldRejectTransfer = true; | ||||
|             await erc1155Receiver.setRejectTransferFlag(shouldRejectTransfer).awaitTransactionSuccessAsync({ | ||||
|                 from: owner, | ||||
|             }); | ||||
|             await erc1155Receiver.setRejectTransferFlag.awaitTransactionSuccessAsync( | ||||
|                 shouldRejectTransfer, | ||||
|                 { | ||||
|                     from: owner, | ||||
|                 }, | ||||
|                 constants.AWAIT_TRANSACTION_MINED_MS, | ||||
|             ); | ||||
|             // setup test parameters | ||||
|             const tokenHolders = [spender, receiverContract]; | ||||
|             const tokensToTransfer = fungibleTokens.slice(0, 1); | ||||
| @@ -1683,14 +1748,9 @@ describe('ERC1155Proxy', () => { | ||||
|                 nftNotOwnerBalance, | ||||
|             ]; | ||||
|             await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); | ||||
|             const expectedError = new SafeMathRevertErrors.Uint256BinOpError( | ||||
|                 SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, | ||||
|                 maxUintValue, | ||||
|                 valueMultiplier, | ||||
|             ); | ||||
|             // execute transfer | ||||
|             // note - this will overflow because we are trying to transfer `maxUintValue * 2` of the 2nd token | ||||
|             await expect( | ||||
|             await expectTransactionFailedAsync( | ||||
|                 erc1155ProxyWrapper.transferFromAsync( | ||||
|                     spender, | ||||
|                     receiver, | ||||
| @@ -1701,7 +1761,8 @@ describe('ERC1155Proxy', () => { | ||||
|                     receiverCallbackData, | ||||
|                     authorized, | ||||
|                 ), | ||||
|             ).to.revertWith(expectedError); | ||||
|                 RevertReason.Uint256Overflow, | ||||
|             ); | ||||
|         }); | ||||
|         it('should revert if transferring > 1 instances of a non-fungible token (valueMultiplier field >1)', async () => { | ||||
|             // setup test parameters | ||||
| @@ -1771,23 +1832,20 @@ describe('ERC1155Proxy', () => { | ||||
|             // check balances before transfer | ||||
|             const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance]; | ||||
|             await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); | ||||
|             const expectedError = new SafeMathRevertErrors.Uint256BinOpError( | ||||
|                 SafeMathRevertErrors.BinOpErrorCodes.SubtractionUnderflow, | ||||
|                 spenderInitialFungibleBalance, | ||||
|                 valuesToTransfer[0].times(valueMultiplier), | ||||
|             ); | ||||
|             // execute transfer | ||||
|             const tx = erc1155ProxyWrapper.transferFromAsync( | ||||
|                 spender, | ||||
|                 receiver, | ||||
|                 erc1155Contract.address, | ||||
|                 tokensToTransfer, | ||||
|                 valuesToTransfer, | ||||
|                 valueMultiplier, | ||||
|                 receiverCallbackData, | ||||
|                 authorized, | ||||
|             await expectTransactionFailedAsync( | ||||
|                 erc1155ProxyWrapper.transferFromAsync( | ||||
|                     spender, | ||||
|                     receiver, | ||||
|                     erc1155Contract.address, | ||||
|                     tokensToTransfer, | ||||
|                     valuesToTransfer, | ||||
|                     valueMultiplier, | ||||
|                     receiverCallbackData, | ||||
|                     authorized, | ||||
|                 ), | ||||
|                 RevertReason.Uint256Underflow, | ||||
|             ); | ||||
|             return expect(tx).to.revertWith(expectedError); | ||||
|         }); | ||||
|         it('should revert if sender allowance is insufficient', async () => { | ||||
|             // dremove allowance for ERC1155 proxy | ||||
|   | ||||
| @@ -1,287 +0,0 @@ | ||||
| import { | ||||
|     blockchainTests, | ||||
|     constants, | ||||
|     expect, | ||||
|     getRandomInteger, | ||||
|     Numberish, | ||||
|     randomAddress, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { AuthorizableRevertErrors } from '@0x/contracts-utils'; | ||||
| import { AssetProxyId } from '@0x/types'; | ||||
| import { AbiEncoder, BigNumber, hexUtils, StringRevertError } from '@0x/utils'; | ||||
| import { DecodedLogs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
|  | ||||
| import { ERC20BridgeProxyContract, TestERC20BridgeContract } from './wrappers'; | ||||
|  | ||||
| blockchainTests.resets('ERC20BridgeProxy unit tests', env => { | ||||
|     const PROXY_ID = AssetProxyId.ERC20Bridge; | ||||
|     const BRIDGE_SUCCESS_RETURN_DATA = hexUtils.rightPad(PROXY_ID); | ||||
|     let owner: string; | ||||
|     let badCaller: string; | ||||
|     let assetProxy: ERC20BridgeProxyContract; | ||||
|     let bridgeContract: TestERC20BridgeContract; | ||||
|     let testTokenAddress: string; | ||||
|  | ||||
|     before(async () => { | ||||
|         [owner, badCaller] = await env.getAccountAddressesAsync(); | ||||
|         assetProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.ERC20BridgeProxy, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         bridgeContract = await TestERC20BridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestERC20Bridge, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         testTokenAddress = await bridgeContract.testToken().callAsync(); | ||||
|         await assetProxy.addAuthorizedAddress(owner).awaitTransactionSuccessAsync(); | ||||
|     }); | ||||
|  | ||||
|     interface AssetDataOpts { | ||||
|         tokenAddress: string; | ||||
|         bridgeAddress: string; | ||||
|         bridgeData: BridgeDataOpts; | ||||
|     } | ||||
|  | ||||
|     interface BridgeDataOpts { | ||||
|         transferAmount: Numberish; | ||||
|         revertError?: string; | ||||
|         returnData: string; | ||||
|     } | ||||
|  | ||||
|     function createAssetData(opts?: Partial<AssetDataOpts>): AssetDataOpts { | ||||
|         return _.merge( | ||||
|             { | ||||
|                 tokenAddress: testTokenAddress, | ||||
|                 bridgeAddress: bridgeContract.address, | ||||
|                 bridgeData: createBridgeData(), | ||||
|             }, | ||||
|             opts, | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function createBridgeData(opts?: Partial<BridgeDataOpts>): BridgeDataOpts { | ||||
|         return _.merge( | ||||
|             { | ||||
|                 transferAmount: constants.ZERO_AMOUNT, | ||||
|                 returnData: BRIDGE_SUCCESS_RETURN_DATA, | ||||
|             }, | ||||
|             opts, | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function encodeAssetData(opts: AssetDataOpts): string { | ||||
|         const encoder = AbiEncoder.createMethod('ERC20BridgeProxy', [ | ||||
|             { name: 'tokenAddress', type: 'address' }, | ||||
|             { name: 'bridgeAddress', type: 'address' }, | ||||
|             { name: 'bridgeData', type: 'bytes' }, | ||||
|         ]); | ||||
|         return encoder.encode([opts.tokenAddress, opts.bridgeAddress, encodeBridgeData(opts.bridgeData)]); | ||||
|     } | ||||
|  | ||||
|     function encodeBridgeData(opts: BridgeDataOpts): string { | ||||
|         const encoder = AbiEncoder.create([ | ||||
|             { name: 'transferAmount', type: 'int256' }, | ||||
|             { name: 'revertData', type: 'bytes' }, | ||||
|             { name: 'returnData', type: 'bytes' }, | ||||
|         ]); | ||||
|         const revertErrorBytes = | ||||
|             opts.revertError !== undefined ? new StringRevertError(opts.revertError).encode() : '0x'; | ||||
|         return encoder.encode([new BigNumber(opts.transferAmount), revertErrorBytes, opts.returnData]); | ||||
|     } | ||||
|  | ||||
|     async function setTestTokenBalanceAsync(_owner: string, balance: Numberish): Promise<void> { | ||||
|         await bridgeContract.setTestTokenBalance(_owner, new BigNumber(balance)).awaitTransactionSuccessAsync(); | ||||
|     } | ||||
|  | ||||
|     describe('transferFrom()', () => { | ||||
|         interface TransferFromOpts { | ||||
|             assetData: AssetDataOpts; | ||||
|             from: string; | ||||
|             to: string; | ||||
|             amount: Numberish; | ||||
|         } | ||||
|  | ||||
|         function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts { | ||||
|             const transferAmount = _.get(opts, ['amount'], getRandomInteger(1, 100e18)) as BigNumber; | ||||
|             return _.merge( | ||||
|                 { | ||||
|                     assetData: createAssetData({ | ||||
|                         bridgeData: createBridgeData({ | ||||
|                             transferAmount, | ||||
|                         }), | ||||
|                     }), | ||||
|                     from: randomAddress(), | ||||
|                     to: randomAddress(), | ||||
|                     amount: transferAmount, | ||||
|                 }, | ||||
|                 opts, | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         async function transferFromAsync(opts?: Partial<TransferFromOpts>, caller?: string): Promise<DecodedLogs> { | ||||
|             const _opts = createTransferFromOpts(opts); | ||||
|             const { logs } = await assetProxy | ||||
|                 .transferFrom(encodeAssetData(_opts.assetData), _opts.from, _opts.to, new BigNumber(_opts.amount)) | ||||
|                 .awaitTransactionSuccessAsync({ from: caller }); | ||||
|             return (logs as any) as DecodedLogs; | ||||
|         } | ||||
|  | ||||
|         it('succeeds if the bridge succeeds and balance increases by `amount`', async () => { | ||||
|             const tx = transferFromAsync(); | ||||
|             return expect(tx).to.be.fulfilled(''); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds if balance increases more than `amount`', async () => { | ||||
|             const amount = getRandomInteger(1, 100e18); | ||||
|             const tx = transferFromAsync({ | ||||
|                 amount, | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         transferAmount: amount.plus(1), | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             return expect(tx).to.be.fulfilled(''); | ||||
|         }); | ||||
|  | ||||
|         it('passes the correct arguments to the bridge contract', async () => { | ||||
|             const opts = createTransferFromOpts(); | ||||
|             const logs = await transferFromAsync(opts); | ||||
|             expect(logs.length).to.eq(1); | ||||
|             const args = logs[0].args; | ||||
|             expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress); | ||||
|             expect(args.from).to.eq(opts.from); | ||||
|             expect(args.to).to.eq(opts.to); | ||||
|             expect(args.amount).to.bignumber.eq(opts.amount); | ||||
|             expect(args.bridgeData).to.eq(encodeBridgeData(opts.assetData.bridgeData)); | ||||
|         }); | ||||
|  | ||||
|         it('fails if not called by an authorized address', async () => { | ||||
|             const tx = transferFromAsync({}, badCaller); | ||||
|             return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(badCaller)); | ||||
|         }); | ||||
|  | ||||
|         it('fails if asset data is truncated', async () => { | ||||
|             const opts = createTransferFromOpts(); | ||||
|             const truncatedAssetData = hexUtils.slice(encodeAssetData(opts.assetData), 0, -1); | ||||
|             const tx = assetProxy | ||||
|                 .transferFrom(truncatedAssetData, opts.from, opts.to, new BigNumber(opts.amount)) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             return expect(tx).to.be.rejected(); | ||||
|         }); | ||||
|  | ||||
|         it('fails if bridge returns nothing', async () => { | ||||
|             const tx = transferFromAsync({ | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         returnData: '0x', | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             // This will actually revert when the AP tries to decode the return | ||||
|             // value. | ||||
|             return expect(tx).to.be.rejected(); | ||||
|         }); | ||||
|  | ||||
|         it('fails if bridge returns true', async () => { | ||||
|             const tx = transferFromAsync({ | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         returnData: hexUtils.leftPad('0x1'), | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             // This will actually revert when the AP tries to decode the return | ||||
|             // value. | ||||
|             return expect(tx).to.be.rejected(); | ||||
|         }); | ||||
|  | ||||
|         it('fails if bridge returns 0x1', async () => { | ||||
|             const tx = transferFromAsync({ | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         returnData: hexUtils.rightPad('0x1'), | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             return expect(tx).to.revertWith('BRIDGE_FAILED'); | ||||
|         }); | ||||
|  | ||||
|         it('fails if bridge is an EOA', async () => { | ||||
|             const tx = transferFromAsync({ | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeAddress: randomAddress(), | ||||
|                 }), | ||||
|             }); | ||||
|             // This will actually revert when the AP tries to decode the return | ||||
|             // value. | ||||
|             return expect(tx).to.be.rejected(); | ||||
|         }); | ||||
|  | ||||
|         it('fails if bridge reverts', async () => { | ||||
|             const revertError = 'FOOBAR'; | ||||
|             const tx = transferFromAsync({ | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         revertError, | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             return expect(tx).to.revertWith(revertError); | ||||
|         }); | ||||
|  | ||||
|         it('fails if balance of `to` increases by less than `amount`', async () => { | ||||
|             const amount = getRandomInteger(1, 100e18); | ||||
|             const tx = transferFromAsync({ | ||||
|                 amount, | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         transferAmount: amount.minus(1), | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             return expect(tx).to.revertWith('BRIDGE_UNDERPAY'); | ||||
|         }); | ||||
|  | ||||
|         it('fails if balance of `to` decreases', async () => { | ||||
|             const toAddress = randomAddress(); | ||||
|             await setTestTokenBalanceAsync(toAddress, 1e18); | ||||
|             const tx = transferFromAsync({ | ||||
|                 to: toAddress, | ||||
|                 assetData: createAssetData({ | ||||
|                     bridgeData: createBridgeData({ | ||||
|                         transferAmount: -1, | ||||
|                     }), | ||||
|                 }), | ||||
|             }); | ||||
|             return expect(tx).to.revertWith('BRIDGE_UNDERPAY'); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('balanceOf()', () => { | ||||
|         it('retrieves the balance of the encoded token', async () => { | ||||
|             const _owner = randomAddress(); | ||||
|             const balance = getRandomInteger(1, 100e18); | ||||
|             await bridgeContract.setTestTokenBalance(_owner, balance).awaitTransactionSuccessAsync(); | ||||
|             const assetData = createAssetData({ | ||||
|                 tokenAddress: testTokenAddress, | ||||
|             }); | ||||
|             const actualBalance = await assetProxy.balanceOf(encodeAssetData(assetData), _owner).callAsync(); | ||||
|             expect(actualBalance).to.bignumber.eq(balance); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('getProxyId()', () => { | ||||
|         it('returns the correct proxy ID', async () => { | ||||
|             const proxyId = await assetProxy.getProxyId().callAsync(); | ||||
|             expect(proxyId).to.eq(PROXY_ID); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,191 +0,0 @@ | ||||
| import { | ||||
|     blockchainTests, | ||||
|     constants, | ||||
|     expect, | ||||
|     filterLogsToArguments, | ||||
|     getRandomInteger, | ||||
|     Numberish, | ||||
|     randomAddress, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { AssetProxyId } from '@0x/types'; | ||||
| import { BigNumber, hexUtils, RawRevertError } from '@0x/utils'; | ||||
| import { DecodedLogs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
|  | ||||
| import { | ||||
|     TestEth2DaiBridgeContract, | ||||
|     TestEth2DaiBridgeEvents, | ||||
|     TestEth2DaiBridgeSellAllAmountEventArgs, | ||||
|     TestEth2DaiBridgeTokenApproveEventArgs, | ||||
|     TestEth2DaiBridgeTokenTransferEventArgs, | ||||
| } from './wrappers'; | ||||
|  | ||||
| blockchainTests.resets('Eth2DaiBridge unit tests', env => { | ||||
|     let testContract: TestEth2DaiBridgeContract; | ||||
|  | ||||
|     before(async () => { | ||||
|         testContract = await TestEth2DaiBridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestEth2DaiBridge, | ||||
|             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 WithdrawToOpts { | ||||
|             toTokenAddress?: string; | ||||
|             fromTokenAddress?: string; | ||||
|             toAddress: string; | ||||
|             amount: Numberish; | ||||
|             fromTokenBalance: Numberish; | ||||
|             revertReason: string; | ||||
|             fillAmount: Numberish; | ||||
|             toTokentransferRevertReason: string; | ||||
|             toTokenTransferReturnData: string; | ||||
|         } | ||||
|  | ||||
|         interface WithdrawToResult { | ||||
|             opts: WithdrawToOpts; | ||||
|             result: string; | ||||
|             logs: DecodedLogs; | ||||
|         } | ||||
|  | ||||
|         function createWithdrawToOpts(opts?: Partial<WithdrawToOpts>): WithdrawToOpts { | ||||
|             return { | ||||
|                 toAddress: randomAddress(), | ||||
|                 amount: getRandomInteger(1, 100e18), | ||||
|                 revertReason: '', | ||||
|                 fillAmount: getRandomInteger(1, 100e18), | ||||
|                 fromTokenBalance: getRandomInteger(1, 100e18), | ||||
|                 toTokentransferRevertReason: '', | ||||
|                 toTokenTransferReturnData: hexUtils.leftPad(1), | ||||
|                 ...opts, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         async function withdrawToAsync(opts?: Partial<WithdrawToOpts>): Promise<WithdrawToResult> { | ||||
|             const _opts = createWithdrawToOpts(opts); | ||||
|             // Set the fill behavior. | ||||
|             await testContract | ||||
|                 .setFillBehavior(_opts.revertReason, new BigNumber(_opts.fillAmount)) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             // Create tokens and balances. | ||||
|             if (_opts.fromTokenAddress === undefined) { | ||||
|                 const createTokenFn = testContract.createToken(new BigNumber(_opts.fromTokenBalance)); | ||||
|                 _opts.fromTokenAddress = await createTokenFn.callAsync(); | ||||
|                 await createTokenFn.awaitTransactionSuccessAsync(); | ||||
|             } | ||||
|             if (_opts.toTokenAddress === undefined) { | ||||
|                 const createTokenFn = testContract.createToken(constants.ZERO_AMOUNT); | ||||
|                 _opts.toTokenAddress = await createTokenFn.callAsync(); | ||||
|                 await createTokenFn.awaitTransactionSuccessAsync(); | ||||
|             } | ||||
|             // Set the transfer behavior of `toTokenAddress`. | ||||
|             await testContract | ||||
|                 .setTransferBehavior( | ||||
|                     _opts.toTokenAddress, | ||||
|                     _opts.toTokentransferRevertReason, | ||||
|                     _opts.toTokenTransferReturnData, | ||||
|                 ) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             // Call bridgeTransferFrom(). | ||||
|             const bridgeTransferFromFn = testContract.bridgeTransferFrom( | ||||
|                 // "to" token address | ||||
|                 _opts.toTokenAddress, | ||||
|                 // Random from address. | ||||
|                 randomAddress(), | ||||
|                 // To address. | ||||
|                 _opts.toAddress, | ||||
|                 new BigNumber(_opts.amount), | ||||
|                 // ABI-encode the "from" token address as the bridge data. | ||||
|                 hexUtils.leftPad(_opts.fromTokenAddress as string), | ||||
|             ); | ||||
|             const result = await bridgeTransferFromFn.callAsync(); | ||||
|             const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync(); | ||||
|             return { | ||||
|                 opts: _opts, | ||||
|                 result, | ||||
|                 logs: (logs as any) as DecodedLogs, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         it('returns magic bytes on success', async () => { | ||||
|             const BRIDGE_SUCCESS_RETURN_DATA = AssetProxyId.ERC20Bridge; | ||||
|             const { result } = await withdrawToAsync(); | ||||
|             expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA); | ||||
|         }); | ||||
|  | ||||
|         it('calls `Eth2Dai.sellAllAmount()`', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync(); | ||||
|             const transfers = filterLogsToArguments<TestEth2DaiBridgeSellAllAmountEventArgs>( | ||||
|                 logs, | ||||
|                 TestEth2DaiBridgeEvents.SellAllAmount, | ||||
|             ); | ||||
|             expect(transfers.length).to.eq(1); | ||||
|             expect(transfers[0].sellToken).to.eq(opts.fromTokenAddress); | ||||
|             expect(transfers[0].buyToken).to.eq(opts.toTokenAddress); | ||||
|             expect(transfers[0].sellTokenAmount).to.bignumber.eq(opts.fromTokenBalance); | ||||
|             expect(transfers[0].minimumFillAmount).to.bignumber.eq(opts.amount); | ||||
|         }); | ||||
|  | ||||
|         it('sets an unlimited allowance on the `fromTokenAddress` token', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync(); | ||||
|             const approvals = filterLogsToArguments<TestEth2DaiBridgeTokenApproveEventArgs>( | ||||
|                 logs, | ||||
|                 TestEth2DaiBridgeEvents.TokenApprove, | ||||
|             ); | ||||
|             expect(approvals.length).to.eq(1); | ||||
|             expect(approvals[0].token).to.eq(opts.fromTokenAddress); | ||||
|             expect(approvals[0].spender).to.eq(testContract.address); | ||||
|             expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); | ||||
|         }); | ||||
|  | ||||
|         it('transfers filled amount to `to`', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync(); | ||||
|             const transfers = filterLogsToArguments<TestEth2DaiBridgeTokenTransferEventArgs>( | ||||
|                 logs, | ||||
|                 TestEth2DaiBridgeEvents.TokenTransfer, | ||||
|             ); | ||||
|             expect(transfers.length).to.eq(1); | ||||
|             expect(transfers[0].token).to.eq(opts.toTokenAddress); | ||||
|             expect(transfers[0].from).to.eq(testContract.address); | ||||
|             expect(transfers[0].to).to.eq(opts.toAddress); | ||||
|             expect(transfers[0].amount).to.bignumber.eq(opts.fillAmount); | ||||
|         }); | ||||
|  | ||||
|         it('fails if `Eth2Dai.sellAllAmount()` reverts', async () => { | ||||
|             const opts = createWithdrawToOpts({ revertReason: 'FOOBAR' }); | ||||
|             const tx = withdrawToAsync(opts); | ||||
|             return expect(tx).to.revertWith(opts.revertReason); | ||||
|         }); | ||||
|  | ||||
|         it('fails if `toTokenAddress.transfer()` reverts', async () => { | ||||
|             const opts = createWithdrawToOpts({ toTokentransferRevertReason: 'FOOBAR' }); | ||||
|             const tx = withdrawToAsync(opts); | ||||
|             return expect(tx).to.revertWith(opts.toTokentransferRevertReason); | ||||
|         }); | ||||
|  | ||||
|         it('fails if `toTokenAddress.transfer()` returns false', async () => { | ||||
|             const opts = createWithdrawToOpts({ toTokenTransferReturnData: hexUtils.leftPad(0) }); | ||||
|             const tx = withdrawToAsync(opts); | ||||
|             return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(0))); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds if `toTokenAddress.transfer()` returns true', async () => { | ||||
|             await withdrawToAsync({ toTokenTransferReturnData: hexUtils.leftPad(1) }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,284 +0,0 @@ | ||||
| import { | ||||
|     blockchainTests, | ||||
|     constants, | ||||
|     expect, | ||||
|     getRandomInteger, | ||||
|     getRandomPortion, | ||||
|     randomAddress, | ||||
|     verifyEventsFromLogs, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { AssetProxyId } from '@0x/types'; | ||||
| import { BigNumber, hexUtils } from '@0x/utils'; | ||||
| import { DecodedLogs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
|  | ||||
| import { TestKyberBridgeContract, TestKyberBridgeEvents } from './wrappers'; | ||||
|  | ||||
| // 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; | ||||
|     const FROM_TOKEN_BASE = new BigNumber(10).pow(FROM_TOKEN_DECIMALS); | ||||
|     const TO_TOKEN_BASE = new BigNumber(10).pow(TO_TOKEN_DECIMALS); | ||||
|     const WETH_BASE = new BigNumber(10).pow(18); | ||||
|     const KYBER_RATE_BASE = WETH_BASE; | ||||
|     let testContract: TestKyberBridgeContract; | ||||
|  | ||||
|     before(async () => { | ||||
|         testContract = await TestKyberBridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestKyberBridge, | ||||
|             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()', () => { | ||||
|         let fromTokenAddress: string; | ||||
|         let toTokenAddress: string; | ||||
|         let wethAddress: string; | ||||
|  | ||||
|         before(async () => { | ||||
|             wethAddress = await testContract.weth().callAsync(); | ||||
|             fromTokenAddress = await testContract.createToken(FROM_TOKEN_DECIMALS).callAsync(); | ||||
|             await testContract.createToken(FROM_TOKEN_DECIMALS).awaitTransactionSuccessAsync(); | ||||
|             toTokenAddress = await testContract.createToken(TO_TOKEN_DECIMALS).callAsync(); | ||||
|             await testContract.createToken(TO_TOKEN_DECIMALS).awaitTransactionSuccessAsync(); | ||||
|         }); | ||||
|  | ||||
|         const STATIC_KYBER_TRADE_ARGS = { | ||||
|             maxBuyTokenAmount: constants.MAX_UINT256, | ||||
|             walletId: constants.NULL_ADDRESS, | ||||
|         }; | ||||
|  | ||||
|         interface TransferFromOpts { | ||||
|             toTokenAddress: string; | ||||
|             fromTokenAddress: string; | ||||
|             toAddress: string; | ||||
|             // Amount to pass into `bridgeTransferFrom()` | ||||
|             amount: BigNumber; | ||||
|             // Amount to convert in `trade()`. | ||||
|             fillAmount: BigNumber; | ||||
|             // Token balance of the bridge. | ||||
|             fromTokenBalance: BigNumber; | ||||
|         } | ||||
|  | ||||
|         interface TransferFromResult { | ||||
|             opts: TransferFromOpts; | ||||
|             result: string; | ||||
|             logs: DecodedLogs; | ||||
|         } | ||||
|  | ||||
|         function createTransferFromOpts(opts?: Partial<TransferFromOpts>): TransferFromOpts { | ||||
|             const amount = getRandomInteger(1, TO_TOKEN_BASE.times(100)); | ||||
|             return { | ||||
|                 fromTokenAddress, | ||||
|                 toTokenAddress, | ||||
|                 amount, | ||||
|                 toAddress: randomAddress(), | ||||
|                 fillAmount: getRandomPortion(amount), | ||||
|                 fromTokenBalance: getRandomInteger(1, FROM_TOKEN_BASE.times(100)), | ||||
|                 ...opts, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         async function withdrawToAsync(opts?: Partial<TransferFromOpts>): Promise<TransferFromResult> { | ||||
|             const _opts = createTransferFromOpts(opts); | ||||
|             // Fund the contract with input tokens. | ||||
|             await testContract | ||||
|                 .grantTokensTo(_opts.fromTokenAddress, testContract.address, _opts.fromTokenBalance) | ||||
|                 .awaitTransactionSuccessAsync({ value: _opts.fromTokenBalance }); | ||||
|             // Fund the contract with output tokens. | ||||
|             await testContract.setNextFillAmount(_opts.fillAmount).awaitTransactionSuccessAsync({ | ||||
|                 value: _opts.toTokenAddress === wethAddress ? _opts.fillAmount : constants.ZERO_AMOUNT, | ||||
|             }); | ||||
|             // Call bridgeTransferFrom(). | ||||
|             const bridgeTransferFromFn = testContract.bridgeTransferFrom( | ||||
|                 // Output token | ||||
|                 _opts.toTokenAddress, | ||||
|                 // Random maker address. | ||||
|                 randomAddress(), | ||||
|                 // Recipient address. | ||||
|                 _opts.toAddress, | ||||
|                 // Transfer amount. | ||||
|                 _opts.amount, | ||||
|                 // ABI-encode the input token address as the bridge data. | ||||
|                 hexUtils.concat(hexUtils.leftPad(_opts.fromTokenAddress), hexUtils.leftPad(32), hexUtils.leftPad(0)), | ||||
|             ); | ||||
|             const result = await bridgeTransferFromFn.callAsync(); | ||||
|             const { logs } = await bridgeTransferFromFn.awaitTransactionSuccessAsync(); | ||||
|             return { | ||||
|                 opts: _opts, | ||||
|                 result, | ||||
|                 logs: (logs as any) as DecodedLogs, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         function getMinimumConversionRate(opts: TransferFromOpts): BigNumber { | ||||
|             const fromBase = opts.fromTokenAddress === wethAddress ? WETH_BASE : FROM_TOKEN_BASE; | ||||
|             const toBase = opts.toTokenAddress === wethAddress ? WETH_BASE : TO_TOKEN_BASE; | ||||
|             return opts.amount | ||||
|                 .div(toBase) | ||||
|                 .div(opts.fromTokenBalance.div(fromBase)) | ||||
|                 .times(KYBER_RATE_BASE) | ||||
|                 .integerValue(BigNumber.ROUND_DOWN); | ||||
|         } | ||||
|  | ||||
|         it('returns magic bytes on success', async () => { | ||||
|             const BRIDGE_SUCCESS_RETURN_DATA = AssetProxyId.ERC20Bridge; | ||||
|             const { result } = await withdrawToAsync(); | ||||
|             expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA); | ||||
|         }); | ||||
|  | ||||
|         it('can trade token -> token', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync(); | ||||
|             verifyEventsFromLogs( | ||||
|                 logs, | ||||
|                 [ | ||||
|                     { | ||||
|                         sellTokenAddress: opts.fromTokenAddress, | ||||
|                         buyTokenAddress: opts.toTokenAddress, | ||||
|                         sellAmount: opts.fromTokenBalance, | ||||
|                         recipientAddress: opts.toAddress, | ||||
|                         minConversionRate: getMinimumConversionRate(opts), | ||||
|                         msgValue: constants.ZERO_AMOUNT, | ||||
|                         ...STATIC_KYBER_TRADE_ARGS, | ||||
|                     }, | ||||
|                 ], | ||||
|                 TestKyberBridgeEvents.KyberBridgeTrade, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('can trade token -> ETH', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync({ | ||||
|                 toTokenAddress: wethAddress, | ||||
|             }); | ||||
|             verifyEventsFromLogs( | ||||
|                 logs, | ||||
|                 [ | ||||
|                     { | ||||
|                         sellTokenAddress: opts.fromTokenAddress, | ||||
|                         buyTokenAddress: KYBER_ETH_ADDRESS, | ||||
|                         sellAmount: opts.fromTokenBalance, | ||||
|                         recipientAddress: testContract.address, | ||||
|                         minConversionRate: getMinimumConversionRate(opts), | ||||
|                         msgValue: constants.ZERO_AMOUNT, | ||||
|                         ...STATIC_KYBER_TRADE_ARGS, | ||||
|                     }, | ||||
|                 ], | ||||
|                 TestKyberBridgeEvents.KyberBridgeTrade, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('can trade ETH -> token', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync({ | ||||
|                 fromTokenAddress: wethAddress, | ||||
|             }); | ||||
|             verifyEventsFromLogs( | ||||
|                 logs, | ||||
|                 [ | ||||
|                     { | ||||
|                         sellTokenAddress: KYBER_ETH_ADDRESS, | ||||
|                         buyTokenAddress: opts.toTokenAddress, | ||||
|                         sellAmount: opts.fromTokenBalance, | ||||
|                         recipientAddress: opts.toAddress, | ||||
|                         minConversionRate: getMinimumConversionRate(opts), | ||||
|                         msgValue: opts.fromTokenBalance, | ||||
|                         ...STATIC_KYBER_TRADE_ARGS, | ||||
|                     }, | ||||
|                 ], | ||||
|                 TestKyberBridgeEvents.KyberBridgeTrade, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('does nothing if bridge has no token balance', async () => { | ||||
|             const { logs } = await withdrawToAsync({ | ||||
|                 fromTokenBalance: constants.ZERO_AMOUNT, | ||||
|             }); | ||||
|             expect(logs).to.be.length(0); | ||||
|         }); | ||||
|  | ||||
|         it('only transfers the token if trading the same token', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync({ | ||||
|                 toTokenAddress: fromTokenAddress, | ||||
|             }); | ||||
|             verifyEventsFromLogs( | ||||
|                 logs, | ||||
|                 [ | ||||
|                     { | ||||
|                         tokenAddress: fromTokenAddress, | ||||
|                         ownerAddress: testContract.address, | ||||
|                         recipientAddress: opts.toAddress, | ||||
|                         amount: opts.fromTokenBalance, | ||||
|                     }, | ||||
|                 ], | ||||
|                 TestKyberBridgeEvents.KyberBridgeTokenTransfer, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('grants Kyber an allowance when selling non-WETH', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync(); | ||||
|             verifyEventsFromLogs( | ||||
|                 logs, | ||||
|                 [ | ||||
|                     { | ||||
|                         tokenAddress: opts.fromTokenAddress, | ||||
|                         ownerAddress: testContract.address, | ||||
|                         spenderAddress: testContract.address, | ||||
|                         allowance: constants.MAX_UINT256, | ||||
|                     }, | ||||
|                 ], | ||||
|                 TestKyberBridgeEvents.KyberBridgeTokenApprove, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('does not grant Kyber an allowance when selling WETH', async () => { | ||||
|             const { logs } = await withdrawToAsync({ | ||||
|                 fromTokenAddress: wethAddress, | ||||
|             }); | ||||
|             verifyEventsFromLogs(logs, [], TestKyberBridgeEvents.KyberBridgeTokenApprove); | ||||
|         }); | ||||
|  | ||||
|         it('withdraws WETH and passes it to Kyber when selling WETH', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync({ | ||||
|                 fromTokenAddress: wethAddress, | ||||
|             }); | ||||
|             expect(logs[0].event).to.eq(TestKyberBridgeEvents.KyberBridgeWethWithdraw); | ||||
|             expect(logs[0].args).to.deep.eq({ | ||||
|                 ownerAddress: testContract.address, | ||||
|                 amount: opts.fromTokenBalance, | ||||
|             }); | ||||
|             expect(logs[1].event).to.eq(TestKyberBridgeEvents.KyberBridgeTrade); | ||||
|             expect(logs[1].args.msgValue).to.bignumber.eq(opts.fromTokenBalance); | ||||
|         }); | ||||
|  | ||||
|         it('wraps WETH and transfers it to the recipient when buyng WETH', async () => { | ||||
|             const { opts, logs } = await withdrawToAsync({ | ||||
|                 toTokenAddress: wethAddress, | ||||
|             }); | ||||
|             expect(logs[0].event).to.eq(TestKyberBridgeEvents.KyberBridgeTokenApprove); | ||||
|             expect(logs[0].args.tokenAddress).to.eq(opts.fromTokenAddress); | ||||
|             expect(logs[1].event).to.eq(TestKyberBridgeEvents.KyberBridgeTrade); | ||||
|             expect(logs[1].args.recipientAddress).to.eq(testContract.address); | ||||
|             expect(logs[2].event).to.eq(TestKyberBridgeEvents.KyberBridgeWethDeposit); | ||||
|             expect(logs[2].args).to.deep.eq({ | ||||
|                 msgValue: opts.fillAmount, | ||||
|                 ownerAddress: testContract.address, | ||||
|                 amount: opts.fillAmount, | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,25 +1,20 @@ | ||||
| import { | ||||
|     chaiSetup, | ||||
|     constants, | ||||
|     expectTransactionFailedAsync, | ||||
|     expectTransactionFailedWithoutReasonAsync, | ||||
|     provider, | ||||
|     txDefaults, | ||||
|     web3Wrapper, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { BlockchainLifecycle } from '@0x/dev-utils'; | ||||
| import { assetDataUtils } from '@0x/order-utils'; | ||||
| import { AssetProxyId, RevertReason } from '@0x/types'; | ||||
| import { AbiEncoder, BigNumber } from '@0x/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as ethUtil from 'ethereumjs-util'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
|  | ||||
| import { | ||||
|     IAssetDataContract, | ||||
|     IAssetProxyContract, | ||||
|     StaticCallProxyContract, | ||||
|     TestStaticCallTargetContract, | ||||
| } from './wrappers'; | ||||
| import { artifacts, IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from '../src'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| @@ -30,7 +25,6 @@ describe('StaticCallProxy', () => { | ||||
|     let fromAddress: string; | ||||
|     let toAddress: string; | ||||
|  | ||||
|     let assetDataInterface: IAssetDataContract; | ||||
|     let staticCallProxy: IAssetProxyContract; | ||||
|     let staticCallTarget: TestStaticCallTargetContract; | ||||
|  | ||||
| @@ -49,14 +43,7 @@ describe('StaticCallProxy', () => { | ||||
|             txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider); | ||||
|         staticCallProxy = new IAssetProxyContract( | ||||
|             staticCallProxyWithoutTransferFrom.address, | ||||
|             provider, | ||||
|             txDefaults, | ||||
|             {}, | ||||
|             StaticCallProxyContract.deployedBytecode, | ||||
|         ); | ||||
|         staticCallProxy = new IAssetProxyContract(staticCallProxyWithoutTransferFrom.address, provider, txDefaults); | ||||
|         staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestStaticCallTarget, | ||||
|             provider, | ||||
| @@ -84,21 +71,26 @@ describe('StaticCallProxy', () => { | ||||
|             ); | ||||
|         }); | ||||
|         it('should have an id of 0xc339d10a', async () => { | ||||
|             const proxyId = await staticCallProxy.getProxyId().callAsync(); | ||||
|             const proxyId = await staticCallProxy.getProxyId.callAsync(); | ||||
|             const expectedProxyId = AssetProxyId.StaticCall; | ||||
|             expect(proxyId).to.equal(expectedProxyId); | ||||
|         }); | ||||
|     }); | ||||
|     describe('transferFrom', () => { | ||||
|         it('should revert if assetData lies outside the bounds of calldata', async () => { | ||||
|             const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const txData = staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             const txData = staticCallProxy.transferFrom.getABIEncodedTransactionData( | ||||
|                 assetData, | ||||
|                 fromAddress, | ||||
|                 toAddress, | ||||
|                 amount, | ||||
|             ); | ||||
|             const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080'; | ||||
|             const txDataEndBuffer = ethUtil.toBuffer((txData.length - 2) / 2 - 4); | ||||
|             const paddedTxDataEndBuffer = ethUtil.setLengthLeft(txDataEndBuffer, 32); | ||||
| @@ -116,22 +108,23 @@ 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 = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData() | ||||
|             const assetData = assetDataUtils | ||||
|                 .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .slice(0, -128); | ||||
|             const assetDataByteLen = (assetData.length - 2) / 2; | ||||
|             expect((assetDataByteLen - 4) % 32).to.equal(0); | ||||
|             await expectTransactionFailedWithoutReasonAsync( | ||||
|                 staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(), | ||||
|                 staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount), | ||||
|             ); | ||||
|         }); | ||||
|         it('should revert if the offset to `staticCallData` points to outside of assetData', async () => { | ||||
|             const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060'; | ||||
|             const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4); | ||||
|             const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32); | ||||
| @@ -142,86 +135,90 @@ describe('StaticCallProxy', () => { | ||||
|                 invalidOffsetToStaticCallData, | ||||
|             )}${newStaticCallData}`; | ||||
|             await expectTransactionFailedWithoutReasonAsync( | ||||
|                 staticCallProxy.transferFrom(badAssetData, fromAddress, toAddress, amount).sendTransactionAsync(), | ||||
|                 staticCallProxy.transferFrom.sendTransactionAsync(badAssetData, fromAddress, toAddress, amount), | ||||
|             ); | ||||
|         }); | ||||
|         it('should revert if the callTarget attempts to write to state', async () => { | ||||
|             const staticCallData = staticCallTarget.updateState().getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData(); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await expectTransactionFailedWithoutReasonAsync( | ||||
|                 staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(), | ||||
|                 staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount), | ||||
|             ); | ||||
|         }); | ||||
|         it('should revert with data provided by the callTarget if the staticcall reverts', async () => { | ||||
|             const staticCallData = staticCallTarget.assertEvenNumber(new BigNumber(1)).getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1)); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             return expect( | ||||
|                 staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(), | ||||
|             ).to.revertWith(RevertReason.TargetNotEven); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await expectTransactionFailedAsync( | ||||
|                 staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount), | ||||
|                 RevertReason.TargetNotEven, | ||||
|             ); | ||||
|         }); | ||||
|         it('should revert if the hash of the output is different than expected expected', async () => { | ||||
|             const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0)); | ||||
|             const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); | ||||
|             const expectedResultHash = ethUtil.bufferToHex(ethUtil.keccak256(trueAsBuffer)); | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             return expect( | ||||
|                 staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(), | ||||
|             ).to.revertWith(RevertReason.UnexpectedStaticCallResult); | ||||
|             const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await expectTransactionFailedAsync( | ||||
|                 staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount), | ||||
|                 RevertReason.UnexpectedStaticCallResult, | ||||
|             ); | ||||
|         }); | ||||
|         it('should be successful if a function call with no inputs and no outputs is successful', async () => { | ||||
|             const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             await staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); | ||||
|         }); | ||||
|         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 = assetDataInterface | ||||
|                 .StaticCall(toAddress, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             await staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash); | ||||
|             await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); | ||||
|         }); | ||||
|         it('should be successful if a function call with one static input returns the correct value', async () => { | ||||
|             const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1)); | ||||
|             const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); | ||||
|             const expectedResultHash = ethUtil.bufferToHex(ethUtil.keccak256(trueAsBuffer)); | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             await staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); | ||||
|         }); | ||||
|         it('should be successful if a function with one dynamic input is successful', async () => { | ||||
|             const dynamicInput = '0x0102030405060708'; | ||||
|             const staticCallData = staticCallTarget.dynamicInputFunction(dynamicInput).getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput); | ||||
|             const expectedResultHash = constants.KECCAK256_NULL; | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             await staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); | ||||
|         }); | ||||
|         it('should be successful if a function call returns a complex type', async () => { | ||||
|             const a = new BigNumber(1); | ||||
|             const b = new BigNumber(2); | ||||
|             const staticCallData = staticCallTarget.returnComplexType(a, b).getABIEncodedTransactionData(); | ||||
|             const staticCallData = staticCallTarget.returnComplexType.getABIEncodedTransactionData(a, b); | ||||
|             const abiEncoder = new AbiEncoder.DynamicBytes({ | ||||
|                 name: '', | ||||
|                 type: 'bytes', | ||||
| @@ -232,14 +229,14 @@ describe('StaticCallProxy', () => { | ||||
|             const offset = '0000000000000000000000000000000000000000000000000000000000000020'; | ||||
|             const encodedExpectedResultWithOffset = `0x${offset}${abiEncoder.encode(expectedResults).slice(2)}`; | ||||
|             const expectedResultHash = ethUtil.bufferToHex( | ||||
|                 ethUtil.keccak256(ethUtil.toBuffer(encodedExpectedResultWithOffset)), | ||||
|                 ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)), | ||||
|             ); | ||||
|             const assetData = assetDataInterface | ||||
|                 .StaticCall(staticCallTarget.address, staticCallData, expectedResultHash) | ||||
|                 .getABIEncodedTransactionData(); | ||||
|             await staticCallProxy | ||||
|                 .transferFrom(assetData, fromAddress, toAddress, amount) | ||||
|                 .awaitTransactionSuccessAsync(); | ||||
|             const assetData = assetDataUtils.encodeStaticCallAssetData( | ||||
|                 staticCallTarget.address, | ||||
|                 staticCallData, | ||||
|                 expectedResultHash, | ||||
|             ); | ||||
|             await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user