Compare commits
1333 Commits
@0x/contra
...
@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 | ||
|
0ae2d8bab5 | ||
|
3e0bd1f02d | ||
|
b2592d1cc2 | ||
|
aa3524c3b2 | ||
|
35fcfb978d | ||
|
c68083cf03 | ||
|
39deb1a05f | ||
|
302d08e290 | ||
|
05489dd7f1 | ||
|
cfb5119efc | ||
|
5d53fa5635 | ||
|
38d2b70ba6 | ||
|
29d5db16c2 | ||
|
a8128c5772 | ||
|
55bd076602 | ||
|
53a08d00fd | ||
|
fccec66463 | ||
|
bc26e807cd | ||
|
46dc37fb20 | ||
|
ccbb8400ee | ||
|
5d3d8a5332 | ||
|
7a224fe08f | ||
|
e045f5f74b | ||
|
e5c07ff0c5 | ||
|
cdf0aa27e4 | ||
|
88998e6bb7 | ||
|
b885dfa606 | ||
|
407495c278 | ||
|
ea50a94355 | ||
|
cb3318972e | ||
|
c057ad7977 | ||
|
eb21718462 | ||
|
7836e10d8a | ||
|
946a31821d | ||
|
92a915f477 | ||
|
60b458dbfb | ||
|
8b13efc89a | ||
|
88b625fa15 | ||
|
2cf9c9b7df | ||
|
d179d6a1a2 | ||
|
08502c1eb6 | ||
|
384cd47416 | ||
|
3bdeb82097 | ||
|
f49ab3f919 | ||
|
42d5bdd3ab | ||
|
7228cbfe92 | ||
|
250c46d6a4 | ||
|
f394d7dba9 | ||
|
ca595cd8cf | ||
|
9ce71739f5 | ||
|
d69da38f7d | ||
|
50f69f734f | ||
|
fc9c6c5434 | ||
|
6e941be1e9 | ||
|
9f677150a4 | ||
|
11e273337f | ||
|
ec807120c3 | ||
|
a5654debeb | ||
|
0869c0d8b0 | ||
|
b456c3f953 | ||
|
8297d68166 | ||
|
18ce6797e0 | ||
|
c1009d440e | ||
|
89ee6fe6db | ||
|
38a12475bc | ||
|
9a800264a2 | ||
|
8ce390be3c | ||
|
cc93532f4f | ||
|
37cc40521c | ||
|
5ac7ff7084 | ||
|
e682b82ca8 | ||
|
7cd1fd0aaa | ||
|
8cd99c5a40 | ||
|
ad83312009 | ||
|
9e3b1fe333 | ||
|
c3f42995f9 | ||
|
3d3a02c892 | ||
|
06bec227ad | ||
|
5d7803323c | ||
|
4303f9a025 | ||
|
fe4c5434fa | ||
|
9325bb70c5 | ||
|
b164557165 | ||
|
424f984ea8 | ||
|
78c704e3d1 | ||
|
50f1a8fbd8 | ||
|
0f90b7b5da | ||
|
bec4384a5d | ||
|
f361efae5a | ||
|
76ca2116ab | ||
|
33d8646dc5 | ||
|
3cb5190bc6 | ||
|
5bba06bef8 | ||
|
dd3f672a35 | ||
|
25ef3b8445 | ||
|
7eb2d290d8 | ||
|
678762910b | ||
|
da28a542c7 | ||
|
92602d33ad | ||
|
03f04f4bb3 | ||
|
0d4dd5ff0d | ||
|
884864cc58 | ||
|
7c199d83be | ||
|
5b4c29c4bb | ||
|
f97ee80955 | ||
|
547322ae63 | ||
|
db74db622e | ||
|
57318c0041 | ||
|
4eb0767834 | ||
|
92bb7808ce | ||
|
abfe7d1613 | ||
|
6c72239365 | ||
|
8001daad8c | ||
|
73a38ab4f4 | ||
|
281c207921 | ||
|
ae531eef5f | ||
|
d8b11238e6 | ||
|
d36eb04ae8 | ||
|
b97ba35279 | ||
|
46efe92a72 | ||
|
9cc27c7d1b | ||
|
7d3396f9c5 | ||
|
918ef13714 | ||
|
9d12462893 | ||
|
ed44e16a95 | ||
|
11e2fc5bc4 | ||
|
3e88f820b8 | ||
|
163750f8c2 | ||
|
4aabc5d791 | ||
|
c9a7b9dcc1 | ||
|
98075b5653 | ||
|
57ae5be916 | ||
|
8caf62997f | ||
|
f8656ad376 | ||
|
29c6c2a2ad | ||
|
dadab94644 | ||
|
f2db67ef02 | ||
|
7ec232a470 | ||
|
dc3569392c | ||
|
11999cd407 | ||
|
f786f8a7f6 | ||
|
aab39e6ae0 | ||
|
31d3968649 | ||
|
72b8ef33d9 | ||
|
2cd0b01019 | ||
|
a6bc0db896 | ||
|
7cba95b523 | ||
|
1b976130ce | ||
|
e9babc5a94 | ||
|
c8d0ff846c | ||
|
db1e9769d0 | ||
|
4b038b07ed | ||
|
4c17c142f9 | ||
|
65b2fa13ac | ||
|
c375199daa | ||
|
805131cf1e | ||
|
6f64115561 | ||
|
0aadb789a5 | ||
|
26ee4d626c | ||
|
a8939d3eda | ||
|
048e48b03a | ||
|
c2f34baee0 | ||
|
8961b476ef | ||
|
58e08335b5 | ||
|
ea8fc1d93f | ||
|
2968dfb2ae | ||
|
24783107ba | ||
|
365c056b0f | ||
|
88a7d9cca8 | ||
|
d8cf9d54aa | ||
|
df746c5ff4 | ||
|
aa29526ae4 | ||
|
f0b5616aba | ||
|
2eca95df00 | ||
|
f560c2e66a | ||
|
5e19496e32 | ||
|
aeadaba005 | ||
|
8dfda9ffdd | ||
|
91992bb034 | ||
|
34a93857a0 | ||
|
fbda096aa9 | ||
|
24a26aef70 | ||
|
ec7f9d8a63 | ||
|
cc7dec7a99 | ||
|
46384ce80d | ||
|
5aeb626045 | ||
|
d2a27f1a48 | ||
|
f07c67202f | ||
|
3a3658708a | ||
|
f3c5d19246 | ||
|
c66d8f202a | ||
|
ec641c171d | ||
|
773d624365 | ||
|
25bd97a014 | ||
|
5dd9e28f72 | ||
|
cc1ef6f268 | ||
|
967e361da3 | ||
|
398097900c | ||
|
b86473f3c7 | ||
|
3d361c6b4a | ||
|
3346024ea7 | ||
|
2fecf6c80b | ||
|
183b4fb7ee | ||
|
0e2afc5dcb | ||
|
91aa716c07 | ||
|
9977626de0 | ||
|
8bb3fb5bb3 | ||
|
6d7adb277e | ||
|
fef1bd13b5 | ||
|
910bba9976 | ||
|
cd2d756717 | ||
|
0a47d89963 | ||
|
65e5b09cd1 | ||
|
6f3cee1a1e | ||
|
c43d4bbf71 | ||
|
b7337410aa | ||
|
10b7d7da3f | ||
|
97a8c6e5af | ||
|
e69d2bb54a | ||
|
ead8099109 | ||
|
9d455b2bca | ||
|
1e6e74878f | ||
|
cbcede3b63 | ||
|
98fd731485 | ||
|
9ca319b4ea | ||
|
ff8fabf49e | ||
|
1e00f68941 | ||
|
6c79edd3b2 | ||
|
b79bc6bab9 | ||
|
c59d886662 | ||
|
e39dce6159 | ||
|
620c66fb4c | ||
|
3af91d54cb | ||
|
1fe1bcff98 | ||
|
c58c12c5b3 | ||
|
1aeea39eb3 | ||
|
d3fbf020de | ||
|
8ce8bee76f | ||
|
dcf4eb2aaf | ||
|
88ff38eca6 | ||
|
bf0d90d079 | ||
|
c4d9ef9f83 | ||
|
37bce53683 | ||
|
05d50b62c9 | ||
|
eb2fb7f790 | ||
|
d280ccb3c4 | ||
|
a569815840 | ||
|
9e41c3093b | ||
|
9dbc9a8ad9 | ||
|
c940157814 | ||
|
4f19875a58 | ||
|
dcbadb2386 | ||
|
405a7b2037 | ||
|
e69ad24737 | ||
|
a31056a4ec | ||
|
d41dddddcd | ||
|
251ae50d3e | ||
|
4ccd2d4955 | ||
|
dfb79e0998 | ||
|
590055e2ba | ||
|
f388751a97 | ||
|
53136caaa4 | ||
|
dd20d8d6de | ||
|
a977957946 | ||
|
8974fcabe3 | ||
|
aff8e1e025 | ||
|
10d767c5ab | ||
|
77484dc69e | ||
|
185e2342d9 | ||
|
54f4727adc | ||
|
6e0f982163 | ||
|
43072ef80d | ||
|
7618e63f49 | ||
|
542255332d | ||
|
6d6e7e1468 | ||
|
0ff88d5c21 | ||
|
092e35bae3 | ||
|
ac82b2622c | ||
|
7197cb57cd | ||
|
030d66cb63 | ||
|
d414e6a7c4 | ||
|
30f9c94620 | ||
|
b6b618e5ce | ||
|
0bb8887027 | ||
|
fabfdd0aa2 | ||
|
8f8336b344 | ||
|
d10659f986 | ||
|
e853555165 | ||
|
2ce09d73ac | ||
|
14f48a5f4f | ||
|
8da4e4a830 | ||
|
88ae8311c8 | ||
|
eabf6a466a | ||
|
989f691d06 | ||
|
52a3dae7cb | ||
|
8a6dfacf71 | ||
|
19ca6c13ad | ||
|
9196f122dd | ||
|
55e3d81c58 | ||
|
80caa16718 | ||
|
ddc5aaacdb | ||
|
38825865cc | ||
|
157b2efa1d | ||
|
212a2d229a | ||
|
ccb89fb26a | ||
|
3a0b0c0973 | ||
|
c159ed9ebb | ||
|
e37dbcc273 | ||
|
841e660b1f | ||
|
391aba5f37 | ||
|
f5d30f4a07 | ||
|
230cf7dfb7 | ||
|
8734b70f83 | ||
|
ff9a2b2d9a | ||
|
a41dab2922 | ||
|
f4504106a1 | ||
|
1a5b8041c7 | ||
|
1e2170f8bb | ||
|
0a4a973a7f | ||
|
67137cadac | ||
|
ead4afa06b | ||
|
e39ef95191 | ||
|
3d7585671f | ||
|
44806106db | ||
|
6a8197a4e8 | ||
|
4d4b4e0f2b | ||
|
82da33d742 | ||
|
1c6130a492 | ||
|
dabe5e939f | ||
|
b4ac6d3439 | ||
|
d0ea74e180 | ||
|
a5f77f3964 | ||
|
9401bb53e8 | ||
|
347c6d02cf | ||
|
64a0080616 | ||
|
288a7d4cea | ||
|
1207b68f57 | ||
|
2b82187fe0 | ||
|
3e2dbfc83c | ||
|
6691f490bc | ||
|
a7db900e51 | ||
|
cfa2a90dae | ||
|
feebb45e9d | ||
|
13a2f3a330 | ||
|
1da8801084 | ||
|
7a7b17c4f3 | ||
|
2afb06de13 | ||
|
ac771e2865 | ||
|
4b09204936 | ||
|
e4a5518a7c | ||
|
e83507ba98 | ||
|
6e5b77edb2 | ||
|
98167da8fa | ||
|
11d5fec59b | ||
|
ed02f4ca88 | ||
|
e7c612971d | ||
|
242a2e21b5 | ||
|
92a1e5413b | ||
|
e1ab9aa690 | ||
|
222f7e6fd4 | ||
|
59001f827b | ||
|
549bfe98f1 | ||
|
64e3b6f5ee | ||
|
2fdc0426ff | ||
|
e6c70fda66 | ||
|
50da1354f3 | ||
|
e503cacf57 | ||
|
6a1e0edc78 | ||
|
048f5c2771 | ||
|
d9378e9a8f | ||
|
f77aaaf2e0 | ||
|
380835b151 | ||
|
857d91df85 | ||
|
cd9a6b0de7 | ||
|
86333f4928 | ||
|
d1975bd5dd | ||
|
08b9f27eac | ||
|
5b2cf8a776 | ||
|
7394106880 | ||
|
9134a7ae1e | ||
|
c617e9f483 | ||
|
545fcef716 | ||
|
e20fa3a1bf | ||
|
9d01b47d5b | ||
|
fa4c34df41 | ||
|
9f8ab4d626 | ||
|
1971c9cecd | ||
|
82f730831d | ||
|
035167e5b7 | ||
|
323fb0a965 | ||
|
45aacf122f | ||
|
5dcf7919fc | ||
|
f15560bd89 | ||
|
bf3ae730d6 | ||
|
92ce258bb4 | ||
|
5810e7df82 | ||
|
f2cbf4a561 | ||
|
0c8bb2e675 | ||
|
f51c4f9617 | ||
|
5345f7c983 | ||
|
7d9e43b2e1 | ||
|
570c1e1809 | ||
|
720d335b09 | ||
|
f0ecda1a48 | ||
|
4ed111a7d4 | ||
|
fc257523c7 | ||
|
9775f8d83c | ||
|
01a1b19556 | ||
|
bd228034fd | ||
|
2672a5c59f | ||
|
5f383430eb | ||
|
66ec3e9f4d | ||
|
c269c427a6 | ||
|
212855ebd8 | ||
|
8f78945a73 | ||
|
86d50cf597 | ||
|
8986d506a5 | ||
|
3d2c945c35 | ||
|
8206a3969f | ||
|
43afe67593 | ||
|
ecf939f8c8 | ||
|
f0c4ccfa1e | ||
|
718d48b7d5 | ||
|
d5e88677ae | ||
|
b1cfdc7a6a | ||
|
5c5f815b20 | ||
|
d9edb9675f | ||
|
be6fce5a89 | ||
|
12afeb30ae | ||
|
23df406ff0 | ||
|
c9ecef4fc3 | ||
|
62f0a867a8 | ||
|
f68b8d82e0 | ||
|
6b7cb13e9a | ||
|
613af6013a | ||
|
0db56a781e | ||
|
fe7674b184 | ||
|
44a6fe7310 | ||
|
46690f0c35 | ||
|
cfc4e345cc | ||
|
c68278d824 | ||
|
09600a71cd | ||
|
d66ba70f5e | ||
|
e7c4120d24 | ||
|
1212e534a8 | ||
|
899d0f1e42 | ||
|
dde4ed3754 | ||
|
b596e02752 | ||
|
d5afe696da | ||
|
976be66dee | ||
|
98c8a6387a | ||
|
be1b636e30 | ||
|
8bae0b81aa | ||
|
7ee19e1306 | ||
|
626d0dfa93 | ||
|
8453c616a5 | ||
|
56bc2944d0 | ||
|
b2cf701e30 | ||
|
9a3b29acb7 | ||
|
85b217f167 | ||
|
a7700d6c22 | ||
|
1e274518dd | ||
|
f4f8927c79 | ||
|
60b7890f16 | ||
|
4d46290ef6 | ||
|
00f7e2cfc3 | ||
|
e742708261 | ||
|
8c9de31c5c | ||
|
2bf992f0ac | ||
|
52a01bcc11 | ||
|
f250e03c40 | ||
|
75acbfb042 | ||
|
740fd6f5d9 | ||
|
c58306cd49 | ||
|
985696631c | ||
|
d8a3d7f920 | ||
|
b6b96f0eee | ||
|
3f037ef3cc | ||
|
5c2d3fb3da | ||
|
84d38ea878 | ||
|
6226aa0b23 | ||
|
72af35834b | ||
|
3019e3817f | ||
|
da9e90faf0 | ||
|
e737395c2b | ||
|
5a33167594 | ||
|
dfb7e50948 | ||
|
b43c9f075c | ||
|
f42ce6adb5 | ||
|
bf533bbdbb | ||
|
9328729c4c | ||
|
2e23a044ca | ||
|
691a3a1e72 | ||
|
fc40f9634b | ||
|
4969441f21 | ||
|
d04d50794e | ||
|
5e1fbe34a9 | ||
|
2b75829a0c | ||
|
3b3fd0a3a2 | ||
|
1e4b61008a | ||
|
ffb71e9fd5 | ||
|
c1aeb4bde6 | ||
|
66bca5cd81 | ||
|
b68df3a067 | ||
|
066f3bb646 | ||
|
661c334928 | ||
|
a1895d4157 | ||
|
1e7efe026a | ||
|
02e7da979a | ||
|
bd2839110b | ||
|
1bcb2697e7 | ||
|
fdb9a664f5 | ||
|
8099c334c7 | ||
|
344d28ab78 | ||
|
5e41168305 | ||
|
dd97669cdd | ||
|
af75581659 | ||
|
3c08f5b86a | ||
|
7809cad6cb | ||
|
3e59029966 | ||
|
24249bcb4d | ||
|
543011c3de | ||
|
4d9f2586d9 | ||
|
7f94ebe362 | ||
|
c9bf1eda54 | ||
|
2cd4d9004c | ||
|
35cd0319d4 | ||
|
899030e966 | ||
|
15e3944d23 | ||
|
f1fbaedb0f | ||
|
cf04062a19 | ||
|
2e922bf7db | ||
|
741a731ecb | ||
|
91bff1976c | ||
|
fad500042a | ||
|
bdb2a01385 | ||
|
f372cd2d13 | ||
|
a435da910f | ||
|
f1d96d9673 | ||
|
45226ee1f6 | ||
|
03b8d29740 | ||
|
80a4af249f | ||
|
900d444946 | ||
|
7ca9393d2d | ||
|
b22d7bb310 | ||
|
c742cdfe5c | ||
|
2d3fe02cd7 | ||
|
7d61cb6bac | ||
|
a804433a7a | ||
|
11082320c2 | ||
|
9f9797b123 | ||
|
05d34616b7 | ||
|
c7f474ada1 | ||
|
c7328a63d0 | ||
|
db818794d5 | ||
|
b4b34e4890 | ||
|
eec016380d | ||
|
dcab272be0 | ||
|
418d033a5c | ||
|
e7a7713b80 | ||
|
52a580d845 | ||
|
ea42a0b5f5 | ||
|
a0b63da9a6 | ||
|
8d9932fc42 | ||
|
54be45bedc | ||
|
3c9d2a562b | ||
|
654bd5175c | ||
|
9db660cd3f | ||
|
9aeadff9bd | ||
|
cd631b789b | ||
|
4d98408aaf | ||
|
9dd4ea1584 | ||
|
9d085cdb61 | ||
|
f00a2dbc59 | ||
|
20862d47ab | ||
|
1bff790628 | ||
|
0010ca3e03 | ||
|
9edb5dae88 | ||
|
85b49096dc | ||
|
a7eaa10220 | ||
|
5a46ce55b6 | ||
|
dbebbecab1 | ||
|
c7593e66bf | ||
|
d52dc69279 | ||
|
1c65fa212d | ||
|
be88eb00f8 | ||
|
65c60f5386 | ||
|
83a043e639 | ||
|
8175192f60 | ||
|
7d2c975d73 | ||
|
e5153737d8 | ||
|
88766a02c7 | ||
|
8162394797 | ||
|
fd001186dd | ||
|
128fef8838 | ||
|
1e25a0654a | ||
|
82b0ff6008 | ||
|
ca7c3630f9 | ||
|
260bb8218f | ||
|
a691de7d55 | ||
|
5674c484e2 | ||
|
9286dc284c | ||
|
624b71bd39 | ||
|
b7ea605a3b | ||
|
489a787de8 | ||
|
84150036ed | ||
|
619123720c | ||
|
cc98ff9fe6 | ||
|
39d159f38c | ||
|
ca8eb90cec | ||
|
f8e3e28d85 | ||
|
4d868489bd | ||
|
b06f09f6af | ||
|
bf00f5f945 | ||
|
6ceb6cc301 | ||
|
00a6afaa8e |
@@ -4,63 +4,53 @@ jobs:
|
||||
build:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
environment:
|
||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
- 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
|
||||
# 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 --global yarn@1.9.4
|
||||
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:no_website
|
||||
- run: yarn build:ci
|
||||
- run: yarn build:ts
|
||||
- save_cache:
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo
|
||||
build-website:
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/abi-gen/test-cli/output
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/abi-gen-wrappers/generated_docs
|
||||
test-contracts-ganache:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: cd packages/website && yarn build:prod
|
||||
test-contracts-ganache:
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun test:circleci @0x/contracts-multisig
|
||||
- run: yarn wsrun test:circleci @0x/contracts-utils
|
||||
- run: yarn wsrun test:circleci @0x/contracts-exchange-libs
|
||||
- run: yarn wsrun test:circleci @0x/contracts-erc20
|
||||
- run: yarn wsrun test:circleci @0x/contracts-erc721
|
||||
- run: yarn wsrun test:circleci @0x/contracts-erc1155
|
||||
- run: yarn wsrun test:circleci @0x/contracts-extensions
|
||||
- run: yarn wsrun test:circleci @0x/contracts-asset-proxy
|
||||
- run: yarn wsrun test:circleci @0x/contracts-exchange
|
||||
- run: yarn wsrun test:circleci @0x/contracts-exchange-forwarder
|
||||
- run: yarn wsrun test:circleci @0x/contracts-coordinator
|
||||
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils
|
||||
test-contracts-geth:
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
- image: 0xorg/devnet
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
@@ -69,21 +59,11 @@ jobs:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
|
||||
# initialized
|
||||
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test @0x/contracts-multisig
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-utils
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-libs
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc20
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc721
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-erc1155
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-extensions
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-asset-proxy
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-exchange-forwarder
|
||||
- run: TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-coordinator
|
||||
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-dev-utils
|
||||
test-publish:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
- image: 0xorg/verdaccio
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
@@ -93,30 +73,16 @@ jobs:
|
||||
- run: yarn test:publish:circleci
|
||||
test-doc-generation:
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:generate_docs:circleci
|
||||
test-pipeline:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
- image: postgres:11-alpine
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: ZEROEX_DATA_PIPELINE_TEST_DB_URL='postgresql://postgres@localhost/postgres' yarn wsrun test:circleci @0x/pipeline
|
||||
- save_cache:
|
||||
key: coverage-pipeline-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/pipeline/coverage/lcov.info
|
||||
test-rest:
|
||||
docker:
|
||||
- image: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
@@ -124,6 +90,7 @@ jobs:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn wsrun test:circleci @0x/contracts-test-utils
|
||||
- run: yarn wsrun test:circleci @0x/abi-gen
|
||||
- run: yarn wsrun test:circleci @0x/asset-buyer
|
||||
- run: yarn wsrun test:circleci @0x/contract-artifacts
|
||||
- run: yarn wsrun test:circleci @0x/assert
|
||||
- run: yarn wsrun test:circleci @0x/base-contract
|
||||
@@ -131,9 +98,7 @@ jobs:
|
||||
- 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/metacoin
|
||||
- run: yarn wsrun test:circleci @0x/order-utils
|
||||
- run: yarn wsrun test:circleci @0x/order-watcher
|
||||
- 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
|
||||
@@ -149,6 +114,10 @@ jobs:
|
||||
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/assert/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-asset-buyer-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/asset-buyer/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@@ -169,18 +138,10 @@ jobs:
|
||||
key: coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/json-schemas/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/metacoin/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/order-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/order-watcher/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@@ -204,34 +165,38 @@ jobs:
|
||||
test-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/python
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
- image: 0xorg/ganache-cli:2.2.2
|
||||
- image: 0xorg/launch-kit-ci
|
||||
- image: 0xorg/launch-kit-backend:74bcc39
|
||||
environment:
|
||||
RPC_URL: http://localhost:8545
|
||||
NETWORK_ID: 50
|
||||
WHITELIST_ALL_TOKENS: True
|
||||
command: bash -c "until curl -sfd'{\"method\":\"net_listening\"}' http://localhost:8545 | grep true; do continue; done; forever ts/lib/index.js"
|
||||
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
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages
|
||||
python -m ensurepip
|
||||
./pre_install
|
||||
./install
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages
|
||||
./cmd_pkgs_in_dep_order.py coverage run setup.py test
|
||||
./parallel_without_sra_client coverage run setup.py test
|
||||
./build_docs
|
||||
- save_cache:
|
||||
key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@@ -256,23 +221,37 @@ jobs:
|
||||
key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/python-packages/sra_client/.coverage
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/*/__init__.py
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_addresses/build
|
||||
- store_artifacts:
|
||||
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: circleci/python
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python -m ensurepip
|
||||
python -m pip install .
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
@@ -287,23 +266,26 @@ jobs:
|
||||
static-tests-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/python
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
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: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
@@ -311,11 +293,12 @@ jobs:
|
||||
- run: yarn lerna run lint
|
||||
- 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: circleci/node:9-browsers
|
||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
@@ -327,6 +310,9 @@ jobs:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-asset-buyer-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
|
||||
@@ -342,15 +328,9 @@ jobs:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
@@ -393,9 +373,6 @@ workflows:
|
||||
main:
|
||||
jobs:
|
||||
- build
|
||||
- build-website:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts-ganache:
|
||||
requires:
|
||||
- build
|
||||
@@ -404,9 +381,6 @@ workflows:
|
||||
# - test-contracts-geth:
|
||||
# requires:
|
||||
# - build
|
||||
- test-pipeline:
|
||||
requires:
|
||||
- build
|
||||
- test-rest:
|
||||
requires:
|
||||
- build
|
||||
@@ -426,6 +400,8 @@ workflows:
|
||||
- static-tests-python:
|
||||
requires:
|
||||
- test-python
|
||||
- test-python
|
||||
- test-python:
|
||||
requires:
|
||||
- build
|
||||
# skip python tox run for now, as we don't yet have multiple test environments to support.
|
||||
#- test-rest-python
|
||||
|
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -1,7 +1,8 @@
|
||||
*.sol linguist-language=Solidity
|
||||
|
||||
# Automatically collapse generated files in GitHub.
|
||||
*.svg linguist-generated
|
||||
packages/contract-artifacts/artifacts/*json linguist-generated
|
||||
packages/abi-gen-wrappers/wrappers/*.ts liguist-generated
|
||||
*.svg linguist-generated=true
|
||||
packages/contract-artifacts/artifacts/*json linguist-generated=true
|
||||
packages/abi-gen-wrappers/src/generated-wrappers/*.ts linguist-generated=true
|
||||
packages/contract-wrappers/src/generated-wrappers/*.ts linguist-generated=true
|
||||
|
||||
|
74
.github/autolabeler.yml
vendored
74
.github/autolabeler.yml
vendored
@@ -1,43 +1,37 @@
|
||||
python: ['python-packages']
|
||||
contracts: ['contracts']
|
||||
sol-doc: ['packages/sol-doc']
|
||||
sol-resolver: ['packages/sol-resolver']
|
||||
contracts-gen: ['packages/contracts-gen']
|
||||
sra-spec: ['packages/sra-spec']
|
||||
subproviders: ['packages/subproviders']
|
||||
contract-addresses: ['packages/contract-addresses']
|
||||
migrations: ['packages/migrations']
|
||||
web3-wrapper: ['packages/web3-wrapper']
|
||||
sol-compiler: ['packages/sol-compiler']
|
||||
types: ['packages/types']
|
||||
instant: ['packages/instant']
|
||||
abi-gen-templates: ['packages/abi-gen-templates']
|
||||
abi-gen: ['packages/abi-gen']
|
||||
website: ['packages/website']
|
||||
sol-coverage: ['packages/sol-coverage']
|
||||
sol-profiler: ['packages/sol-profiler']
|
||||
sol-trace: ['packages/sol-trace']
|
||||
sol-tracing-utils: ['packages/sol-tracing-utils']
|
||||
utils: ['packages/utils']
|
||||
tslint-config: ['packages/tslint-config']
|
||||
asset-buyer: ['packages/asset-buyer']
|
||||
order-watcher: ['packages/order-watcher']
|
||||
react-docs: ['packages/react-docs']
|
||||
order-utils: ['packages/order-utils']
|
||||
react-shared: ['packages/react-shared']
|
||||
assert: ['packages/assert']
|
||||
base-contract: ['packages/base-contract']
|
||||
typescript-typings: ['packages/typescript-typings']
|
||||
@0x/sol-doc: ['packages/sol-doc']
|
||||
@0x/sol-resolver: ['packages/sol-resolver']
|
||||
@0x/contracts-gen: ['packages/contracts-gen']
|
||||
@0x/sra-spec: ['packages/sra-spec']
|
||||
@0x/subproviders: ['packages/subproviders']
|
||||
@0x/contract-addresses: ['packages/contract-addresses']
|
||||
@0x/migrations: ['packages/migrations']
|
||||
@0x/web3-wrapper: ['packages/web3-wrapper']
|
||||
@0x/sol-compiler: ['packages/sol-compiler']
|
||||
@0x/types: ['packages/types']
|
||||
@0x/instant: ['packages/instant']
|
||||
@0x/abi-gen-templates: ['packages/abi-gen-templates']
|
||||
@0x/abi-gen: ['packages/abi-gen']
|
||||
@0x/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']
|
||||
abi-gen-wrappers: ['packages/abi-gen-wrappers']
|
||||
metacoin: ['packages/metacoin']
|
||||
contract-artifacts: ['packages/contract-artifacts']
|
||||
dev-utils: ['packages/dev-utils']
|
||||
contract-wrappers: ['packages/contract-wrappers']
|
||||
json-schemas: ['packages/json-schemas']
|
||||
ethereum-types: ['ethereum-types']
|
||||
connect: ['packages/connect']
|
||||
fill-scenarios: ['packages/fill-scenarios']
|
||||
dev-tools-pages: ['packages/dev-tools-pages']
|
||||
testnet-faucets: ['packages/testnet-faucets']
|
||||
monorepo-scripts: ['packages/monorepo-scripts']
|
||||
@0x/abi-gen-wrappers: ['packages/abi-gen-wrappers']
|
||||
@0x/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']
|
||||
|
47
.gitignore
vendored
47
.gitignore
vendored
@@ -40,9 +40,12 @@ build/Release
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# NVM config
|
||||
.nvmrc
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
.npmrc
|
||||
@@ -75,10 +78,6 @@ TODO.md
|
||||
# VSCode file
|
||||
.vscode
|
||||
|
||||
packages/website/public/bundle*
|
||||
packages/dev-tools-pages/public/bundle*
|
||||
packages/react-docs/example/public/bundle*
|
||||
|
||||
# server cli
|
||||
packages/testnet-faucets/server/
|
||||
|
||||
@@ -94,11 +93,12 @@ contracts/erc721/generated-artifacts/
|
||||
contracts/erc1155/generated-artifacts/
|
||||
contracts/extensions/generated-artifacts/
|
||||
contracts/exchange-forwarder/generated-artifacts/
|
||||
contracts/dev-utils/generated-artifacts/
|
||||
packages/sol-tracing-utils/test/fixtures/artifacts/
|
||||
packages/metacoin/artifacts/
|
||||
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
|
||||
|
||||
# generated contract wrappers
|
||||
packages/abi-gen-wrappers/wrappers
|
||||
packages/python-contract-wrappers/generated/
|
||||
contracts/coordinator/generated-wrappers/
|
||||
contracts/exchange/generated-wrappers/
|
||||
contracts/asset-proxy/generated-wrappers/
|
||||
@@ -110,14 +110,31 @@ contracts/erc721/generated-wrappers/
|
||||
contracts/erc1155/generated-wrappers/
|
||||
contracts/extensions/generated-wrappers/
|
||||
contracts/exchange-forwarder/generated-wrappers/
|
||||
packages/metacoin/src/contract_wrappers
|
||||
contracts/dev-utils/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/
|
||||
|
||||
# Monorepo scripts
|
||||
packages/*/scripts/
|
||||
|
||||
# python stuff
|
||||
.eggs
|
||||
.mypy_cache
|
||||
@@ -127,3 +144,11 @@ 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
|
||||
|
@@ -22,18 +22,19 @@ lib
|
||||
/contracts/extensions/generated-artifacts
|
||||
/contracts/exchange-forwarder/generated-wrappers
|
||||
/contracts/exchange-forwarder/generated-artifacts
|
||||
/packages/abi-gen-wrappers/src/generated-wrappers
|
||||
/packages/contract-artifacts/artifacts
|
||||
/python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts
|
||||
/contracts/dev-utils/generated-wrappers
|
||||
/contracts/dev-utils/generated-artifacts
|
||||
/packages/abi-gen/test-cli/output
|
||||
/packages/json-schemas/schemas
|
||||
/python-packages/json_schemas/src/zero_ex/json_schemas/schemas
|
||||
/packages/metacoin/src/contract_wrappers
|
||||
/packages/metacoin/artifacts
|
||||
/packages/sra-spec/public/
|
||||
/packages/dev-tools-pages/ts/**/data.json
|
||||
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
|
||||
|
10
CODEOWNERS
10
CODEOWNERS
@@ -7,22 +7,21 @@
|
||||
# Website
|
||||
packages/asset-buyer/ @BMillman19 @fragosti @steveklebanoff
|
||||
packages/instant/ @BMillman19 @fragosti @steveklebanoff
|
||||
packages/website/ @BMillman19 @fragosti @fabioberger @steveklebanoff
|
||||
|
||||
# Dev tools & setup
|
||||
.circleci/ @LogvinovLeon
|
||||
packages/abi-gen/ @LogvinovLeon
|
||||
packages/base-contract/ @LogvinovLeon
|
||||
packages/abi-gen/ @feuGeneA
|
||||
packages/base-contract/ @xianny
|
||||
packages/connect/ @fragosti
|
||||
packages/abi-gen-templates/ @LogvinovLeon
|
||||
packages/abi-gen-templates/ @feuGeneA @xianny
|
||||
packages/contract-addresses/ @albrow
|
||||
packages/contract-artifacts/ @albrow
|
||||
packages/dev-utils/ @LogvinovLeon @fabioberger
|
||||
packages/devnet/ @albrow
|
||||
packages/ethereum-types/ @LogvinovLeon
|
||||
packages/metacoin/ @LogvinovLeon
|
||||
packages/monorepo-scripts/ @fabioberger
|
||||
packages/order-utils/ @fabioberger @LogvinovLeon
|
||||
packages/python-contract-wrappers/ @feuGeneA
|
||||
packages/sol-compiler/ @LogvinovLeon
|
||||
packages/sol-coverage/ @LogvinovLeon
|
||||
packages/sol-profiler/ @LogvinovLeon
|
||||
@@ -36,5 +35,4 @@ python-packages/ @feuGeneA
|
||||
packages/utils/ @hysz
|
||||
|
||||
# Protocol/smart contracts
|
||||
contracts/core/test/ @albrow
|
||||
contracts/ @abandeali1 @hysz
|
||||
|
@@ -29,9 +29,9 @@ ALL PRs should be opened against `development`.
|
||||
|
||||
Branch names should be prefixed with `fix`, `feature` or `refactor`.
|
||||
|
||||
- e.g `fix/broken-wiki-link`
|
||||
- e.g `fix/missing-import`
|
||||
- If the PR only edits a single package, add it's name too
|
||||
- e.g `fix/website/broken-wiki-link`
|
||||
- e.g `fix/subproviders/missing-import`
|
||||
|
||||
### CHANGELOGs
|
||||
|
||||
@@ -55,7 +55,7 @@ If an entry without a `timestamp` already exists, this means other changes have
|
||||
|
||||
### Development Tooling
|
||||
|
||||
We strongly recommend you use the [VSCode](https://code.visualstudio.com/) text editor since most of our code is written in Typescript and it offers amazing support for the language.
|
||||
We strongly recommend you use the [VSCode](https://code.visualstudio.com/) text editor since most of our code is written in TypeScript and it offers amazing support for the language.
|
||||
|
||||
#### Linter
|
||||
|
||||
@@ -89,7 +89,7 @@ A few of our coding conventions are not yet enforced by the linter/auto-formatte
|
||||
1. Do not import from a project's `index.ts` (e.g import { Token } from '../src';). Always import from the source file itself.
|
||||
1. Generic error variables should be named `err` instead of `e` or `error`.
|
||||
1. If you _must_ cast a variable to any - try to type it back as fast as possible. (e.g., `const cw = ((zeroEx as any)._contractWrappers as ContractWrappers);`). This ensures subsequent code is type-safe.
|
||||
1. Our enum conventions coincide with the recommended Typescript conventions, using capitalized keys, and all-caps snake-case values. Eg `GetStats = 'GET_STATS'`
|
||||
1. Our enum conventions coincide with the recommended TypeScript conventions, using capitalized keys, and all-caps snake-case values. Eg `GetStats = 'GET_STATS'`
|
||||
1. All public, exported methods/functions/classes must have associated Javadoc-style comments.
|
||||
|
||||
### Fix `submit-coverage` CI failure
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--- Before submitting please check to see if this issue was already reported -->
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
<!--- Prefix your issue title with the package name it relates to (e.g., `0x.js: ` or `general:`) -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
|
50
README.md
50
README.md
@@ -6,21 +6,16 @@
|
||||
|
||||
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
|
||||
|
||||
If you're developing on 0x now or are interested in using 0x infrastructure in the future, please join our [developer mailing list][dev-mailing-list-url] for updates.
|
||||
|
||||
[website-url]: https://0xproject.com
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
[dev-mailing-list-url]: http://eepurl.com/dx4cPf
|
||||
[website-url]: https://0x.org
|
||||
|
||||
[](https://circleci.com/gh/0xProject/0x-monorepo)
|
||||
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)
|
||||
[](https://chat.0xproject.com)
|
||||
[](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://discordapp.com/invite/d3FTX3M)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
|
||||
## Packages
|
||||
|
||||
Visit our [developer portal](https://0xproject.com/docs/order-utils) for a comprehensive list of core & community maintained packages. All packages maintained with this monorepo are listed below.
|
||||
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
|
||||
|
||||
@@ -28,6 +23,7 @@ Visit our [developer portal](https://0xproject.com/docs/order-utils) for a compr
|
||||
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| [`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 |
|
||||
@@ -47,11 +43,12 @@ These packages are all under development. See [/contracts/README.md](/contracts/
|
||||
| [`@0x/contracts-exchange-libs`](/contracts/exchange-libs) | [](https://www.npmjs.com/package/@0x/contracts-exchange-libs) | Protocol specific libraries used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract |
|
||||
| [`@0x/contracts-extensions`](/contracts/extensions) | [](https://www.npmjs.com/package/@0x/contracts-extensions) | Contracts that interact with and extend the functionality of the core protocol |
|
||||
| [`@0x/contracts-multisig`](/contracts/multisig) | [](https://www.npmjs.com/package/@0x/contracts-multisig) | Various implementations of multisignature wallets, including the [`AssetProxyOwner`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxyowner) contract that has permissions to upgrade the protocol |
|
||||
| [`@0x/contracts-test-utils`](/contracts/test-utils) | [](https://www.npmjs.com/package/@0x/contracts-test-utils) | Typescript/Javascript shared utilities used for testing contracts |
|
||||
| [`@0x/contracts-test-utils`](/contracts/test-utils) | [](https://www.npmjs.com/package/@0x/contracts-test-utils) | TypeScript/Javascript shared utilities used for testing contracts |
|
||||
| [`@0x/contracts-utils`](/contracts/utils) | [](https://www.npmjs.com/package/@0x/contracts-utils) | Generic libraries and utilities used throughout all of the contracts |
|
||||
| [`@0x/contracts-coordinator`](/contracts/coordinator) | [](https://www.npmjs.com/package/@0x/contracts-coordinator) | A contract that allows users to execute 0x transactions with permission from a Coordinator |
|
||||
| [`@0x/contracts-dev-utils`](/contracts/dev-utils) | [](https://www.npmjs.com/package/@0x/contracts-dev-utils) | A contract contains utility functions for developers (such as validating many orders using a single eth_call) |
|
||||
|
||||
### Typescript/Javascript Packages
|
||||
### TypeScript/Javascript Packages
|
||||
|
||||
#### 0x-specific packages
|
||||
|
||||
@@ -61,14 +58,14 @@ These packages are all under development. See [/contracts/README.md](/contracts/
|
||||
| [`@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/order-watcher`](/packages/order-watcher) | [](https://www.npmjs.com/package/@0x/order-watcher) | An order watcher daemon that watches for order validity |
|
||||
| [`@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
|
||||
|
||||
@@ -85,19 +82,17 @@ These packages are all under development. See [/contracts/README.md](/contracts/
|
||||
|
||||
#### 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/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0x/react-docs) | React documentation component for rendering TypeDoc & sol-doc generated JSON |
|
||||
| [`@0x/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0x/react-shared) | 0x shared react components |
|
||||
| [`@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 |
|
||||
| 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
|
||||
|
||||
@@ -105,11 +100,10 @@ These packages are all under development. See [/contracts/README.md](/contracts/
|
||||
| -------------------------------------------------- | -------------------------------------------------------------------------------- |
|
||||
| [`@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 |
|
||||
| [`@0x/website`](/packages/website) | 0x website |
|
||||
|
||||
## Usage
|
||||
|
||||
Node version >= 6.12 is required.
|
||||
Node version 6.x or 8.x is required.
|
||||
|
||||
Most of the packages require additional typings for external dependencies.
|
||||
You can include those by prepending the `@0x/typescript-typings` package to your [`typeRoots`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) config.
|
||||
@@ -138,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:
|
||||
|
@@ -10,3 +10,7 @@
|
||||
| Forwarder | [`@0x/contracts-exchange-forwarder`](/contracts/exchange-forwarder) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-exchange-forwarder/v/1.0.1) | [@0x/contracts-exchange-forwarder@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-exchange-forwarder@1.0.1) |
|
||||
| MultiAssetProxy | [`@0x/contracts-asset-proxy`](/contracts/asset-proxy) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-asset-proxy/v/1.0.1) | [@0x/contracts-asset-proxy@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-asset-proxy@1.0.1) |
|
||||
| ZRXToken | [`@0x/contracts-erc20`](/contracts/erc20) | [v1.0.1](https://www.npmjs.com/package/@0x/contracts-erc20/v/1.0.1) | [@0x/contracts-erc20@1.0.1](https://github.com/0xProject/0x-monorepo/releases/tag/@0x/contracts-erc20@1.0.1) |
|
||||
|
||||
#### Development
|
||||
|
||||
Building solidity files will update the contract artifact in `{package-name}/generated-artifacts/{contract}.json`, but does not automatically update the `abi-gen-wrappers` package, which are generated from the artifact JSON. To ensure consistency, clean and rebuild `abi-gen-wrappers` after any changes to the artifact JSON.
|
||||
|
@@ -1,4 +1,122 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.2.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564607468
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.2.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.2.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `LibAssetProxyIds` contract",
|
||||
"pr": 1835
|
||||
},
|
||||
{
|
||||
"note": "Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases.",
|
||||
"pr": 1852
|
||||
},
|
||||
{
|
||||
"note": "Implement StaticCallProxy",
|
||||
"pr": 1863
|
||||
}
|
||||
],
|
||||
"timestamp": 1563006338
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557799313,
|
||||
"version": "2.1.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.2",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,56 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.2.8 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.7 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.6 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.5 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.4 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.2.3 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.2 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.1 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.0 - _July 13, 2019_
|
||||
|
||||
* Add `LibAssetProxyIds` contract (#1835)
|
||||
* Updated ERC1155 Asset Proxy. Less optimization. More explicit handling of edge cases. (#1852)
|
||||
* Implement StaticCallProxy (#1863)
|
||||
|
||||
## v2.1.5 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.4 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.3 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.2 - _May 10, 2019_
|
||||
|
||||
* Update tests to use contract-built-in `awaitTransactionSuccessAsync` (#1797)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## AssetProxy
|
||||
|
||||
This package contains the implementations of all of the [`AssetProxy`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy) contracts available within the 0x protocol. These contracts are responsible for decoding the `assetData` sent to them and performing the actual transfer of assets. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains the implementations of all of the [`AssetProxy`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#assetproxy) contracts available within the 0x protocol. These contracts are responsible for decoding the `assetData` sent to them and performing the actual transfer of assets. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-asset-proxy --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
@@ -28,9 +29,10 @@
|
||||
"src/ERC721Proxy.sol",
|
||||
"src/MixinAuthorizable.sol",
|
||||
"src/MultiAssetProxy.sol",
|
||||
"src/StaticCallProxy.sol",
|
||||
"src/interfaces/IAssetData.sol",
|
||||
"src/interfaces/IAssetProxy.sol",
|
||||
"src/interfaces/IAuthorizable.sol",
|
||||
"src/libs/LibAssetData.sol"
|
||||
"test/TestStaticCallTarget.sol"
|
||||
]
|
||||
}
|
||||
|
@@ -16,243 +16,73 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
|
||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
|
||||
import "./MixinAuthorizable.sol";
|
||||
import "./interfaces/IAssetProxy.sol";
|
||||
|
||||
|
||||
contract ERC1155Proxy is
|
||||
MixinAuthorizable
|
||||
MixinAuthorizable,
|
||||
SafeMath,
|
||||
IAssetProxy
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
|
||||
|
||||
function ()
|
||||
/// @dev Transfers batch of ERC1155 assets. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded with ERC1155 token address, array of ids, array of values, and callback data.
|
||||
/// @param from Address to transfer assets from.
|
||||
/// @param to Address to transfer assets to.
|
||||
/// @param amount Amount that will be multiplied with each element of `assetData.values` to scale the
|
||||
/// values that will be transferred.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
onlyAuthorized
|
||||
{
|
||||
// Input calldata to this function is encoded as follows:
|
||||
// -- TABLE #1 --
|
||||
// | Area | Offset (**) | Length | Contents |
|
||||
// |----------|-------------|-------------|---------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. offset to assetData (*) |
|
||||
// | | 36 | | 2. from |
|
||||
// | | 68 | | 3. to |
|
||||
// | | 100 | | 4. amount |
|
||||
// | Data | | | assetData: |
|
||||
// | | 132 | 32 | assetData Length |
|
||||
// | | 164 | (see below) | assetData Contents |
|
||||
//
|
||||
//
|
||||
// Asset data is encoded as follows:
|
||||
// -- TABLE #2 --
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|-------------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | assetProxyId |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | | 4 | | 1. address of ERC1155 contract |
|
||||
// | | 36 | | 2. offset to ids (*) |
|
||||
// | | 68 | | 3. offset to values (*) |
|
||||
// | | 100 | | 4. offset to data (*) |
|
||||
// | Data | | | ids: |
|
||||
// | | 132 | 32 | 1. ids Length |
|
||||
// | | 164 | a | 2. ids Contents |
|
||||
// | | | | values: |
|
||||
// | | 164 + a | 32 | 1. values Length |
|
||||
// | | 196 + a | b | 2. values Contents |
|
||||
// | | | | data |
|
||||
// | | 196 + a + b | 32 | 1. data Length |
|
||||
// | | 228 + a + b | c | 2. data Contents |
|
||||
//
|
||||
//
|
||||
// Calldata for target ERC155 asset is encoded for safeBatchTransferFrom:
|
||||
// -- TABLE #3 --
|
||||
// | Area | Offset (**) | Length | Contents |
|
||||
// |----------|-------------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | safeBatchTransferFrom selector |
|
||||
// | Params | | 5 * 32 | function parameters: |
|
||||
// | | 4 | | 1. from address |
|
||||
// | | 36 | | 2. to address |
|
||||
// | | 68 | | 3. offset to ids (*) |
|
||||
// | | 100 | | 4. offset to values (*) |
|
||||
// | | 132 | | 5. offset to data (*) |
|
||||
// | Data | | | ids: |
|
||||
// | | 164 | 32 | 1. ids Length |
|
||||
// | | 196 | a | 2. ids Contents |
|
||||
// | | | | values: |
|
||||
// | | 196 + a | 32 | 1. values Length |
|
||||
// | | 228 + a | b | 2. values Contents |
|
||||
// | | | | data |
|
||||
// | | 228 + a + b | 32 | 1. data Length |
|
||||
// | | 260 + a + b | c | 2. data Contents |
|
||||
//
|
||||
//
|
||||
// (*): offset is computed from start of function parameters, so offset
|
||||
// by an additional 4 bytes in the calldata.
|
||||
//
|
||||
// (**): the `Offset` column is computed assuming no calldata compression;
|
||||
// offsets in the Data Area are dynamic and should be evaluated in
|
||||
// real-time.
|
||||
//
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
//
|
||||
// Note: Table #1 and Table #2 exists in Calldata. We construct Table #3 in memory.
|
||||
//
|
||||
//
|
||||
assembly {
|
||||
// The first 4 bytes of calldata holds the function selector
|
||||
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
|
||||
// Decode params from `assetData`
|
||||
// solhint-disable indent
|
||||
(
|
||||
address erc1155TokenAddress,
|
||||
uint256[] memory ids,
|
||||
uint256[] memory values,
|
||||
bytes memory data
|
||||
) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address, uint256[], uint256[], bytes)
|
||||
);
|
||||
// solhint-enable indent
|
||||
|
||||
// `transferFrom` will be called with the following parameters:
|
||||
// assetData Encoded byte array.
|
||||
// from Address to transfer asset from.
|
||||
// to Address to transfer asset to.
|
||||
// amount Amount of asset to transfer.
|
||||
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
|
||||
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
|
||||
|
||||
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
|
||||
// where k is the key left padded to 32 bytes and p is the storage slot
|
||||
mstore(0, caller)
|
||||
mstore(32, authorized_slot)
|
||||
|
||||
// Revert if authorized[msg.sender] == false
|
||||
if iszero(sload(keccak256(0, 64))) {
|
||||
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Construct Table #3 in memory, starting at memory offset 0.
|
||||
// The algorithm below maps asset data from Table #1 and Table #2 to Table #3, while
|
||||
// scaling the `values` (Table #2) by `amount` (Table #1). Once Table #3 has
|
||||
// been constructed in memory, the destination erc1155 contract is called using this
|
||||
// as its calldata. This process is divided into four steps, below.
|
||||
|
||||
////////// STEP 1/4 //////////
|
||||
// Map relevant fields from assetData (Table #2) into memory (Table #3)
|
||||
// The Contents column of Table #2 is the same as Table #3,
|
||||
// beginning from parameter 3 - `offset to ids (*)`
|
||||
// The offsets in these rows are offset by 32 bytes in Table #3.
|
||||
// Strategy:
|
||||
// 1. Copy the assetData into memory at offset 32
|
||||
// 2. Increment by 32 the offsets to `ids`, `values`, and `data`
|
||||
|
||||
// Load offset to `assetData`
|
||||
let assetDataOffset := calldataload(4)
|
||||
|
||||
// Load length in bytes of `assetData`, computed by:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
let assetDataLength := calldataload(add(4, assetDataOffset))
|
||||
|
||||
// This corresponds to the beginning of the Data Area for Table #3.
|
||||
// Computed by:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// + 32 (length of assetData)
|
||||
calldatacopy(
|
||||
32, // aligned such that "offset to ids" is at the correct location for Table #3
|
||||
add(36, assetDataOffset), // beginning of asset data contents
|
||||
assetDataLength // length of asset data
|
||||
)
|
||||
|
||||
// Increment by 32 the offsets to `ids`, `values`, and `data`
|
||||
mstore(68, add(mload(68), 32))
|
||||
mstore(100, add(mload(100), 32))
|
||||
mstore(132, add(mload(132), 32))
|
||||
|
||||
// Record the address of the destination erc1155 asset for later.
|
||||
let assetAddress := and(
|
||||
mload(36),
|
||||
0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
|
||||
)
|
||||
|
||||
////////// STEP 2/4 //////////
|
||||
let amount := calldataload(100)
|
||||
let valuesOffset := add(mload(100), 4) // add 4 for calldata offset
|
||||
let valuesLengthInBytes := mul(
|
||||
mload(valuesOffset),
|
||||
32
|
||||
)
|
||||
let valuesBegin := add(valuesOffset, 32)
|
||||
let valuesEnd := add(valuesBegin, valuesLengthInBytes)
|
||||
for { let tokenValueOffset := valuesBegin }
|
||||
lt(tokenValueOffset, valuesEnd)
|
||||
{ tokenValueOffset := add(tokenValueOffset, 32) }
|
||||
{
|
||||
// Load token value and generate scaled value
|
||||
let tokenValue := mload(tokenValueOffset)
|
||||
let scaledTokenValue := mul(tokenValue, amount)
|
||||
|
||||
// Revert if `amount` != 0 and multiplication resulted in an overflow
|
||||
if iszero(or(
|
||||
iszero(amount),
|
||||
eq(div(scaledTokenValue, amount), tokenValue)
|
||||
)) {
|
||||
// Revert with `Error("UINT256_OVERFLOW")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// There was no overflow, update `tokenValue` with its scaled counterpart
|
||||
mstore(tokenValueOffset, scaledTokenValue)
|
||||
}
|
||||
|
||||
////////// STEP 3/4 //////////
|
||||
// Store the safeBatchTransferFrom function selector,
|
||||
// and copy `from`/`to` fields from Table #1 to Table #3.
|
||||
|
||||
// The function selector is computed using:
|
||||
// bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))
|
||||
mstore(0, 0x2eb2c2d600000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// Copy `from` and `to` fields from Table #1 to Table #3
|
||||
calldatacopy(
|
||||
4, // aligned such that `from` and `to` are at the correct location for Table #3
|
||||
36, // beginning of `from` field from Table #1
|
||||
64 // 32 bytes for `from` + 32 bytes for `to` field
|
||||
)
|
||||
|
||||
////////// STEP 4/4 //////////
|
||||
// Call into the destination erc1155 contract using as calldata Table #3 (constructed in-memory above)
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
assetAddress, // call address of erc1155 asset
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
add(assetDataLength, 32), // length of input (Table #3) is 32 bytes longer than `assetData` (Table #2)
|
||||
0, // write output over memory that won't be reused
|
||||
0 // don't copy output to memory
|
||||
)
|
||||
|
||||
// Revert with reason given by AssetProxy if `transferFrom` call failed
|
||||
if iszero(success) {
|
||||
returndatacopy(
|
||||
0, // copy to memory at 0
|
||||
0, // copy from return data at 0
|
||||
returndatasize() // copy all return data
|
||||
)
|
||||
revert(0, returndatasize())
|
||||
}
|
||||
|
||||
// Return if call was successful
|
||||
return(0, 0)
|
||||
}
|
||||
|
||||
// Revert if undefined function is called
|
||||
revert(0, 0)
|
||||
// Scale values up by `amount`
|
||||
uint256 length = values.length;
|
||||
uint256[] memory scaledValues = new uint256[](length);
|
||||
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
|
||||
// same location in the ABI encoded calldata.
|
||||
scaledValues[i] = safeMul(values[i], amount);
|
||||
}
|
||||
|
||||
// Execute `safeBatchTransferFrom` call
|
||||
// Either succeeds or throws
|
||||
IERC1155(erc1155TokenAddress).safeBatchTransferFrom(
|
||||
from,
|
||||
to,
|
||||
ids,
|
||||
scaledValues,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
|
@@ -90,7 +90,10 @@ contract MultiAssetProxy is
|
||||
// offset to assetData.
|
||||
|
||||
// Load offset to `assetData`
|
||||
let assetDataOffset := calldataload(4)
|
||||
let assetDataOffset := add(calldataload(4), 4)
|
||||
|
||||
// Load length in bytes of `assetData`
|
||||
let assetDataLength := calldataload(assetDataOffset)
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
@@ -108,41 +111,62 @@ contract MultiAssetProxy is
|
||||
// | | 132 + a | b | nestedAssetData Contents (offsets) |
|
||||
// | | 132 + a + b | | nestedAssetData[0, ..., len] |
|
||||
|
||||
// Assert that the length of asset data:
|
||||
// 1. Must be at least 68 bytes (see table above)
|
||||
// 2. Must be a multiple of 32 (excluding the 4-byte selector)
|
||||
if or(lt(assetDataLength, 68), mod(sub(assetDataLength, 4), 32)) {
|
||||
// Revert with `Error("INVALID_ASSET_DATA_LENGTH")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x00000019494e56414c49445f41535345545f444154415f4c454e475448000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// End of asset data in calldata
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
let assetDataEnd := add(assetDataOffset, add(assetDataLength, 32))
|
||||
if gt(assetDataEnd, calldatasize()) {
|
||||
// Revert with `Error("INVALID_ASSET_DATA_END")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x00000016494e56414c49445f41535345545f444154415f454e44000000000000)
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// In order to find the offset to `amounts`, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
let amountsOffset := calldataload(add(assetDataOffset, 40))
|
||||
let amountsOffset := calldataload(add(assetDataOffset, 36))
|
||||
|
||||
// In order to find the offset to `nestedAssetData`, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + 32 (amounts offset)
|
||||
let nestedAssetDataOffset := calldataload(add(assetDataOffset, 72))
|
||||
let nestedAssetDataOffset := calldataload(add(assetDataOffset, 68))
|
||||
|
||||
// In order to find the start of the `amounts` contents, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + amountsOffset
|
||||
// + 32 (amounts len)
|
||||
let amountsContentsStart := add(assetDataOffset, add(amountsOffset, 72))
|
||||
let amountsContentsStart := add(assetDataOffset, add(amountsOffset, 68))
|
||||
|
||||
// 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:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
let nestedAssetDataContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, 72))
|
||||
let nestedAssetDataContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, 68))
|
||||
|
||||
// Load number of elements in `nestedAssetData`
|
||||
let nestedAssetDataLen := calldataload(sub(nestedAssetDataContentsStart, 32))
|
||||
@@ -204,15 +228,20 @@ contract MultiAssetProxy is
|
||||
let nestedAssetDataElementOffset := calldataload(add(nestedAssetDataContentsStart, i))
|
||||
|
||||
// In order to find the start of the `nestedAssetData[i]` contents, we must add:
|
||||
// 4 (function selector)
|
||||
// + assetDataOffset
|
||||
// assetDataOffset
|
||||
// + 32 (assetData len)
|
||||
// + 4 (assetProxyId)
|
||||
// + nestedAssetDataOffset
|
||||
// + 32 (nestedAssetData len)
|
||||
// + nestedAssetDataElementOffset
|
||||
// + 32 (nestedAssetDataElement len)
|
||||
let nestedAssetDataElementContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, add(nestedAssetDataElementOffset, 104)))
|
||||
let nestedAssetDataElementContentsStart := add(
|
||||
assetDataOffset,
|
||||
add(
|
||||
nestedAssetDataOffset,
|
||||
add(nestedAssetDataElementOffset, 100)
|
||||
)
|
||||
)
|
||||
|
||||
// Load length of `nestedAssetData[i]`
|
||||
let nestedAssetDataElementLenStart := sub(nestedAssetDataElementContentsStart, 32)
|
||||
|
83
contracts/asset-proxy/contracts/src/StaticCallProxy.sol
Normal file
83
contracts/asset-proxy/contracts/src/StaticCallProxy.sol
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
|
||||
|
||||
// solhint-disable no-unused-vars
|
||||
contract StaticCallProxy {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
// Id of this proxy.
|
||||
bytes4 constant internal PROXY_ID = bytes4(keccak256("StaticCall(address,bytes,bytes32)"));
|
||||
|
||||
/// @dev Makes a staticcall to a target address and verifies that the data returned matches the expected return data.
|
||||
/// @param assetData Byte array encoded with staticCallTarget, staticCallData, and expectedCallResultHash
|
||||
/// @param from This value is ignored.
|
||||
/// @param to This value is ignored.
|
||||
/// @param amount This value is ignored.
|
||||
function transferFrom(
|
||||
bytes calldata assetData,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
)
|
||||
external
|
||||
view
|
||||
{
|
||||
// Decode params from `assetData`
|
||||
(
|
||||
address staticCallTarget,
|
||||
bytes memory staticCallData,
|
||||
bytes32 expectedReturnDataHash
|
||||
) = abi.decode(
|
||||
assetData.sliceDestructive(4, assetData.length),
|
||||
(address, bytes, bytes32)
|
||||
);
|
||||
|
||||
// Execute staticcall
|
||||
(bool success, bytes memory returnData) = staticCallTarget.staticcall(staticCallData);
|
||||
|
||||
// Revert with returned data if staticcall is unsuccessful
|
||||
if (!success) {
|
||||
assembly {
|
||||
revert(add(returnData, 32), mload(returnData))
|
||||
}
|
||||
}
|
||||
|
||||
// Revert if hash of return data is not as expected
|
||||
bytes32 returnDataHash = keccak256(returnData);
|
||||
require(
|
||||
expectedReturnDataHash == returnDataHash,
|
||||
"UNEXPECTED_STATIC_CALL_RESULT"
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
/// @return Proxy id.
|
||||
function getProxyId()
|
||||
external
|
||||
pure
|
||||
returns (bytes4)
|
||||
{
|
||||
return PROXY_ID;
|
||||
}
|
||||
}
|
@@ -26,19 +26,33 @@ pragma experimental ABIEncoderV2;
|
||||
// This argument is ABI encoded as one of the methods of this interface.
|
||||
interface IAssetData {
|
||||
|
||||
function ERC20Token(address tokenContract)
|
||||
function ERC20Token(address tokenAddress)
|
||||
external;
|
||||
|
||||
function ERC721Token(
|
||||
address tokenContract,
|
||||
address tokenAddress,
|
||||
uint256 tokenId
|
||||
)
|
||||
external;
|
||||
|
||||
function ERC1155Assets(
|
||||
address tokenAddress,
|
||||
uint256[] calldata tokenIds,
|
||||
uint256[] calldata tokenValues,
|
||||
bytes calldata callbackData
|
||||
)
|
||||
external;
|
||||
|
||||
function MultiAsset(
|
||||
uint256[] calldata amounts,
|
||||
bytes[] calldata nestedAssetData
|
||||
)
|
||||
external;
|
||||
|
||||
|
||||
function StaticCall(
|
||||
address callTarget,
|
||||
bytes calldata staticCallData,
|
||||
bytes32 callResultHash
|
||||
)
|
||||
external;
|
||||
}
|
||||
|
@@ -21,9 +21,8 @@ pragma solidity ^0.5.5;
|
||||
import "./IAuthorizable.sol";
|
||||
|
||||
|
||||
contract IAssetProxy is
|
||||
IAuthorizable
|
||||
{
|
||||
contract IAssetProxy {
|
||||
|
||||
/// @dev Transfers assets. Either succeeds or throws.
|
||||
/// @param assetData Byte array encoded for the respective asset proxy.
|
||||
/// @param from Address to transfer asset from.
|
||||
|
@@ -1,420 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
||||
|
||||
|
||||
library LibAssetData {
|
||||
bytes4 constant public ERC20_PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
|
||||
bytes4 constant public ERC721_PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
|
||||
bytes4 constant public ERC1155_PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)"));
|
||||
bytes4 constant public MULTI_ASSET_PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
|
||||
|
||||
/// @dev Returns the owner's balance of the token(s) specified in
|
||||
/// assetData. When the asset data contains multiple tokens (eg in
|
||||
/// ERC1155 or Multi-Asset), the return value indicates how many
|
||||
/// complete "baskets" of those tokens are owned by owner.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @return Number of tokens (or token baskets) held by owner.
|
||||
function getBalance(address owner, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
if (proxyId == ERC20_PROXY_ID) {
|
||||
address tokenAddress = LibBytes.readAddress(assetData, 16);
|
||||
return IERC20Token(tokenAddress).balanceOf(owner);
|
||||
} else if (proxyId == ERC721_PROXY_ID) {
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
return getERC721TokenOwner(tokenAddress, tokenId) == owner ? 1 : 0;
|
||||
} else if (proxyId == ERC1155_PROXY_ID) {
|
||||
uint256 lowestTokenBalance = 0;
|
||||
(
|
||||
,
|
||||
address tokenAddress,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory tokenValues,
|
||||
) = decodeERC1155AssetData(assetData);
|
||||
for (uint256 i = 0; i < tokenIds.length; i++) {
|
||||
uint256 tokenBalance = IERC1155(tokenAddress).balanceOf(owner, tokenIds[i]) / tokenValues[i];
|
||||
if (tokenBalance < lowestTokenBalance || lowestTokenBalance == 0) {
|
||||
lowestTokenBalance = tokenBalance;
|
||||
}
|
||||
}
|
||||
return lowestTokenBalance;
|
||||
} else if (proxyId == MULTI_ASSET_PROXY_ID) {
|
||||
uint256 lowestAssetBalance = 0;
|
||||
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
for (uint256 i = 0; i < nestedAssetData.length; i++) {
|
||||
uint256 assetBalance = getBalance(owner, nestedAssetData[i]) / assetAmounts[i];
|
||||
if (assetBalance < lowestAssetBalance || lowestAssetBalance == 0) {
|
||||
lowestAssetBalance = assetBalance;
|
||||
}
|
||||
}
|
||||
return lowestAssetBalance;
|
||||
} else {
|
||||
revert("UNSUPPORTED_PROXY_IDENTIFIER");
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() for each element of assetData.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param assetData Array of token descriptors, each encoded per the
|
||||
/// AssetProxy contract specification.
|
||||
/// @return Array of token balances from getBalance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalances(address owner, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory balances)
|
||||
{
|
||||
balances = new uint256[](assetData.length);
|
||||
for (uint256 i = 0; i < assetData.length; i++) {
|
||||
balances[i] = getBalance(owner, assetData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Returns the number of token(s) (described by assetData) that
|
||||
/// spender is authorized to spend. When the asset data contains
|
||||
/// multiple tokens (eg for Multi-Asset), the return value indicates
|
||||
/// how many complete "baskets" of those tokens may be spent by spender.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param spender Address whose authority to spend is in question.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @return Number of tokens (or token baskets) that the spender is
|
||||
/// authorized to spend.
|
||||
function getAllowance(address owner, address spender, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 allowance)
|
||||
{
|
||||
bytes4 proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
|
||||
if (proxyId == ERC20_PROXY_ID) {
|
||||
address tokenAddress = LibBytes.readAddress(assetData, 16);
|
||||
return IERC20Token(tokenAddress).allowance(owner, spender);
|
||||
} else if (proxyId == ERC721_PROXY_ID) {
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
IERC721Token token = IERC721Token(tokenAddress);
|
||||
if (spender == token.getApproved(tokenId) || token.isApprovedForAll(owner, spender)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (proxyId == ERC1155_PROXY_ID) {
|
||||
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
|
||||
if (IERC1155(tokenAddress).isApprovedForAll(owner, spender)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (proxyId == MULTI_ASSET_PROXY_ID) {
|
||||
uint256 lowestAssetAllowance = 0;
|
||||
// solhint-disable-next-line indent
|
||||
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
for (uint256 i = 0; i < nestedAssetData.length; i++) {
|
||||
uint256 assetAllowance = getAllowance(owner, spender, nestedAssetData[i]) / amounts[i];
|
||||
if (assetAllowance < lowestAssetAllowance || lowestAssetAllowance == 0) {
|
||||
lowestAssetAllowance = assetAllowance;
|
||||
}
|
||||
}
|
||||
return lowestAssetAllowance;
|
||||
} else {
|
||||
revert("UNSUPPORTED_PROXY_IDENTIFIER");
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Calls getAllowance() for each element of assetData.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param spender Address whose authority to spend is in question.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @return An array of token allowances from getAllowance(), with each
|
||||
/// element corresponding to the same-indexed element in the assetData
|
||||
/// input.
|
||||
function getBatchAllowances(address owner, address spender, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory allowances)
|
||||
{
|
||||
allowances = new uint256[](assetData.length);
|
||||
for (uint256 i = 0; i < assetData.length; i++) {
|
||||
allowances[i] = getAllowance(owner, spender, assetData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() and getAllowance() for assetData.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param spender Address whose authority to spend is in question.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @return Number of tokens (or token baskets) held by owner, and number
|
||||
/// of tokens (or token baskets) that the spender is authorized to
|
||||
/// spend.
|
||||
function getBalanceAndAllowance(address owner, address spender, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 balance, uint256 allowance)
|
||||
{
|
||||
balance = getBalance(owner, assetData);
|
||||
allowance = getAllowance(owner, spender, assetData);
|
||||
}
|
||||
|
||||
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element
|
||||
/// of assetData.
|
||||
/// @param owner Owner of the tokens specified by assetData.
|
||||
/// @param spender Address whose authority to spend is in question.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @return An array of token balances from getBalance(), and an array of
|
||||
/// token allowances from getAllowance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalancesAndAllowances(address owner, address spender, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory balances, uint256[] memory allowances)
|
||||
{
|
||||
balances = getBatchBalances(owner, assetData);
|
||||
allowances = getBatchAllowances(owner, spender, assetData);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-20 asset data into the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param tokenAddress The address of the ERC-20 contract hosting the
|
||||
/// token to be traded.
|
||||
/// @return AssetProxy-compliant data describing the asset.
|
||||
function encodeERC20AssetData(address tokenAddress)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
return abi.encodeWithSelector(ERC20_PROXY_ID, tokenAddress);
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-20 asset data from the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-20
|
||||
/// asset.
|
||||
/// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20
|
||||
/// contract hosting this asset.
|
||||
function decodeERC20AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 proxyId,
|
||||
address tokenAddress
|
||||
)
|
||||
{
|
||||
proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
|
||||
require(proxyId == ERC20_PROXY_ID, "WRONG_PROXY_ID");
|
||||
|
||||
tokenAddress = LibBytes.readAddress(assetData, 16);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-721 asset data into the format described in the
|
||||
/// AssetProxy specification.
|
||||
/// @param tokenAddress The address of the ERC-721 contract hosting the
|
||||
/// token to be traded.
|
||||
/// @param tokenId The identifier of the specific token to be traded.
|
||||
/// @return AssetProxy-compliant asset data describing the asset.
|
||||
function encodeERC721AssetData(
|
||||
address tokenAddress,
|
||||
uint256 tokenId
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
return abi.encodeWithSelector(ERC721_PROXY_ID, tokenAddress, tokenId);
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-721 asset data from the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-721
|
||||
/// asset.
|
||||
/// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
|
||||
/// contract hosting this asset, and the identifier of the specific
|
||||
/// token to be traded.
|
||||
function decodeERC721AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 proxyId,
|
||||
address tokenAddress,
|
||||
uint256 tokenId
|
||||
)
|
||||
{
|
||||
proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
|
||||
require(proxyId == ERC721_PROXY_ID, "WRONG_PROXY_ID");
|
||||
|
||||
tokenAddress = LibBytes.readAddress(assetData, 16);
|
||||
tokenId = LibBytes.readUint256(assetData, 36);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-1155 asset data into the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param tokenAddress The address of the ERC-1155 contract hosting the
|
||||
/// token(s) to be traded.
|
||||
/// @param tokenIds The identifiers of the specific tokens to be traded.
|
||||
/// @param tokenValues The amounts of each token to be traded.
|
||||
/// @param callbackData ...
|
||||
/// @return AssetProxy-compliant asset data describing the set of assets.
|
||||
function encodeERC1155AssetData(
|
||||
address tokenAddress,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory tokenValues,
|
||||
bytes memory callbackData
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
return abi.encodeWithSelector(ERC1155_PROXY_ID, tokenAddress, tokenIds, tokenValues, callbackData);
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-1155 asset data from the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-1155
|
||||
/// set of assets.
|
||||
/// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
|
||||
/// contract hosting the assets, an array of the identifiers of the
|
||||
/// tokens to be traded, an array of token amounts to be traded, and
|
||||
/// callback data. Each element of the arrays corresponds to the
|
||||
/// same-indexed element of the other array. Return values specified as
|
||||
/// `memory` are returned as pointers to locations within the memory of
|
||||
/// the input parameter `assetData`.
|
||||
function decodeERC1155AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 proxyId,
|
||||
address tokenAddress,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory tokenValues,
|
||||
bytes memory callbackData
|
||||
)
|
||||
{
|
||||
proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
|
||||
require(proxyId == ERC1155_PROXY_ID, "WRONG_PROXY_ID");
|
||||
|
||||
assembly {
|
||||
// Skip selector and length to get to the first parameter:
|
||||
assetData := add(assetData, 36)
|
||||
// Read the value of the first parameter:
|
||||
tokenAddress := mload(assetData)
|
||||
// Point to the next parameter's data:
|
||||
tokenIds := add(assetData, mload(add(assetData, 32)))
|
||||
// Point to the next parameter's data:
|
||||
tokenValues := add(assetData, mload(add(assetData, 64)))
|
||||
// Point to the next parameter's data:
|
||||
callbackData := add(assetData, mload(add(assetData, 96)))
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Encode data for multiple assets, per the AssetProxy contract
|
||||
/// specification.
|
||||
/// @param amounts The amounts of each asset to be traded.
|
||||
/// @param nestedAssetData AssetProxy-compliant data describing each asset
|
||||
/// to be traded.
|
||||
/// @return AssetProxy-compliant data describing the set of assets.
|
||||
function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
assetData = abi.encodeWithSelector(MULTI_ASSET_PROXY_ID, amounts, nestedAssetData);
|
||||
}
|
||||
|
||||
/// @dev Decode multi-asset data from the format described in the
|
||||
/// AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant data describing a multi-asset
|
||||
/// basket.
|
||||
/// @return The Multi-Asset AssetProxy identifier, an array of the amounts
|
||||
/// of the assets to be traded, and an array of the
|
||||
/// AssetProxy-compliant data describing each asset to be traded. Each
|
||||
/// element of the arrays corresponds to the same-indexed element of
|
||||
/// the other array.
|
||||
function decodeMultiAssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 proxyId,
|
||||
uint256[] memory amounts,
|
||||
bytes[] memory nestedAssetData
|
||||
)
|
||||
{
|
||||
proxyId = LibBytes.readBytes4(assetData, 0);
|
||||
|
||||
require(proxyId == MULTI_ASSET_PROXY_ID, "WRONG_PROXY_ID");
|
||||
|
||||
// solhint-disable-next-line indent
|
||||
(amounts, nestedAssetData) = abi.decode(LibBytes.slice(assetData, 4, assetData.length), (uint256[], bytes[]));
|
||||
}
|
||||
|
||||
/// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
|
||||
/// @param token Address of ERC721 token.
|
||||
/// @param tokenId The identifier for the specific NFT.
|
||||
/// @return Owner of tokenId or null address if unowned.
|
||||
function getERC721TokenOwner(address token, uint256 tokenId)
|
||||
public
|
||||
view
|
||||
returns (address owner)
|
||||
{
|
||||
assembly {
|
||||
// load free memory pointer
|
||||
let cdStart := mload(64)
|
||||
|
||||
// bytes4(keccak256(ownerOf(uint256))) = 0x6352211e
|
||||
mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)
|
||||
mstore(add(cdStart, 4), tokenId)
|
||||
|
||||
// staticcall `ownerOf(tokenId)`
|
||||
// `ownerOf` will revert if tokenId is not owned
|
||||
let success := staticcall(
|
||||
gas, // forward all gas
|
||||
token, // call token contract
|
||||
cdStart, // start of calldata
|
||||
36, // length of input is 36 bytes
|
||||
cdStart, // write output over input
|
||||
32 // size of output is 32 bytes
|
||||
)
|
||||
|
||||
// Success implies that tokenId is owned
|
||||
// Copy owner from return data if successful
|
||||
if success {
|
||||
owner := mload(cdStart)
|
||||
}
|
||||
}
|
||||
|
||||
// Owner initialized to address(0), no need to modify if call is unsuccessful
|
||||
return owner;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
|
||||
|
||||
contract LibAssetProxyIds {
|
||||
|
||||
// AssetProxy Ids are equiavalent the first 4 bytes of the keccak256 hash of the function signature assigned to each AssetProxy.
|
||||
|
||||
// ERC20Token(address)
|
||||
bytes4 constant public ERC20_PROXY_ID = 0xf47261b0;
|
||||
|
||||
// ERC721Token(address,uint256)
|
||||
bytes4 constant public ERC721_PROXY_ID = 0x02571792;
|
||||
|
||||
// ERC1155Assets(address,uint256[],uint256[],bytes)
|
||||
bytes4 constant public ERC1155_PROXY_ID = 0xa7cb5fb7;
|
||||
|
||||
// MultiAsset(uint256[],bytes[])
|
||||
bytes4 constant public MULTI_ASSET_PROXY_ID = 0x94cfcdd7;
|
||||
|
||||
// StaticCall(address,bytes,bytes32)
|
||||
bytes4 constant public STATIC_CALL_PROXY_ID = 0xc339d10a;
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
|
||||
|
||||
contract TestStaticCallTarget {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
uint256 internal _state;
|
||||
|
||||
function updateState()
|
||||
external
|
||||
{
|
||||
_state++;
|
||||
}
|
||||
|
||||
function assertEvenNumber(uint256 target)
|
||||
external
|
||||
pure
|
||||
{
|
||||
require(
|
||||
target % 2 == 0,
|
||||
"TARGET_NOT_EVEN"
|
||||
);
|
||||
}
|
||||
|
||||
function isOddNumber(uint256 target)
|
||||
external
|
||||
pure
|
||||
returns (bool isOdd)
|
||||
{
|
||||
isOdd = target % 2 == 1;
|
||||
return isOdd;
|
||||
}
|
||||
|
||||
function noInputFunction()
|
||||
external
|
||||
pure
|
||||
{
|
||||
assert(msg.data.length == 4 && msg.data.readBytes4(0) == bytes4(keccak256("noInputFunction()")));
|
||||
}
|
||||
|
||||
function dynamicInputFunction(bytes calldata a)
|
||||
external
|
||||
pure
|
||||
{
|
||||
bytes memory abiEncodedData = abi.encodeWithSignature("dynamicInputFunction(bytes)", a);
|
||||
assert(msg.data.equals(abiEncodedData));
|
||||
}
|
||||
|
||||
function returnComplexType(uint256 a, uint256 b)
|
||||
external
|
||||
view
|
||||
returns (bytes memory result)
|
||||
{
|
||||
result = abi.encodePacked(
|
||||
address(this),
|
||||
a,
|
||||
b
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-asset-proxy",
|
||||
"version": "2.1.2",
|
||||
"version": "2.2.8",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -34,7 +34,7 @@
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|LibAssetData|MixinAuthorizable|MultiAssetProxy).json",
|
||||
"abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy|StaticCallProxy|TestStaticCallTarget).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
@@ -47,20 +47,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,17 +69,18 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-erc1155": "^1.1.2",
|
||||
"@0x/contracts-erc20": "^2.2.1",
|
||||
"@0x/contracts-erc721": "^2.1.2",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/order-utils": "^8.0.0",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.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": {
|
||||
|
@@ -11,17 +11,19 @@ import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
|
||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
|
||||
import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
|
||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
|
||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
|
||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
|
||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
|
||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
|
||||
import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json';
|
||||
export const artifacts = {
|
||||
LibAssetData: LibAssetData as ContractArtifact,
|
||||
ERC1155Proxy: ERC1155Proxy as ContractArtifact,
|
||||
ERC20Proxy: ERC20Proxy as ContractArtifact,
|
||||
ERC721Proxy: ERC721Proxy as ContractArtifact,
|
||||
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
|
||||
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
||||
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
||||
IAssetData: IAssetData as ContractArtifact,
|
||||
IAssetProxy: IAssetProxy as ContractArtifact,
|
||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||
TestStaticCallTarget: TestStaticCallTarget as ContractArtifact,
|
||||
};
|
||||
|
@@ -9,6 +9,7 @@ export * from '../generated-wrappers/erc721_proxy';
|
||||
export * from '../generated-wrappers/i_asset_data';
|
||||
export * from '../generated-wrappers/i_asset_proxy';
|
||||
export * from '../generated-wrappers/i_authorizable';
|
||||
export * from '../generated-wrappers/lib_asset_data';
|
||||
export * from '../generated-wrappers/mixin_authorizable';
|
||||
export * from '../generated-wrappers/multi_asset_proxy';
|
||||
export * from '../generated-wrappers/static_call_proxy';
|
||||
export * from '../generated-wrappers/test_static_call_target';
|
||||
|
@@ -37,6 +37,7 @@ describe('Authorizable', () => {
|
||||
artifacts.MixinAuthorizable,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,426 +0,0 @@
|
||||
// TODO: change test titles to say "... from asset data"
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
|
||||
import {
|
||||
artifacts as erc1155Artifacts,
|
||||
ERC1155MintableContract,
|
||||
ERC1155TransferSingleEventArgs,
|
||||
IERC1155MintableContract,
|
||||
} from '@0x/contracts-erc1155';
|
||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract, IERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { artifacts as erc721Artifacts, DummyERC721TokenContract, IERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { artifacts, LibAssetDataContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
const KNOWN_ERC20_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
};
|
||||
const KNOWN_ERC721_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenId: new BigNumber(1),
|
||||
assetData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
};
|
||||
const KNOWN_ERC1155_ENCODING = {
|
||||
tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
|
||||
tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
|
||||
callbackData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
assetData:
|
||||
'0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
const KNOWN_MULTI_ASSET_ENCODING = {
|
||||
amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
|
||||
nestedAssetData: [
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
KNOWN_ERC721_ENCODING.assetData,
|
||||
KNOWN_ERC1155_ENCODING.assetData,
|
||||
],
|
||||
assetData:
|
||||
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
|
||||
describe('LibAssetData', () => {
|
||||
let libAssetData: LibAssetDataContract;
|
||||
|
||||
let tokenOwnerAddress: string;
|
||||
let approvedSpenderAddress: string;
|
||||
let anotherApprovedSpenderAddress: string;
|
||||
|
||||
let erc20TokenAddress: string;
|
||||
const erc20TokenTotalSupply = new BigNumber(1);
|
||||
|
||||
let erc721TokenAddress: string;
|
||||
const firstERC721TokenId = new BigNumber(1);
|
||||
const numberOfERC721Tokens = 10;
|
||||
|
||||
let erc1155MintableAddress: string;
|
||||
let erc1155TokenId: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
|
||||
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibAssetData,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
|
||||
[
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
anotherApprovedSpenderAddress,
|
||||
] = await web3Wrapper.getAvailableAddressesAsync();
|
||||
|
||||
erc20TokenAddress = (await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
new BigNumber(1),
|
||||
erc20TokenTotalSupply,
|
||||
)).address;
|
||||
|
||||
const erc721TokenContract = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||
erc721Artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
);
|
||||
erc721TokenAddress = erc721TokenContract.address;
|
||||
// mint `numberOfERC721Tokens` tokens
|
||||
const transactionMinedPromises = [];
|
||||
for (let i = 0; i < numberOfERC721Tokens; i++) {
|
||||
transactionMinedPromises.push(
|
||||
web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc721TokenContract.mint.sendTransactionAsync(
|
||||
tokenOwnerAddress,
|
||||
firstERC721TokenId.plus(i - 1),
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
),
|
||||
);
|
||||
}
|
||||
await Promise.all(transactionMinedPromises);
|
||||
|
||||
const erc1155MintableContract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
||||
erc1155Artifacts.ERC1155Mintable,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
erc1155MintableAddress = erc1155MintableContract.address;
|
||||
// Somewhat re-inventing the wheel here, but the prior art currently
|
||||
// exists only as an unexported test util in the erc1155 package
|
||||
// (Erc1155Wrapper.mintFungibleTokensAsync() in erc1155/test/utils/).
|
||||
// This is concise enough to justify duplication, but it sure is ugly.
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion
|
||||
erc1155TokenId = ((await new LogDecoder(web3Wrapper, erc1155Artifacts).getTxWithDecodedLogsAsync(
|
||||
await erc1155MintableContract.create.sendTransactionAsync('uri:Dummy', /*isNonFungible:*/ false),
|
||||
)).logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await erc1155MintableContract.mintFungible.sendTransactionAsync(
|
||||
erc1155TokenId,
|
||||
[tokenOwnerAddress],
|
||||
[new BigNumber(1)],
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
});
|
||||
|
||||
async function setERC20AllowanceAsync(): Promise<any> {
|
||||
return web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await new IERC20TokenContract(
|
||||
erc20Artifacts.IERC20Token.compilerOutput.abi,
|
||||
erc20TokenAddress,
|
||||
provider,
|
||||
).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
}
|
||||
|
||||
async function setERC721AllowanceAsync(): Promise<any> {
|
||||
return web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await new IERC721TokenContract(
|
||||
erc721Artifacts.IERC721Token.compilerOutput.abi,
|
||||
erc721TokenAddress,
|
||||
provider,
|
||||
).approve.sendTransactionAsync(approvedSpenderAddress, new BigNumber(1), { from: tokenOwnerAddress }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
}
|
||||
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
it('should have a deployed-to address', () => {
|
||||
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
|
||||
});
|
||||
|
||||
it('should encode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
);
|
||||
});
|
||||
|
||||
it('should decode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.ERC20,
|
||||
KNOWN_ERC20_ENCODING.address,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC721 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeERC721AssetData.callAsync(
|
||||
KNOWN_ERC721_ENCODING.address,
|
||||
KNOWN_ERC721_ENCODING.tokenId,
|
||||
),
|
||||
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC721 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC721AssetData.callAsync(KNOWN_ERC721_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.ERC721,
|
||||
KNOWN_ERC721_ENCODING.address,
|
||||
KNOWN_ERC721_ENCODING.tokenId,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeERC1155AssetData.callAsync(
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
),
|
||||
).to.equal(KNOWN_ERC1155_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC1155 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC1155AssetData.callAsync(KNOWN_ERC1155_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.ERC1155,
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeMultiAssetData.callAsync(
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
),
|
||||
).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode multiasset data', async () => {
|
||||
expect(await libAssetData.decodeMultiAssetData.callAsync(KNOWN_MULTI_ASSET_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.MultiAsset,
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should query ERC20 balance by asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.getBalance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
),
|
||||
).to.bignumber.equal(erc20TokenTotalSupply);
|
||||
});
|
||||
|
||||
it('should query ERC721 balance by asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.getBalance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC1155 balances by asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.getBalance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
await libAssetData.encodeERC1155AssetData.callAsync(
|
||||
erc1155MintableAddress,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)], // token values
|
||||
'0x', // callback data
|
||||
),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query multi-asset batch balance by asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.getBalance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
await libAssetData.encodeMultiAssetData.callAsync(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
],
|
||||
),
|
||||
),
|
||||
).to.bignumber.equal(Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens));
|
||||
});
|
||||
|
||||
it('should query ERC20 allowances by asset data', async () => {
|
||||
await setERC20AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC721 approval by asset data', async () => {
|
||||
await setERC721AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC721 approvalForAll by assetData', async () => {
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await new IERC721TokenContract(
|
||||
erc721Artifacts.IERC721Token.compilerOutput.abi,
|
||||
erc721TokenAddress,
|
||||
provider,
|
||||
).setApprovalForAll.sendTransactionAsync(anotherApprovedSpenderAddress, true, {
|
||||
from: tokenOwnerAddress,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
expect(
|
||||
await libAssetData.getAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
anotherApprovedSpenderAddress,
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC1155 allowances by asset data', async () => {
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await new IERC1155MintableContract(
|
||||
erc1155Artifacts.IERC1155Mintable.compilerOutput.abi,
|
||||
erc1155MintableAddress,
|
||||
provider,
|
||||
).setApprovalForAll.sendTransactionAsync(approvedSpenderAddress, true, { from: tokenOwnerAddress }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
expect(
|
||||
await libAssetData.getAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
await libAssetData.encodeERC1155AssetData.callAsync(
|
||||
erc1155MintableAddress,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
'0x',
|
||||
),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query multi-asset allowances by asset data', async () => {
|
||||
await setERC20AllowanceAsync();
|
||||
await setERC721AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
await libAssetData.encodeMultiAssetData.callAsync(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
],
|
||||
),
|
||||
),
|
||||
).to.bignumber.equal(1);
|
||||
return;
|
||||
});
|
||||
|
||||
it('should query balances for a batch of asset data strings', async () => {
|
||||
expect(
|
||||
await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
]),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
|
||||
});
|
||||
|
||||
it('should query allowances for a batch of asset data strings', async () => {
|
||||
await setERC20AllowanceAsync();
|
||||
await setERC721AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
await libAssetData.encodeERC721AssetData.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
]),
|
||||
).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
|
||||
});
|
||||
|
||||
describe('getERC721TokenOwner', async () => {
|
||||
it('should return the null address when tokenId is not owned', async () => {
|
||||
const nonexistentTokenId = new BigNumber(1234567890);
|
||||
expect(
|
||||
await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, nonexistentTokenId),
|
||||
).to.be.equal(constants.NULL_ADDRESS);
|
||||
});
|
||||
it('should return the owner address when tokenId is owned', async () => {
|
||||
expect(
|
||||
await libAssetData.getERC721TokenOwner.callAsync(erc721TokenAddress, firstERC721TokenId),
|
||||
).to.be.equal(tokenOwnerAddress);
|
||||
});
|
||||
});
|
||||
|
||||
it('should query balance and allowance together, from asset data', async () => {
|
||||
await setERC20AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getBalanceAndAllowance.callAsync(
|
||||
tokenOwnerAddress,
|
||||
approvedSpenderAddress,
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
|
||||
});
|
||||
|
||||
it('should query balances and allowances together, from an asset data array', async () => {
|
||||
await setERC20AllowanceAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchBalancesAndAllowances.callAsync(tokenOwnerAddress, approvedSpenderAddress, [
|
||||
await libAssetData.encodeERC20AssetData.callAsync(erc20TokenAddress),
|
||||
]),
|
||||
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [new BigNumber(1)]]);
|
||||
});
|
||||
});
|
@@ -23,7 +23,7 @@ import {
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { RevertReason } from '@0x/types';
|
||||
import { AssetProxyId, RevertReason } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
@@ -31,6 +31,7 @@ import * as _ from 'lodash';
|
||||
|
||||
import {
|
||||
artifacts,
|
||||
ERC1155ProxyContract,
|
||||
ERC1155ProxyWrapper,
|
||||
ERC20ProxyContract,
|
||||
ERC20Wrapper,
|
||||
@@ -44,16 +45,8 @@ import {
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
const assetProxyInterface = new IAssetProxyContract(
|
||||
artifacts.IAssetProxy.compilerOutput.abi,
|
||||
constants.NULL_ADDRESS,
|
||||
provider,
|
||||
);
|
||||
const assetDataInterface = new IAssetDataContract(
|
||||
artifacts.IAssetData.compilerOutput.abi,
|
||||
constants.NULL_ADDRESS,
|
||||
provider,
|
||||
);
|
||||
const assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
|
||||
const assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
|
||||
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
describe('Asset Transfer Proxies', () => {
|
||||
@@ -79,7 +72,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
let erc721AFromTokenId: BigNumber;
|
||||
let erc721BFromTokenId: BigNumber;
|
||||
|
||||
let erc1155Proxy: ERC721ProxyContract;
|
||||
let erc1155Proxy: ERC1155ProxyContract;
|
||||
let erc1155ProxyWrapper: ERC1155ProxyWrapper;
|
||||
let erc1155Contract: ERC1155MintableContract;
|
||||
let erc1155Contract2: ERC1155MintableContract;
|
||||
@@ -108,6 +101,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
artifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
// Configure ERC20Proxy
|
||||
@@ -180,6 +174,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
erc20Artifacts.DummyNoReturnERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
@@ -189,6 +184,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
erc20Artifacts.DummyMultipleReturnERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
@@ -199,6 +195,9 @@ describe('Asset Transfer Proxies', () => {
|
||||
await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
|
||||
fromAddress,
|
||||
constants.INITIAL_ERC20_BALANCE,
|
||||
{
|
||||
from: owner,
|
||||
},
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await noReturnErc20Token.approve.awaitTransactionSuccessAsync(
|
||||
@@ -210,6 +209,9 @@ describe('Asset Transfer Proxies', () => {
|
||||
await multipleReturnErc20Token.setBalance.awaitTransactionSuccessAsync(
|
||||
fromAddress,
|
||||
constants.INITIAL_ERC20_BALANCE,
|
||||
{
|
||||
from: owner,
|
||||
},
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await multipleReturnErc20Token.approve.awaitTransactionSuccessAsync(
|
||||
@@ -225,6 +227,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
erc721Artifacts.DummyERC721Receiver,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
await erc721Wrapper.setBalancesAndAllowancesAsync();
|
||||
@@ -1331,7 +1334,7 @@ describe('Asset Transfer Proxies', () => {
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
|
||||
const amounts = [erc20Amount, erc721Amount];
|
||||
const nestedAssetData = [erc20AssetData, erc721AssetData];
|
||||
const extraData = '0102030405060708';
|
||||
const extraData = '0102030405060708090001020304050607080900010203040506070809000102';
|
||||
const assetData = `${assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData)}${extraData}`;
|
||||
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetData,
|
||||
@@ -1626,6 +1629,120 @@ describe('Asset Transfer Proxies', () => {
|
||||
RevertReason.SenderNotAuthorized,
|
||||
);
|
||||
});
|
||||
it('should revert if asset data overflows beyond the bounds of calldata', async () => {
|
||||
const inputAmount = new BigNumber(1);
|
||||
const erc20Amount = new BigNumber(10);
|
||||
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
|
||||
const erc721Amount = new BigNumber(1);
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
|
||||
const amounts = [erc20Amount, erc721Amount];
|
||||
const nestedAssetData = [erc20AssetData, erc721AssetData];
|
||||
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
|
||||
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetData,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
inputAmount,
|
||||
);
|
||||
// append asset data to end of tx data with a length of 0x300 bytes, which will extend past actual calldata.
|
||||
const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080';
|
||||
const invalidOffsetToAssetData = '00000000000000000000000000000000000000000000000000000000000002a0';
|
||||
const newAssetData = '0000000000000000000000000000000000000000000000000000000000000304';
|
||||
const badData = `${data.replace(offsetToAssetData, invalidOffsetToAssetData)}${newAssetData}`;
|
||||
// execute transfer
|
||||
await expectTransactionFailedAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
to: multiAssetProxy.address,
|
||||
data: badData,
|
||||
from: authorized,
|
||||
}),
|
||||
RevertReason.InvalidAssetDataEnd,
|
||||
);
|
||||
});
|
||||
it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => {
|
||||
const inputAmount = new BigNumber(1);
|
||||
const erc20Amount = new BigNumber(10);
|
||||
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
|
||||
const erc721Amount = new BigNumber(1);
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
|
||||
const amounts = [erc20Amount, erc721Amount];
|
||||
const nestedAssetData = [erc20AssetData, erc721AssetData];
|
||||
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
|
||||
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetData,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
inputAmount,
|
||||
);
|
||||
const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080';
|
||||
const invalidOffsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000400';
|
||||
const badData = data.replace(offsetToAssetData, invalidOffsetToAssetData);
|
||||
// execute transfer
|
||||
// note that this triggers `InvalidAssetDataLength` because the length is zero, otherwise it would
|
||||
// trigger `InvalidAssetDataEnd`.
|
||||
await expectTransactionFailedAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
to: multiAssetProxy.address,
|
||||
data: badData,
|
||||
from: authorized,
|
||||
}),
|
||||
RevertReason.InvalidAssetDataLength,
|
||||
);
|
||||
});
|
||||
it('should revert if length of assetData, excluding the selector, is not a multiple of 32', async () => {
|
||||
// setup test parameters
|
||||
const inputAmount = new BigNumber(1);
|
||||
const erc20Amount = new BigNumber(10);
|
||||
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
|
||||
const erc721Amount = new BigNumber(1);
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
|
||||
const amounts = [erc20Amount, erc721Amount];
|
||||
const nestedAssetData = [erc20AssetData, erc721AssetData];
|
||||
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData);
|
||||
const extraData = '01';
|
||||
const assetDataWithExtraData = `${assetData}${extraData}`;
|
||||
const badData = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetDataWithExtraData,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
inputAmount,
|
||||
);
|
||||
// execute transfer
|
||||
await expectTransactionFailedAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
to: multiAssetProxy.address,
|
||||
data: badData,
|
||||
from: authorized,
|
||||
}),
|
||||
RevertReason.InvalidAssetDataLength,
|
||||
);
|
||||
});
|
||||
it('should revert if length of assetData is less than 68 bytes', async () => {
|
||||
// setup test parameters
|
||||
const inputAmount = new BigNumber(1);
|
||||
// we'll construct asset data that has a 4 byte selector plus
|
||||
// 32 byte payload. This results in asset data that is 36 bytes
|
||||
// long and will trigger the `invalid length` error.
|
||||
// we must be sure to use a # of bytes that is still %32
|
||||
// so that we know the error is not triggered by another check in the code.
|
||||
const zeros32Bytes = '0'.repeat(64);
|
||||
const assetData36Bytes = `${AssetProxyId.MultiAsset}${zeros32Bytes}`;
|
||||
const badData = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetData36Bytes,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
inputAmount,
|
||||
);
|
||||
// execute transfer
|
||||
await expectTransactionFailedAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
to: multiAssetProxy.address,
|
||||
data: badData,
|
||||
from: authorized,
|
||||
}),
|
||||
RevertReason.InvalidAssetDataLength,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
242
contracts/asset-proxy/test/static_call_proxy.ts
Normal file
242
contracts/asset-proxy/test/static_call_proxy.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
import {
|
||||
chaiSetup,
|
||||
constants,
|
||||
expectTransactionFailedAsync,
|
||||
expectTransactionFailedWithoutReasonAsync,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { AssetProxyId, RevertReason } from '@0x/types';
|
||||
import { AbiEncoder, BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import { artifacts, IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('StaticCallProxy', () => {
|
||||
const amount = constants.ZERO_AMOUNT;
|
||||
let fromAddress: string;
|
||||
let toAddress: string;
|
||||
|
||||
let staticCallProxy: IAssetProxyContract;
|
||||
let staticCallTarget: TestStaticCallTargetContract;
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
[fromAddress, toAddress] = accounts.slice(0, 2);
|
||||
const staticCallProxyWithoutTransferFrom = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.StaticCallProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
staticCallProxy = new IAssetProxyContract(staticCallProxyWithoutTransferFrom.address, provider, txDefaults);
|
||||
staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestStaticCallTarget,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
describe('general', () => {
|
||||
it('should revert if undefined function is called', async () => {
|
||||
const undefinedSelector = '0x01020304';
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
from: fromAddress,
|
||||
to: staticCallProxy.address,
|
||||
value: constants.ZERO_AMOUNT,
|
||||
data: undefinedSelector,
|
||||
}),
|
||||
);
|
||||
});
|
||||
it('should have an id of 0xc339d10a', async () => {
|
||||
const proxyId = await staticCallProxy.getProxyId.callAsync();
|
||||
const expectedProxyId = AssetProxyId.StaticCall;
|
||||
expect(proxyId).to.equal(expectedProxyId);
|
||||
});
|
||||
});
|
||||
describe('transferFrom', () => {
|
||||
it('should revert if assetData lies outside the bounds of calldata', async () => {
|
||||
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
const txData = staticCallProxy.transferFrom.getABIEncodedTransactionData(
|
||||
assetData,
|
||||
fromAddress,
|
||||
toAddress,
|
||||
amount,
|
||||
);
|
||||
const offsetToAssetData = '0000000000000000000000000000000000000000000000000000000000000080';
|
||||
const txDataEndBuffer = ethUtil.toBuffer((txData.length - 2) / 2 - 4);
|
||||
const paddedTxDataEndBuffer = ethUtil.setLengthLeft(txDataEndBuffer, 32);
|
||||
const invalidOffsetToAssetData = ethUtil.bufferToHex(paddedTxDataEndBuffer).slice(2);
|
||||
const newAssetData = '0000000000000000000000000000000000000000000000000000000000000304';
|
||||
const badTxData = `${txData.replace(offsetToAssetData, invalidOffsetToAssetData)}${newAssetData}`;
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
web3Wrapper.sendTransactionAsync({
|
||||
to: staticCallProxy.address,
|
||||
from: fromAddress,
|
||||
data: badTxData,
|
||||
}),
|
||||
);
|
||||
});
|
||||
it('should revert if the length of assetData is less than 100 bytes', async () => {
|
||||
const staticCallData = constants.NULL_BYTES;
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||
.slice(0, -128);
|
||||
const assetDataByteLen = (assetData.length - 2) / 2;
|
||||
expect((assetDataByteLen - 4) % 32).to.equal(0);
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
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 expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
|
||||
const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
|
||||
const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
|
||||
const invalidOffsetToStaticCallData = ethUtil.bufferToHex(paddedAssetDataEndBuffer).slice(2);
|
||||
const newStaticCallData = '0000000000000000000000000000000000000000000000000000000000000304';
|
||||
const badAssetData = `${assetData.replace(
|
||||
offsetToStaticCallData,
|
||||
invalidOffsetToStaticCallData,
|
||||
)}${newStaticCallData}`;
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
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 expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await expectTransactionFailedWithoutReasonAsync(
|
||||
staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
|
||||
);
|
||||
});
|
||||
it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
|
||||
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await expectTransactionFailedAsync(
|
||||
staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
|
||||
RevertReason.TargetNotEven,
|
||||
);
|
||||
});
|
||||
it('should revert if the hash of the output is different than expected expected', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await expectTransactionFailedAsync(
|
||||
staticCallProxy.transferFrom.sendTransactionAsync(assetData, fromAddress, toAddress, amount),
|
||||
RevertReason.UnexpectedStaticCallResult,
|
||||
);
|
||||
});
|
||||
it('should be successful if a function call with no inputs and no outputs is successful', async () => {
|
||||
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
|
||||
});
|
||||
it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => {
|
||||
const staticCallData = '0x0102030405060708';
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash);
|
||||
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
|
||||
});
|
||||
it('should be successful if a function call with one static input returns the correct value', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
|
||||
});
|
||||
it('should be successful if a function with one dynamic input is successful', async () => {
|
||||
const dynamicInput = '0x0102030405060708';
|
||||
const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput);
|
||||
const expectedResultHash = constants.KECCAK256_NULL;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
|
||||
});
|
||||
it('should be successful if a function call returns a complex type', async () => {
|
||||
const a = new BigNumber(1);
|
||||
const b = new BigNumber(2);
|
||||
const staticCallData = staticCallTarget.returnComplexType.getABIEncodedTransactionData(a, b);
|
||||
const abiEncoder = new AbiEncoder.DynamicBytes({
|
||||
name: '',
|
||||
type: 'bytes',
|
||||
});
|
||||
const aHex = '0000000000000000000000000000000000000000000000000000000000000001';
|
||||
const bHex = '0000000000000000000000000000000000000000000000000000000000000002';
|
||||
const expectedResults = `${staticCallTarget.address}${aHex}${bHex}`;
|
||||
const offset = '0000000000000000000000000000000000000000000000000000000000000020';
|
||||
const encodedExpectedResultWithOffset = `0x${offset}${abiEncoder.encode(expectedResults).slice(2)}`;
|
||||
const expectedResultHash = ethUtil.bufferToHex(
|
||||
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
|
||||
);
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
|
||||
});
|
||||
});
|
||||
});
|
@@ -36,11 +36,7 @@ export class ERC1155ProxyWrapper {
|
||||
const allArtifacts = _.merge(artifacts, erc1155Artifacts);
|
||||
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
|
||||
this._dummyTokenWrappers = [];
|
||||
this._assetProxyInterface = new IAssetProxyContract(
|
||||
artifacts.IAssetProxy.compilerOutput.abi,
|
||||
constants.NULL_ADDRESS,
|
||||
provider,
|
||||
);
|
||||
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
|
||||
this._tokenOwnerAddresses = tokenOwnerAddresses;
|
||||
this._contractOwnerAddress = contractOwnerAddress;
|
||||
this._fungibleTokenIds = [];
|
||||
@@ -58,6 +54,7 @@ export class ERC1155ProxyWrapper {
|
||||
erc1155Artifacts.ERC1155Mintable,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._provider, this._contractOwnerAddress);
|
||||
this._dummyTokenWrappers.push(erc1155Wrapper);
|
||||
@@ -73,6 +70,7 @@ export class ERC1155ProxyWrapper {
|
||||
artifacts.ERC1155Proxy,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
|
||||
return this._proxyContract;
|
||||
@@ -84,6 +82,66 @@ export class ERC1155ProxyWrapper {
|
||||
this._validateProxyContractExistsOrThrow();
|
||||
return this._proxyIdIfExists as string;
|
||||
}
|
||||
/**
|
||||
* @dev generates abi-encoded tx data for transferring erc1155 fungible/non-fungible tokens.
|
||||
* @param from source address
|
||||
* @param to destination address
|
||||
* @param contractAddress address of erc155 contract
|
||||
* @param tokensToTransfer array of erc1155 tokens to transfer
|
||||
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
|
||||
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
|
||||
* @param receiverCallbackData callback data if `to` is a contract
|
||||
* @param authorizedSender sender of `transferFrom` transaction
|
||||
* @param extraData extra data to append to `transferFrom` transaction. Optional.
|
||||
* @return abi encoded tx data.
|
||||
*/
|
||||
public getTransferFromAbiEncodedTxData(
|
||||
from: string,
|
||||
to: string,
|
||||
contractAddress: string,
|
||||
tokensToTransfer: BigNumber[],
|
||||
valuesToTransfer: BigNumber[],
|
||||
valueMultiplier: BigNumber,
|
||||
receiverCallbackData: string,
|
||||
authorizedSender: string,
|
||||
assetData_?: string,
|
||||
): string {
|
||||
this._validateProxyContractExistsOrThrow();
|
||||
const assetData =
|
||||
assetData_ === undefined
|
||||
? assetDataUtils.encodeERC1155AssetData(
|
||||
contractAddress,
|
||||
tokensToTransfer,
|
||||
valuesToTransfer,
|
||||
receiverCallbackData,
|
||||
)
|
||||
: assetData_;
|
||||
const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
assetData,
|
||||
from,
|
||||
to,
|
||||
valueMultiplier,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* @dev transfers erc1155 fungible/non-fungible tokens.
|
||||
* @param txData: abi-encoded tx data
|
||||
* @param authorizedSender sender of `transferFrom` transaction
|
||||
*/
|
||||
public async transferFromRawAsync(
|
||||
txData: string,
|
||||
authorizedSender: string,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txHash = await this._web3Wrapper.sendTransactionAsync({
|
||||
to: (this._proxyContract as ERC1155ProxyContract).address,
|
||||
data: txData,
|
||||
from: authorizedSender,
|
||||
gas: 300000,
|
||||
});
|
||||
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return txReceipt;
|
||||
}
|
||||
/**
|
||||
* @dev transfers erc1155 fungible/non-fungible tokens.
|
||||
* @param from source address
|
||||
@@ -106,20 +164,20 @@ export class ERC1155ProxyWrapper {
|
||||
valueMultiplier: BigNumber,
|
||||
receiverCallbackData: string,
|
||||
authorizedSender: string,
|
||||
extraData?: string,
|
||||
): Promise<string> {
|
||||
assetData_?: string,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
this._validateProxyContractExistsOrThrow();
|
||||
let encodedAssetData = assetDataUtils.encodeERC1155AssetData(
|
||||
contractAddress,
|
||||
tokensToTransfer,
|
||||
valuesToTransfer,
|
||||
receiverCallbackData,
|
||||
);
|
||||
if (extraData !== undefined) {
|
||||
encodedAssetData = `${encodedAssetData}${extraData}`;
|
||||
}
|
||||
const assetData =
|
||||
assetData_ === undefined
|
||||
? assetDataUtils.encodeERC1155AssetData(
|
||||
contractAddress,
|
||||
tokensToTransfer,
|
||||
valuesToTransfer,
|
||||
receiverCallbackData,
|
||||
)
|
||||
: assetData_;
|
||||
const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
|
||||
encodedAssetData,
|
||||
assetData,
|
||||
from,
|
||||
to,
|
||||
valueMultiplier,
|
||||
@@ -128,46 +186,9 @@ export class ERC1155ProxyWrapper {
|
||||
to: (this._proxyContract as ERC1155ProxyContract).address,
|
||||
data,
|
||||
from: authorizedSender,
|
||||
gas: 300000,
|
||||
});
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* @dev transfers erc1155 fungible/non-fungible tokens.
|
||||
* @param from source address
|
||||
* @param to destination address
|
||||
* @param contractAddress address of erc155 contract
|
||||
* @param tokensToTransfer array of erc1155 tokens to transfer
|
||||
* @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
|
||||
* @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
|
||||
* @param receiverCallbackData callback data if `to` is a contract
|
||||
* @param authorizedSender sender of `transferFrom` transaction
|
||||
* @param extraData extra data to append to `transferFrom` transaction. Optional.
|
||||
* @return tranasction receipt with decoded logs.
|
||||
*/
|
||||
public async transferFromWithLogsAsync(
|
||||
from: string,
|
||||
to: string,
|
||||
contractAddress: string,
|
||||
tokensToTransfer: BigNumber[],
|
||||
valuesToTransfer: BigNumber[],
|
||||
valueMultiplier: BigNumber,
|
||||
receiverCallbackData: string,
|
||||
authorizedSender: string,
|
||||
extraData?: string,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
|
||||
await this.transferFromAsync(
|
||||
from,
|
||||
to,
|
||||
contractAddress,
|
||||
tokensToTransfer,
|
||||
valuesToTransfer,
|
||||
valueMultiplier,
|
||||
receiverCallbackData,
|
||||
authorizedSender,
|
||||
extraData,
|
||||
),
|
||||
);
|
||||
const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
|
||||
return txReceipt;
|
||||
}
|
||||
/**
|
||||
|
@@ -37,6 +37,7 @@ export class ERC20Wrapper {
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
decimals,
|
||||
@@ -51,6 +52,7 @@ export class ERC20Wrapper {
|
||||
artifacts.ERC20Proxy,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
|
||||
return this._proxyContract;
|
||||
|
@@ -29,6 +29,7 @@ export class ERC721Wrapper {
|
||||
erc721Artifacts.DummyERC721Token,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
),
|
||||
@@ -41,6 +42,7 @@ export class ERC721Wrapper {
|
||||
artifacts.ERC721Proxy,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
|
||||
return this._proxyContract;
|
||||
|
@@ -9,9 +9,10 @@
|
||||
"generated-artifacts/IAssetData.json",
|
||||
"generated-artifacts/IAssetProxy.json",
|
||||
"generated-artifacts/IAuthorizable.json",
|
||||
"generated-artifacts/LibAssetData.json",
|
||||
"generated-artifacts/MixinAuthorizable.json",
|
||||
"generated-artifacts/MultiAssetProxy.json"
|
||||
"generated-artifacts/MultiAssetProxy.json",
|
||||
"generated-artifacts/StaticCallProxy.json",
|
||||
"generated-artifacts/TestStaticCallTarget.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
||||
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.0.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.0.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.0.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.0.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564607468
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "2.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557799313,
|
||||
"version": "2.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "2.0.1",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.0.13 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.12 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.11 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.10 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.9 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.0.8 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.7 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.6 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.5 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.4 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.3 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.2 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.0.1 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## Coordinator
|
||||
|
||||
This package contains a contract that allows users to call arbitrary functions on the Exchange contract with permission from one or more Coordinators. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains a contract that allows users to call arbitrary functions on the Exchange contract with permission from one or more Coordinators. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-coordinator --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-coordinator",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.13",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -47,20 +47,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,18 +69,18 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-asset-proxy": "^2.1.2",
|
||||
"@0x/contracts-erc20": "^2.2.1",
|
||||
"@0x/contracts-exchange": "1.0.2",
|
||||
"@0x/contracts-exchange-libs": "^2.1.2",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/order-utils": "^8.0.0",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-asset-proxy": "^2.2.8",
|
||||
"@0x/contracts-erc20": "^2.2.14",
|
||||
"@0x/contracts-exchange": "^2.1.14",
|
||||
"@0x/contracts-exchange-libs": "^3.0.8",
|
||||
"@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"
|
||||
},
|
||||
|
@@ -74,6 +74,7 @@ describe('Coordinator tests', () => {
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
assetDataUtils.encodeERC20AssetData(zrxToken.address),
|
||||
);
|
||||
|
||||
@@ -91,6 +92,7 @@ describe('Coordinator tests', () => {
|
||||
artifacts.Coordinator,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
exchange.address,
|
||||
);
|
||||
|
||||
|
@@ -25,6 +25,7 @@ describe('Libs tests', () => {
|
||||
artifacts.Coordinator,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
exchangeAddress,
|
||||
);
|
||||
});
|
||||
|
@@ -44,6 +44,7 @@ describe('Mixins tests', () => {
|
||||
artifacts.Coordinator,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
exchangeAddress,
|
||||
);
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
@@ -103,8 +104,7 @@ describe('Mixins tests', () => {
|
||||
transaction.signature.length - 2,
|
||||
)}${illegalSignatureByte}`;
|
||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
||||
expectContractCallFailedAsync(
|
||||
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
||||
expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
|
||||
RevertReason.SignatureIllegal,
|
||||
);
|
||||
});
|
||||
@@ -114,8 +114,7 @@ describe('Mixins tests', () => {
|
||||
const invalidSignatureByte = ethUtil.toBuffer(SignatureType.Invalid).toString('hex');
|
||||
transaction.signature = `0x${invalidSignatureByte}`;
|
||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
||||
expectContractCallFailedAsync(
|
||||
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
||||
expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
|
||||
RevertReason.SignatureInvalid,
|
||||
);
|
||||
});
|
||||
@@ -128,8 +127,7 @@ describe('Mixins tests', () => {
|
||||
transaction.signature.length - 2,
|
||||
)}${invalidSignatureByte}`;
|
||||
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
||||
expectContractCallFailedAsync(
|
||||
mixins.getSignerAddress.callAsync(transactionHash, transaction.signature),
|
||||
expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith(
|
||||
RevertReason.SignatureUnsupported,
|
||||
);
|
||||
});
|
||||
@@ -192,8 +190,7 @@ describe('Mixins tests', () => {
|
||||
});
|
||||
it('should revert if data is less than 4 bytes long', async () => {
|
||||
const data = '0x010203';
|
||||
await expectContractCallFailedAsync(
|
||||
mixins.decodeOrdersFromFillData.callAsync(data),
|
||||
expect(mixins.decodeOrdersFromFillData.callAsync(data)).to.be.rejectedWith(
|
||||
RevertReason.LibBytesGreaterOrEqualTo4LengthRequired,
|
||||
);
|
||||
});
|
||||
|
@@ -24,6 +24,7 @@ export class CoordinatorRegistryWrapper {
|
||||
artifacts.CoordinatorRegistry,
|
||||
this._provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
if (this._coordinatorRegistryContract === undefined) {
|
||||
throw new Error(`Failed to deploy Coordinator Registry contract.`);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { artifacts, IExchangeContract } from '@0x/contracts-exchange';
|
||||
import { IExchangeContract } from '@0x/contracts-exchange';
|
||||
import { constants as devConstants, provider } from '@0x/contracts-test-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
|
||||
@@ -6,11 +6,7 @@ import { constants } from './index';
|
||||
|
||||
export const exchangeDataEncoder = {
|
||||
encodeOrdersToExchangeData(fnName: string, orders: SignedOrder[]): string {
|
||||
const exchangeInstance = new IExchangeContract(
|
||||
artifacts.IExchange.compilerOutput.abi,
|
||||
devConstants.NULL_ADDRESS,
|
||||
provider,
|
||||
);
|
||||
const exchangeInstance = new IExchangeContract(devConstants.NULL_ADDRESS, provider);
|
||||
let data;
|
||||
if (constants.SINGLE_FILL_FN_NAMES.indexOf(fnName) !== -1) {
|
||||
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
|
||||
|
122
contracts/dev-utils/CHANGELOG.json
Normal file
122
contracts/dev-utils/CHANGELOG.json
Normal file
@@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "0.0.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "0.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "0.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "0.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1564607468,
|
||||
"version": "0.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564604963
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "0.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "0.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "0.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "0.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Create dev-utils package",
|
||||
"pr": 1848
|
||||
},
|
||||
{
|
||||
"note": "Add `LibAssetData` and `LibTransactionDecoder` contracts",
|
||||
"pr": 1848
|
||||
},
|
||||
{
|
||||
"note": "Refactor `LibAssetData` to only check 0x-specific allowances",
|
||||
"pr": 1848
|
||||
},
|
||||
{
|
||||
"note": "Refactor `LibAssetData` balance/allowance checks to never revert",
|
||||
"pr": 1848
|
||||
},
|
||||
{
|
||||
"note": "Refactor `OrderValidationUtils` to calculate `fillableTakerAssetAmount`",
|
||||
"pr": 1848
|
||||
},
|
||||
{
|
||||
"note": "Add support for StaticCallProxy",
|
||||
"pr": 1863
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
55
contracts/dev-utils/CHANGELOG.md
Normal file
55
contracts/dev-utils/CHANGELOG.md
Normal file
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.0.10 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.9 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.8 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.7 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.6 - _July 31, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.5 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v0.0.5 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.4 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.3 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.2 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.0.1 - _Invalid date_
|
||||
|
||||
* Create dev-utils package (#1848)
|
||||
* Add `LibAssetData` and `LibTransactionDecoder` contracts (#1848)
|
||||
* Refactor `LibAssetData` to only check 0x-specific allowances (#1848)
|
||||
* Refactor `LibAssetData` balance/allowance checks to never revert (#1848)
|
||||
* Refactor `OrderValidationUtils` to calculate `fillableTakerAssetAmount` (#1848)
|
||||
* Add support for StaticCallProxy (#1863)
|
1
contracts/dev-utils/DEPLOYS.json
Normal file
1
contracts/dev-utils/DEPLOYS.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
73
contracts/dev-utils/README.md
Normal file
73
contracts/dev-utils/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
## Dev-Utils
|
||||
|
||||
This package implements various utilities for developers. For example, the `DevUtils` contract can query batches of balances or allowances given some `assetData`, can validate batches of orders, and can decode 0x-specific calldata. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
**Install**
|
||||
|
||||
```bash
|
||||
npm install @0x/contracts-dev-utils --save
|
||||
```
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-extensions yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0x/contracts-extensions yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
#### Testing options
|
||||
|
||||
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
32
contracts/dev-utils/compiler.json
Normal file
32
contracts/dev-utils/compiler.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"artifactsDir": "./generated-artifacts",
|
||||
"contractsDir": "./contracts",
|
||||
"useDockerisedSolc": false,
|
||||
"isOfflineMode": false,
|
||||
"compilerSettings": {
|
||||
"evmVersion": "constantinople",
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000000,
|
||||
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contracts": [
|
||||
"src/DevUtils.sol",
|
||||
"src/LibAssetData.sol",
|
||||
"src/LibTransactionDecoder.sol",
|
||||
"src/EthBalanceChecker.sol"
|
||||
]
|
||||
}
|
37
contracts/dev-utils/contracts/src/DevUtils.sol
Normal file
37
contracts/dev-utils/contracts/src/DevUtils.sol
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./OrderValidationUtils.sol";
|
||||
import "./LibTransactionDecoder.sol";
|
||||
import "./EthBalanceChecker.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract DevUtils is
|
||||
OrderValidationUtils,
|
||||
LibTransactionDecoder,
|
||||
EthBalanceChecker
|
||||
{
|
||||
constructor (address _exchange, bytes memory _zrxAssetData)
|
||||
public
|
||||
OrderValidationUtils(_exchange, _zrxAssetData)
|
||||
{}
|
||||
}
|
39
contracts/dev-utils/contracts/src/EthBalanceChecker.sol
Normal file
39
contracts/dev-utils/contracts/src/EthBalanceChecker.sol
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
|
||||
|
||||
contract EthBalanceChecker {
|
||||
|
||||
/// @dev Batch fetches ETH balances
|
||||
/// @param addresses Array of addresses.
|
||||
/// @return Array of ETH balances.
|
||||
function getEthBalances(address[] memory addresses)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
uint256[] memory balances = new uint256[](addresses.length);
|
||||
for (uint256 i = 0; i != addresses.length; i++) {
|
||||
balances[i] = addresses[i].balance;
|
||||
}
|
||||
return balances;
|
||||
}
|
||||
|
||||
}
|
541
contracts/dev-utils/contracts/src/LibAssetData.sol
Normal file
541
contracts/dev-utils/contracts/src/LibAssetData.sol
Normal file
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-asset-proxy/contracts/src/libs/LibAssetProxyIds.sol";
|
||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||
|
||||
|
||||
contract LibAssetData is
|
||||
LibAssetProxyIds
|
||||
{
|
||||
// 2^256 - 1
|
||||
uint256 constant internal _MAX_UINT256 = uint256(-1);
|
||||
|
||||
// ERC20 selectors
|
||||
bytes4 constant internal _ERC20_BALANCE_OF_SELECTOR = 0x70a08231;
|
||||
bytes4 constant internal _ERC20_ALLOWANCE_SELECTOR = 0xdd62ed3e;
|
||||
|
||||
// ERC721 selectors
|
||||
bytes4 constant internal _ERC721_OWNER_OF_SELECTOR = 0x6352211e;
|
||||
bytes4 constant internal _ERC721_IS_APPROVED_FOR_ALL_SELECTOR = 0xe985e9c5;
|
||||
bytes4 constant internal _ERC721_GET_APPROVED_SELECTOR = 0x081812fc;
|
||||
|
||||
// ERC1155 selectors
|
||||
bytes4 constant internal _ERC1155_BALANCE_OF_SELECTOR = 0x00fdd58e;
|
||||
bytes4 constant internal _ERC1155_IS_APPROVED_FOR_ALL_SELECTOR = 0xe985e9c5;
|
||||
|
||||
// `transferFrom` selector for all AssetProxy contracts
|
||||
bytes4 constant internal _ASSET_PROXY_TRANSFER_FROM_SELECTOR = 0xa85e59e4;
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
// solhint-disable var-name-mixedcase
|
||||
IExchange internal _EXCHANGE;
|
||||
address internal _ERC20_PROXY_ADDRESS;
|
||||
address internal _ERC721_PROXY_ADDRESS;
|
||||
address internal _ERC1155_PROXY_ADDRESS;
|
||||
address internal _STATIC_CALL_PROXY_ADDRESS;
|
||||
// solhint-enable var-name-mixedcase
|
||||
|
||||
constructor (address _exchange)
|
||||
public
|
||||
{
|
||||
_EXCHANGE = IExchange(_exchange);
|
||||
_ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC20_PROXY_ID);
|
||||
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC721_PROXY_ID);
|
||||
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(ERC1155_PROXY_ID);
|
||||
_STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(STATIC_CALL_PROXY_ID);
|
||||
}
|
||||
|
||||
/// @dev Returns the owner's balance of the assets(s) specified in
|
||||
/// assetData. When the asset data contains multiple assets (eg in
|
||||
/// ERC1155 or Multi-Asset), the return value indicates how many
|
||||
/// complete "baskets" of those assets are owned by owner.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) held by owner.
|
||||
function getBalance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
// Get id of AssetProxy contract
|
||||
bytes4 assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
if (assetProxyId == ERC20_PROXY_ID) {
|
||||
// Get ERC20 token address
|
||||
address tokenAddress = assetData.readAddress(16);
|
||||
|
||||
// Encode data for `balanceOf(ownerAddress)`
|
||||
bytes memory balanceOfData = abi.encodeWithSelector(_ERC20_BALANCE_OF_SELECTOR, ownerAddress);
|
||||
|
||||
// Query balance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
|
||||
balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
} else if (assetProxyId == ERC721_PROXY_ID) {
|
||||
// Get ERC721 token address and id
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
|
||||
// Check if id is owned by ownerAddress
|
||||
balance = getERC721TokenOwner(tokenAddress, tokenId) == ownerAddress ? 1 : 0;
|
||||
} else if (assetProxyId == ERC1155_PROXY_ID) {
|
||||
// Get ERC1155 token address, array of ids, and array of values
|
||||
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
|
||||
|
||||
uint256 length = tokenIds.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
|
||||
bytes memory balanceOfData = abi.encodeWithSelector(
|
||||
_ERC1155_BALANCE_OF_SELECTOR,
|
||||
ownerAddress,
|
||||
tokenIds[i]
|
||||
);
|
||||
|
||||
// Query balance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
|
||||
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
|
||||
// Scale total balance down by corresponding value in assetData
|
||||
uint256 scaledBalance = totalBalance / tokenValues[i];
|
||||
if (scaledBalance < balance || balance == 0) {
|
||||
balance = scaledBalance;
|
||||
}
|
||||
}
|
||||
} else if (assetProxyId == STATIC_CALL_PROXY_ID) {
|
||||
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
|
||||
bytes memory transferFromData = abi.encodeWithSelector(
|
||||
_ASSET_PROXY_TRANSFER_FROM_SELECTOR,
|
||||
assetData,
|
||||
address(0), // `from` address is not used
|
||||
address(0), // `to` address is not used
|
||||
0 // `amount` is not used
|
||||
);
|
||||
|
||||
// Check if staticcall would be successful
|
||||
(bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
|
||||
|
||||
// Success means that the staticcall can be made an unlimited amount of times
|
||||
balance = success ? _MAX_UINT256 : 0;
|
||||
} else if (assetProxyId == MULTI_ASSET_PROXY_ID) {
|
||||
// Get array of values and array of assetDatas
|
||||
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
|
||||
uint256 length = nestedAssetData.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Query balance of individual assetData
|
||||
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
|
||||
|
||||
// Scale total balance down by corresponding value in assetData
|
||||
uint256 scaledBalance = totalBalance / assetAmounts[i];
|
||||
if (scaledBalance < balance || balance == 0) {
|
||||
balance = scaledBalance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Balance will be 0 if assetProxyId is unknown
|
||||
return balance;
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return Array of asset balances from getBalance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory balances)
|
||||
{
|
||||
uint256 length = assetData.length;
|
||||
balances = new uint256[](length);
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
balances[i] = getBalance(ownerAddress, assetData[i]);
|
||||
}
|
||||
return balances;
|
||||
}
|
||||
|
||||
/// @dev Returns the number of asset(s) (described by assetData) that
|
||||
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
|
||||
/// multiple assets (eg for Multi-Asset), the return value indicates
|
||||
/// how many complete "baskets" of those assets may be spent by all of the corresponding
|
||||
/// AssetProxy contracts.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
||||
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 allowance)
|
||||
{
|
||||
// Get id of AssetProxy contract
|
||||
bytes4 assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
if (assetProxyId == MULTI_ASSET_PROXY_ID) {
|
||||
// Get array of values and array of assetDatas
|
||||
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
|
||||
uint256 length = nestedAssetData.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Query allowance of individual assetData
|
||||
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
|
||||
|
||||
// Scale total allowance down by corresponding value in assetData
|
||||
uint256 scaledAllowance = totalAllowance / amounts[i];
|
||||
if (scaledAllowance < allowance || allowance == 0) {
|
||||
allowance = scaledAllowance;
|
||||
}
|
||||
}
|
||||
return allowance;
|
||||
}
|
||||
|
||||
if (assetProxyId == ERC20_PROXY_ID) {
|
||||
// Get ERC20 token address
|
||||
address tokenAddress = assetData.readAddress(16);
|
||||
|
||||
// Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
|
||||
bytes memory allowanceData = abi.encodeWithSelector(
|
||||
_ERC20_ALLOWANCE_SELECTOR,
|
||||
ownerAddress,
|
||||
_ERC20_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
// Query allowance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
|
||||
allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
} else if (assetProxyId == ERC721_PROXY_ID) {
|
||||
// Get ERC721 token address and id
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
|
||||
// Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
|
||||
bytes memory isApprovedForAllData = abi.encodeWithSelector(
|
||||
_ERC721_IS_APPROVED_FOR_ALL_SELECTOR,
|
||||
ownerAddress,
|
||||
_ERC721_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
|
||||
|
||||
// If not approved for all, call `getApproved(tokenId)`
|
||||
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
|
||||
// Encode data for `getApproved(tokenId)`
|
||||
bytes memory getApprovedData = abi.encodeWithSelector(_ERC721_GET_APPROVED_SELECTOR, tokenId);
|
||||
(success, returnData) = tokenAddress.staticcall(getApprovedData);
|
||||
|
||||
// Allowance is 1 if successful and the approved address is the ERC721Proxy
|
||||
allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
|
||||
} else {
|
||||
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
|
||||
allowance = _MAX_UINT256;
|
||||
}
|
||||
} else if (assetProxyId == ERC1155_PROXY_ID) {
|
||||
// Get ERC1155 token address
|
||||
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
|
||||
|
||||
// Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
|
||||
bytes memory isApprovedForAllData = abi.encodeWithSelector(
|
||||
_ERC1155_IS_APPROVED_FOR_ALL_SELECTOR,
|
||||
ownerAddress,
|
||||
_ERC1155_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
// Query allowance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
|
||||
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
|
||||
} else if (assetProxyId == STATIC_CALL_PROXY_ID) {
|
||||
// The StaticCallProxy does not require any approvals
|
||||
allowance = _MAX_UINT256;
|
||||
}
|
||||
|
||||
// Allowance will be 0 if the assetProxyId is unknown
|
||||
return allowance;
|
||||
}
|
||||
|
||||
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return An array of asset allowances from getAllowance(), with each
|
||||
/// element corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory allowances)
|
||||
{
|
||||
uint256 length = assetData.length;
|
||||
allowances = new uint256[](length);
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
|
||||
}
|
||||
return allowances;
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() and getAllowance() for assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) held by owner, and number
|
||||
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
||||
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 balance, uint256 allowance)
|
||||
{
|
||||
balance = getBalance(ownerAddress, assetData);
|
||||
allowance = getAssetProxyAllowance(ownerAddress, assetData);
|
||||
return (balance, allowance);
|
||||
}
|
||||
|
||||
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return An array of asset balances from getBalance(), and an array of
|
||||
/// asset allowances from getAllowance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256[] memory balances, uint256[] memory allowances)
|
||||
{
|
||||
balances = getBatchBalances(ownerAddress, assetData);
|
||||
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
|
||||
return (balances, allowances);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
|
||||
/// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
|
||||
/// @return AssetProxy-compliant data describing the asset.
|
||||
function encodeERC20AssetData(address tokenAddress)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
assetData = abi.encodeWithSelector(ERC20_PROXY_ID, tokenAddress);
|
||||
return assetData;
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
|
||||
/// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20
|
||||
/// contract hosting this asset.
|
||||
function decodeERC20AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 assetProxyId,
|
||||
address tokenAddress
|
||||
)
|
||||
{
|
||||
assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
require(
|
||||
assetProxyId == ERC20_PROXY_ID,
|
||||
"WRONG_PROXY_ID"
|
||||
);
|
||||
|
||||
tokenAddress = assetData.readAddress(16);
|
||||
return (assetProxyId, tokenAddress);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification.
|
||||
/// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded.
|
||||
/// @param tokenId The identifier of the specific asset to be traded.
|
||||
/// @return AssetProxy-compliant asset data describing the asset.
|
||||
function encodeERC721AssetData(address tokenAddress, uint256 tokenId)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
assetData = abi.encodeWithSelector(
|
||||
ERC721_PROXY_ID,
|
||||
tokenAddress,
|
||||
tokenId
|
||||
);
|
||||
return assetData;
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset.
|
||||
/// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
|
||||
/// contract hosting this asset, and the identifier of the specific
|
||||
/// asset to be traded.
|
||||
function decodeERC721AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 assetProxyId,
|
||||
address tokenAddress,
|
||||
uint256 tokenId
|
||||
)
|
||||
{
|
||||
assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
require(
|
||||
assetProxyId == ERC721_PROXY_ID,
|
||||
"WRONG_PROXY_ID"
|
||||
);
|
||||
|
||||
tokenAddress = assetData.readAddress(16);
|
||||
tokenId = assetData.readUint256(36);
|
||||
return (assetProxyId, tokenAddress, tokenId);
|
||||
}
|
||||
|
||||
/// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.
|
||||
/// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded.
|
||||
/// @param tokenIds The identifiers of the specific assets to be traded.
|
||||
/// @param tokenValues The amounts of each asset to be traded.
|
||||
/// @param callbackData Data to be passed to receiving contracts when a transfer is performed.
|
||||
/// @return AssetProxy-compliant asset data describing the set of assets.
|
||||
function encodeERC1155AssetData(
|
||||
address tokenAddress,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory tokenValues,
|
||||
bytes memory callbackData
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
assetData = abi.encodeWithSelector(
|
||||
ERC1155_PROXY_ID,
|
||||
tokenAddress,
|
||||
tokenIds,
|
||||
tokenValues,
|
||||
callbackData
|
||||
);
|
||||
return assetData;
|
||||
}
|
||||
|
||||
/// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets.
|
||||
/// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
|
||||
/// contract hosting the assets, an array of the identifiers of the
|
||||
/// assets to be traded, an array of asset amounts to be traded, and
|
||||
/// callback data. Each element of the arrays corresponds to the
|
||||
/// same-indexed element of the other array. Return values specified as
|
||||
/// `memory` are returned as pointers to locations within the memory of
|
||||
/// the input parameter `assetData`.
|
||||
function decodeERC1155AssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 assetProxyId,
|
||||
address tokenAddress,
|
||||
uint256[] memory tokenIds,
|
||||
uint256[] memory tokenValues,
|
||||
bytes memory callbackData
|
||||
)
|
||||
{
|
||||
assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
require(
|
||||
assetProxyId == ERC1155_PROXY_ID,
|
||||
"WRONG_PROXY_ID"
|
||||
);
|
||||
|
||||
assembly {
|
||||
// Skip selector and length to get to the first parameter:
|
||||
assetData := add(assetData, 36)
|
||||
// Read the value of the first parameter:
|
||||
tokenAddress := mload(assetData)
|
||||
// Point to the next parameter's data:
|
||||
tokenIds := add(assetData, mload(add(assetData, 32)))
|
||||
// Point to the next parameter's data:
|
||||
tokenValues := add(assetData, mload(add(assetData, 64)))
|
||||
// Point to the next parameter's data:
|
||||
callbackData := add(assetData, mload(add(assetData, 96)))
|
||||
}
|
||||
|
||||
return (
|
||||
assetProxyId,
|
||||
tokenAddress,
|
||||
tokenIds,
|
||||
tokenValues,
|
||||
callbackData
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Encode data for multiple assets, per the AssetProxy contract specification.
|
||||
/// @param amounts The amounts of each asset to be traded.
|
||||
/// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded.
|
||||
/// @return AssetProxy-compliant data describing the set of assets.
|
||||
function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory assetData)
|
||||
{
|
||||
assetData = abi.encodeWithSelector(
|
||||
MULTI_ASSET_PROXY_ID,
|
||||
amounts,
|
||||
nestedAssetData
|
||||
);
|
||||
return assetData;
|
||||
}
|
||||
|
||||
/// @dev Decode multi-asset data from the format described in the AssetProxy contract specification.
|
||||
/// @param assetData AssetProxy-compliant data describing a multi-asset basket.
|
||||
/// @return The Multi-Asset AssetProxy identifier, an array of the amounts
|
||||
/// of the assets to be traded, and an array of the
|
||||
/// AssetProxy-compliant data describing each asset to be traded. Each
|
||||
/// element of the arrays corresponds to the same-indexed element of the other array.
|
||||
function decodeMultiAssetData(bytes memory assetData)
|
||||
public
|
||||
pure
|
||||
returns (
|
||||
bytes4 assetProxyId,
|
||||
uint256[] memory amounts,
|
||||
bytes[] memory nestedAssetData
|
||||
)
|
||||
{
|
||||
assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
require(
|
||||
assetProxyId == MULTI_ASSET_PROXY_ID,
|
||||
"WRONG_PROXY_ID"
|
||||
);
|
||||
|
||||
// solhint-disable indent
|
||||
(amounts, nestedAssetData) = abi.decode(
|
||||
assetData.slice(4, assetData.length),
|
||||
(uint256[], bytes[])
|
||||
);
|
||||
// solhint-enable indent
|
||||
}
|
||||
|
||||
/// @dev Calls `asset.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned asset.
|
||||
/// @param tokenAddress Address of ERC721 asset.
|
||||
/// @param tokenId The identifier for the specific NFT.
|
||||
/// @return Owner of tokenId or null address if unowned.
|
||||
function getERC721TokenOwner(address tokenAddress, uint256 tokenId)
|
||||
public
|
||||
view
|
||||
returns (address ownerAddress)
|
||||
{
|
||||
bytes memory ownerOfCalldata = abi.encodeWithSelector(
|
||||
_ERC721_OWNER_OF_SELECTOR,
|
||||
tokenId
|
||||
);
|
||||
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
|
||||
|
||||
ownerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
|
||||
return ownerAddress;
|
||||
}
|
||||
}
|
193
contracts/dev-utils/contracts/src/LibTransactionDecoder.sol
Normal file
193
contracts/dev-utils/contracts/src/LibTransactionDecoder.sol
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibExchangeSelectors.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
|
||||
|
||||
contract LibTransactionDecoder is
|
||||
LibExchangeSelectors
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
/// @dev Decodes the call data for an Exchange contract method call.
|
||||
/// @param transactionData ABI-encoded calldata for an Exchange
|
||||
/// contract method call.
|
||||
/// @return The name of the function called, and the parameters it was
|
||||
/// given. For single-order fills and cancels, the arrays will have
|
||||
/// just one element.
|
||||
function decodeZeroExTransactionData(bytes memory transactionData)
|
||||
public
|
||||
pure
|
||||
returns(
|
||||
string memory functionName,
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
{
|
||||
bytes4 functionSelector = transactionData.readBytes4(0);
|
||||
|
||||
if (functionSelector == BATCH_CANCEL_ORDERS_SELECTOR) {
|
||||
functionName = "batchCancelOrders";
|
||||
} else if (functionSelector == BATCH_FILL_ORDERS_SELECTOR) {
|
||||
functionName = "batchFillOrders";
|
||||
} else if (functionSelector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR) {
|
||||
functionName = "batchFillOrdersNoThrow";
|
||||
} else if (functionSelector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR) {
|
||||
functionName = "batchFillOrKillOrders";
|
||||
} else if (functionSelector == CANCEL_ORDER_SELECTOR) {
|
||||
functionName = "cancelOrder";
|
||||
} else if (functionSelector == FILL_ORDER_SELECTOR) {
|
||||
functionName = "fillOrder";
|
||||
} else if (functionSelector == FILL_ORDER_NO_THROW_SELECTOR) {
|
||||
functionName = "fillOrderNoThrow";
|
||||
} else if (functionSelector == FILL_OR_KILL_ORDER_SELECTOR) {
|
||||
functionName = "fillOrKillOrder";
|
||||
} else if (functionSelector == MARKET_BUY_ORDERS_SELECTOR) {
|
||||
functionName = "marketBuyOrders";
|
||||
} else if (functionSelector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR) {
|
||||
functionName = "marketBuyOrdersNoThrow";
|
||||
} else if (functionSelector == MARKET_SELL_ORDERS_SELECTOR) {
|
||||
functionName = "marketSellOrders";
|
||||
} else if (functionSelector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR) {
|
||||
functionName = "marketSellOrdersNoThrow";
|
||||
} else if (functionSelector == MATCH_ORDERS_SELECTOR) {
|
||||
functionName = "matchOrders";
|
||||
} else if (
|
||||
functionSelector == CANCEL_ORDERS_UP_TO_SELECTOR ||
|
||||
functionSelector == EXECUTE_TRANSACTION_SELECTOR
|
||||
// TODO: add new noThrow cancel functions when https://github.com/0xProject/ZEIPs/issues/35 is merged.
|
||||
) {
|
||||
revert("UNIMPLEMENTED");
|
||||
} else {
|
||||
revert("UNKNOWN_FUNCTION_SELECTOR");
|
||||
}
|
||||
|
||||
if (functionSelector == BATCH_CANCEL_ORDERS_SELECTOR) {
|
||||
// solhint-disable-next-line indent
|
||||
orders = abi.decode(transactionData.slice(4, transactionData.length), (LibOrder.Order[]));
|
||||
takerAssetFillAmounts = new uint256[](0);
|
||||
signatures = new bytes[](0);
|
||||
} else if (
|
||||
functionSelector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR ||
|
||||
functionSelector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR ||
|
||||
functionSelector == BATCH_FILL_ORDERS_SELECTOR
|
||||
) {
|
||||
(orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForBatchFill(transactionData);
|
||||
} else if (functionSelector == CANCEL_ORDER_SELECTOR) {
|
||||
orders = new LibOrder.Order[](1);
|
||||
orders[0] = abi.decode(transactionData.slice(4, transactionData.length), (LibOrder.Order));
|
||||
takerAssetFillAmounts = new uint256[](0);
|
||||
signatures = new bytes[](0);
|
||||
} else if (
|
||||
functionSelector == FILL_OR_KILL_ORDER_SELECTOR ||
|
||||
functionSelector == FILL_ORDER_SELECTOR ||
|
||||
functionSelector == FILL_ORDER_NO_THROW_SELECTOR
|
||||
) {
|
||||
(orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForSingleOrderFill(transactionData);
|
||||
} else if (
|
||||
functionSelector == MARKET_BUY_ORDERS_SELECTOR ||
|
||||
functionSelector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR ||
|
||||
functionSelector == MARKET_SELL_ORDERS_SELECTOR ||
|
||||
functionSelector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR
|
||||
) {
|
||||
(orders, takerAssetFillAmounts, signatures) = _makeReturnValuesForMarketFill(transactionData);
|
||||
} else if (functionSelector == MATCH_ORDERS_SELECTOR) {
|
||||
(
|
||||
LibOrder.Order memory leftOrder,
|
||||
LibOrder.Order memory rightOrder,
|
||||
bytes memory leftSignature,
|
||||
bytes memory rightSignature
|
||||
) = abi.decode(
|
||||
transactionData.slice(4, transactionData.length),
|
||||
(LibOrder.Order, LibOrder.Order, bytes, bytes)
|
||||
);
|
||||
|
||||
orders = new LibOrder.Order[](2);
|
||||
orders[0] = leftOrder;
|
||||
orders[1] = rightOrder;
|
||||
|
||||
takerAssetFillAmounts = new uint256[](2);
|
||||
takerAssetFillAmounts[0] = leftOrder.takerAssetAmount;
|
||||
takerAssetFillAmounts[1] = rightOrder.takerAssetAmount;
|
||||
|
||||
signatures = new bytes[](2);
|
||||
signatures[0] = leftSignature;
|
||||
signatures[1] = rightSignature;
|
||||
}
|
||||
}
|
||||
|
||||
function _makeReturnValuesForSingleOrderFill(bytes memory transactionData)
|
||||
private
|
||||
pure
|
||||
returns(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
{
|
||||
orders = new LibOrder.Order[](1);
|
||||
takerAssetFillAmounts = new uint256[](1);
|
||||
signatures = new bytes[](1);
|
||||
// solhint-disable-next-line indent
|
||||
(orders[0], takerAssetFillAmounts[0], signatures[0]) = abi.decode(
|
||||
transactionData.slice(4, transactionData.length),
|
||||
(LibOrder.Order, uint256, bytes)
|
||||
);
|
||||
}
|
||||
|
||||
function _makeReturnValuesForBatchFill(bytes memory transactionData)
|
||||
private
|
||||
pure
|
||||
returns(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
{
|
||||
// solhint-disable-next-line indent
|
||||
(orders, takerAssetFillAmounts, signatures) = abi.decode(
|
||||
transactionData.slice(4, transactionData.length),
|
||||
// solhint-disable-next-line indent
|
||||
(LibOrder.Order[], uint256[], bytes[])
|
||||
);
|
||||
}
|
||||
|
||||
function _makeReturnValuesForMarketFill(bytes memory transactionData)
|
||||
private
|
||||
pure
|
||||
returns(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures
|
||||
)
|
||||
{
|
||||
takerAssetFillAmounts = new uint256[](1);
|
||||
// solhint-disable-next-line indent
|
||||
(orders, takerAssetFillAmounts[0], signatures) = abi.decode(
|
||||
transactionData.slice(4, transactionData.length),
|
||||
// solhint-disable-next-line indent
|
||||
(LibOrder.Order[], uint256, bytes[])
|
||||
);
|
||||
}
|
||||
}
|
184
contracts/dev-utils/contracts/src/OrderValidationUtils.sol
Normal file
184
contracts/dev-utils/contracts/src/OrderValidationUtils.sol
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "./LibAssetData.sol";
|
||||
|
||||
|
||||
contract OrderValidationUtils is
|
||||
LibAssetData,
|
||||
LibMath
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
// solhint-disable var-name-mixedcase
|
||||
bytes internal _ZRX_ASSET_DATA;
|
||||
// solhint-enable var-name-mixedcase
|
||||
|
||||
constructor (address _exchange, bytes memory _zrxAssetData)
|
||||
public
|
||||
LibAssetData(_exchange)
|
||||
{
|
||||
_ZRX_ASSET_DATA = _zrxAssetData;
|
||||
}
|
||||
|
||||
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
|
||||
/// @param order The order structure.
|
||||
/// @param signature Signature provided by maker that proves the order's authenticity.
|
||||
/// `0x01` can always be provided if the signature does not need to be validated.
|
||||
/// @return The orderInfo (hash, status, and `takerAssetAmount` already filled for the given order),
|
||||
/// fillableTakerAssetAmount (amount of the order's `takerAssetAmount` that is fillable given all on-chain state),
|
||||
/// and isValidSignature (validity of the provided signature).
|
||||
/// NOTE: If the `takerAssetData` encodes data for multiple assets, `fillableTakerAssetAmount` will represent a "scaled"
|
||||
/// amount, meaning it must be multiplied by all the individual asset amounts within the `takerAssetData` to get the final
|
||||
/// amount of each asset that can be filled.
|
||||
function getOrderRelevantState(LibOrder.Order memory order, bytes memory signature)
|
||||
public
|
||||
view
|
||||
returns (
|
||||
LibOrder.OrderInfo memory orderInfo,
|
||||
uint256 fillableTakerAssetAmount,
|
||||
bool isValidSignature
|
||||
)
|
||||
{
|
||||
// Get info specific to order
|
||||
orderInfo = _EXCHANGE.getOrderInfo(order);
|
||||
|
||||
// Validate the maker's signature
|
||||
address makerAddress = order.makerAddress;
|
||||
isValidSignature = _EXCHANGE.isValidSignature(
|
||||
orderInfo.orderHash,
|
||||
makerAddress,
|
||||
signature
|
||||
);
|
||||
|
||||
// Get the transferable amount of the `makerAsset`
|
||||
uint256 transferableMakerAssetAmount = getTransferableAssetAmount(makerAddress, order.makerAssetData);
|
||||
|
||||
// Assign to stack variables to reduce redundant mloads/sloads
|
||||
uint256 takerAssetAmount = order.takerAssetAmount;
|
||||
uint256 makerFee = order.makerFee;
|
||||
bytes memory zrxAssetData = _ZRX_ASSET_DATA;
|
||||
|
||||
// Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`,
|
||||
// and the total amounts specified in the order
|
||||
uint256 transferableTakerAssetAmount;
|
||||
if (order.makerAssetData.equals(zrxAssetData)) {
|
||||
// If `makerAsset` equals `makerFeeAsset`, the % that can be filled is
|
||||
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
||||
transferableTakerAssetAmount = getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
safeAdd(order.makerAssetAmount, makerFee),
|
||||
takerAssetAmount
|
||||
);
|
||||
} else {
|
||||
// Get the transferable amount of the `makerFeeAsset`
|
||||
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, zrxAssetData);
|
||||
|
||||
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
||||
if (makerFee == 0) {
|
||||
transferableTakerAssetAmount = getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
takerAssetAmount
|
||||
);
|
||||
|
||||
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
||||
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
||||
} else {
|
||||
uint256 transferableMakerToTakerAmount = getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
takerAssetAmount
|
||||
);
|
||||
uint256 transferableMakerFeeToTakerAmount = getPartialAmountFloor(
|
||||
transferableMakerFeeAssetAmount,
|
||||
makerFee,
|
||||
takerAssetAmount
|
||||
);
|
||||
transferableTakerAssetAmount = min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
|
||||
}
|
||||
}
|
||||
|
||||
// `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
|
||||
fillableTakerAssetAmount = min256(
|
||||
safeSub(takerAssetAmount, orderInfo.orderTakerAssetFilledAmount),
|
||||
transferableTakerAssetAmount
|
||||
);
|
||||
|
||||
return (orderInfo, fillableTakerAssetAmount, isValidSignature);
|
||||
}
|
||||
|
||||
/// @dev Fetches all order-relevant information needed to validate if the supplied orders are fillable.
|
||||
/// @param orders Array of order structures.
|
||||
/// @param signatures Array of signatures provided by makers that prove the authenticity of the orders.
|
||||
/// `0x01` can always be provided if a signature does not need to be validated.
|
||||
/// @return The ordersInfo (array of the hash, status, and `takerAssetAmount` already filled for each order),
|
||||
/// fillableTakerAssetAmounts (array of amounts for each order's `takerAssetAmount` that is fillable given all on-chain state),
|
||||
/// and isValidSignature (array containing the validity of each provided signature).
|
||||
/// NOTE: If the `takerAssetData` encodes data for multiple assets, each element of `fillableTakerAssetAmounts`
|
||||
/// will represent a "scaled" amount, meaning it must be multiplied by all the individual asset amounts within
|
||||
/// the `takerAssetData` to get the final amount of each asset that can be filled.
|
||||
function getOrderRelevantStates(LibOrder.Order[] memory orders, bytes[] memory signatures)
|
||||
public
|
||||
view
|
||||
returns (
|
||||
LibOrder.OrderInfo[] memory ordersInfo,
|
||||
uint256[] memory fillableTakerAssetAmounts,
|
||||
bool[] memory isValidSignature
|
||||
)
|
||||
{
|
||||
uint256 length = orders.length;
|
||||
ordersInfo = new LibOrder.OrderInfo[](length);
|
||||
fillableTakerAssetAmounts = new uint256[](length);
|
||||
isValidSignature = new bool[](length);
|
||||
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
(ordersInfo[i], fillableTakerAssetAmounts[i], isValidSignature[i]) = getOrderRelevantState(
|
||||
orders[i],
|
||||
signatures[i]
|
||||
);
|
||||
}
|
||||
|
||||
return (ordersInfo, fillableTakerAssetAmounts, isValidSignature);
|
||||
}
|
||||
|
||||
/// @dev Gets the amount of an asset transferable by the owner.
|
||||
/// @param ownerAddress Address of the owner of the asset.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract specification.
|
||||
/// @return The amount of the asset tranferable by the owner.
|
||||
/// NOTE: If the `assetData` encodes data for multiple assets, the `transferableAssetAmount`
|
||||
/// will represent the amount of times the entire `assetData` can be transferred. To calculate
|
||||
/// the total individual transferable amounts, this scaled `transferableAmount` must be multiplied by
|
||||
/// the individual asset amounts located within the `assetData`.
|
||||
function getTransferableAssetAmount(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
view
|
||||
returns (uint256 transferableAssetAmount)
|
||||
{
|
||||
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
|
||||
transferableAssetAmount = min256(balance, allowance);
|
||||
return transferableAssetAmount;
|
||||
}
|
||||
}
|
91
contracts/dev-utils/package.json
Normal file
91
contracts/dev-utils/package.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"name": "@0x/contracts-dev-utils",
|
||||
"version": "0.0.10",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "0x protocol specific utility contracts",
|
||||
"main": "lib/src/index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile generate_contract_wrappers",
|
||||
"test": "yarn run_mocha",
|
||||
"rebuild_and_test": "run-s build test",
|
||||
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
|
||||
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers",
|
||||
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||
"coverage:report:lcov": "istanbul report lcov",
|
||||
"test:circleci": "yarn test",
|
||||
"contracts:gen": "contracts-gen",
|
||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||
},
|
||||
"config": {
|
||||
"abis": "./generated-artifacts/@(DevUtils|LibAssetData|LibTransactionDecoder|EthBalanceChecker).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-asset-proxy": "^2.2.8",
|
||||
"@0x/contracts-erc1155": "^1.1.15",
|
||||
"@0x/contracts-erc20": "^2.2.14",
|
||||
"@0x/contracts-erc721": "^2.1.15",
|
||||
"@0x/contracts-exchange": "^2.1.14",
|
||||
"@0x/contracts-exchange-libs": "^3.0.8",
|
||||
"@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"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
15
contracts/dev-utils/src/artifacts.ts
Normal file
15
contracts/dev-utils/src/artifacts.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as DevUtils from '../generated-artifacts/DevUtils.json';
|
||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
|
||||
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
|
||||
export const artifacts = {
|
||||
DevUtils: DevUtils as ContractArtifact,
|
||||
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
||||
LibAssetData: LibAssetData as ContractArtifact,
|
||||
};
|
2
contracts/dev-utils/src/index.ts
Normal file
2
contracts/dev-utils/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './artifacts';
|
||||
export * from './wrappers';
|
8
contracts/dev-utils/src/wrappers.ts
Normal file
8
contracts/dev-utils/src/wrappers.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
export * from '../generated-wrappers/dev_utils';
|
||||
export * from '../generated-wrappers/lib_asset_data';
|
||||
export * from '../generated-wrappers/lib_transaction_decoder';
|
@@ -2,6 +2,7 @@ import { env, EnvVars } from '@0x/dev-utils';
|
||||
|
||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||
import { providerUtils } from '@0x/utils';
|
||||
|
||||
before('start web3 provider', () => {
|
||||
providerUtils.startProviderEngine(provider);
|
||||
});
|
538
contracts/dev-utils/test/lib_asset_data.ts
Normal file
538
contracts/dev-utils/test/lib_asset_data.ts
Normal file
@@ -0,0 +1,538 @@
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
|
||||
import {
|
||||
artifacts as proxyArtifacts,
|
||||
ERC1155ProxyContract,
|
||||
ERC20ProxyContract,
|
||||
ERC721ProxyContract,
|
||||
MultiAssetProxyContract,
|
||||
StaticCallProxyContract,
|
||||
TestStaticCallTargetContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import {
|
||||
artifacts as erc1155Artifacts,
|
||||
ERC1155MintableContract,
|
||||
ERC1155TransferSingleEventArgs,
|
||||
} from '@0x/contracts-erc1155';
|
||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import { artifacts, LibAssetDataContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
const KNOWN_ERC20_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
};
|
||||
const KNOWN_ERC721_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenId: new BigNumber(1),
|
||||
assetData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
};
|
||||
const KNOWN_ERC1155_ENCODING = {
|
||||
tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
|
||||
tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
|
||||
callbackData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
assetData:
|
||||
'0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
const KNOWN_MULTI_ASSET_ENCODING = {
|
||||
amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
|
||||
nestedAssetData: [
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
KNOWN_ERC721_ENCODING.assetData,
|
||||
KNOWN_ERC1155_ENCODING.assetData,
|
||||
],
|
||||
assetData:
|
||||
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
|
||||
describe('LibAssetData', () => {
|
||||
let exchange: ExchangeContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let erc721Proxy: ERC721ProxyContract;
|
||||
let erc1155Proxy: ERC1155ProxyContract;
|
||||
let multiAssetProxy: MultiAssetProxyContract;
|
||||
let staticCallProxy: StaticCallProxyContract;
|
||||
let staticCallTarget: TestStaticCallTargetContract;
|
||||
let libAssetData: LibAssetDataContract;
|
||||
|
||||
let tokenOwnerAddress: string;
|
||||
|
||||
let erc20Token: DummyERC20TokenContract;
|
||||
let erc721Token: DummyERC721TokenContract;
|
||||
let erc1155Token: ERC1155MintableContract;
|
||||
|
||||
const erc20TokenTotalSupply = new BigNumber(1);
|
||||
|
||||
const firstERC721TokenId = new BigNumber(1);
|
||||
const numberOfERC721Tokens = 10;
|
||||
|
||||
let erc1155TokenId: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
|
||||
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.NULL_BYTES,
|
||||
);
|
||||
|
||||
erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC20Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC721Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC1155Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.StaticCallProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address);
|
||||
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address);
|
||||
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address);
|
||||
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(multiAssetProxy.address);
|
||||
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address);
|
||||
|
||||
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibAssetData,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
exchange.address,
|
||||
);
|
||||
|
||||
staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.TestStaticCallTarget,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
[tokenOwnerAddress] = await web3Wrapper.getAvailableAddressesAsync();
|
||||
|
||||
erc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
new BigNumber(1),
|
||||
erc20TokenTotalSupply,
|
||||
);
|
||||
|
||||
erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||
erc721Artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
);
|
||||
// mint `numberOfERC721Tokens` tokens
|
||||
const transactionMinedPromises = [];
|
||||
for (let i = 0; i < numberOfERC721Tokens; i++) {
|
||||
transactionMinedPromises.push(
|
||||
erc721Token.mint.awaitTransactionSuccessAsync(tokenOwnerAddress, firstERC721TokenId.plus(i - 1)),
|
||||
);
|
||||
}
|
||||
await Promise.all(transactionMinedPromises);
|
||||
|
||||
erc1155Token = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
||||
erc1155Artifacts.ERC1155Mintable,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
const logDecoder = new LogDecoder(web3Wrapper, erc1155Artifacts);
|
||||
const transactionReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||
await erc1155Token.create.sendTransactionAsync('uri:Dummy', /*isNonFungible:*/ false),
|
||||
);
|
||||
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion
|
||||
erc1155TokenId = (transactionReceipt.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
|
||||
await erc1155Token.mintFungible.awaitTransactionSuccessAsync(
|
||||
erc1155TokenId,
|
||||
[tokenOwnerAddress],
|
||||
[new BigNumber(1)],
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
it('should have a deployed-to address', () => {
|
||||
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
|
||||
});
|
||||
|
||||
describe('encoding and decoding', () => {
|
||||
it('should encode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
);
|
||||
});
|
||||
|
||||
it('should decode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.ERC20,
|
||||
KNOWN_ERC20_ENCODING.address,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC721 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeERC721AssetData.callAsync(
|
||||
KNOWN_ERC721_ENCODING.address,
|
||||
KNOWN_ERC721_ENCODING.tokenId,
|
||||
),
|
||||
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC721 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC721AssetData.callAsync(KNOWN_ERC721_ENCODING.assetData)).to.deep.equal([
|
||||
AssetProxyId.ERC721,
|
||||
KNOWN_ERC721_ENCODING.address,
|
||||
KNOWN_ERC721_ENCODING.tokenId,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeERC1155AssetData.callAsync(
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
),
|
||||
).to.equal(KNOWN_ERC1155_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC1155 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC1155AssetData.callAsync(KNOWN_ERC1155_ENCODING.assetData)).to.deep.equal(
|
||||
[
|
||||
AssetProxyId.ERC1155,
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('should encode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData.encodeMultiAssetData.callAsync(
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
),
|
||||
).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeMultiAssetData.callAsync(KNOWN_MULTI_ASSET_ENCODING.assetData),
|
||||
).to.deep.equal([
|
||||
AssetProxyId.MultiAsset,
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalance', () => {
|
||||
it('should query ERC20 balance by asset data', async () => {
|
||||
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
|
||||
erc20TokenTotalSupply,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC20 token does not exist', async () => {
|
||||
const assetData = assetDataUtils.encodeERC20AssetData(constants.NULL_ADDRESS);
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC721 balance by asset data', async () => {
|
||||
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
|
||||
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC721 token does not exist', async () => {
|
||||
const assetData = assetDataUtils.encodeERC721AssetData(constants.NULL_ADDRESS, firstERC721TokenId);
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC1155 balances by asset data', async () => {
|
||||
const assetData = assetDataUtils.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
);
|
||||
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC1155 token does not exist', async () => {
|
||||
const assetData = assetDataUtils.encodeERC1155AssetData(
|
||||
constants.NULL_ADDRESS,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
);
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query multi-asset batch balance by asset data', async () => {
|
||||
const assetData = assetDataUtils.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
assetDataUtils.encodeERC20AssetData(erc20Token.address),
|
||||
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
|
||||
],
|
||||
);
|
||||
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
|
||||
Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens),
|
||||
);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, fakeAssetData);
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
expectedResultHash,
|
||||
);
|
||||
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssetProxyAllowance', () => {
|
||||
it('should query ERC20 allowances by asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.bignumber.equal(allowance);
|
||||
});
|
||||
|
||||
it('should query ERC721 approval by asset data', async () => {
|
||||
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC721 approvalForAll by assetData', async () => {
|
||||
await erc721Token.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, true, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should query ERC1155 allowances by asset data', async () => {
|
||||
await erc1155Token.setApprovalForAll.awaitTransactionSuccessAsync(erc1155Proxy.address, true, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
);
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should query multi-asset allowances by asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
assetDataUtils.encodeERC20AssetData(erc20Token.address),
|
||||
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
|
||||
],
|
||||
);
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.bignumber.equal(1);
|
||||
return;
|
||||
});
|
||||
|
||||
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const allowance = await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, fakeAssetData);
|
||||
expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
|
||||
const staticCallData = AssetProxyId.StaticCall;
|
||||
const assetData = assetDataUtils.encodeStaticCallAssetData(
|
||||
staticCallTarget.address,
|
||||
staticCallData,
|
||||
constants.KECCAK256_NULL,
|
||||
);
|
||||
const allowance = await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData);
|
||||
expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchBalances', () => {
|
||||
it('should query balances for a batch of asset data strings', async () => {
|
||||
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
|
||||
expect(
|
||||
await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [erc20AssetData, erc721AssetData]),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getERC721TokenOwner', async () => {
|
||||
it('should return the null address when tokenId is not owned', async () => {
|
||||
const nonexistentTokenId = new BigNumber(1234567890);
|
||||
expect(
|
||||
await libAssetData.getERC721TokenOwner.callAsync(erc721Token.address, nonexistentTokenId),
|
||||
).to.be.equal(constants.NULL_ADDRESS);
|
||||
});
|
||||
it('should return the owner address when tokenId is owned', async () => {
|
||||
expect(
|
||||
await libAssetData.getERC721TokenOwner.callAsync(erc721Token.address, firstERC721TokenId),
|
||||
).to.be.equal(tokenOwnerAddress);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalanceAndAllowance', () => {
|
||||
it('should query balance and allowance together, from asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
expect(
|
||||
await libAssetData.getBalanceAndAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]);
|
||||
});
|
||||
});
|
||||
describe('getBatchBalancesAndAllowances', () => {
|
||||
it('should query balances and allowances together, from an asset data array', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
expect(
|
||||
await libAssetData.getBatchBalancesAndAssetProxyAllowances.callAsync(tokenOwnerAddress, [assetData]),
|
||||
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchAssetProxyAllowances', () => {
|
||||
it('should query allowances for a batch of asset data strings', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
|
||||
expect(
|
||||
await libAssetData.getBatchAssetProxyAllowances.callAsync(tokenOwnerAddress, [
|
||||
erc20AssetData,
|
||||
erc721AssetData,
|
||||
]),
|
||||
).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
140
contracts/dev-utils/test/lib_transaction_decoder.ts
Normal file
140
contracts/dev-utils/test/lib_transaction_decoder.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { IExchangeContract } from '@0x/contracts-exchange';
|
||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { artifacts, LibTransactionDecoderContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
const order = {
|
||||
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
|
||||
takerAddress: '0x0000000000000000000000000000000000000000',
|
||||
feeRecipientAddress: '0x78dc5d2d739606d31509c31d654056a45185ecb6',
|
||||
senderAddress: '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb',
|
||||
makerAssetAmount: new BigNumber('100000000000000000000'),
|
||||
takerAssetAmount: new BigNumber('200000000000000000000'),
|
||||
makerFee: new BigNumber('1000000000000000000'),
|
||||
takerFee: new BigNumber('1000000000000000000'),
|
||||
expirationTimeSeconds: new BigNumber('1552396423'),
|
||||
salt: new BigNumber('66097384406870180066678463045003379626790660770396923976862707230261946348951'),
|
||||
makerAssetData: '0xf47261b000000000000000000000000034d402f14d58e001d8efbe6585051bf9706aa064',
|
||||
takerAssetData: '0xf47261b000000000000000000000000025b8fe1de9daf8ba351890744ff28cf7dfa8f5e3',
|
||||
};
|
||||
const takerAssetFillAmount = new BigNumber('100000000000000000000');
|
||||
const signature =
|
||||
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
|
||||
|
||||
describe('LibTransactionDecoder', () => {
|
||||
let libTxDecoder: LibTransactionDecoderContract;
|
||||
const exchangeInterface = new IExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibTransactionDecoder,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
it('should decode an Exchange.batchCancelOrders() transaction', async () => {
|
||||
const input = exchangeInterface.batchCancelOrders.getABIEncodedTransactionData([order, order]);
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
'batchCancelOrders',
|
||||
[order, order],
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
});
|
||||
|
||||
for (const func of ['batchFillOrders', 'batchFillOrdersNoThrow', 'batchFillOrKillOrders']) {
|
||||
const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
|
||||
[order, order],
|
||||
[takerAssetFillAmount, takerAssetFillAmount],
|
||||
[signature, signature],
|
||||
);
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount, takerAssetFillAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
it('should decode an Exchange.cancelOrder() transaction', async () => {
|
||||
const input = exchangeInterface.cancelOrder.getABIEncodedTransactionData(order);
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
'cancelOrder',
|
||||
[order],
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
});
|
||||
|
||||
for (const func of ['fillOrder', 'fillOrderNoThrow', 'fillOrKillOrder']) {
|
||||
const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
signature,
|
||||
);
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
func,
|
||||
[order],
|
||||
[takerAssetFillAmount],
|
||||
[signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
for (const func of ['marketBuyOrders', 'marketBuyOrdersNoThrow', 'marketSellOrders', 'marketSellOrdersNoThrow']) {
|
||||
const input = (exchangeInterface as any)[func].getABIEncodedTransactionData(
|
||||
[order, order],
|
||||
takerAssetFillAmount,
|
||||
[signature, signature],
|
||||
);
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
it('should decode an Exchange.matchOrders() transaction', async () => {
|
||||
const complementaryOrder = {
|
||||
...order,
|
||||
makerAddress: order.takerAddress,
|
||||
takerAddress: order.makerAddress,
|
||||
makerAssetData: order.takerAssetData,
|
||||
takerAssetData: order.makerAssetData,
|
||||
makerAssetAmount: order.takerAssetAmount,
|
||||
takerAssetAmount: order.makerAssetAmount,
|
||||
makerFee: order.takerFee,
|
||||
takerFee: order.makerFee,
|
||||
};
|
||||
const input = exchangeInterface.matchOrders.getABIEncodedTransactionData(
|
||||
order,
|
||||
complementaryOrder,
|
||||
signature,
|
||||
signature,
|
||||
);
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData.callAsync(input)).to.deep.equal([
|
||||
'matchOrders',
|
||||
[order, complementaryOrder],
|
||||
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
});
|
445
contracts/dev-utils/test/order_validation_utils.ts
Normal file
445
contracts/dev-utils/test/order_validation_utils.ts
Normal file
@@ -0,0 +1,445 @@
|
||||
import {
|
||||
artifacts as proxyArtifacts,
|
||||
ERC20ProxyContract,
|
||||
ERC20Wrapper,
|
||||
ERC721ProxyContract,
|
||||
ERC721Wrapper,
|
||||
MultiAssetProxyContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { artifacts as exchangeArtifacts, ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
|
||||
import {
|
||||
chaiSetup,
|
||||
constants,
|
||||
OrderFactory,
|
||||
OrderStatus,
|
||||
provider,
|
||||
txDefaults,
|
||||
web3Wrapper,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { artifacts, DevUtilsContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('OrderValidationUtils', () => {
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let owner: string;
|
||||
let erc20AssetData: string;
|
||||
let erc20AssetData2: string;
|
||||
let erc721AssetData: string;
|
||||
let zrxAssetData: string;
|
||||
|
||||
let erc20Token: DummyERC20TokenContract;
|
||||
let erc20Token2: DummyERC20TokenContract;
|
||||
let zrxToken: DummyERC20TokenContract;
|
||||
let erc721Token: DummyERC721TokenContract;
|
||||
let exchange: ExchangeContract;
|
||||
let devUtils: DevUtilsContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let erc721Proxy: ERC721ProxyContract;
|
||||
let multiAssetProxy: MultiAssetProxyContract;
|
||||
|
||||
let signedOrder: SignedOrder;
|
||||
let orderFactory: OrderFactory;
|
||||
|
||||
const tokenId = new BigNumber(123456789);
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const usedAddresses = ([owner, makerAddress, takerAddress] = accounts.slice(0, 3));
|
||||
|
||||
const erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
|
||||
const erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
|
||||
|
||||
const numDummyErc20ToDeploy = 3;
|
||||
[erc20Token, zrxToken, erc20Token2] = await erc20Wrapper.deployDummyTokensAsync(
|
||||
numDummyErc20ToDeploy,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
);
|
||||
erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
|
||||
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
|
||||
erc721Proxy = await erc721Wrapper.deployProxyAsync();
|
||||
|
||||
zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
|
||||
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
zrxAssetData,
|
||||
);
|
||||
|
||||
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
const exchangeWrapper = new ExchangeWrapper(exchange, provider);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
|
||||
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
|
||||
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
|
||||
await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
|
||||
|
||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
exchange.address,
|
||||
zrxAssetData,
|
||||
);
|
||||
|
||||
erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address);
|
||||
erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
|
||||
const defaultOrderParams = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
exchangeAddress: exchange.address,
|
||||
makerAddress,
|
||||
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||
makerAssetData: erc20AssetData,
|
||||
takerAssetData: erc20AssetData2,
|
||||
};
|
||||
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
||||
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
describe('getTransferableAssetAmount', () => {
|
||||
it('should return the balance when balance < allowance', async () => {
|
||||
const balance = new BigNumber(123);
|
||||
const allowance = new BigNumber(456);
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, balance);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
|
||||
makerAddress,
|
||||
erc20AssetData,
|
||||
);
|
||||
expect(transferableAmount).to.bignumber.equal(balance);
|
||||
});
|
||||
it('should return the allowance when allowance < balance', async () => {
|
||||
const balance = new BigNumber(456);
|
||||
const allowance = new BigNumber(123);
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, balance);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
|
||||
makerAddress,
|
||||
erc20AssetData,
|
||||
);
|
||||
expect(transferableAmount).to.bignumber.equal(allowance);
|
||||
});
|
||||
it('should return the correct transferable amount for multiAssetData', async () => {
|
||||
const multiAssetData = assetDataUtils.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[erc20AssetData, erc20AssetData2],
|
||||
);
|
||||
const transferableAmount1 = new BigNumber(10);
|
||||
const transferableAmount2 = new BigNumber(5);
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableAmount1);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableAmount1, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await erc20Token2.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableAmount2);
|
||||
await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableAmount2, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const transferableAmount = await devUtils.getTransferableAssetAmount.callAsync(
|
||||
makerAddress,
|
||||
multiAssetData,
|
||||
);
|
||||
expect(transferableAmount).to.bignumber.equal(transferableAmount2);
|
||||
});
|
||||
});
|
||||
describe('getOrderRelevantState', () => {
|
||||
beforeEach(async () => {
|
||||
signedOrder = await orderFactory.newSignedOrderAsync();
|
||||
});
|
||||
it('should return the correct orderInfo when the order is valid', async () => {
|
||||
const [orderInfo] = await devUtils.getOrderRelevantState.callAsync(signedOrder, signedOrder.signature);
|
||||
expect(orderInfo.orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
|
||||
expect(orderInfo.orderStatus).to.equal(OrderStatus.Fillable);
|
||||
expect(orderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return isValidSignature=true when the signature is valid', async () => {
|
||||
const [, , isValidSignature] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(isValidSignature).to.equal(true);
|
||||
});
|
||||
it('should return isValidSignature=false when the signature is invalid', async () => {
|
||||
const invalidSignature = '0x01';
|
||||
const [, , isValidSignature] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
invalidSignature,
|
||||
);
|
||||
expect(isValidSignature).to.equal(false);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when balances or allowances are insufficient', async () => {
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when fee balances/allowances are insufficient', async () => {
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when balances/allowances of one asset within a multiAssetData are insufficient', async () => {
|
||||
const multiAssetData = assetDataUtils.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[erc20AssetData, erc20AssetData2],
|
||||
);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: multiAssetData });
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when fee balances/allowances are partially sufficient', async () => {
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const divisor = 4;
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
signedOrder.makerFee.dividedToIntegerBy(divisor),
|
||||
);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when non-fee balances/allowances are partially sufficient', async () => {
|
||||
const divisor = 4;
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when balances/allowances of one asset within a multiAssetData are partially sufficient', async () => {
|
||||
const multiAssetData = assetDataUtils.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[erc20AssetData, erc20AssetData2],
|
||||
);
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: multiAssetData });
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const divisor = 4;
|
||||
await erc20Token2.setBalance.awaitTransactionSuccessAsync(
|
||||
makerAddress,
|
||||
signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
await erc20Token2.approve.awaitTransactionSuccessAsync(
|
||||
erc20Proxy.address,
|
||||
signedOrder.makerAssetAmount.dividedToIntegerBy(divisor),
|
||||
{
|
||||
from: makerAddress,
|
||||
},
|
||||
);
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when non-fee balances/allowances are insufficient', async () => {
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount equal to the takerAssetAmount when the order is unfilled and balances/allowances are sufficient', async () => {
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when balances/allowances are partially sufficient and makerAsset=makerFeeAsset', async () => {
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||
makerAssetData: zrxAssetData,
|
||||
makerAssetAmount: new BigNumber(10),
|
||||
takerAssetAmount: new BigNumber(20),
|
||||
makerFee: new BigNumber(40),
|
||||
});
|
||||
const transferableMakerAssetAmount = new BigNumber(10);
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, transferableMakerAssetAmount);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, transferableMakerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const expectedFillableTakerAssetAmount = transferableMakerAssetAmount
|
||||
.times(signedOrder.takerAssetAmount)
|
||||
.dividedToIntegerBy(signedOrder.makerAssetAmount.plus(signedOrder.makerFee));
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(expectedFillableTakerAssetAmount);
|
||||
});
|
||||
it('should return the correct fillabeTakerassetAmount when makerAsset balances/allowances are sufficient and there are no maker fees', async () => {
|
||||
signedOrder = await orderFactory.newSignedOrderAsync({ makerFee: constants.ZERO_AMOUNT });
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount when the remaining takerAssetAmount is less than the transferable amount', async () => {
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await erc20Token2.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerAssetAmount);
|
||||
await erc20Token2.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerAssetAmount, {
|
||||
from: takerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(takerAddress, signedOrder.takerFee);
|
||||
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.takerFee, {
|
||||
from: takerAddress,
|
||||
});
|
||||
const takerAssetFillAmount = signedOrder.takerAssetAmount.dividedToIntegerBy(4);
|
||||
await exchange.fillOrder.awaitTransactionSuccessAsync(
|
||||
signedOrder,
|
||||
takerAssetFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState.callAsync(
|
||||
signedOrder,
|
||||
signedOrder.signature,
|
||||
);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.minus(takerAssetFillAmount),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('getOrderRelevantStates', async () => {
|
||||
it('should return the correct information for multiple orders', async () => {
|
||||
await erc20Token.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerAssetAmount);
|
||||
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerAssetAmount, {
|
||||
from: makerAddress,
|
||||
});
|
||||
await zrxToken.setBalance.awaitTransactionSuccessAsync(makerAddress, signedOrder.makerFee);
|
||||
await zrxToken.approve.awaitTransactionSuccessAsync(erc20Proxy.address, signedOrder.makerFee, {
|
||||
from: makerAddress,
|
||||
});
|
||||
const signedOrder2 = await orderFactory.newSignedOrderAsync({ makerAssetData: erc721AssetData });
|
||||
const invalidSignature = '0x01';
|
||||
await exchange.cancelOrder.awaitTransactionSuccessAsync(signedOrder2, { from: makerAddress });
|
||||
const [
|
||||
ordersInfo,
|
||||
fillableTakerAssetAmounts,
|
||||
isValidSignature,
|
||||
] = await devUtils.getOrderRelevantStates.callAsync(
|
||||
[signedOrder, signedOrder2],
|
||||
[signedOrder.signature, invalidSignature],
|
||||
);
|
||||
expect(ordersInfo[0].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
|
||||
expect(ordersInfo[1].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder2));
|
||||
expect(ordersInfo[0].orderStatus).to.equal(OrderStatus.Fillable);
|
||||
expect(ordersInfo[1].orderStatus).to.equal(OrderStatus.Cancelled);
|
||||
expect(ordersInfo[0].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(ordersInfo[1].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(fillableTakerAssetAmounts[0]).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
expect(fillableTakerAssetAmounts[1]).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(isValidSignature[0]).to.equal(true);
|
||||
expect(isValidSignature[1]).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
12
contracts/dev-utils/tsconfig.json
Normal file
12
contracts/dev-utils/tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"generated-artifacts/DevUtils.json",
|
||||
"generated-artifacts/LibAssetData.json",
|
||||
"generated-artifacts/LibTransactionDecoder.json",
|
||||
"generated-artifacts/EthBalanceChecker.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
}
|
6
contracts/dev-utils/tslint.json
Normal file
6
contracts/dev-utils/tslint.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
}
|
||||
}
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "1.1.15",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "1.1.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "1.1.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "1.1.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.1.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564604963
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "1.1.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "1.1.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "1.1.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "1.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "1.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "1.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1557799313
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "1.1.2",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.1.15 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.14 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.13 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.12 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.11 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v1.1.10 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.9 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.8 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.7 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.6 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.5 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.4 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.1.2 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## ERC1155 Tokens
|
||||
|
||||
This package contains implementations of various [ERC1155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) tokens. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains implementations of various [ERC1155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) tokens. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-erc1155 --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
|
@@ -63,6 +63,32 @@ contract ERC1155Mintable is
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev creates a new token
|
||||
/// @param type_ of token
|
||||
/// @param uri URI of token
|
||||
function createWithType(
|
||||
uint256 type_,
|
||||
string calldata uri
|
||||
)
|
||||
external
|
||||
{
|
||||
// This will allow restricted access to creators.
|
||||
creators[type_] = msg.sender;
|
||||
|
||||
// emit a Transfer event with Create semantic to help with discovery.
|
||||
emit TransferSingle(
|
||||
msg.sender,
|
||||
address(0x0),
|
||||
address(0x0),
|
||||
type_,
|
||||
0
|
||||
);
|
||||
|
||||
if (bytes(uri).length > 0) {
|
||||
emit URI(uri, type_);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev mints fungible tokens
|
||||
/// @param id token type
|
||||
/// @param to beneficiaries of minted tokens
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc1155",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.15",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -47,19 +47,20 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^4.2.1",
|
||||
"@0x/contracts-gen": "^1.0.15",
|
||||
"@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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -67,14 +68,14 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-test-utils": "^3.1.16",
|
||||
"@0x/contracts-utils": "^3.2.4",
|
||||
"@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",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -60,11 +60,13 @@ describe('ERC1155Token', () => {
|
||||
artifacts.ERC1155Mintable,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DummyERC1155Receiver,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
receiver = erc1155Receiver.address;
|
||||
// create wrapper & mint erc1155 tokens
|
||||
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.2.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.2.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.2.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.2.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564604963
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.2.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "2.2.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.2.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1557799313
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "2.2.1",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.2.14 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.13 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.12 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.11 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.10 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.2.9 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.8 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.7 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.6 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.5 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.4 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.3 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.2.1 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## ERC20 Tokens
|
||||
|
||||
This package contains implementations of various [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) tokens, including WETH (Wrapped Ether) and ZRX. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains implementations of various [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) tokens, including WETH (Wrapped Ether) and ZRX. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-erc20 --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -14,10 +14,12 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
"evm.deployedBytecode.sourceMap",
|
||||
"devdoc"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc20",
|
||||
"version": "2.2.1",
|
||||
"version": "2.2.14",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -47,20 +47,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,14 +69,13 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-exchange-libs": "^2.1.2",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-utils": "^3.2.4",
|
||||
"@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",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -37,6 +37,7 @@ describe('UnlimitedAllowanceToken', () => {
|
||||
artifacts.DummyERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
constants.DUMMY_TOKEN_DECIMALS,
|
||||
|
@@ -33,10 +33,15 @@ describe('EtherToken', () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
account = accounts[0];
|
||||
|
||||
etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, {
|
||||
gasPrice,
|
||||
...txDefaults,
|
||||
});
|
||||
etherToken = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||
artifacts.WETH9,
|
||||
provider,
|
||||
{
|
||||
gasPrice,
|
||||
...txDefaults,
|
||||
},
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
|
@@ -26,7 +26,12 @@ describe('ZRXToken', () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
owner = accounts[0];
|
||||
spender = accounts[1];
|
||||
zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(artifacts.ZRXToken, provider, txDefaults);
|
||||
zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ZRXToken,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
MAX_UINT = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.1.15",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.1.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.1.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.1.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564604963
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.1.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.1.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.1.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "2.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1557799313
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "2.1.2",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.1.15 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.14 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.13 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.12 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.11 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.1.10 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.9 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.8 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.7 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.6 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.5 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.4 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.2 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## ERC721 Tokens
|
||||
|
||||
This package contains implementations of various [ERC721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md) tokens. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains implementations of various [ERC721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md) tokens. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-erc721 --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc721",
|
||||
"version": "2.1.2",
|
||||
"version": "2.1.15",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -47,20 +47,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,13 +69,13 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-utils": "^3.2.4",
|
||||
"@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",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -48,6 +48,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
);
|
||||
@@ -55,6 +56,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.DummyERC721Receiver,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
logDecoder = new LogDecoder(web3Wrapper, artifacts);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
@@ -176,6 +178,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
);
|
||||
@@ -190,6 +193,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.InvalidERC721Receiver,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
const from = owner;
|
||||
const to = invalidErc721Receiver.address;
|
||||
@@ -237,6 +241,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
constants.DUMMY_TOKEN_NAME,
|
||||
constants.DUMMY_TOKEN_SYMBOL,
|
||||
);
|
||||
@@ -251,6 +256,7 @@ describe('ERC721Token', () => {
|
||||
artifacts.InvalidERC721Receiver,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
const from = owner;
|
||||
const to = invalidErc721Receiver.address;
|
||||
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "3.0.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "3.0.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "3.0.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "3.0.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564607468
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "3.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "3.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "3.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "3.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "3.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "3.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557799313,
|
||||
"version": "3.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.0.12 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.11 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.10 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.9 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.8 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v3.0.7 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.6 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.5 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.4 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.3 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.2 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.1 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.0 - _May 10, 2019_
|
||||
|
||||
* Update contracts to solidity ^0.5.5 and unpin dependencies (#1796)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## Exchange Forwarder
|
||||
|
||||
This package contains the implementation of the [`Forwarder`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract. This contract is intended to improve the UX of interacting with the 0x [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract by abstracting user approvals, converting ETH to WETH, and paying fees. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains the implementation of the [`Forwarder`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract. This contract is intended to improve the UX of interacting with the 0x [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract by abstracting user approvals, converting ETH to WETH, and paying fees. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-exchange-forwarder --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-exchange-forwarder",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.12",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
@@ -46,21 +46,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contract-wrappers": "^9.1.0",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,19 +68,19 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-asset-proxy": "^2.1.2",
|
||||
"@0x/contracts-erc20": "^2.2.1",
|
||||
"@0x/contracts-erc721": "^2.1.2",
|
||||
"@0x/contracts-exchange": "^2.1.2",
|
||||
"@0x/contracts-exchange-libs": "^2.1.2",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/order-utils": "^8.0.0",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.1",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@0x/contracts-asset-proxy": "^2.2.8",
|
||||
"@0x/contracts-erc20": "^2.2.14",
|
||||
"@0x/contracts-erc721": "^2.1.15",
|
||||
"@0x/contracts-exchange": "^2.1.14",
|
||||
"@0x/contracts-exchange-libs": "^3.0.8",
|
||||
"@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",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -32,6 +32,7 @@ const DECIMALS_DEFAULT = 18;
|
||||
const MAX_WETH_FILL_PERCENTAGE = 95;
|
||||
|
||||
describe(ContractName.Forwarder, () => {
|
||||
const dependencyArtifacts = { ...artifacts, ...erc20Artifacts, ...exchangeArtifacts };
|
||||
let makerAddress: string;
|
||||
let owner: string;
|
||||
let takerAddress: string;
|
||||
@@ -88,8 +89,13 @@ describe(ContractName.Forwarder, () => {
|
||||
const erc721Balances = await erc721Wrapper.getBalancesAsync();
|
||||
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
|
||||
|
||||
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(erc20Artifacts.WETH9, provider, txDefaults);
|
||||
weth = new DummyERC20TokenContract(wethContract.abi, wethContract.address, provider);
|
||||
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.WETH9,
|
||||
provider,
|
||||
txDefaults,
|
||||
dependencyArtifacts,
|
||||
);
|
||||
weth = new DummyERC20TokenContract(wethContract.address, provider);
|
||||
erc20Wrapper.addDummyTokenContract(weth);
|
||||
|
||||
wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
|
||||
@@ -98,6 +104,7 @@ describe(ContractName.Forwarder, () => {
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
dependencyArtifacts,
|
||||
zrxAssetData,
|
||||
);
|
||||
exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider);
|
||||
@@ -131,11 +138,12 @@ describe(ContractName.Forwarder, () => {
|
||||
artifacts.Forwarder,
|
||||
provider,
|
||||
txDefaults,
|
||||
dependencyArtifacts,
|
||||
exchangeInstance.address,
|
||||
zrxAssetData,
|
||||
wethAssetData,
|
||||
);
|
||||
forwarderContract = new ForwarderContract(forwarderInstance.abi, forwarderInstance.address, provider);
|
||||
forwarderContract = new ForwarderContract(forwarderInstance.address, provider);
|
||||
forwarderWrapper = new ForwarderWrapper(forwarderContract, provider);
|
||||
const zrxDepositAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
@@ -169,6 +177,7 @@ describe(ContractName.Forwarder, () => {
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
dependencyArtifacts,
|
||||
zrxAssetData,
|
||||
);
|
||||
return expectContractCreationFailedAsync(
|
||||
@@ -176,6 +185,7 @@ describe(ContractName.Forwarder, () => {
|
||||
artifacts.Forwarder,
|
||||
provider,
|
||||
txDefaults,
|
||||
dependencyArtifacts,
|
||||
exchangeInstance.address,
|
||||
zrxAssetData,
|
||||
wethAssetData,
|
||||
|
@@ -1,4 +1,114 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "3.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "3.0.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "3.0.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "3.0.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564604963
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "3.0.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "3.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "3.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Move `LibTransactionDecoder` to contracts/dev-utils package",
|
||||
"pr": 1848
|
||||
}
|
||||
],
|
||||
"timestamp": 1563006338
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
],
|
||||
"timestamp": 1557799313
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "2.1.2",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.0.8 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.7 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.6 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.5 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.4 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v3.0.3 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.2 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.1 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.0.0 - _July 13, 2019_
|
||||
|
||||
* Move `LibTransactionDecoder` to contracts/dev-utils package (#1848)
|
||||
|
||||
## v2.1.6 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.5 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.4 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.2 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## Exchange Libraries
|
||||
|
||||
This package contains the implementations of various libraries and utilities used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract. These libraries may be useful when creating external contracts that interact with the `Exchange` contract. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains the implementations of various libraries and utilities used within the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange) contract. These libraries may be useful when creating external contracts that interact with the `Exchange` contract. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"devdoc",
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-exchange-libs",
|
||||
"version": "2.1.2",
|
||||
"version": "3.0.8",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"compile": "sol-compiler",
|
||||
"watch": "sol-compiler -w",
|
||||
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||
"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",
|
||||
@@ -47,20 +47,21 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/libs/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"@0x/contracts-gen": "^1.0.9",
|
||||
"@0x/contracts-test-utils": "^3.1.3",
|
||||
"@0x/dev-utils": "^2.2.2",
|
||||
"@0x/sol-compiler": "^3.1.7",
|
||||
"@0x/abi-gen": "^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": "*",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solhint": "^1.4.1",
|
||||
@@ -68,14 +69,14 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^5.1.0",
|
||||
"@0x/contracts-utils": "^3.1.2",
|
||||
"@0x/order-utils": "^8.0.0",
|
||||
"@0x/types": "^2.2.2",
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"@0x/web3-wrapper": "^6.0.6",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"@0x/base-contract": "^5.4.0",
|
||||
"@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",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@@ -35,7 +35,7 @@ describe('Exchange libs', () => {
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
const makerAddress = accounts[0];
|
||||
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
|
||||
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults, artifacts);
|
||||
|
||||
const defaultOrderParams = {
|
||||
...constants.STATIC_ORDER_PARAMS,
|
||||
|
@@ -1,4 +1,113 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1568744790,
|
||||
"version": "2.1.14",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1567521715,
|
||||
"version": "2.1.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1566446343,
|
||||
"version": "2.1.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1565296576,
|
||||
"version": "2.1.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies.",
|
||||
"pr": 1995
|
||||
}
|
||||
],
|
||||
"timestamp": 1564607468
|
||||
},
|
||||
{
|
||||
"timestamp": 1563957393,
|
||||
"version": "2.1.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "2.1.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.1.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "2.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557961111,
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557799313,
|
||||
"version": "2.1.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1557507213,
|
||||
"version": "2.1.2",
|
||||
|
@@ -5,6 +5,54 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v2.1.14 - _September 17, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.13 - _September 3, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.12 - _August 22, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.11 - _August 8, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.10 - _July 31, 2019_
|
||||
|
||||
* Updated calls to <contract wrapper>.deployFrom0xArtifactAsync to include artifact dependencies. (#1995)
|
||||
|
||||
## v2.1.9 - _July 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.8 - _July 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.7 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.6 - _July 13, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.5 - _May 24, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.4 - _May 15, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.3 - _May 14, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v2.1.2 - _May 10, 2019_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
## Exchange
|
||||
|
||||
This package contains the implementation of the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange). This contract is responsible for settling trades and is typically the entry point for all transactions that interact with the 0x protocol. Lightweight examples of how external contracts can interct with the `Exchange` contract can be found in the [examples](./contracts/examples) directory. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
This package contains the implementation of the [`Exchange`](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#exchange). This contract is responsible for settling trades and is typically the entry point for all transactions that interact with the 0x protocol. Lightweight examples of how external contracts can interct with the `Exchange` contract can be found in the [examples](./contracts/examples) directory. Addresses of the deployed contracts can be found in this 0x [guide](https://0x.org/docs/guides/0x-cheat-sheet) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -12,7 +12,7 @@ npm install @0x/contracts-exchange --save
|
||||
|
||||
## Bug bounty
|
||||
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0x.org/docs/guides/bug-bounty-program).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user