diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f5940d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# Created by .ignore support plugin (hsz.mobi) +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### Scala template +*.class +*.log +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +.idea +target + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..448a530 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: scala +scala: + - 2.12.8 +script: + - sbt compile + - sbt test \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc4aa9c --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +## eth-abi + +[![Build Status](https://travis-ci.com/Lbqds/eth-abi.svg?token=iUBC3d9KBxXjFrs9989Y&branch=master)](https://travis-ci.com/Lbqds/eth-abi) + +generate scala code from solidity contract + +### codegen + +download from the [release](https://github.com/Lbqds/eth-abi/releases) page, then execute: + +``` +$ tar -xf abi-codegen.tar.gz +$ scala abi-codegen.jar --help +``` + +it will show usage as follow: + +```text +abi-codegen 0.1 +Usage: abi-codegen [options] + + -a, --abi contract abi file + -b, --bin contract bin file + -p, --package package name e.g. "examples.token" + -c, --className class name + -o, --output output directory + -h, --help show usage +``` + +there are some generated [examples](https://github.com/Lbqds/eth-abi/tree/master/examples/src/main/scala/examples) + +### ABIEncoderV2 + +`eth-abi` support [experimental ABIEncoderV2](https://solidity.readthedocs.io/en/latest/abi-spec.html#handling-tuple-types) feature, +tuple will map to `TupleTypeN`, the generated [exchange](https://github.com/Lbqds/eth-abi/blob/master/examples/src/main/scala/examples/exchange/Exchange.scala) +use this feature heavily. + +### Sonatype + +`eth-abi` can also be used to interact directly with ethereum, please wait to publish diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..cec6cdd --- /dev/null +++ b/build.sbt @@ -0,0 +1,69 @@ +val commonSettings = Seq( + organization := "com.github.lbqds", + scalaVersion := "2.12.8", + version := "0.1", + scalacOptions ++= Seq( + "-encoding", "utf8", +// "-Xfatal-warnings", + "-deprecation", +// "-unchecked", + "-language:implicitConversions", + "-language:higherKinds", + "-language:existentials", +// "-Xlog-implicits", +// "-Xlog-implicit-conversions", + "-language:postfixOps"), + test in assembly := {} +) + +import xerial.sbt.Sonatype._ +val publishSettings = Seq( + publishTo := sonatypePublishTo.value, + sonatypeProfileName := "com.github.lbqds", + publishMavenStyle := true, + licenses := Seq("GPL" -> url("https://www.gnu.org/licenses/gpl-3.0.txt")), + sonatypeProjectHosting := Some(GitHubHosting("lbqds", "eth-abi", "lbqds@outlook.com")), + homepage := Some(url("https://github.com/lbqds")), + scmInfo := Some( + ScmInfo( + url("https://github.com/lbqds/eth-abi"), + "scm:git@github.com:lbqds/eth-abi.git" + ) + ), + developers := List( + Developer(id = "lbqds", name = "lbqds", email = "lbqds@outlook.com", url = new URL("https://github.com/lbqds")) + ), + publishConfiguration := publishConfiguration.value.withOverwrite(true), + publishLocalConfiguration := publishLocalConfiguration.value.withOverwrite(true) +) + +lazy val ethabi = + Project(id = "eth-abi", base = file(".")) + .settings(commonSettings) + .settings(name := "eth-abi") + .settings(Dependencies.deps) + .settings(publishSettings) + .enablePlugins(spray.boilerplate.BoilerplatePlugin) + .disablePlugins(sbtassembly.AssemblyPlugin) + +lazy val codegen = + Project(id = "codegen", base = file("codegen")) + .settings(commonSettings) + .dependsOn(ethabi) + .settings(Dependencies.codegenDeps) + .settings( + name := "codegen", + assemblyJarName := "abi-codegen.jar", + skip in publish := true + ) + +lazy val example = + Project(id = "examples", base = file("examples")) + .settings(commonSettings) + .settings(Dependencies.examplesDpes) + .dependsOn(ethabi) + .disablePlugins(sbtassembly.AssemblyPlugin) + .settings( + name := "examples", + skip in publish := true + ) diff --git a/codegen/src/main/scala/codegen/AbiDefinition.scala b/codegen/src/main/scala/codegen/AbiDefinition.scala new file mode 100644 index 0000000..95c6f0b --- /dev/null +++ b/codegen/src/main/scala/codegen/AbiDefinition.scala @@ -0,0 +1,183 @@ +package codegen + +import io.circe.jawn.decode +import io.circe.generic.auto._ +import scala.meta._ +import ethabi.util.{Hash, Hex} + +// fallback function have no name and inputs +case class AbiDefinition(`type`: String, name: Option[String], inputs: Option[Seq[Param]], outputs: Option[Seq[Param]], + stateMutability: Option[String], anonymous: Option[Boolean]) { + import AbiDefinition._ + def isPayable: Boolean = stateMutability.isDefined && stateMutability.get == "payable" + def isConstant: Boolean = stateMutability.isDefined && (stateMutability.get == "pure" || stateMutability.get == "view") + def isEvent: Boolean = `type` == "event" + def isFunction: Boolean = `type` == "function" + def isConstructor: Boolean = `type` == "constructor" + def isFallback: Boolean = `type` == "fallback" + def isAnonymous: Boolean = anonymous.isDefined && anonymous.get + + private [codegen] val signature = + if (isFunction || isEvent) name.map(_ + "(" + inputs.map(_.map(_.signature).mkString(",")).getOrElse("") + ")") + else None + private [codegen] val signatureHash = signature.map(sig => Hash.hash(sig.getBytes)) + private [codegen] val identifier = signatureHash.map(_.bytes.slice(0, 4)) + private val args = peel(inputs.map(_.map(p => Term.Param(List.empty, p.termName, Some(p.tpe), None)).toList)) + private val argsTpe = peel(inputs.map(_.map(_.tpe).toList)) + + private val returnType: Option[Type] = { + outputs match { + case None => None + case Some(params) if params.isEmpty => None + case Some(params) => Some(paramsToTuple(params)) + } + } + + private def funcArgsAndEncodeStat = { + val id = identifier.map(id => Hex.bytes2Hex(id)).getOrElse("") + val defaultEncodeStat = Term.Block(List(q"val encoded = Hex.hex2Bytes(${Lit.String(id)})")) + val encodeStat = for { + params <- args + paramsTpe <- argsTpe + } yield { + Term.Block(List( + q"val paramsEncoded = ${encodeParams(paramsTpe, params, params.map(_.name.asInstanceOf[Term.Name]))}", + q"val functionId = Hex.hex2Bytes(${Lit.String(id)})", + q"val encoded = functionId ++ paramsEncoded", + )) + } + (args.getOrElse(List.empty), encodeStat.getOrElse(defaultEncodeStat)) + } + + private def ctorArgsAndEncodeStat = { + val defaultEncodeStat = Term.Block(List(q"val encoded = Hex.hex2Bytes(binary)")) + val encodeStat = for { + params <- args + paramsTpe <- argsTpe + } yield { + Term.Block(List( + q"val paramsEncoded = ${encodeParams(paramsTpe, params, params.map(_.name.asInstanceOf[Term.Name]))}", + q"val code = Hex.hex2Bytes(binary)", + q"val encoded = code ++ paramsEncoded" + )) + } + (args.getOrElse(List.empty), encodeStat.getOrElse(defaultEncodeStat)) + } + + private [codegen] def genConstructor: Defn = { + assert(isConstructor) + val (args, encodeStat) = ctorArgsAndEncodeStat + val body = Term.Block(encodeStat.stats :+ q"impl.deploy(encoded, sender, opt)") + Defn.Def(List.empty, Term.Name("deploy"), List.empty, List(args :+ sender :+ opt), Some(Type.Name("Unit")), body) + } + + private def callAndDecodeStat(retTpe: Option[Type]) = { + if (retTpe.isDefined) { + Term.Block(List( + q""" + impl.call(encoded, sender, opt).map { bytes => + val result = ${decodeParams(retTpe.get, Term.Name("bytes"))} + result._1 + } + """ + )) + } else { + Term.Block(List( + q"impl.call(encoded, sender, opt)" + )) + } + } + + private def genConstantFunction(retTpe: Option[Type]): Defn = { + val (args, encodeStat) = funcArgsAndEncodeStat + val body = Term.Block(encodeStat.stats ++ callAndDecodeStat(retTpe).stats) + Defn.Def(List.empty, Term.Name(name.get), List.empty, List(args :+ sender :+ opt), retTpe.map(t => Type.Apply(Type.Name("Future"), List(t))), body) + } + + private def genTransactionFunction(retTpe: Option[Type]): Defn = { + val (args, encodeStat) = funcArgsAndEncodeStat + val body = Term.Block(encodeStat.stats :+ q"impl.sendTransaction(encoded, sender, opt)") + Defn.Def(List.empty, Term.Name(name.get), List.empty, List(args :+ sender :+ opt), retTpe, body) + } + + private [codegen] def genFunction: Defn = { + assert(isFunction && name.isDefined) + if (isConstant) genConstantFunction(returnType) + else genTransactionFunction(Some(defaultRetTpe)) + } + + private [codegen] def genEventDecodeFunc: Defn.Def = { + assert(isEvent && !isAnonymous && name.isDefined) + val typeInfosDecl = q"""var typeInfos = Seq.empty[TypeInfo[SolType]]""" + val indexedTypeInfos = inputs.map(_.filter(_.isIndexed).map(p => q"""typeInfos = typeInfos :+ implicitly[TypeInfo[${p.tpe}]]""")) + val nonIndexTypeInfo = inputs.flatMap { params => + val tpes = params.filter(!_.isIndexed).map(_.tpe).toList + if (tpes.nonEmpty) { + val tupleType = Type.Name(s"TupleType${tpes.length}") + Some(q"""typeInfos = typeInfos :+ implicitly[TypeInfo[${Type.Apply(tupleType, tpes)}]]""") + } else None + } + var stats: List[Stat] = List(typeInfosDecl) + if (indexedTypeInfos.isDefined) stats = stats ++ indexedTypeInfos.get + if (nonIndexTypeInfo.isDefined) stats = stats :+ nonIndexTypeInfo.get + stats = stats :+ q"""EventValue.decodeEvent(typeInfos, log)""" + Defn.Def(List.empty, Term.Name(s"decode${name.get.capitalize}"), List.empty, List(List(log)), Some(Type.Name("EventValue")), Term.Block(stats)) + } + + private [codegen] def genSubscribeEventFunc: Defn.Def = { + assert(isEvent && !isAnonymous && name.isDefined) + val funcName = Term.Name(s"subscribe${name.get.capitalize}") + val decodeFunc = Term.Name(s"decode${name.get.capitalize}") + val topic = signatureHash.get.toString + q""" + def $funcName: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash(${Lit.String(topic)})) + impl.subscribeLogs(query).map($decodeFunc) + } + """ + } + + private [codegen] def genEvent: List[Defn] = List(genEventDecodeFunc, genSubscribeEventFunc) +} + +object AbiDefinition { + private val defaultRetTpe = Type.Apply(Type.Name("Future"), List(Type.Name("Hash"))) + private val opt = Term.Param(List.empty, Term.Name("opt"), Some(Type.Name("TransactionOpt")), None) + private val sender = Term.Param(List.empty, Term.Name("sender"), Some(Type.Name("Address")), None) + private val log = Term.Param(List.empty, Term.Name("log"), Some(Type.Name("Log")), None) + + def apply(json: String): AbiDefinition = decode[AbiDefinition](json).right.get + + private def paramsToTuple(params: Seq[Param]): Type = { + if (params.length == 1) params.head.tpe + else { + val paramTypes = params.map(_.tpe) + val tupleType = Type.Name(s"TupleType${paramTypes.length}") + Type.Apply(tupleType, paramTypes.toList) + } + } + + private def encodeParams(paramsTpe: List[Type], params: List[Term.Param], inputs: List[Term.Name]): Term.Apply = { + val name = s"TupleType${params.length}" + val typeName = Type.Name(name) + val termName = Term.Name(name) + val applyFunc = Term.Select(termName, Term.Name("apply")) + val bundle = Term.Apply(Term.ApplyType(applyFunc, params.map(_.decltpe.get)), inputs) + val typeInfo = q"implicitly[TypeInfo[${Type.Apply(typeName, paramsTpe)}]]" + val encodeFunc = Term.Select(typeInfo, Term.Name("encode")) + Term.Apply(encodeFunc, List(bundle)) + } + + private def decodeParams(paramsTpe: Type, input: Term.Name): Term.Apply = { + val typeInfo = q"implicitly[TypeInfo[$paramsTpe]]" + val decodeFunc = Term.Select(typeInfo, Term.Name("decode")) + Term.Apply(decodeFunc, List(input, Lit.Int(0))) + } + + private def peel[Coll <: Traversable[_]](coll: Option[Coll]): Option[Coll] = { + coll match { + case Some(c) if c.isEmpty => None + case c => c + } + } +} diff --git a/codegen/src/main/scala/codegen/Codegen.scala b/codegen/src/main/scala/codegen/Codegen.scala new file mode 100644 index 0000000..70d6336 --- /dev/null +++ b/codegen/src/main/scala/codegen/Codegen.scala @@ -0,0 +1,58 @@ +package codegen + +import scala.io.Source +import io.circe.jawn.decode +import io.circe.generic.auto._ +import scala.meta._ + +object Codegen { + private def genImpl: List[Stat] = List( + q"private val impl = Contract(endpoint)", + q"import impl.dispatcher" + ) + private def genBinary(code: String): List[Stat] = List(q"""private val binary = ${Lit.String(code)}""") + private def genFunctions(abiDefinitions: Seq[AbiDefinition]): List[Stat] = + abiDefinitions.filter(_.isFunction).map(_.genFunction).toList + private def genCtor(abiDefinitions: Seq[AbiDefinition]): List[Stat] = + abiDefinitions.filter(_.isConstructor).map(_.genConstructor).toList + private def genEvent(abiDefinitions: Seq[AbiDefinition]): List[Stat] = + abiDefinitions.filter(_.isEvent).flatMap(_.genEvent).toList + private def genSupMethods: List[Stat] = { + val isDeployed = q"def isDeployed: Boolean = impl.isDeployed" + val contractAddress = q"def contractAddress: Address = impl.address.get" + val loadFrom = q"def loadFrom(contractAddress: Address) = impl.load(contractAddress)" + List(isDeployed, contractAddress, loadFrom) + } + + private def stats(abiFile: String, binFile: Option[String]) = { + val source = Source.fromFile(abiFile).getLines().mkString + val abiDefs = decode[Seq[AbiDefinition]](source).right.get + val code = binFile.map(f => Source.fromFile(f).getLines().mkString) + genImpl ::: genBinary(code.getOrElse("")) ::: genFunctions(abiDefs) ::: genCtor(abiDefs) ::: genEvent(abiDefs) ::: genSupMethods + } + + def codeGen(abiFile: String, binFile: Option[String], packages: List[String], className: String): Pkg = { + val contents = stats(abiFile, binFile) + val template = Template(List.empty, List.empty, Self(Term.Name("self"), None), contents) + val primary = Ctor.Primary(List.empty, Term.Name(className), List(List(Term.Param(List.empty, Term.Name("endpoint"), Some(Type.Name("String")), None)))) + val classDef = Defn.Class(List.empty, Type.Name(className), List.empty, primary, template) + val selector: (Term.Ref, Term.Name) => Term.Ref = (p, c) => Term.Select(p, c) + val packagesDef = packages.map(pkg => Term.Name(pkg)).reduceLeft(selector) + + q""" + package $packagesDef { + import akka.NotUsed + import akka.stream.scaladsl.Source + import ethabi.util.{Hex, Hash} + import ethabi.types._ + import ethabi.types.generated._ + import ethabi.protocol.{Contract, EventValue} + import ethabi.protocol.Request._ + import ethabi.protocol.Response.Log + import scala.concurrent.Future + + $classDef + } + """ + } +} diff --git a/codegen/src/main/scala/codegen/Main.scala b/codegen/src/main/scala/codegen/Main.scala new file mode 100644 index 0000000..b6efae0 --- /dev/null +++ b/codegen/src/main/scala/codegen/Main.scala @@ -0,0 +1,63 @@ +package codegen + +import java.io.{File, PrintWriter} + +import scopt.OParser + +object Main extends App { + def writeToFile(path: String, fileName: String, code: String): Unit = { + val dir = new File(path) + dir.mkdirs + new PrintWriter(path + s"/$fileName") { + write(code) + close() + } + } + + case class Params(abiFile: String = "", binFile: Option[String] = None, packages: String = "", className: String = "", output: String = "") + + val builder = OParser.builder[Params] + val cmdParser = { + import builder._ + OParser.sequence( + programName("abi-codegen"), + head("abi-codegen", "0.1"), + opt[String]('a', "abi") + .required() + .valueName("") + .action((value, params) => params.copy(abiFile = value)) + .text("contract abi file"), + opt[String]('b', "bin") + .optional() + .valueName("") + .action((value, params) => params.copy(binFile = Some(value))) + .text("contract bin file"), + opt[String]('p', "package") + .required() + .valueName("") + .action((value, params) => params.copy(packages = value)) + .text("""package name e.g. "examples.token""""), + opt[String]('c', "className") + .required() + .valueName("") + .action((value, params) => params.copy(className = value)) + .text("class name"), + opt[String]('o', "output") + .required() + .valueName("") + .action((value, params) => params.copy(output = value)) + .text("output directory"), + help('h', "help").text("show usage") + ) + } + + OParser.parse(cmdParser, args, Params()) match { + case Some(params) => + val header = "// AUTO GENERATED, DO NOT EDIT\n\n" + val code = Codegen.codeGen(params.abiFile, params.binFile, params.packages.split('.').toList, params.className) + val path = params.output + "/" + params.packages.split('.').mkString("/") + val fileName = s"${params.className}.scala" + writeToFile(path, fileName, header + code.syntax) + case None => println("invalid params, please refer to usage") + } +} diff --git a/codegen/src/main/scala/codegen/Param.scala b/codegen/src/main/scala/codegen/Param.scala new file mode 100644 index 0000000..7aae0bc --- /dev/null +++ b/codegen/src/main/scala/codegen/Param.scala @@ -0,0 +1,86 @@ +package codegen + +import scala.meta.{Type, Term} +import fastparse._ +import NoWhitespace._ + +// we assume that Tuple0 does not exist +case class Param(name: String, `type`: String, components: Option[Seq[Param]] = None, indexed: Option[Boolean] = None) { + private val canonical = { + if (`type` == "uint") "uint256" + else if (`type` == "int") "int256" + else `type` + } + private [codegen] val tpe: Type = parseType() + private [codegen] val termName: Term.Name = if (name.isEmpty) Term.fresh() else Term.Name(name) + private [codegen] val signature: String = { + if (canonical.startsWith("tuple")) { + val postfix = canonical.slice(5, `type`.length) + "(" + components.get.map(_.signature).mkString(",") + ")" + postfix + } else { + canonical + } + } + + private [codegen] def isIndexed: Boolean = indexed.isDefined && indexed.get + + private def parseType(): Type = { + def number[_ : P] = P(CharIn("0-9").rep.?.!.map(str => { + if (str.isEmpty) 0 // dynamic array + else str.toInt // static array + })) + + def uint[_ : P] = P("uint" ~ CharIn("0-9").rep.?) + def int[_ : P] = P("int" ~ CharIn("0-9").rep.?) + def address[_ : P] = P("address") + def bool[_ : P] = P("bool") + def string[_ : P] = P("string") + def bytes[_ : P] = P("bytes" ~ CharIn("0-9").rep.?) + def tuple[_ : P] = P("tuple") + def baseType[_ : P] = P(uint | int | address | bool | string | bytes | tuple) + def array[_ : P] = P(("[" ~ number ~ "]").rep.?) + def t[_ : P] = P(baseType.! ~ array.?) + + parse(`type`, t(_)) match { + case Parsed.Success((base, arr), _) => + val baseTypeName = typeName(base) + parseWithArray(baseTypeName, arr.get.get) + case failure: Parsed.Failure => throw new RuntimeException(s"parse type failed: $failure") + } + } + + private def parseWithArray(baseTypeName: String, arr: Seq[Int]): Type = { + val baseTpe = baseTypeName match { + case _ if baseTypeName == "TupleType" => + assert(components.isDefined && components.get.nonEmpty) + val componentTypes = components.get.map(_.parseType()) + val tupleType = Type.Name(s"TupleType${componentTypes.length}") + Type.Apply(tupleType, componentTypes.toList) + case _ => Type.Name(baseTypeName) + } + val dynamicArrayTpe = Type.Name("DynamicArray") + val staticArrayTpe = Type.Name("StaticArray") + arr.foldLeft(baseTpe)((acc, length) => { + if (length == 0) Type.Apply(dynamicArrayTpe, List(acc)) + else Type.Apply(staticArrayTpe, List(acc)) + }) + } + + private def typeName(base: String): String = { + base match { + case _ if base == "uint" => "uint256".capitalize + case _ if base == "int" => "int256".capitalize + case _ if base == "bytes" => "DynamicBytes" + case _ if base == "string" => "StringType" + case _ if base == "bool" => "Bool" + case _ if base == "tuple" => "TupleType" + case n => n.capitalize + } + } +} + +object Param { + import io.circe.jawn.decode + import io.circe.generic.auto._ + def apply(json: String): Param = decode[Param](json).right.get +} \ No newline at end of file diff --git a/codegen/src/test/scala/codegen/AbiDefinitionSpec.scala b/codegen/src/test/scala/codegen/AbiDefinitionSpec.scala new file mode 100644 index 0000000..343232a --- /dev/null +++ b/codegen/src/test/scala/codegen/AbiDefinitionSpec.scala @@ -0,0 +1,197 @@ +package codegen + +class AbiDefinitionSpec extends WordSpec with Matchers { + "test gen const function" in { + val json = + """ + |{ + | "constant": true, + | "inputs": [ + | { + | "name": "", + | "type": "bytes32" + | } + | ], + | "name": "filled", + | "outputs": [ + | { + | "name": "", + | "type": "uint256" + | } + | ], + | "payable": false, + | "stateMutability": "view", + | "type": "function" + |} + """.stripMargin + val entity = AbiDefinition(json) + entity.name shouldBe Some("filled") + entity.`type` shouldBe "function" + } + + "test gen non-const function" in { + val json = + """ + |{ + | "constant": false, + | "inputs": [ + | { + | "components": [ + | { + | "name": "makerAddress", + | "type": "address" + | }, + | { + | "name": "takerAddress", + | "type": "address" + | }, + | { + | "name": "feeRecipientAddress", + | "type": "address" + | }, + | { + | "name": "senderAddress", + | "type": "address" + | }, + | { + | "name": "makerAssetAmount", + | "type": "uint256" + | }, + | { + | "name": "takerAssetAmount", + | "type": "uint256" + | }, + | { + | "name": "makerFee", + | "type": "uint256" + | }, + | { + | "name": "takerFee", + | "type": "uint256" + | }, + | { + | "name": "expirationTimeSeconds", + | "type": "uint256" + | }, + | { + | "name": "salt", + | "type": "uint256" + | }, + | { + | "name": "makerAssetData", + | "type": "bytes" + | }, + | { + | "name": "takerAssetData", + | "type": "bytes" + | } + | ], + | "name": "orders", + | "type": "tuple[]" + | }, + | { + | "name": "takerAssetFillAmounts", + | "type": "uint256[]" + | }, + | { + | "name": "signatures", + | "type": "bytes[]" + | } + | ], + | "name": "batchFillOrders", + | "outputs": [ + | { + | "components": [ + | { + | "name": "makerAssetFilledAmount", + | "type": "uint256" + | }, + | { + | "name": "takerAssetFilledAmount", + | "type": "uint256" + | }, + | { + | "name": "makerFeePaid", + | "type": "uint256" + | }, + | { + | "name": "takerFeePaid", + | "type": "uint256" + | } + | ], + | "name": "totalFillResults", + | "type": "tuple" + | } + | ], + | "payable": false, + | "stateMutability": "nonpayable", + | "type": "function" + |} + """.stripMargin + val entity = AbiDefinition(json) + entity.signature.get shouldBe "batchFillOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],uint256[],bytes[])" + Hex.bytes2Hex(entity.identifier.get) shouldBe "297bb70b" + } + + "test function signature" in { + val json = + """ + |{ + | "name": "f", + | "type": "function", + | "inputs": [ + | { + | "name": "s", + | "type": "tuple", + | "components": [ + | { + | "name": "a", + | "type": "uint256" + | }, + | { + | "name": "b", + | "type": "uint256[]" + | }, + | { + | "name": "c", + | "type": "tuple[4]", + | "components": [ + | { + | "name": "x", + | "type": "uint256" + | }, + | { + | "name": "y", + | "type": "uint256" + | } + | ] + | } + | ] + | }, + | { + | "name": "t", + | "type": "tuple", + | "components": [ + | { + | "name": "x", + | "type": "uint256" + | }, + | { + | "name": "y", + | "type": "uint256" + | } + | ] + | }, + | { + | "name": "a", + | "type": "uint256" + | } + | ], + | "outputs": [] + |} + """.stripMargin + val entity = AbiDefinition(json) + entity.signature.get shouldBe "f((uint256,uint256[],(uint256,uint256)[4]),(uint256,uint256),uint256)" + Hex.bytes2Hex(entity.identifier.get) shouldBe "df297bad" + } +} diff --git a/codegen/src/test/scala/codegen/ParamSpec.scala b/codegen/src/test/scala/codegen/ParamSpec.scala new file mode 100644 index 0000000..c1918d5 --- /dev/null +++ b/codegen/src/test/scala/codegen/ParamSpec.scala @@ -0,0 +1,210 @@ +package codegen + +class ParamSpec extends WordSpec with Matchers { + "test deserialize argument(without components)" in { + val json = """{"name":"balance","type":"uint256"}""" + val argument = decode[Param](json).right.get + argument.name shouldBe "balance" + argument.`type` shouldBe "uint256" + argument.components shouldBe None + argument.indexed shouldBe None + } + + "test serialize argument(without components)" in { + val argument = Param(name = "balance", `type` = "uint256", components = None, indexed = None) + val json = argument.asJson.noSpaces + json shouldBe """{"name":"balance","type":"uint256","components":null,"indexed":null}""" + } + + "test deserialize argument(with components)" in { + val json = """{"name":"account","type":"tuple","components":[{"name":"name","type":"string"}],"indexed":null}""" + val argument = decode[Param](json).right.get + argument.name shouldBe "account" + argument.`type` shouldBe "tuple" + argument.components.get.head.name shouldBe "name" + argument.components.get.head.`type` shouldBe "string" + argument.indexed shouldBe None + } + + "test serialize argument(with components)" in { + val argument = Param("account", "tuple", Some(Seq(Param("name", "string"))), None) + val json = argument.asJson.noSpaces + json shouldBe """{"name":"account","type":"tuple","components":[{"name":"name","type":"string","components":null,"indexed":null}],"indexed":null}""" + } + + "test deserialize nested arguments" in { + val json = + """ + |{ + | "name": "s", + | "type": "tuple", + | "components": [ + | { + | "name": "a", + | "type": "uint256" + | }, + | { + | "name": "b", + | "type": "uint256[]" + | }, + | { + | "name": "c", + | "type": "tuple[]", + | "components": [ + | { + | "name": "x", + | "type": "uint256" + | }, + | { + | "name": "y", + | "type": "uint256" + | } + | ] + | } + | ] + |} + """.stripMargin + val result = decode[Param](json).right.get + val components = result.components.get + components.length shouldBe 3 + val nested = components(2) + nested.components.get.length shouldBe 2 + nested.`type` shouldBe "tuple[]" + nested.name shouldBe "c" + } + + "test param type" in { + val json = """{"name":"array","type":"uint16[4][5]"}""" + val param = Param(json) + param.tpe.syntax shouldBe "StaticArray[StaticArray[Uint16]]" + } + + "test param type(with tuple)" in { + val json = + """ + |{ + | "name": "whatever", + | "type": "tuple", + | "components": [ + | {"name": "whatever", "type": "uint"}, + | {"name": "whatever", "type": "int"}, + | {"name": "whatever", "type": "bytes"} + | ] + |} + """.stripMargin + val param = Param(json) + param.tpe.syntax shouldBe "TupleType3[Uint256, Int256, DynamicBytes]" + } + + "test param type(with nested params)" in { + val json = + """ + |{ + | "name": "s", + | "type": "tuple", + | "components": [ + | { + | "name": "a", + | "type": "bytes12" + | }, + | { + | "name": "b", + | "type": "address[]" + | }, + | { + | "name": "c", + | "type": "tuple[]", + | "components": [ + | { + | "name": "x", + | "type": "bool" + | }, + | { + | "name": "y", + | "type": "string" + | } + | ] + | }, + | { + | "name": "d", + | "type": "string[]" + | } + | ] + |} + """.stripMargin + val param = Param(json) + param.tpe.syntax shouldBe "TupleType4[Bytes12, DynamicArray[Address], DynamicArray[TupleType2[Bool, StringType]], DynamicArray[StringType]]" + } + + "test param signature(with nested tuple dynamic array)" in { + val json = + """ + |{ + | "name": "s", + | "type": "tuple", + | "components": [ + | { + | "name": "a", + | "type": "uint256" + | }, + | { + | "name": "b", + | "type": "uint256[]" + | }, + | { + | "name": "c", + | "type": "tuple[]", + | "components": [ + | { + | "name": "x", + | "type": "uint256" + | }, + | { + | "name": "y", + | "type": "uint256" + | } + | ] + | } + | ] + |} + """.stripMargin + val param = Param(json) + param.signature shouldBe "(uint256,uint256[],(uint256,uint256)[])" + } + + "test param signature(with nested tuple static array)" in { + val json = + """ + |{ + | "name": "s", + | "type": "tuple", + | "components": [ + | { + | "name": "a", + | "type": "uint256" + | }, + | { + | "name": "b", + | "type": "uint256[]" + | }, + | { + | "name": "c", + | "type": "tuple[4]", + | "components": [ + | { + | "name": "x", + | "type": "uint256" + | }, + | { + | "name": "y", + | "type": "uint256" + | } + | ] + | } + | ] + |} + """.stripMargin + val param = Param(json) + param.signature shouldBe "(uint256,uint256[],(uint256,uint256)[4])" + } +} \ No newline at end of file diff --git a/examples/src/main/resources/Exchange.abi b/examples/src/main/resources/Exchange.abi new file mode 100644 index 0000000..235854e --- /dev/null +++ b/examples/src/main/resources/Exchange.abi @@ -0,0 +1,1993 @@ +[ + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"bytes32" + } + ], + "name":"filled", + "outputs":[ + { + "name":"", + "type":"uint256" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"takerAssetFillAmounts", + "type":"uint256[]" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"batchFillOrders", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"bytes32" + } + ], + "name":"cancelled", + "outputs":[ + { + "name":"", + "type":"bool" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"hash", + "type":"bytes32" + }, + { + "name":"signerAddress", + "type":"address" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"preSign", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"leftOrder", + "type":"tuple" + }, + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"rightOrder", + "type":"tuple" + }, + { + "name":"leftSignature", + "type":"bytes" + }, + { + "name":"rightSignature", + "type":"bytes" + } + ], + "name":"matchOrders", + "outputs":[ + { + "components":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"left", + "type":"tuple" + }, + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"right", + "type":"tuple" + }, + { + "name":"leftMakerAssetSpreadAmount", + "type":"uint256" + } + ], + "name":"matchedFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"order", + "type":"tuple" + }, + { + "name":"takerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"fillOrderNoThrow", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"fillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"bytes4" + } + ], + "name":"assetProxies", + "outputs":[ + { + "name":"", + "type":"address" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + } + ], + "name":"batchCancelOrders", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"takerAssetFillAmounts", + "type":"uint256[]" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"batchFillOrKillOrders", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"targetOrderEpoch", + "type":"uint256" + } + ], + "name":"cancelOrdersUpTo", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"takerAssetFillAmounts", + "type":"uint256[]" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"batchFillOrdersNoThrow", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"assetProxyId", + "type":"bytes4" + } + ], + "name":"getAssetProxy", + "outputs":[ + { + "name":"", + "type":"address" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"bytes32" + } + ], + "name":"transactions", + "outputs":[ + { + "name":"", + "type":"bool" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"order", + "type":"tuple" + }, + { + "name":"takerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"fillOrKillOrder", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"fillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"validatorAddress", + "type":"address" + }, + { + "name":"approval", + "type":"bool" + } + ], + "name":"setSignatureValidatorApproval", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"address" + }, + { + "name":"", + "type":"address" + } + ], + "name":"allowedValidators", + "outputs":[ + { + "name":"", + "type":"bool" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"takerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"marketSellOrders", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + } + ], + "name":"getOrdersInfo", + "outputs":[ + { + "components":[ + { + "name":"orderStatus", + "type":"uint8" + }, + { + "name":"orderHash", + "type":"bytes32" + }, + { + "name":"orderTakerAssetFilledAmount", + "type":"uint256" + } + ], + "name":"", + "type":"tuple[]" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"bytes32" + }, + { + "name":"", + "type":"address" + } + ], + "name":"preSigned", + "outputs":[ + { + "name":"", + "type":"bool" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":true, + "inputs":[ + + ], + "name":"owner", + "outputs":[ + { + "name":"", + "type":"address" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"hash", + "type":"bytes32" + }, + { + "name":"signerAddress", + "type":"address" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"isValidSignature", + "outputs":[ + { + "name":"isValid", + "type":"bool" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"makerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"marketBuyOrdersNoThrow", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"order", + "type":"tuple" + }, + { + "name":"takerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"fillOrder", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"fillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"salt", + "type":"uint256" + }, + { + "name":"signerAddress", + "type":"address" + }, + { + "name":"data", + "type":"bytes" + }, + { + "name":"signature", + "type":"bytes" + } + ], + "name":"executeTransaction", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"assetProxy", + "type":"address" + } + ], + "name":"registerAssetProxy", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"order", + "type":"tuple" + } + ], + "name":"getOrderInfo", + "outputs":[ + { + "components":[ + { + "name":"orderStatus", + "type":"uint8" + }, + { + "name":"orderHash", + "type":"bytes32" + }, + { + "name":"orderTakerAssetFilledAmount", + "type":"uint256" + } + ], + "name":"orderInfo", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"order", + "type":"tuple" + } + ], + "name":"cancelOrder", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + { + "name":"", + "type":"address" + }, + { + "name":"", + "type":"address" + } + ], + "name":"orderEpoch", + "outputs":[ + { + "name":"", + "type":"uint256" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":true, + "inputs":[ + + ], + "name":"ZRX_ASSET_DATA", + "outputs":[ + { + "name":"", + "type":"bytes" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"takerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"marketSellOrdersNoThrow", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + + ], + "name":"EIP712_DOMAIN_HASH", + "outputs":[ + { + "name":"", + "type":"bytes32" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "components":[ + { + "name":"makerAddress", + "type":"address" + }, + { + "name":"takerAddress", + "type":"address" + }, + { + "name":"feeRecipientAddress", + "type":"address" + }, + { + "name":"senderAddress", + "type":"address" + }, + { + "name":"makerAssetAmount", + "type":"uint256" + }, + { + "name":"takerAssetAmount", + "type":"uint256" + }, + { + "name":"makerFee", + "type":"uint256" + }, + { + "name":"takerFee", + "type":"uint256" + }, + { + "name":"expirationTimeSeconds", + "type":"uint256" + }, + { + "name":"salt", + "type":"uint256" + }, + { + "name":"makerAssetData", + "type":"bytes" + }, + { + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"orders", + "type":"tuple[]" + }, + { + "name":"makerAssetFillAmount", + "type":"uint256" + }, + { + "name":"signatures", + "type":"bytes[]" + } + ], + "name":"marketBuyOrders", + "outputs":[ + { + "components":[ + { + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "name":"makerFeePaid", + "type":"uint256" + }, + { + "name":"takerFeePaid", + "type":"uint256" + } + ], + "name":"totalFillResults", + "type":"tuple" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + + ], + "name":"currentContextAddress", + "outputs":[ + { + "name":"", + "type":"address" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "constant":false, + "inputs":[ + { + "name":"newOwner", + "type":"address" + } + ], + "name":"transferOwnership", + "outputs":[ + + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"function" + }, + { + "constant":true, + "inputs":[ + + ], + "name":"VERSION", + "outputs":[ + { + "name":"", + "type":"string" + } + ], + "payable":false, + "stateMutability":"view", + "type":"function" + }, + { + "inputs":[ + { + "name":"_zrxAssetData", + "type":"bytes" + } + ], + "payable":false, + "stateMutability":"nonpayable", + "type":"constructor" + }, + { + "anonymous":false, + "inputs":[ + { + "indexed":true, + "name":"signerAddress", + "type":"address" + }, + { + "indexed":true, + "name":"validatorAddress", + "type":"address" + }, + { + "indexed":false, + "name":"approved", + "type":"bool" + } + ], + "name":"SignatureValidatorApproval", + "type":"event" + }, + { + "anonymous":false, + "inputs":[ + { + "indexed":true, + "name":"makerAddress", + "type":"address" + }, + { + "indexed":true, + "name":"feeRecipientAddress", + "type":"address" + }, + { + "indexed":false, + "name":"takerAddress", + "type":"address" + }, + { + "indexed":false, + "name":"senderAddress", + "type":"address" + }, + { + "indexed":false, + "name":"makerAssetFilledAmount", + "type":"uint256" + }, + { + "indexed":false, + "name":"takerAssetFilledAmount", + "type":"uint256" + }, + { + "indexed":false, + "name":"makerFeePaid", + "type":"uint256" + }, + { + "indexed":false, + "name":"takerFeePaid", + "type":"uint256" + }, + { + "indexed":true, + "name":"orderHash", + "type":"bytes32" + }, + { + "indexed":false, + "name":"makerAssetData", + "type":"bytes" + }, + { + "indexed":false, + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"Fill", + "type":"event" + }, + { + "anonymous":false, + "inputs":[ + { + "indexed":true, + "name":"makerAddress", + "type":"address" + }, + { + "indexed":true, + "name":"feeRecipientAddress", + "type":"address" + }, + { + "indexed":false, + "name":"senderAddress", + "type":"address" + }, + { + "indexed":true, + "name":"orderHash", + "type":"bytes32" + }, + { + "indexed":false, + "name":"makerAssetData", + "type":"bytes" + }, + { + "indexed":false, + "name":"takerAssetData", + "type":"bytes" + } + ], + "name":"Cancel", + "type":"event" + }, + { + "anonymous":false, + "inputs":[ + { + "indexed":true, + "name":"makerAddress", + "type":"address" + }, + { + "indexed":true, + "name":"senderAddress", + "type":"address" + }, + { + "indexed":false, + "name":"orderEpoch", + "type":"uint256" + } + ], + "name":"CancelUpTo", + "type":"event" + }, + { + "anonymous":false, + "inputs":[ + { + "indexed":false, + "name":"id", + "type":"bytes4" + }, + { + "indexed":false, + "name":"assetProxy", + "type":"address" + } + ], + "name":"AssetProxyRegistered", + "type":"event" + } +] \ No newline at end of file diff --git a/examples/src/main/resources/Exchange.bin b/examples/src/main/resources/Exchange.bin new file mode 100644 index 0000000..8a30a88 --- /dev/null +++ b/examples/src/main/resources/Exchange.bin @@ -0,0 +1 @@ +608060405260008060006101000a81548160ff0219169083151502179055503480156200002b57600080fd5b50604051620077c2380380620077c2833981018060405262000051919081019062000515565b8080600190805190602001906200006a92919062000408565b505060405160200180807f454950373132446f6d61696e2800000000000000000000000000000000000000815250600d01807f737472696e67206e616d652c0000000000000000000000000000000000000000815250600c01807f737472696e672076657273696f6e2c0000000000000000000000000000000000815250600f01807f6164647265737320766572696679696e67436f6e747261637400000000000000815250601901807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b6020831015156200018357805182526020820191506020810190506020830392506200015c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206040805190810160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518082805190602001908083835b6020831015156200021d5780518252602082019150602081019050602083039250620001f6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206040805190810160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506040518082805190602001908083835b602083101515620002b7578051825260208201915060208101905060208303925062000290565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390203073ffffffffffffffffffffffffffffffffffffffff166001026040516020018085600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019450505050506040516020818303038152906040526040518082805190602001908083835b60208310151562000389578051825260208201915060208101905060208303925062000362565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206002816000191690555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050620005eb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044b57805160ff19168380011785556200047c565b828001600101855582156200047c579182015b828111156200047b5782518255916020019190600101906200045e565b5b5090506200048b91906200048f565b5090565b620004b491905b80821115620004b057600081600090555060010162000496565b5090565b90565b600082601f8301121515620004cb57600080fd5b8151620004e2620004dc8262000588565b6200055a565b91508082526020830160208301858383011115620004ff57600080fd5b6200050c838284620005b5565b50505092915050565b6000602082840312156200052857600080fd5b600082015167ffffffffffffffff8111156200054357600080fd5b6200055184828501620004b7565b91505092915050565b6000604051905081810181811067ffffffffffffffff821117156200057e57600080fd5b8060405250919050565b600067ffffffffffffffff821115620005a057600080fd5b601f19601f8301169050602081019050919050565b60005b83811015620005d5578082015181840152602081019050620005b8565b83811115620005e5576000848401525b50505050565b6171c780620005fb6000396000f3006080604052600436106101b7576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063288cdc91146101bc578063297bb70b146101f95780632ac12622146102365780633683ef8e146102735780633c28d8611461029c5780633e228bae146102d95780633fd3c997146103165780634ac14782146103535780634d0ae5461461037c5780634f9559b1146103b957806350dde190146103e2578063607041081461041f578063642f2eaf1461045c57806364a3bc151461049957806377fcce68146104d65780637b8e3514146104ff5780637e1d98081461053c5780637e9d74dc1461057957806382c174d0146105b65780638da5cb5b146105f3578063936347021461061e578063a3e203801461065b578063b4be83d514610698578063bfc8bfce146106d5578063c585bb93146106fe578063c75e0a8114610727578063d46b02c314610764578063d9bfa73e1461078d578063db123b1a146107ca578063dd1c7d18146107f5578063e306f77914610832578063e5fa431b1461085d578063eea086ba1461089a578063f2fde38b146108c5578063ffa1ad74146108ee575b600080fd5b3480156101c857600080fd5b506101e360048036036101de91908101906159c2565b610919565b6040516101f09190616ee5565b60405180910390f35b34801561020557600080fd5b50610220600480360361021b91908101906158ac565b610931565b60405161022d9190616e93565b60405180910390f35b34801561024257600080fd5b5061025d600480360361025891908101906159c2565b610a51565b60405161026a9190616902565b60405180910390f35b34801561027f57600080fd5b5061029a60048036036102959190810190615a27565b610a71565b005b3480156102a857600080fd5b506102c360048036036102be9190810190615b8d565b610b9c565b6040516102d09190616eae565b60405180910390f35b3480156102e557600080fd5b5061030060048036036102fb9190810190615c50565b610d47565b60405161030d9190616e93565b60405180910390f35b34801561032257600080fd5b5061033d60048036036103389190810190615afa565b610d9f565b60405161034a9190616a36565b60405180910390f35b34801561035f57600080fd5b5061037a6004803603610375919081019061586b565b610dd2565b005b34801561038857600080fd5b506103a3600480360361039e91908101906158ac565b610e9e565b6040516103b09190616e93565b60405180910390f35b3480156103c557600080fd5b506103e060048036036103db9190810190615ccf565b610fbe565b005b3480156103ee57600080fd5b50610409600480360361040491908101906158ac565b611247565b6040516104169190616e93565b60405180910390f35b34801561042b57600080fd5b5061044660048036036104419190810190615afa565b6112e2565b60405161045391906167f4565b60405180910390f35b34801561046857600080fd5b50610483600480360361047e91908101906159c2565b61135d565b6040516104909190616902565b60405180910390f35b3480156104a557600080fd5b506104c060048036036104bb9190810190615c50565b61137d565b6040516104cd9190616e93565b60405180910390f35b3480156104e257600080fd5b506104fd60048036036104f8919081019061582f565b611421565b005b34801561050b57600080fd5b50610526600480360361052191908101906157f3565b6115b0565b6040516105339190616902565b60405180910390f35b34801561054857600080fd5b50610563600480360361055e9190810190615943565b6115df565b6040516105709190616e93565b60405180910390f35b34801561058557600080fd5b506105a0600480360361059b919081019061586b565b611751565b6040516105ad91906168e0565b60405180910390f35b3480156105c257600080fd5b506105dd60048036036105d891908101906159eb565b6117fb565b6040516105ea9190616902565b60405180910390f35b3480156105ff57600080fd5b5061060861182a565b60405161061591906167f4565b60405180910390f35b34801561062a57600080fd5b5061064560048036036106409190810190615a93565b611850565b6040516106529190616902565b60405180910390f35b34801561066757600080fd5b50610682600480360361067d9190810190615943565b611fcf565b60405161068f9190616e93565b60405180910390f35b3480156106a457600080fd5b506106bf60048036036106ba9190810190615c50565b612101565b6040516106cc9190616e93565b60405180910390f35b3480156106e157600080fd5b506106fc60048036036106f79190810190615cf8565b6121a5565b005b34801561070a57600080fd5b50610725600480360361072091908101906157ca565b612511565b005b34801561073357600080fd5b5061074e60048036036107499190810190615b4c565b6127fd565b60405161075b9190616eca565b60405180910390f35b34801561077057600080fd5b5061078b60048036036107869190810190615b4c565b612a4f565b005b34801561079957600080fd5b506107b460048036036107af91908101906157f3565b612ae0565b6040516107c19190616ee5565b60405180910390f35b3480156107d657600080fd5b506107df612b05565b6040516107ec9190616a14565b60405180910390f35b34801561080157600080fd5b5061081c60048036036108179190810190615943565b612ba3565b6040516108299190616e93565b60405180910390f35b34801561083e57600080fd5b50610847612c90565b604051610854919061691d565b60405180910390f35b34801561086957600080fd5b50610884600480360361087f9190810190615943565b612c96565b6040516108919190616e93565b60405180910390f35b3480156108a657600080fd5b506108af612e4d565b6040516108bc91906167f4565b60405180910390f35b3480156108d157600080fd5b506108ec60048036036108e791908101906157ca565b612e73565b005b3480156108fa57600080fd5b50610903612f80565b6040516109109190616a51565b60405180910390f35b60046020528060005260406000206000915090505481565b61093961517c565b60008061094461517c565b6000809054906101000a900460ff16151515610995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098c90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555086519250600091505b8282141515610a2a57610a1187838151811015156109d257fe5b9060200190602002015187848151811015156109ea57fe5b906020019060200201518785815181101515610a0257fe5b90602001906020020151612fb9565b9050610a1d848261305a565b81806001019250506109b8565b83935060008060006101000a81548160ff0219169083151502179055505050509392505050565b60056020528060005260406000206000915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515610b2557610ae3848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611850565b1515610b24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1b90616bf3565b60405180910390fd5b5b600160076000866000191660001916815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b610ba46151a5565b610bac6151d4565b610bb46151d4565b60008060009054906101000a900460ff16151515610c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfe90616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550876101600151876101400181905250876101400151876101600181905250610c48886127fd565b9250610c53876127fd565b9150610c5d6130ca565b9050610c6b8884838961313a565b610c778783838861313a565b610c81888861335a565b610c958888856040015185604001516133c5565b9350610cbc88848660000151602001518760000151602001518860000151600001516135b2565b610ce187838660200151602001518760200151602001518860200151600001516135b2565b610cfa88828560200151866040015188600001516136f9565b610d1387828460200151856040015188602001516136f9565b610d1f888883876137c7565b83935060008060006101000a81548160ff021916908315150217905550505050949350505050565b610d4f61517c565b6060610d5c85858561399b565b9050608081825160208401305af48015610d9357815183526020820151602084015260408201516040840152606082015160608401525b50819150509392505050565b600b6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000809054906101000a900460ff16151515610e26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1d90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555082519150600090505b8181141515610e7f57610e728382815181101515610e6357fe5b90602001906020020151613b8a565b8080600101915050610e49565b60008060006101000a81548160ff021916908315150217905550505050565b610ea661517c565b600080610eb161517c565b6000809054906101000a900460ff16151515610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef990616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555086519250600091505b8282141515610f9757610f7e8783815181101515610f3f57fe5b906020019060200201518784815181101515610f5757fe5b906020019060200201518785815181101515610f6f57fe5b90602001906020020151613bb9565b9050610f8a848261305a565b8180600101925050610f25565b83935060008060006101000a81548160ff0219169083151502179055505050509392505050565b6000806000806000809054906101000a900460ff16151515611015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100c90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506110376130ca565b93503373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146110725733611075565b60005b9250600185019150600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508082111515611140576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113790616d13565b60405180910390fd5b81600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f08460405161121e9190616ee5565b60405180910390a360008060006101000a81548160ff0219169083151502179055505050505050565b61124f61517c565b60008061125a61517c565b86519250600091505b82821415156112d5576112bc878381518110151561127d57fe5b90602001906020020151878481518110151561129557fe5b9060200190602002015187858151811015156112ad57fe5b90602001906020020151610d47565b90506112c8848261305a565b8180600101925050611263565b8393505050509392505050565b6000600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60096020528060005260406000206000915054906101000a900460ff1681565b61138561517c565b6000809054906101000a900460ff161515156113d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113cd90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506113fb848484613bb9565b905080905060008060006101000a81548160ff0219169083151502179055509392505050565b60008060009054906101000a900460ff16151515611474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146b90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506114966130ca565b905081600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba891846040516115899190616902565b60405180910390a360008060006101000a81548160ff021916908315150217905550505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6115e761517c565b606060008060006115f661517c565b6000809054906101000a900460ff16151515611647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163e90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555088600081518110151561167057fe5b906020019060200201516101600151945088519350600092505b8383141515611728578489848151811015156116a257fe5b9060200190602002015161016001819052506116c2888760200151613c20565b91506116fd89848151811015156116d557fe5b906020019060200201518389868151811015156116ee57fe5b90602001906020020151612fb9565b9050611709868261305a565b87866020015110151561171b57611728565b828060010193505061168a565b85955060008060006101000a81548160ff02191690831515021790555050505050509392505050565b6060600060606000845192508260405190808252806020026020018201604052801561179757816020015b6117846151fc565b81526020019060019003908161177c5790505b509150600090505b82811415156117f0576117c885828151811015156117b957fe5b906020019060200201516127fd565b82828151811015156117d657fe5b90602001906020020181905250808060010191505061179f565b819350505050919050565b60076020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600080600080600080600089511115156118a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189990616cf3565b60405180910390fd5b6118ab89613c72565b7f0100000000000000000000000000000000000000000000000000000000000000900496506007808111156118dc57fe5b60ff168760ff16101515611925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191c90616b33565b60405180910390fd5b8660ff16600781111561193457fe5b95506000600781111561194357fe5b86600781111561194f57fe5b1415611990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198790616cd3565b60405180910390fd5b6001600781111561199d57fe5b8660078111156119a957fe5b1415611a0157600089511415156119f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ec90616e73565b60405180910390fd5b60009750879750611fc1565b60026007811115611a0e57fe5b866007811115611a1a57fe5b1415611b9d5760418951141515611a66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5d90616a73565b60405180910390fd5b886000815181101515611a7557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049450611af960018a613d2990919063ffffffff16565b9350611b0f60218a613d2990919063ffffffff16565b925060018b86868660405160008152602001604052604051611b3494939291906169a6565b60206040516020810390808403906000865af1158015611b58573d6000803e3d6000fd5b5050506020604051035191508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16149750879750611fc1565b60036007811115611baa57fe5b866007811115611bb657fe5b1415611dea5760418951141515611c02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf990616a73565b60405180910390fd5b886000815181101515611c1157fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049450611c9560018a613d2990919063ffffffff16565b9350611cab60218a613d2990919063ffffffff16565b925060018b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083101515611d345780518252602082019150602081019050602083039250611d0f565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902086868660405160008152602001604052604051611d8194939291906169a6565b60206040516020810390808403906000865af1158015611da5573d6000803e3d6000fd5b5050506020604051035191508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16149750879750611fc1565b60046007811115611df757fe5b866007811115611e0357fe5b1415611e1e57611e148b8b8b613d89565b9750879750611fc1565b60056007811115611e2b57fe5b866007811115611e3757fe5b1415611ef757611e4689613ee3565b9050600860008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611ee15760009750611fc1565b611eed818c8c8c613f4d565b9750879750611fc1565b60066007811115611f0457fe5b866007811115611f1057fe5b1415611f8657600760008c6000191660001916815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169750879750611fc1565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb890616b33565b60405180910390fd5b505050505050509392505050565b611fd761517c565b6060600080600080611fe761517c565b896000815181101515611ff657fe5b906020019060200201516101400151955089519450600093505b84841415156120f157858a8581518110151561202857fe5b906020019060200201516101400181905250612048898860000151613c20565b925061208b8a8581518110151561205b57fe5b9060200190602002015160a001518b8681518110151561207757fe5b9060200190602002015160800151856140aa565b91506120c68a8581518110151561209e57fe5b90602001906020020151838a878151811015156120b757fe5b90602001906020020151610d47565b90506120d2878261305a565b8887600001511015156120e4576120f1565b8380600101945050612010565b8696505050505050509392505050565b61210961517c565b6000809054906101000a900460ff1615151561215a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215190616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555061217f848484612fb9565b905080905060008060006101000a81548160ff0219169083151502179055509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515612239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223090616d93565b60405180910390fd5b61227e612279888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061410f565b6142fe565b905060096000826000191660001916815260200190815260200160002060009054906101000a900460ff161515156122eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122e290616bd3565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415156123e05761235d818785858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611850565b151561239e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239590616e53565b60405180910390fd5b85600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b600160096000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055503073ffffffffffffffffffffffffffffffffffffffff16858560405180838380828437820191505092505050600060405180830381855af49150501515612490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248790616c33565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141515612508576000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505050505050565b6000806000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156125a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259f90616db3565b60405180910390fd5b8392508273ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561260f57600080fd5b505af1158015612623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126479190810190615b23565b9150600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151561272e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161272590616af3565b60405180910390fd5b82600b6000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c0319482856040516127ef9291906169eb565b60405180910390a150505050565b6128056151d4565b61280e82614348565b81602001906000191690816000191681525050600460008260200151600019166000191681526020019081526020016000205481604001818152505060008260800151141561287d576001600681111561286457fe5b816000019060ff16908160ff1681525050809050612a4a565b60008260a0015114156128b0576002600681111561289757fe5b816000019060ff16908160ff1681525050809050612a4a565b8160a0015181604001511015156128e757600560068111156128ce57fe5b816000019060ff16908160ff1681525050809050612a4a565b8161010001514210151561291b576004600681111561290257fe5b816000019060ff16908160ff1681525050809050612a4a565b6005600082602001516000191660001916815260200190815260200160002060009054906101000a900460ff16156129725760068081111561295957fe5b816000019060ff16908160ff1681525050809050612a4a565b81610120015160066000846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000846060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612a2857600680811115612a0f57fe5b816000019060ff16908160ff1681525050809050612a4a565b60036006811115612a3557fe5b816000019060ff16908160ff16815250508090505b919050565b6000809054906101000a900460ff16151515612aa0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9790616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550612ac381613b8a565b60008060006101000a81548160ff02191690831515021790555050565b6006602052816000526040600020602052806000526040600020600091509150505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612b9b5780601f10612b7057610100808354040283529160200191612b9b565b820191906000526020600020905b815481529060010190602001808311612b7e57829003601f168201915b505050505081565b612bab61517c565b60606000806000612bba61517c565b886000815181101515612bc957fe5b906020019060200201516101600151945088519350600092505b8383141515612c8157848984815181101515612bfb57fe5b906020019060200201516101600181905250612c1b888760200151613c20565b9150612c568984815181101515612c2e57fe5b90602001906020020151838986815181101515612c4757fe5b90602001906020020151610d47565b9050612c62868261305a565b878660200151101515612c7457612c81565b8280600101935050612be3565b85955050505050509392505050565b60025481565b612c9e61517c565b6060600080600080612cae61517c565b6000809054906101000a900460ff16151515612cff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cf690616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550896000815181101515612d2857fe5b906020019060200201516101400151955089519450600093505b8484141515612e2357858a85815181101515612d5a57fe5b906020019060200201516101400181905250612d7a898860000151613c20565b9250612dbd8a85815181101515612d8d57fe5b9060200190602002015160a001518b86815181101515612da957fe5b9060200190602002015160800151856140aa565b9150612df88a85815181101515612dd057fe5b90602001906020020151838a87815181101515612de957fe5b90602001906020020151612fb9565b9050612e04878261305a565b888760000151101515612e1657612e23565b8380600101945050612d42565b86965060008060006101000a81548160ff0219169083151502179055505050505050509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612f05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612efc90616db3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515612f7d5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6040805190810160405280600b81526020017f322e302e312d616c70686100000000000000000000000000000000000000000081525081565b612fc161517c565b612fc96151d4565b6000806000612fd7886127fd565b9350612fe16130ca565b9250612fef8885858961313a565b6130018860a001518560400151613c20565b915061300d8783614365565b90506130208885898489600001516135b2565b61302a888261437e565b9450613041888486602001518760400151896136f9565b61304c8884876143f1565b849450505050509392505050565b61306c826000015182600001516144f4565b826000018181525050613087826020015182602001516144f4565b8260200181815250506130a2826040015182604001516144f4565b8260400181815250506130bd826060015182606001516144f4565b8260600181815250505050565b6000806000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461312e5781613130565b335b9050809250505090565b6003600681111561314757fe5b60ff16836000015160ff16141515613194576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318b90616df3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16846060015173ffffffffffffffffffffffffffffffffffffffff16141515613243573373ffffffffffffffffffffffffffffffffffffffff16846060015173ffffffffffffffffffffffffffffffffffffffff16141515613242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323990616e13565b60405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff161415156132f2578173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff161415156132f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132e890616a93565b60405180910390fd5b5b600083604001511415613354576133128360200151856000015183611850565b1515613353576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334a90616b73565b60405180910390fd5b5b50505050565b61336c8260a001518260a0015161454b565b61337e8360800151836080015161454b565b101515156133c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133b890616e33565b60405180910390fd5b5050565b6133cd6151a5565b6000806000806133e18960a0015188613c20565b93506133f689608001518a60a00151866145bf565b92506134068860a0015187613c20565b915061341b88608001518960a00151846145bf565b9050808410151561348557808560200151600001818152505081856020015160200181815250508460200151600001518560000151602001818152505061347389608001518a60a001518760000151602001516145bf565b856000015160000181815250506134e0565b82856000015160000181815250508385600001516020018181525050846000015160200151856020015160000181815250506134d28860a001518960800151876020015160000151614671565b856020015160200181815250505b6134fa856000015160000151866020015160200151613c20565b85604001818152505061351e8560000151600001518a608001518b60c001516145bf565b856000015160400181815250506135468560000151602001518a60a001518b60e001516145bf565b8560000151606001818152505061356e85602001516000015189608001518a60c001516145bf565b856020015160400181815250506135968560200151602001518960a001518a60e001516145bf565b8560200151606001818152505084945050505050949350505050565b600083141515156135f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135ef90616c73565b60405180910390fd5b82821115151561363d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363490616c53565b60405180910390fd5b8460a001516136508560400151846144f4565b11151515613693576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161368a90616ab3565b60405180910390fd5b6136a185608001518361454b565b6136af828760a0015161454b565b111515156136f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136e990616d73565b60405180910390fd5b5050505050565b6137078282602001516144f4565b600460008560001916600019168152602001908152602001600020819055508260001916856040015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c371129873386600001518760200151886040015189606001518e61014001518f61016001516040516137b898979695949392919061680f565b60405180910390a45050505050565b606060018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561385f5780601f106138345761010080835404028352916020019161385f565b820191906000526020600020905b81548152906001019060200180831161384257829003601f168201915b5050505050905061388785610140015186600001518660000151856020015160200151614736565b6138a884610140015185600001518760000151856000015160200151614736565b6138c18561014001518660000151858560400151614736565b6138dd8186600001518760400151856000015160400151614736565b6138f98185600001518660400151856020015160400151614736565b836040015173ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1614156139635761395e818487604001516139598660000151606001518760200151606001516144f4565b614736565b613994565b61397b81848760400151856000015160600151614736565b61399381848660400151856020015160600151614736565b5b5050505050565b606060405190507fb4be83d5000000000000000000000000000000000000000000000000000000006020820152602481018060608101818180896000808784038652602086019550825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010083015161010085015261012083015161012085015261014083015161014085015261016083015161016085015261018084019350610180830192508484036020600a028601526101408d01519250825191506020830192506020601f830104905081845260208401935060005b81811015613ac05783518552602085019450602084019350600181019050613a9d565b508484036020600b028601526101608d01519250825191506020830192506020601f830104905081845260208401935060005b81811015613b165783518552602085019450602084019350600181019050613af3565b508b865260208601955087840386528a9250825191506020830192506020601f830104905081845260208401935060005b81811015613b6a5783518552602085019450602084019350600181019050613b47565b5060208a0184038a52836040525050505050505050508090509392505050565b613b926151d4565b613b9b826127fd565b9050613ba78282614996565b613bb5828260200151614b24565b5050565b613bc161517c565b613bcc848484612fb9565b9050828160200151141515613c16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c0d90616d53565b60405180910390fd5b8090509392505050565b6000828211151515613c67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c5e90616ad3565b60405180910390fd5b818303905092915050565b6000808251111515613cb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cb090616cb3565b60405180910390fd5b816001835103815181101515613ccb57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000029050600182510380835250809050919050565b600060208201835110151515613d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d6b90616b13565b60405180910390fd5b60208201915081830151905080905092915050565b600060608373ffffffffffffffffffffffffffffffffffffffff16631626ba7e90507c0100000000000000000000000000000000000000000000000000000000028584604051602401613ddd929190616976565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060208101602081835183885afa8060008114613e5f5760018114613ed057613ed5565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0c57414c4c45545f4552524f5200000000000000000000000000000000604052600060605260646000fd5b825194505b505050819150509392505050565b60006014825110151515613f2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f2390616dd3565b60405180910390fd5b613f3a826014845103614bdc565b9050601482510380835250809050919050565b600060608373ffffffffffffffffffffffffffffffffffffffff16639363470290507c010000000000000000000000000000000000000000000000000000000002858585604051602401613fa393929190616938565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602081016020818351838a5afa806000811461402557600181146140965761409b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f56414c494441544f525f4552524f5200000000000000000000000000604052600060605260646000fd5b825194505b50505081915050949350505050565b600080831115156140f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140e790616b53565b60405180910390fd5b6141036140fd858461454b565b84614c52565b90508090509392505050565b600080600060405160200180807f5a65726f45785472616e73616374696f6e280000000000000000000000000000815250601201807f75696e743235362073616c742c00000000000000000000000000000000000000815250600d01807f61646472657373207369676e6572416464726573732c00000000000000000000815250601601807f6279746573206461746100000000000000000000000000000000000000000000815250600a01807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b6020831015156142295780518252602082019150602081019050602083039250614204565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150836040518082805190602001908083835b60208310151561428e5780518252602082019150602081019050602083039250614269565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060405182815286602082015273ffffffffffffffffffffffffffffffffffffffff861660408201528160608201526080812093505082925050509392505050565b60008060025490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b600061435b61435683614c6d565b6142fe565b9050809050919050565b60008183106143745781614376565b825b905092915050565b61438661517c565b818160200181815250506143a3828460a0015185608001516145bf565b8160000181815250506143c3816000015184608001518560c001516145bf565b8160400181815250506143df828460a001518560e001516145bf565b81606001818152505080905092915050565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156144895780601f1061445e57610100808354040283529160200191614489565b820191906000526020600020905b81548152906001019060200180831161446c57829003601f168201915b505050505090506144a98461014001518560000151858560000151614736565b6144c28461016001518486600001518560200151614736565b6144da81856000015186604001518560400151614736565b6144ee818486604001518560600151614736565b50505050565b6000808284019050838110151515614541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161453890616bb3565b60405180910390fd5b8091505092915050565b600080600084141561456057600091506145b8565b828402905082848281151561457157fe5b041415156145b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145ab90616bb3565b60405180910390fd5b8091505b5092915050565b60008083111515614605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145fc90616b53565b60405180910390fd5b614610848484615031565b151515614652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161464990616c13565b60405180910390fd5b61466561465f858461454b565b84614c52565b90508090509392505050565b600080831115156146b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146ae90616b53565b60405180910390fd5b6146c28484846150cb565b151515614704576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146fb90616c13565b60405180910390fd5b61472a614724614714868561454b565b61471f866001613c20565b6144f4565b84614c52565b90508090509392505050565b60008060008311801561477557508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b1561498e57600386511115156147c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016147b790616d33565b60405180910390fd5b7fffffffff000000000000000000000000000000000000000000000000000000006020870151169150600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156148cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c690616c93565b60405180910390fd5b604051660fffffffffffe0603f885101168060840182017fa85e59e40000000000000000000000000000000000000000000000000000000083526080600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff87166044840152856064840152608483015b81811015614970578951815260208101905060208a019950614953565b61020084858403866000895af1801515614988573d85fd5b50505050505b505050505050565b6000600360068111156149a557fe5b60ff16826000015160ff161415156149f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016149e990616df3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16836060015173ffffffffffffffffffffffffffffffffffffffff16141515614aa1573373ffffffffffffffffffffffffffffffffffffffff16836060015173ffffffffffffffffffffffffffffffffffffffff16141515614aa0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614a9790616e13565b60405180910390fd5b5b614aa96130ca565b90508073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16141515614b1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1690616b93565b60405180910390fd5b505050565b600160056000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508060001916826040015173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167fdc47b3613d9fe400085f6dbdc99453462279057e6207385042827ed6b1a62cf733866101400151876101600151604051614bd09392919061689b565b60405180910390a45050565b600060148201835110151515614c27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614c1e90616dd3565b60405180910390fd5b60148201915073ffffffffffffffffffffffffffffffffffffffff8284015116905080905092915050565b6000808284811515614c6057fe5b0490508091505092915050565b60008060008060405160200180807f4f72646572280000000000000000000000000000000000000000000000000000815250600601807f61646472657373206d616b6572416464726573732c0000000000000000000000815250601501807f616464726573732074616b6572416464726573732c0000000000000000000000815250601501807f6164647265737320666565526563697069656e74416464726573732c00000000815250601c01807f616464726573732073656e646572416464726573732c00000000000000000000815250601601807f75696e74323536206d616b65724173736574416d6f756e742c00000000000000815250601901807f75696e743235362074616b65724173736574416d6f756e742c00000000000000815250601901807f75696e74323536206d616b65724665652c000000000000000000000000000000815250601101807f75696e743235362074616b65724665652c000000000000000000000000000000815250601101807f75696e743235362065787069726174696f6e54696d655365636f6e64732c0000815250601e01807f75696e743235362073616c742c00000000000000000000000000000000000000815250600d01807f6279746573206d616b65724173736574446174612c0000000000000000000000815250601501807f62797465732074616b6572417373657444617461000000000000000000000000815250601401807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b602083101515614ef05780518252602082019150602081019050602083039250614ecb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092508461014001516040518082805190602001908083835b602083101515614f5a5780518252602082019150602081019050602083039250614f35565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508461016001516040518082805190602001908083835b602083101515614fc45780518252602082019150602081019050602083039250614f9f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060208503610140860161016087018251825182518886528785528684526101a086209950828652818552808452505050505050839350505050919050565b600080600084111515615079576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161507090616b53565b60405180910390fd5b60008314806150885750600085145b1561509657600091506150c3565b838015156150a057fe5b85840990506150af858461454b565b6150bb6103e88361454b565b101591508191505b509392505050565b600080600084111515615113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161510a90616b53565b60405180910390fd5b60008314806151225750600085145b156151305760009150615174565b8380151561513a57fe5b85840990508361514a8583613c20565b81151561515357fe5b069050615160858461454b565b61516c6103e88361454b565b101591508191505b509392505050565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b610120604051908101604052806151ba615224565b81526020016151c7615224565b8152602001600081525090565b606060405190810160405280600060ff16815260200160008019168152602001600081525090565b606060405190810160405280600060ff16815260200160008019168152602001600081525090565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b600061525982356170bc565b905092915050565b600082601f830112151561527457600080fd5b813561528761528282616f2d565b616f00565b9150818183526020840193506020810190508360005b838110156152cd57813586016152b3888261546e565b84526020840193506020830192505060018101905061529d565b5050505092915050565b600082601f83011215156152ea57600080fd5b81356152fd6152f882616f55565b616f00565b9150818183526020840193506020810190508360005b838110156153435781358601615329888261551a565b845260208401935060208301925050600181019050615313565b5050505092915050565b600082601f830112151561536057600080fd5b813561537361536e82616f7d565b616f00565b9150818183526020840193506020810190508385602084028201111561539857600080fd5b60005b838110156153c857816153ae88826157b6565b84526020840193506020830192505060018101905061539b565b5050505092915050565b60006153de82356170dc565b905092915050565b60006153f282356170e8565b905092915050565b600061540682356170f2565b905092915050565b600061541a82516170f2565b905092915050565b60008083601f840112151561543657600080fd5b8235905067ffffffffffffffff81111561544f57600080fd5b60208301915083600182028301111561546757600080fd5b9250929050565b600082601f830112151561548157600080fd5b813561549461548f82616fa5565b616f00565b915080825260208301602083018583830111156154b057600080fd5b6154bb83828461713a565b50505092915050565b600082601f83011215156154d757600080fd5b81356154ea6154e582616fd1565b616f00565b9150808252602083016020830185838301111561550657600080fd5b61551183828461713a565b50505092915050565b6000610180828403121561552d57600080fd5b615538610180616f00565b905060006155488482850161524d565b600083015250602061555c8482850161524d565b60208301525060406155708482850161524d565b60408301525060606155848482850161524d565b6060830152506080615598848285016157b6565b60808301525060a06155ac848285016157b6565b60a08301525060c06155c0848285016157b6565b60c08301525060e06155d4848285016157b6565b60e0830152506101006155e9848285016157b6565b610100830152506101206155ff848285016157b6565b6101208301525061014082013567ffffffffffffffff81111561562157600080fd5b61562d8482850161546e565b6101408301525061016082013567ffffffffffffffff81111561564f57600080fd5b61565b8482850161546e565b6101608301525092915050565b6000610180828403121561567b57600080fd5b615686610180616f00565b905060006156968482850161524d565b60008301525060206156aa8482850161524d565b60208301525060406156be8482850161524d565b60408301525060606156d28482850161524d565b60608301525060806156e6848285016157b6565b60808301525060a06156fa848285016157b6565b60a08301525060c061570e848285016157b6565b60c08301525060e0615722848285016157b6565b60e083015250610100615737848285016157b6565b6101008301525061012061574d848285016157b6565b6101208301525061014082013567ffffffffffffffff81111561576f57600080fd5b61577b8482850161546e565b6101408301525061016082013567ffffffffffffffff81111561579d57600080fd5b6157a98482850161546e565b6101608301525092915050565b60006157c2823561711e565b905092915050565b6000602082840312156157dc57600080fd5b60006157ea8482850161524d565b91505092915050565b6000806040838503121561580657600080fd5b60006158148582860161524d565b92505060206158258582860161524d565b9150509250929050565b6000806040838503121561584257600080fd5b60006158508582860161524d565b9250506020615861858286016153d2565b9150509250929050565b60006020828403121561587d57600080fd5b600082013567ffffffffffffffff81111561589757600080fd5b6158a3848285016152d7565b91505092915050565b6000806000606084860312156158c157600080fd5b600084013567ffffffffffffffff8111156158db57600080fd5b6158e7868287016152d7565b935050602084013567ffffffffffffffff81111561590457600080fd5b6159108682870161534d565b925050604084013567ffffffffffffffff81111561592d57600080fd5b61593986828701615261565b9150509250925092565b60008060006060848603121561595857600080fd5b600084013567ffffffffffffffff81111561597257600080fd5b61597e868287016152d7565b935050602061598f868287016157b6565b925050604084013567ffffffffffffffff8111156159ac57600080fd5b6159b886828701615261565b9150509250925092565b6000602082840312156159d457600080fd5b60006159e2848285016153e6565b91505092915050565b600080604083850312156159fe57600080fd5b6000615a0c858286016153e6565b9250506020615a1d8582860161524d565b9150509250929050565b60008060008060608587031215615a3d57600080fd5b6000615a4b878288016153e6565b9450506020615a5c8782880161524d565b935050604085013567ffffffffffffffff811115615a7957600080fd5b615a8587828801615422565b925092505092959194509250565b600080600060608486031215615aa857600080fd5b6000615ab6868287016153e6565b9350506020615ac78682870161524d565b925050604084013567ffffffffffffffff811115615ae457600080fd5b615af0868287016154c4565b9150509250925092565b600060208284031215615b0c57600080fd5b6000615b1a848285016153fa565b91505092915050565b600060208284031215615b3557600080fd5b6000615b438482850161540e565b91505092915050565b600060208284031215615b5e57600080fd5b600082013567ffffffffffffffff811115615b7857600080fd5b615b8484828501615668565b91505092915050565b60008060008060808587031215615ba357600080fd5b600085013567ffffffffffffffff811115615bbd57600080fd5b615bc987828801615668565b945050602085013567ffffffffffffffff811115615be657600080fd5b615bf287828801615668565b935050604085013567ffffffffffffffff811115615c0f57600080fd5b615c1b878288016154c4565b925050606085013567ffffffffffffffff811115615c3857600080fd5b615c44878288016154c4565b91505092959194509250565b600080600060608486031215615c6557600080fd5b600084013567ffffffffffffffff811115615c7f57600080fd5b615c8b86828701615668565b9350506020615c9c868287016157b6565b925050604084013567ffffffffffffffff811115615cb957600080fd5b615cc5868287016154c4565b9150509250925092565b600060208284031215615ce157600080fd5b6000615cef848285016157b6565b91505092915050565b60008060008060008060808789031215615d1157600080fd5b6000615d1f89828a016157b6565b9650506020615d3089828a0161524d565b955050604087013567ffffffffffffffff811115615d4d57600080fd5b615d5989828a01615422565b9450945050606087013567ffffffffffffffff811115615d7857600080fd5b615d8489828a01615422565b92509250509295509295509295565b615d9c81617043565b82525050565b6000615dad8261700a565b808452602084019350615dbf83616ffd565b60005b82811015615df157615dd5868351616794565b615dde82617036565b9150606086019550600181019050615dc2565b50849250505092915050565b615e0681617063565b82525050565b615e158161706f565b82525050565b615e2481617079565b82525050565b6000615e3582617020565b808452615e49816020860160208601617149565b615e528161717c565b602085010191505092915050565b6000615e6b82617015565b808452615e7f816020860160208601617149565b615e888161717c565b602085010191505092915050565b615e9f81617128565b82525050565b6000615eb08261702b565b808452615ec4816020860160208601617149565b615ecd8161717c565b602085010191505092915050565b6000601282527f4c454e4754485f36355f524551554952454400000000000000000000000000006020830152604082019050919050565b6000600d82527f494e56414c49445f54414b4552000000000000000000000000000000000000006020830152604082019050919050565b6000600e82527f4f524445525f4f56455246494c4c0000000000000000000000000000000000006020830152604082019050919050565b6000601182527f55494e543235365f554e444552464c4f570000000000000000000000000000006020830152604082019050919050565b6000601a82527f41535345545f50524f58595f414c52454144595f4558495354530000000000006020830152604082019050919050565b6000602682527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208301527f51554952454400000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601582527f5349474e41545552455f554e535550504f5254454400000000000000000000006020830152604082019050919050565b6000601082527f4449564953494f4e5f42595f5a45524f000000000000000000000000000000006020830152604082019050919050565b6000601782527f494e56414c49445f4f524445525f5349474e41545552450000000000000000006020830152604082019050919050565b6000600d82527f494e56414c49445f4d414b4552000000000000000000000000000000000000006020830152604082019050919050565b6000601082527f55494e543235365f4f564552464c4f57000000000000000000000000000000006020830152604082019050919050565b6000600f82527f494e56414c49445f54585f4841534800000000000000000000000000000000006020830152604082019050919050565b6000601182527f494e56414c49445f5349474e41545552450000000000000000000000000000006020830152604082019050919050565b6000600e82527f524f554e44494e475f4552524f520000000000000000000000000000000000006020830152604082019050919050565b6000601082527f4641494c45445f455845435554494f4e000000000000000000000000000000006020830152604082019050919050565b6000600d82527f54414b45525f4f564552504159000000000000000000000000000000000000006020830152604082019050919050565b6000601482527f494e56414c49445f54414b45525f414d4f554e540000000000000000000000006020830152604082019050919050565b6000601a82527f41535345545f50524f58595f444f45535f4e4f545f45584953540000000000006020830152604082019050919050565b6000602182527f475245415445525f5448414e5f5a45524f5f4c454e4754485f5245515549524560208301527f44000000000000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601182527f5349474e41545552455f494c4c4547414c0000000000000000000000000000006020830152604082019050919050565b6000601e82527f4c454e4754485f475245415445525f5448414e5f305f524551554952454400006020830152604082019050919050565b6000601782527f494e56414c49445f4e45575f4f524445525f45504f43480000000000000000006020830152604082019050919050565b6000601e82527f4c454e4754485f475245415445525f5448414e5f335f524551554952454400006020830152604082019050919050565b6000601482527f434f4d504c4554455f46494c4c5f4641494c45440000000000000000000000006020830152604082019050919050565b6000601282527f494e56414c49445f46494c4c5f505249434500000000000000000000000000006020830152604082019050919050565b6000601282527f5245454e5452414e43595f494c4c4547414c00000000000000000000000000006020830152604082019050919050565b6000601382527f4f4e4c595f434f4e54524143545f4f574e4552000000000000000000000000006020830152604082019050919050565b6000602682527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208301527f51554952454400000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601082527f4f524445525f554e46494c4c41424c45000000000000000000000000000000006020830152604082019050919050565b6000600e82527f494e56414c49445f53454e4445520000000000000000000000000000000000006020830152604082019050919050565b6000601882527f4e454741544956455f5350524541445f524551554952454400000000000000006020830152604082019050919050565b6000601482527f494e56414c49445f54585f5349474e41545552450000000000000000000000006020830152604082019050919050565b6000601182527f4c454e4754485f305f52455155495245440000000000000000000000000000006020830152604082019050919050565b60808201600082015161667a60008501826167d6565b50602082015161668d60208501826167d6565b5060408201516166a060408501826167d6565b5060608201516166b360608501826167d6565b50505050565b6080820160008201516166cf60008501826167d6565b5060208201516166e260208501826167d6565b5060408201516166f560408501826167d6565b50606082015161670860608501826167d6565b50505050565b6101208201600082015161672560008501826166b9565b50602082015161673860808501826166b9565b50604082015161674c6101008501826167d6565b50505050565b60608201600082015161676860008501826167e5565b50602082015161677b6020850182615e0c565b50604082015161678e60408501826167d6565b50505050565b6060820160008201516167aa60008501826167e5565b5060208201516167bd6020850182615e0c565b5060408201516167d060408501826167d6565b50505050565b6167df816170a5565b82525050565b6167ee816170af565b82525050565b60006020820190506168096000830184615d93565b92915050565b600061010082019050616825600083018b615d93565b616832602083018a615d93565b61683f60408301896167d6565b61684c60608301886167d6565b61685960808301876167d6565b61686660a08301866167d6565b81810360c08301526168788185615e60565b905081810360e083015261688c8184615e60565b90509998505050505050505050565b60006060820190506168b06000830186615d93565b81810360208301526168c28185615e60565b905081810360408301526168d68184615e60565b9050949350505050565b600060208201905081810360008301526168fa8184615da2565b905092915050565b60006020820190506169176000830184615dfd565b92915050565b60006020820190506169326000830184615e0c565b92915050565b600060608201905061694d6000830186615e0c565b61695a6020830185615d93565b818103604083015261696c8184615e2a565b9050949350505050565b600060408201905061698b6000830185615e0c565b818103602083015261699d8184615e2a565b90509392505050565b60006080820190506169bb6000830187615e0c565b6169c860208301866167e5565b6169d56040830185615e0c565b6169e26060830184615e0c565b95945050505050565b6000604082019050616a006000830185615e1b565b616a0d6020830184615d93565b9392505050565b60006020820190508181036000830152616a2e8184615e60565b905092915050565b6000602082019050616a4b6000830184615e96565b92915050565b60006020820190508181036000830152616a6b8184615ea5565b905092915050565b60006020820190508181036000830152616a8c81615edb565b9050919050565b60006020820190508181036000830152616aac81615f12565b9050919050565b60006020820190508181036000830152616acc81615f49565b9050919050565b60006020820190508181036000830152616aec81615f80565b9050919050565b60006020820190508181036000830152616b0c81615fb7565b9050919050565b60006020820190508181036000830152616b2c81615fee565b9050919050565b60006020820190508181036000830152616b4c8161604b565b9050919050565b60006020820190508181036000830152616b6c81616082565b9050919050565b60006020820190508181036000830152616b8c816160b9565b9050919050565b60006020820190508181036000830152616bac816160f0565b9050919050565b60006020820190508181036000830152616bcc81616127565b9050919050565b60006020820190508181036000830152616bec8161615e565b9050919050565b60006020820190508181036000830152616c0c81616195565b9050919050565b60006020820190508181036000830152616c2c816161cc565b9050919050565b60006020820190508181036000830152616c4c81616203565b9050919050565b60006020820190508181036000830152616c6c8161623a565b9050919050565b60006020820190508181036000830152616c8c81616271565b9050919050565b60006020820190508181036000830152616cac816162a8565b9050919050565b60006020820190508181036000830152616ccc816162df565b9050919050565b60006020820190508181036000830152616cec8161633c565b9050919050565b60006020820190508181036000830152616d0c81616373565b9050919050565b60006020820190508181036000830152616d2c816163aa565b9050919050565b60006020820190508181036000830152616d4c816163e1565b9050919050565b60006020820190508181036000830152616d6c81616418565b9050919050565b60006020820190508181036000830152616d8c8161644f565b9050919050565b60006020820190508181036000830152616dac81616486565b9050919050565b60006020820190508181036000830152616dcc816164bd565b9050919050565b60006020820190508181036000830152616dec816164f4565b9050919050565b60006020820190508181036000830152616e0c81616551565b9050919050565b60006020820190508181036000830152616e2c81616588565b9050919050565b60006020820190508181036000830152616e4c816165bf565b9050919050565b60006020820190508181036000830152616e6c816165f6565b9050919050565b60006020820190508181036000830152616e8c8161662d565b9050919050565b6000608082019050616ea86000830184616664565b92915050565b600061012082019050616ec4600083018461670e565b92915050565b6000606082019050616edf6000830184616752565b92915050565b6000602082019050616efa60008301846167d6565b92915050565b6000604051905081810181811067ffffffffffffffff82111715616f2357600080fd5b8060405250919050565b600067ffffffffffffffff821115616f4457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616f6c57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616f9457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616fbc57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115616fe857600080fd5b601f19601f8301169050602081019050919050565b6000602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600060ff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600061713382617043565b9050919050565b82818337600083830152505050565b60005b8381101561716757808201518184015260208101905061714c565b83811115617176576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a7230582077660df1266e2183c378e8f2513f33170c0994f2c2d9335e426dd87fd4a7c3916c6578706572696d656e74616cf50037 \ No newline at end of file diff --git a/examples/src/main/resources/Simple.abi b/examples/src/main/resources/Simple.abi new file mode 100644 index 0000000..98920a4 --- /dev/null +++ b/examples/src/main/resources/Simple.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"components":[{"name":"a","type":"uint256"},{"name":"b","type":"bytes"},{"name":"c","type":"uint256"},{"name":"d","type":"bytes"}],"name":"t","type":"tuple"}],"name":"trigger","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"a","type":"uint256"},{"indexed":false,"name":"b","type":"bytes"},{"indexed":true,"name":"c","type":"uint256"},{"indexed":false,"name":"d","type":"bytes"}],"name":"TestEvent","type":"event"}] \ No newline at end of file diff --git a/examples/src/main/resources/Simple.bin b/examples/src/main/resources/Simple.bin new file mode 100644 index 0000000..2a93ae5 --- /dev/null +++ b/examples/src/main/resources/Simple.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610374806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806385799c3614610046575b600080fd5b34801561005257600080fd5b5061006d600480360361006891908101906101cb565b61006f565b005b806040015181600001517f174e799db4473820d2ac095205358bba921759d7f2fb09509751a40a543842aa836020015184606001516040516100b2929190610242565b60405180910390a350565b600082601f83011215156100d057600080fd5b81356100e36100de826102a6565b610279565b915080825260208301602083018583830111156100ff57600080fd5b61010a8382846102e7565b50505092915050565b60006080828403121561012557600080fd5b61012f6080610279565b9050600061013f848285016101b7565b600083015250602082013567ffffffffffffffff81111561015f57600080fd5b61016b848285016100bd565b602083015250604061017f848285016101b7565b604083015250606082013567ffffffffffffffff81111561019f57600080fd5b6101ab848285016100bd565b60608301525092915050565b60006101c382356102dd565b905092915050565b6000602082840312156101dd57600080fd5b600082013567ffffffffffffffff8111156101f757600080fd5b61020384828501610113565b91505092915050565b6000610217826102d2565b80845261022b8160208601602086016102f6565b61023481610329565b602085010191505092915050565b6000604082019050818103600083015261025c818561020c565b90508181036020830152610270818461020c565b90509392505050565b6000604051905081810181811067ffffffffffffffff8211171561029c57600080fd5b8060405250919050565b600067ffffffffffffffff8211156102bd57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156103145780820151818401526020810190506102f9565b83811115610323576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a723058201ce538708976bc5eb642066442b9156e9bf442c7f38e3977bac329d2191e7b236c6578706572696d656e74616cf50037 \ No newline at end of file diff --git a/examples/src/main/resources/SimpleToken.abi b/examples/src/main/resources/SimpleToken.abi new file mode 100644 index 0000000..e992707 --- /dev/null +++ b/examples/src/main/resources/SimpleToken.abi @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"DECIMALS","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}] \ No newline at end of file diff --git a/examples/src/main/resources/SimpleToken.bin b/examples/src/main/resources/SimpleToken.bin new file mode 100644 index 0000000..825aea0 --- /dev/null +++ b/examples/src/main/resources/SimpleToken.bin @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b506040805190810160405280600b81526020017f53696d706c65546f6b656e0000000000000000000000000000000000000000008152506040805190810160405280600381526020017f53494d0000000000000000000000000000000000000000000000000000000000815250601282600390805190602001906200009892919062000293565b508160049080519060200190620000b192919062000293565b5080600560006101000a81548160ff021916908360ff160217905550505050620000f633601260ff16600a0a61271002620000fc640100000000026401000000009004565b62000342565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156200013957600080fd5b6200015e81600254620002716401000000000262001159179091906401000000009004565b600281905550620001c5816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054620002716401000000000262001159179091906401000000009004565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60008082840190508381101515156200028957600080fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002d657805160ff191683800117855562000307565b8280016001018555821562000307579182015b8281111562000306578251825591602001919060010190620002e9565b5b5090506200031691906200031a565b5090565b6200033f91905b808211156200033b57600081600090555060010162000321565b5090565b90565b6111a680620003526000396000f3fe608060405234801561001057600080fd5b50600436106100ec576000357c010000000000000000000000000000000000000000000000000000000090048063313ce567116100a957806395d89b411161008357806395d89b41146103a2578063a457c2d714610425578063a9059cbb1461048b578063dd62ed3e146104f1576100ec565b8063313ce567146102c057806339509351146102e457806370a082311461034a576100ec565b806306fdde03146100f1578063095ea7b31461017457806318160ddd146101da57806323b872dd146101f85780632e0f26251461027e5780632ff2e9dc146102a2575b600080fd5b6100f9610569565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013957808201518184015260208101905061011e565b50505050905090810190601f1680156101665780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c06004803603604081101561018a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061060b565b604051808215151515815260200191505060405180910390f35b6101e2610738565b6040518082815260200191505060405180910390f35b6102646004803603606081101561020e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610742565b604051808215151515815260200191505060405180910390f35b61028661094a565b604051808260ff1660ff16815260200191505060405180910390f35b6102aa61094f565b6040518082815260200191505060405180910390f35b6102c861095e565b604051808260ff1660ff16815260200191505060405180910390f35b610330600480360360408110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610975565b604051808215151515815260200191505060405180910390f35b61038c6004803603602081101561036057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bac565b6040518082815260200191505060405180910390f35b6103aa610bf4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103ea5780820151818401526020810190506103cf565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104716004803603604081101561043b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c96565b604051808215151515815260200191505060405180910390f35b6104d7600480360360408110156104a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ecd565b604051808215151515815260200191505060405180910390f35b6105536004803603604081101561050757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ee4565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106015780601f106105d657610100808354040283529160200191610601565b820191906000526020600020905b8154815290600101906020018083116105e457829003601f168201915b5050505050905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415151561064857600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600254905090565b60006107d382600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061085e848484610f8d565b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600190509392505050565b601281565b601260ff16600a0a6127100281565b6000600560009054906101000a900460ff16905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156109b257600080fd5b610a4182600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461115990919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c8c5780601f10610c6157610100808354040283529160200191610c8c565b820191906000526020600020905b815481529060010190602001808311610c6f57829003601f168201915b5050505050905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610cd357600080fd5b610d6282600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000610eda338484610f8d565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000828211151515610f7c57600080fd5b600082840390508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610fc957600080fd5b61101a816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110ad816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461115990919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600080828401905083811015151561117057600080fd5b809150509291505056fea165627a7a7230582008f3a090533ddacdd7c8c5ec44ffd7b040994ae055e7f95b00e42d19cbc274e20029 \ No newline at end of file diff --git a/examples/src/main/scala/examples/exchange/Exchange.scala b/examples/src/main/scala/examples/exchange/Exchange.scala new file mode 100644 index 0000000..0884b59 --- /dev/null +++ b/examples/src/main/scala/examples/exchange/Exchange.scala @@ -0,0 +1,329 @@ +// AUTO GENERATED, DO NOT EDIT + +package examples.exchange +import akka.NotUsed +import akka.stream.scaladsl.Source +import ethabi.util.{ Hex, Hash } +import ethabi.types._ +import ethabi.types.generated._ +import ethabi.protocol.{ Contract, EventValue } +import ethabi.protocol.Request._ +import ethabi.protocol.Response.Log +import scala.concurrent.Future +class Exchange(endpoint: String) { self => + private val impl = Contract(endpoint) + import impl.dispatcher + private val binary = "608060405260008060006101000a81548160ff0219169083151502179055503480156200002b57600080fd5b50604051620077c2380380620077c2833981018060405262000051919081019062000515565b8080600190805190602001906200006a92919062000408565b505060405160200180807f454950373132446f6d61696e2800000000000000000000000000000000000000815250600d01807f737472696e67206e616d652c0000000000000000000000000000000000000000815250600c01807f737472696e672076657273696f6e2c0000000000000000000000000000000000815250600f01807f6164647265737320766572696679696e67436f6e747261637400000000000000815250601901807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b6020831015156200018357805182526020820191506020810190506020830392506200015c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206040805190810160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518082805190602001908083835b6020831015156200021d5780518252602082019150602081019050602083039250620001f6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206040805190810160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506040518082805190602001908083835b602083101515620002b7578051825260208201915060208101905060208303925062000290565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390203073ffffffffffffffffffffffffffffffffffffffff166001026040516020018085600019166000191681526020018460001916600019168152602001836000191660001916815260200182600019166000191681526020019450505050506040516020818303038152906040526040518082805190602001908083835b60208310151562000389578051825260208201915060208101905060208303925062000362565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206002816000191690555033600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050620005eb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044b57805160ff19168380011785556200047c565b828001600101855582156200047c579182015b828111156200047b5782518255916020019190600101906200045e565b5b5090506200048b91906200048f565b5090565b620004b491905b80821115620004b057600081600090555060010162000496565b5090565b90565b600082601f8301121515620004cb57600080fd5b8151620004e2620004dc8262000588565b6200055a565b91508082526020830160208301858383011115620004ff57600080fd5b6200050c838284620005b5565b50505092915050565b6000602082840312156200052857600080fd5b600082015167ffffffffffffffff8111156200054357600080fd5b6200055184828501620004b7565b91505092915050565b6000604051905081810181811067ffffffffffffffff821117156200057e57600080fd5b8060405250919050565b600067ffffffffffffffff821115620005a057600080fd5b601f19601f8301169050602081019050919050565b60005b83811015620005d5578082015181840152602081019050620005b8565b83811115620005e5576000848401525b50505050565b6171c780620005fb6000396000f3006080604052600436106101b7576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063288cdc91146101bc578063297bb70b146101f95780632ac12622146102365780633683ef8e146102735780633c28d8611461029c5780633e228bae146102d95780633fd3c997146103165780634ac14782146103535780634d0ae5461461037c5780634f9559b1146103b957806350dde190146103e2578063607041081461041f578063642f2eaf1461045c57806364a3bc151461049957806377fcce68146104d65780637b8e3514146104ff5780637e1d98081461053c5780637e9d74dc1461057957806382c174d0146105b65780638da5cb5b146105f3578063936347021461061e578063a3e203801461065b578063b4be83d514610698578063bfc8bfce146106d5578063c585bb93146106fe578063c75e0a8114610727578063d46b02c314610764578063d9bfa73e1461078d578063db123b1a146107ca578063dd1c7d18146107f5578063e306f77914610832578063e5fa431b1461085d578063eea086ba1461089a578063f2fde38b146108c5578063ffa1ad74146108ee575b600080fd5b3480156101c857600080fd5b506101e360048036036101de91908101906159c2565b610919565b6040516101f09190616ee5565b60405180910390f35b34801561020557600080fd5b50610220600480360361021b91908101906158ac565b610931565b60405161022d9190616e93565b60405180910390f35b34801561024257600080fd5b5061025d600480360361025891908101906159c2565b610a51565b60405161026a9190616902565b60405180910390f35b34801561027f57600080fd5b5061029a60048036036102959190810190615a27565b610a71565b005b3480156102a857600080fd5b506102c360048036036102be9190810190615b8d565b610b9c565b6040516102d09190616eae565b60405180910390f35b3480156102e557600080fd5b5061030060048036036102fb9190810190615c50565b610d47565b60405161030d9190616e93565b60405180910390f35b34801561032257600080fd5b5061033d60048036036103389190810190615afa565b610d9f565b60405161034a9190616a36565b60405180910390f35b34801561035f57600080fd5b5061037a6004803603610375919081019061586b565b610dd2565b005b34801561038857600080fd5b506103a3600480360361039e91908101906158ac565b610e9e565b6040516103b09190616e93565b60405180910390f35b3480156103c557600080fd5b506103e060048036036103db9190810190615ccf565b610fbe565b005b3480156103ee57600080fd5b50610409600480360361040491908101906158ac565b611247565b6040516104169190616e93565b60405180910390f35b34801561042b57600080fd5b5061044660048036036104419190810190615afa565b6112e2565b60405161045391906167f4565b60405180910390f35b34801561046857600080fd5b50610483600480360361047e91908101906159c2565b61135d565b6040516104909190616902565b60405180910390f35b3480156104a557600080fd5b506104c060048036036104bb9190810190615c50565b61137d565b6040516104cd9190616e93565b60405180910390f35b3480156104e257600080fd5b506104fd60048036036104f8919081019061582f565b611421565b005b34801561050b57600080fd5b50610526600480360361052191908101906157f3565b6115b0565b6040516105339190616902565b60405180910390f35b34801561054857600080fd5b50610563600480360361055e9190810190615943565b6115df565b6040516105709190616e93565b60405180910390f35b34801561058557600080fd5b506105a0600480360361059b919081019061586b565b611751565b6040516105ad91906168e0565b60405180910390f35b3480156105c257600080fd5b506105dd60048036036105d891908101906159eb565b6117fb565b6040516105ea9190616902565b60405180910390f35b3480156105ff57600080fd5b5061060861182a565b60405161061591906167f4565b60405180910390f35b34801561062a57600080fd5b5061064560048036036106409190810190615a93565b611850565b6040516106529190616902565b60405180910390f35b34801561066757600080fd5b50610682600480360361067d9190810190615943565b611fcf565b60405161068f9190616e93565b60405180910390f35b3480156106a457600080fd5b506106bf60048036036106ba9190810190615c50565b612101565b6040516106cc9190616e93565b60405180910390f35b3480156106e157600080fd5b506106fc60048036036106f79190810190615cf8565b6121a5565b005b34801561070a57600080fd5b50610725600480360361072091908101906157ca565b612511565b005b34801561073357600080fd5b5061074e60048036036107499190810190615b4c565b6127fd565b60405161075b9190616eca565b60405180910390f35b34801561077057600080fd5b5061078b60048036036107869190810190615b4c565b612a4f565b005b34801561079957600080fd5b506107b460048036036107af91908101906157f3565b612ae0565b6040516107c19190616ee5565b60405180910390f35b3480156107d657600080fd5b506107df612b05565b6040516107ec9190616a14565b60405180910390f35b34801561080157600080fd5b5061081c60048036036108179190810190615943565b612ba3565b6040516108299190616e93565b60405180910390f35b34801561083e57600080fd5b50610847612c90565b604051610854919061691d565b60405180910390f35b34801561086957600080fd5b50610884600480360361087f9190810190615943565b612c96565b6040516108919190616e93565b60405180910390f35b3480156108a657600080fd5b506108af612e4d565b6040516108bc91906167f4565b60405180910390f35b3480156108d157600080fd5b506108ec60048036036108e791908101906157ca565b612e73565b005b3480156108fa57600080fd5b50610903612f80565b6040516109109190616a51565b60405180910390f35b60046020528060005260406000206000915090505481565b61093961517c565b60008061094461517c565b6000809054906101000a900460ff16151515610995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098c90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555086519250600091505b8282141515610a2a57610a1187838151811015156109d257fe5b9060200190602002015187848151811015156109ea57fe5b906020019060200201518785815181101515610a0257fe5b90602001906020020151612fb9565b9050610a1d848261305a565b81806001019250506109b8565b83935060008060006101000a81548160ff0219169083151502179055505050509392505050565b60056020528060005260406000206000915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515610b2557610ae3848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611850565b1515610b24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1b90616bf3565b60405180910390fd5b5b600160076000866000191660001916815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b610ba46151a5565b610bac6151d4565b610bb46151d4565b60008060009054906101000a900460ff16151515610c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfe90616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550876101600151876101400181905250876101400151876101600181905250610c48886127fd565b9250610c53876127fd565b9150610c5d6130ca565b9050610c6b8884838961313a565b610c778783838861313a565b610c81888861335a565b610c958888856040015185604001516133c5565b9350610cbc88848660000151602001518760000151602001518860000151600001516135b2565b610ce187838660200151602001518760200151602001518860200151600001516135b2565b610cfa88828560200151866040015188600001516136f9565b610d1387828460200151856040015188602001516136f9565b610d1f888883876137c7565b83935060008060006101000a81548160ff021916908315150217905550505050949350505050565b610d4f61517c565b6060610d5c85858561399b565b9050608081825160208401305af48015610d9357815183526020820151602084015260408201516040840152606082015160608401525b50819150509392505050565b600b6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000809054906101000a900460ff16151515610e26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1d90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555082519150600090505b8181141515610e7f57610e728382815181101515610e6357fe5b90602001906020020151613b8a565b8080600101915050610e49565b60008060006101000a81548160ff021916908315150217905550505050565b610ea661517c565b600080610eb161517c565b6000809054906101000a900460ff16151515610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef990616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555086519250600091505b8282141515610f9757610f7e8783815181101515610f3f57fe5b906020019060200201518784815181101515610f5757fe5b906020019060200201518785815181101515610f6f57fe5b90602001906020020151613bb9565b9050610f8a848261305a565b8180600101925050610f25565b83935060008060006101000a81548160ff0219169083151502179055505050509392505050565b6000806000806000809054906101000a900460ff16151515611015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100c90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506110376130ca565b93503373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146110725733611075565b60005b9250600185019150600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508082111515611140576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113790616d13565b60405180910390fd5b81600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f08460405161121e9190616ee5565b60405180910390a360008060006101000a81548160ff0219169083151502179055505050505050565b61124f61517c565b60008061125a61517c565b86519250600091505b82821415156112d5576112bc878381518110151561127d57fe5b90602001906020020151878481518110151561129557fe5b9060200190602002015187858151811015156112ad57fe5b90602001906020020151610d47565b90506112c8848261305a565b8180600101925050611263565b8393505050509392505050565b6000600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60096020528060005260406000206000915054906101000a900460ff1681565b61138561517c565b6000809054906101000a900460ff161515156113d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113cd90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506113fb848484613bb9565b905080905060008060006101000a81548160ff0219169083151502179055509392505050565b60008060009054906101000a900460ff16151515611474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146b90616d93565b60405180910390fd5b60016000806101000a81548160ff0219169083151502179055506114966130ca565b905081600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba891846040516115899190616902565b60405180910390a360008060006101000a81548160ff021916908315150217905550505050565b60086020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6115e761517c565b606060008060006115f661517c565b6000809054906101000a900460ff16151515611647576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163e90616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555088600081518110151561167057fe5b906020019060200201516101600151945088519350600092505b8383141515611728578489848151811015156116a257fe5b9060200190602002015161016001819052506116c2888760200151613c20565b91506116fd89848151811015156116d557fe5b906020019060200201518389868151811015156116ee57fe5b90602001906020020151612fb9565b9050611709868261305a565b87866020015110151561171b57611728565b828060010193505061168a565b85955060008060006101000a81548160ff02191690831515021790555050505050509392505050565b6060600060606000845192508260405190808252806020026020018201604052801561179757816020015b6117846151fc565b81526020019060019003908161177c5790505b509150600090505b82811415156117f0576117c885828151811015156117b957fe5b906020019060200201516127fd565b82828151811015156117d657fe5b90602001906020020181905250808060010191505061179f565b819350505050919050565b60076020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600080600080600080600089511115156118a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189990616cf3565b60405180910390fd5b6118ab89613c72565b7f0100000000000000000000000000000000000000000000000000000000000000900496506007808111156118dc57fe5b60ff168760ff16101515611925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191c90616b33565b60405180910390fd5b8660ff16600781111561193457fe5b95506000600781111561194357fe5b86600781111561194f57fe5b1415611990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198790616cd3565b60405180910390fd5b6001600781111561199d57fe5b8660078111156119a957fe5b1415611a0157600089511415156119f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ec90616e73565b60405180910390fd5b60009750879750611fc1565b60026007811115611a0e57fe5b866007811115611a1a57fe5b1415611b9d5760418951141515611a66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5d90616a73565b60405180910390fd5b886000815181101515611a7557fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049450611af960018a613d2990919063ffffffff16565b9350611b0f60218a613d2990919063ffffffff16565b925060018b86868660405160008152602001604052604051611b3494939291906169a6565b60206040516020810390808403906000865af1158015611b58573d6000803e3d6000fd5b5050506020604051035191508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16149750879750611fc1565b60036007811115611baa57fe5b866007811115611bb657fe5b1415611dea5760418951141515611c02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf990616a73565b60405180910390fd5b886000815181101515611c1157fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000027f010000000000000000000000000000000000000000000000000000000000000090049450611c9560018a613d2990919063ffffffff16565b9350611cab60218a613d2990919063ffffffff16565b925060018b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083101515611d345780518252602082019150602081019050602083039250611d0f565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902086868660405160008152602001604052604051611d8194939291906169a6565b60206040516020810390808403906000865af1158015611da5573d6000803e3d6000fd5b5050506020604051035191508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16149750879750611fc1565b60046007811115611df757fe5b866007811115611e0357fe5b1415611e1e57611e148b8b8b613d89565b9750879750611fc1565b60056007811115611e2b57fe5b866007811115611e3757fe5b1415611ef757611e4689613ee3565b9050600860008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611ee15760009750611fc1565b611eed818c8c8c613f4d565b9750879750611fc1565b60066007811115611f0457fe5b866007811115611f1057fe5b1415611f8657600760008c6000191660001916815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169750879750611fc1565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb890616b33565b60405180910390fd5b505050505050509392505050565b611fd761517c565b6060600080600080611fe761517c565b896000815181101515611ff657fe5b906020019060200201516101400151955089519450600093505b84841415156120f157858a8581518110151561202857fe5b906020019060200201516101400181905250612048898860000151613c20565b925061208b8a8581518110151561205b57fe5b9060200190602002015160a001518b8681518110151561207757fe5b9060200190602002015160800151856140aa565b91506120c68a8581518110151561209e57fe5b90602001906020020151838a878151811015156120b757fe5b90602001906020020151610d47565b90506120d2878261305a565b8887600001511015156120e4576120f1565b8380600101945050612010565b8696505050505050509392505050565b61210961517c565b6000809054906101000a900460ff1615151561215a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215190616d93565b60405180910390fd5b60016000806101000a81548160ff02191690831515021790555061217f848484612fb9565b905080905060008060006101000a81548160ff0219169083151502179055509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515612239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223090616d93565b60405180910390fd5b61227e612279888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061410f565b6142fe565b905060096000826000191660001916815260200190815260200160002060009054906101000a900460ff161515156122eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122e290616bd3565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415156123e05761235d818785858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611850565b151561239e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239590616e53565b60405180910390fd5b85600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b600160096000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055503073ffffffffffffffffffffffffffffffffffffffff16858560405180838380828437820191505092505050600060405180830381855af49150501515612490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248790616c33565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141515612508576000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50505050505050565b6000806000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156125a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259f90616db3565b60405180910390fd5b8392508273ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561260f57600080fd5b505af1158015612623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126479190810190615b23565b9150600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151561272e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161272590616af3565b60405180910390fd5b82600b6000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c0319482856040516127ef9291906169eb565b60405180910390a150505050565b6128056151d4565b61280e82614348565b81602001906000191690816000191681525050600460008260200151600019166000191681526020019081526020016000205481604001818152505060008260800151141561287d576001600681111561286457fe5b816000019060ff16908160ff1681525050809050612a4a565b60008260a0015114156128b0576002600681111561289757fe5b816000019060ff16908160ff1681525050809050612a4a565b8160a0015181604001511015156128e757600560068111156128ce57fe5b816000019060ff16908160ff1681525050809050612a4a565b8161010001514210151561291b576004600681111561290257fe5b816000019060ff16908160ff1681525050809050612a4a565b6005600082602001516000191660001916815260200190815260200160002060009054906101000a900460ff16156129725760068081111561295957fe5b816000019060ff16908160ff1681525050809050612a4a565b81610120015160066000846000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000846060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541115612a2857600680811115612a0f57fe5b816000019060ff16908160ff1681525050809050612a4a565b60036006811115612a3557fe5b816000019060ff16908160ff16815250508090505b919050565b6000809054906101000a900460ff16151515612aa0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a9790616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550612ac381613b8a565b60008060006101000a81548160ff02191690831515021790555050565b6006602052816000526040600020602052806000526040600020600091509150505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612b9b5780601f10612b7057610100808354040283529160200191612b9b565b820191906000526020600020905b815481529060010190602001808311612b7e57829003601f168201915b505050505081565b612bab61517c565b60606000806000612bba61517c565b886000815181101515612bc957fe5b906020019060200201516101600151945088519350600092505b8383141515612c8157848984815181101515612bfb57fe5b906020019060200201516101600181905250612c1b888760200151613c20565b9150612c568984815181101515612c2e57fe5b90602001906020020151838986815181101515612c4757fe5b90602001906020020151610d47565b9050612c62868261305a565b878660200151101515612c7457612c81565b8280600101935050612be3565b85955050505050509392505050565b60025481565b612c9e61517c565b6060600080600080612cae61517c565b6000809054906101000a900460ff16151515612cff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cf690616d93565b60405180910390fd5b60016000806101000a81548160ff021916908315150217905550896000815181101515612d2857fe5b906020019060200201516101400151955089519450600093505b8484141515612e2357858a85815181101515612d5a57fe5b906020019060200201516101400181905250612d7a898860000151613c20565b9250612dbd8a85815181101515612d8d57fe5b9060200190602002015160a001518b86815181101515612da957fe5b9060200190602002015160800151856140aa565b9150612df88a85815181101515612dd057fe5b90602001906020020151838a87815181101515612de957fe5b90602001906020020151612fb9565b9050612e04878261305a565b888760000151101515612e1657612e23565b8380600101945050612d42565b86965060008060006101000a81548160ff0219169083151502179055505050505050509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612f05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612efc90616db3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515612f7d5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6040805190810160405280600b81526020017f322e302e312d616c70686100000000000000000000000000000000000000000081525081565b612fc161517c565b612fc96151d4565b6000806000612fd7886127fd565b9350612fe16130ca565b9250612fef8885858961313a565b6130018860a001518560400151613c20565b915061300d8783614365565b90506130208885898489600001516135b2565b61302a888261437e565b9450613041888486602001518760400151896136f9565b61304c8884876143f1565b849450505050509392505050565b61306c826000015182600001516144f4565b826000018181525050613087826020015182602001516144f4565b8260200181815250506130a2826040015182604001516144f4565b8260400181815250506130bd826060015182606001516144f4565b8260600181815250505050565b6000806000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461312e5781613130565b335b9050809250505090565b6003600681111561314757fe5b60ff16836000015160ff16141515613194576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318b90616df3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16846060015173ffffffffffffffffffffffffffffffffffffffff16141515613243573373ffffffffffffffffffffffffffffffffffffffff16846060015173ffffffffffffffffffffffffffffffffffffffff16141515613242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323990616e13565b60405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff161415156132f2578173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff161415156132f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132e890616a93565b60405180910390fd5b5b600083604001511415613354576133128360200151856000015183611850565b1515613353576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161334a90616b73565b60405180910390fd5b5b50505050565b61336c8260a001518260a0015161454b565b61337e8360800151836080015161454b565b101515156133c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133b890616e33565b60405180910390fd5b5050565b6133cd6151a5565b6000806000806133e18960a0015188613c20565b93506133f689608001518a60a00151866145bf565b92506134068860a0015187613c20565b915061341b88608001518960a00151846145bf565b9050808410151561348557808560200151600001818152505081856020015160200181815250508460200151600001518560000151602001818152505061347389608001518a60a001518760000151602001516145bf565b856000015160000181815250506134e0565b82856000015160000181815250508385600001516020018181525050846000015160200151856020015160000181815250506134d28860a001518960800151876020015160000151614671565b856020015160200181815250505b6134fa856000015160000151866020015160200151613c20565b85604001818152505061351e8560000151600001518a608001518b60c001516145bf565b856000015160400181815250506135468560000151602001518a60a001518b60e001516145bf565b8560000151606001818152505061356e85602001516000015189608001518a60c001516145bf565b856020015160400181815250506135968560200151602001518960a001518a60e001516145bf565b8560200151606001818152505084945050505050949350505050565b600083141515156135f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135ef90616c73565b60405180910390fd5b82821115151561363d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161363490616c53565b60405180910390fd5b8460a001516136508560400151846144f4565b11151515613693576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161368a90616ab3565b60405180910390fd5b6136a185608001518361454b565b6136af828760a0015161454b565b111515156136f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136e990616d73565b60405180910390fd5b5050505050565b6137078282602001516144f4565b600460008560001916600019168152602001908152602001600020819055508260001916856040015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c371129873386600001518760200151886040015189606001518e61014001518f61016001516040516137b898979695949392919061680f565b60405180910390a45050505050565b606060018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561385f5780601f106138345761010080835404028352916020019161385f565b820191906000526020600020905b81548152906001019060200180831161384257829003601f168201915b5050505050905061388785610140015186600001518660000151856020015160200151614736565b6138a884610140015185600001518760000151856000015160200151614736565b6138c18561014001518660000151858560400151614736565b6138dd8186600001518760400151856000015160400151614736565b6138f98185600001518660400151856020015160400151614736565b836040015173ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1614156139635761395e818487604001516139598660000151606001518760200151606001516144f4565b614736565b613994565b61397b81848760400151856000015160600151614736565b61399381848660400151856020015160600151614736565b5b5050505050565b606060405190507fb4be83d5000000000000000000000000000000000000000000000000000000006020820152602481018060608101818180896000808784038652602086019550825184526020830151602085015260408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010083015161010085015261012083015161012085015261014083015161014085015261016083015161016085015261018084019350610180830192508484036020600a028601526101408d01519250825191506020830192506020601f830104905081845260208401935060005b81811015613ac05783518552602085019450602084019350600181019050613a9d565b508484036020600b028601526101608d01519250825191506020830192506020601f830104905081845260208401935060005b81811015613b165783518552602085019450602084019350600181019050613af3565b508b865260208601955087840386528a9250825191506020830192506020601f830104905081845260208401935060005b81811015613b6a5783518552602085019450602084019350600181019050613b47565b5060208a0184038a52836040525050505050505050508090509392505050565b613b926151d4565b613b9b826127fd565b9050613ba78282614996565b613bb5828260200151614b24565b5050565b613bc161517c565b613bcc848484612fb9565b9050828160200151141515613c16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c0d90616d53565b60405180910390fd5b8090509392505050565b6000828211151515613c67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c5e90616ad3565b60405180910390fd5b818303905092915050565b6000808251111515613cb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cb090616cb3565b60405180910390fd5b816001835103815181101515613ccb57fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f0100000000000000000000000000000000000000000000000000000000000000029050600182510380835250809050919050565b600060208201835110151515613d74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d6b90616b13565b60405180910390fd5b60208201915081830151905080905092915050565b600060608373ffffffffffffffffffffffffffffffffffffffff16631626ba7e90507c0100000000000000000000000000000000000000000000000000000000028584604051602401613ddd929190616976565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060208101602081835183885afa8060008114613e5f5760018114613ed057613ed5565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0c57414c4c45545f4552524f5200000000000000000000000000000000604052600060605260646000fd5b825194505b505050819150509392505050565b60006014825110151515613f2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f2390616dd3565b60405180910390fd5b613f3a826014845103614bdc565b9050601482510380835250809050919050565b600060608373ffffffffffffffffffffffffffffffffffffffff16639363470290507c010000000000000000000000000000000000000000000000000000000002858585604051602401613fa393929190616938565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602081016020818351838a5afa806000811461402557600181146140965761409b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f56414c494441544f525f4552524f5200000000000000000000000000604052600060605260646000fd5b825194505b50505081915050949350505050565b600080831115156140f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140e790616b53565b60405180910390fd5b6141036140fd858461454b565b84614c52565b90508090509392505050565b600080600060405160200180807f5a65726f45785472616e73616374696f6e280000000000000000000000000000815250601201807f75696e743235362073616c742c00000000000000000000000000000000000000815250600d01807f61646472657373207369676e6572416464726573732c00000000000000000000815250601601807f6279746573206461746100000000000000000000000000000000000000000000815250600a01807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b6020831015156142295780518252602082019150602081019050602083039250614204565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150836040518082805190602001908083835b60208310151561428e5780518252602082019150602081019050602083039250614269565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060405182815286602082015273ffffffffffffffffffffffffffffffffffffffff861660408201528160608201526080812093505082925050509392505050565b60008060025490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b600061435b61435683614c6d565b6142fe565b9050809050919050565b60008183106143745781614376565b825b905092915050565b61438661517c565b818160200181815250506143a3828460a0015185608001516145bf565b8160000181815250506143c3816000015184608001518560c001516145bf565b8160400181815250506143df828460a001518560e001516145bf565b81606001818152505080905092915050565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156144895780601f1061445e57610100808354040283529160200191614489565b820191906000526020600020905b81548152906001019060200180831161446c57829003601f168201915b505050505090506144a98461014001518560000151858560000151614736565b6144c28461016001518486600001518560200151614736565b6144da81856000015186604001518560400151614736565b6144ee818486604001518560600151614736565b50505050565b6000808284019050838110151515614541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161453890616bb3565b60405180910390fd5b8091505092915050565b600080600084141561456057600091506145b8565b828402905082848281151561457157fe5b041415156145b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145ab90616bb3565b60405180910390fd5b8091505b5092915050565b60008083111515614605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145fc90616b53565b60405180910390fd5b614610848484615031565b151515614652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161464990616c13565b60405180910390fd5b61466561465f858461454b565b84614c52565b90508090509392505050565b600080831115156146b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146ae90616b53565b60405180910390fd5b6146c28484846150cb565b151515614704576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146fb90616c13565b60405180910390fd5b61472a614724614714868561454b565b61471f866001613c20565b6144f4565b84614c52565b90508090509392505050565b60008060008311801561477557508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b1561498e57600386511115156147c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016147b790616d33565b60405180910390fd5b7fffffffff000000000000000000000000000000000000000000000000000000006020870151169150600b6000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156148cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c690616c93565b60405180910390fd5b604051660fffffffffffe0603f885101168060840182017fa85e59e40000000000000000000000000000000000000000000000000000000083526080600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff87166044840152856064840152608483015b81811015614970578951815260208101905060208a019950614953565b61020084858403866000895af1801515614988573d85fd5b50505050505b505050505050565b6000600360068111156149a557fe5b60ff16826000015160ff161415156149f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016149e990616df3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16836060015173ffffffffffffffffffffffffffffffffffffffff16141515614aa1573373ffffffffffffffffffffffffffffffffffffffff16836060015173ffffffffffffffffffffffffffffffffffffffff16141515614aa0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614a9790616e13565b60405180910390fd5b5b614aa96130ca565b90508073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16141515614b1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1690616b93565b60405180910390fd5b505050565b600160056000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508060001916826040015173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167fdc47b3613d9fe400085f6dbdc99453462279057e6207385042827ed6b1a62cf733866101400151876101600151604051614bd09392919061689b565b60405180910390a45050565b600060148201835110151515614c27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614c1e90616dd3565b60405180910390fd5b60148201915073ffffffffffffffffffffffffffffffffffffffff8284015116905080905092915050565b6000808284811515614c6057fe5b0490508091505092915050565b60008060008060405160200180807f4f72646572280000000000000000000000000000000000000000000000000000815250600601807f61646472657373206d616b6572416464726573732c0000000000000000000000815250601501807f616464726573732074616b6572416464726573732c0000000000000000000000815250601501807f6164647265737320666565526563697069656e74416464726573732c00000000815250601c01807f616464726573732073656e646572416464726573732c00000000000000000000815250601601807f75696e74323536206d616b65724173736574416d6f756e742c00000000000000815250601901807f75696e743235362074616b65724173736574416d6f756e742c00000000000000815250601901807f75696e74323536206d616b65724665652c000000000000000000000000000000815250601101807f75696e743235362074616b65724665652c000000000000000000000000000000815250601101807f75696e743235362065787069726174696f6e54696d655365636f6e64732c0000815250601e01807f75696e743235362073616c742c00000000000000000000000000000000000000815250600d01807f6279746573206d616b65724173736574446174612c0000000000000000000000815250601501807f62797465732074616b6572417373657444617461000000000000000000000000815250601401807f290000000000000000000000000000000000000000000000000000000000000081525060010190506040516020818303038152906040526040518082805190602001908083835b602083101515614ef05780518252602082019150602081019050602083039250614ecb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092508461014001516040518082805190602001908083835b602083101515614f5a5780518252602082019150602081019050602083039250614f35565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508461016001516040518082805190602001908083835b602083101515614fc45780518252602082019150602081019050602083039250614f9f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060208503610140860161016087018251825182518886528785528684526101a086209950828652818552808452505050505050839350505050919050565b600080600084111515615079576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161507090616b53565b60405180910390fd5b60008314806150885750600085145b1561509657600091506150c3565b838015156150a057fe5b85840990506150af858461454b565b6150bb6103e88361454b565b101591508191505b509392505050565b600080600084111515615113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161510a90616b53565b60405180910390fd5b60008314806151225750600085145b156151305760009150615174565b8380151561513a57fe5b85840990508361514a8583613c20565b81151561515357fe5b069050615160858461454b565b61516c6103e88361454b565b101591508191505b509392505050565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b610120604051908101604052806151ba615224565b81526020016151c7615224565b8152602001600081525090565b606060405190810160405280600060ff16815260200160008019168152602001600081525090565b606060405190810160405280600060ff16815260200160008019168152602001600081525090565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b600061525982356170bc565b905092915050565b600082601f830112151561527457600080fd5b813561528761528282616f2d565b616f00565b9150818183526020840193506020810190508360005b838110156152cd57813586016152b3888261546e565b84526020840193506020830192505060018101905061529d565b5050505092915050565b600082601f83011215156152ea57600080fd5b81356152fd6152f882616f55565b616f00565b9150818183526020840193506020810190508360005b838110156153435781358601615329888261551a565b845260208401935060208301925050600181019050615313565b5050505092915050565b600082601f830112151561536057600080fd5b813561537361536e82616f7d565b616f00565b9150818183526020840193506020810190508385602084028201111561539857600080fd5b60005b838110156153c857816153ae88826157b6565b84526020840193506020830192505060018101905061539b565b5050505092915050565b60006153de82356170dc565b905092915050565b60006153f282356170e8565b905092915050565b600061540682356170f2565b905092915050565b600061541a82516170f2565b905092915050565b60008083601f840112151561543657600080fd5b8235905067ffffffffffffffff81111561544f57600080fd5b60208301915083600182028301111561546757600080fd5b9250929050565b600082601f830112151561548157600080fd5b813561549461548f82616fa5565b616f00565b915080825260208301602083018583830111156154b057600080fd5b6154bb83828461713a565b50505092915050565b600082601f83011215156154d757600080fd5b81356154ea6154e582616fd1565b616f00565b9150808252602083016020830185838301111561550657600080fd5b61551183828461713a565b50505092915050565b6000610180828403121561552d57600080fd5b615538610180616f00565b905060006155488482850161524d565b600083015250602061555c8482850161524d565b60208301525060406155708482850161524d565b60408301525060606155848482850161524d565b6060830152506080615598848285016157b6565b60808301525060a06155ac848285016157b6565b60a08301525060c06155c0848285016157b6565b60c08301525060e06155d4848285016157b6565b60e0830152506101006155e9848285016157b6565b610100830152506101206155ff848285016157b6565b6101208301525061014082013567ffffffffffffffff81111561562157600080fd5b61562d8482850161546e565b6101408301525061016082013567ffffffffffffffff81111561564f57600080fd5b61565b8482850161546e565b6101608301525092915050565b6000610180828403121561567b57600080fd5b615686610180616f00565b905060006156968482850161524d565b60008301525060206156aa8482850161524d565b60208301525060406156be8482850161524d565b60408301525060606156d28482850161524d565b60608301525060806156e6848285016157b6565b60808301525060a06156fa848285016157b6565b60a08301525060c061570e848285016157b6565b60c08301525060e0615722848285016157b6565b60e083015250610100615737848285016157b6565b6101008301525061012061574d848285016157b6565b6101208301525061014082013567ffffffffffffffff81111561576f57600080fd5b61577b8482850161546e565b6101408301525061016082013567ffffffffffffffff81111561579d57600080fd5b6157a98482850161546e565b6101608301525092915050565b60006157c2823561711e565b905092915050565b6000602082840312156157dc57600080fd5b60006157ea8482850161524d565b91505092915050565b6000806040838503121561580657600080fd5b60006158148582860161524d565b92505060206158258582860161524d565b9150509250929050565b6000806040838503121561584257600080fd5b60006158508582860161524d565b9250506020615861858286016153d2565b9150509250929050565b60006020828403121561587d57600080fd5b600082013567ffffffffffffffff81111561589757600080fd5b6158a3848285016152d7565b91505092915050565b6000806000606084860312156158c157600080fd5b600084013567ffffffffffffffff8111156158db57600080fd5b6158e7868287016152d7565b935050602084013567ffffffffffffffff81111561590457600080fd5b6159108682870161534d565b925050604084013567ffffffffffffffff81111561592d57600080fd5b61593986828701615261565b9150509250925092565b60008060006060848603121561595857600080fd5b600084013567ffffffffffffffff81111561597257600080fd5b61597e868287016152d7565b935050602061598f868287016157b6565b925050604084013567ffffffffffffffff8111156159ac57600080fd5b6159b886828701615261565b9150509250925092565b6000602082840312156159d457600080fd5b60006159e2848285016153e6565b91505092915050565b600080604083850312156159fe57600080fd5b6000615a0c858286016153e6565b9250506020615a1d8582860161524d565b9150509250929050565b60008060008060608587031215615a3d57600080fd5b6000615a4b878288016153e6565b9450506020615a5c8782880161524d565b935050604085013567ffffffffffffffff811115615a7957600080fd5b615a8587828801615422565b925092505092959194509250565b600080600060608486031215615aa857600080fd5b6000615ab6868287016153e6565b9350506020615ac78682870161524d565b925050604084013567ffffffffffffffff811115615ae457600080fd5b615af0868287016154c4565b9150509250925092565b600060208284031215615b0c57600080fd5b6000615b1a848285016153fa565b91505092915050565b600060208284031215615b3557600080fd5b6000615b438482850161540e565b91505092915050565b600060208284031215615b5e57600080fd5b600082013567ffffffffffffffff811115615b7857600080fd5b615b8484828501615668565b91505092915050565b60008060008060808587031215615ba357600080fd5b600085013567ffffffffffffffff811115615bbd57600080fd5b615bc987828801615668565b945050602085013567ffffffffffffffff811115615be657600080fd5b615bf287828801615668565b935050604085013567ffffffffffffffff811115615c0f57600080fd5b615c1b878288016154c4565b925050606085013567ffffffffffffffff811115615c3857600080fd5b615c44878288016154c4565b91505092959194509250565b600080600060608486031215615c6557600080fd5b600084013567ffffffffffffffff811115615c7f57600080fd5b615c8b86828701615668565b9350506020615c9c868287016157b6565b925050604084013567ffffffffffffffff811115615cb957600080fd5b615cc5868287016154c4565b9150509250925092565b600060208284031215615ce157600080fd5b6000615cef848285016157b6565b91505092915050565b60008060008060008060808789031215615d1157600080fd5b6000615d1f89828a016157b6565b9650506020615d3089828a0161524d565b955050604087013567ffffffffffffffff811115615d4d57600080fd5b615d5989828a01615422565b9450945050606087013567ffffffffffffffff811115615d7857600080fd5b615d8489828a01615422565b92509250509295509295509295565b615d9c81617043565b82525050565b6000615dad8261700a565b808452602084019350615dbf83616ffd565b60005b82811015615df157615dd5868351616794565b615dde82617036565b9150606086019550600181019050615dc2565b50849250505092915050565b615e0681617063565b82525050565b615e158161706f565b82525050565b615e2481617079565b82525050565b6000615e3582617020565b808452615e49816020860160208601617149565b615e528161717c565b602085010191505092915050565b6000615e6b82617015565b808452615e7f816020860160208601617149565b615e888161717c565b602085010191505092915050565b615e9f81617128565b82525050565b6000615eb08261702b565b808452615ec4816020860160208601617149565b615ecd8161717c565b602085010191505092915050565b6000601282527f4c454e4754485f36355f524551554952454400000000000000000000000000006020830152604082019050919050565b6000600d82527f494e56414c49445f54414b4552000000000000000000000000000000000000006020830152604082019050919050565b6000600e82527f4f524445525f4f56455246494c4c0000000000000000000000000000000000006020830152604082019050919050565b6000601182527f55494e543235365f554e444552464c4f570000000000000000000000000000006020830152604082019050919050565b6000601a82527f41535345545f50524f58595f414c52454144595f4558495354530000000000006020830152604082019050919050565b6000602682527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208301527f51554952454400000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601582527f5349474e41545552455f554e535550504f5254454400000000000000000000006020830152604082019050919050565b6000601082527f4449564953494f4e5f42595f5a45524f000000000000000000000000000000006020830152604082019050919050565b6000601782527f494e56414c49445f4f524445525f5349474e41545552450000000000000000006020830152604082019050919050565b6000600d82527f494e56414c49445f4d414b4552000000000000000000000000000000000000006020830152604082019050919050565b6000601082527f55494e543235365f4f564552464c4f57000000000000000000000000000000006020830152604082019050919050565b6000600f82527f494e56414c49445f54585f4841534800000000000000000000000000000000006020830152604082019050919050565b6000601182527f494e56414c49445f5349474e41545552450000000000000000000000000000006020830152604082019050919050565b6000600e82527f524f554e44494e475f4552524f520000000000000000000000000000000000006020830152604082019050919050565b6000601082527f4641494c45445f455845435554494f4e000000000000000000000000000000006020830152604082019050919050565b6000600d82527f54414b45525f4f564552504159000000000000000000000000000000000000006020830152604082019050919050565b6000601482527f494e56414c49445f54414b45525f414d4f554e540000000000000000000000006020830152604082019050919050565b6000601a82527f41535345545f50524f58595f444f45535f4e4f545f45584953540000000000006020830152604082019050919050565b6000602182527f475245415445525f5448414e5f5a45524f5f4c454e4754485f5245515549524560208301527f44000000000000000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601182527f5349474e41545552455f494c4c4547414c0000000000000000000000000000006020830152604082019050919050565b6000601e82527f4c454e4754485f475245415445525f5448414e5f305f524551554952454400006020830152604082019050919050565b6000601782527f494e56414c49445f4e45575f4f524445525f45504f43480000000000000000006020830152604082019050919050565b6000601e82527f4c454e4754485f475245415445525f5448414e5f335f524551554952454400006020830152604082019050919050565b6000601482527f434f4d504c4554455f46494c4c5f4641494c45440000000000000000000000006020830152604082019050919050565b6000601282527f494e56414c49445f46494c4c5f505249434500000000000000000000000000006020830152604082019050919050565b6000601282527f5245454e5452414e43595f494c4c4547414c00000000000000000000000000006020830152604082019050919050565b6000601382527f4f4e4c595f434f4e54524143545f4f574e4552000000000000000000000000006020830152604082019050919050565b6000602682527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208301527f51554952454400000000000000000000000000000000000000000000000000006040830152606082019050919050565b6000601082527f4f524445525f554e46494c4c41424c45000000000000000000000000000000006020830152604082019050919050565b6000600e82527f494e56414c49445f53454e4445520000000000000000000000000000000000006020830152604082019050919050565b6000601882527f4e454741544956455f5350524541445f524551554952454400000000000000006020830152604082019050919050565b6000601482527f494e56414c49445f54585f5349474e41545552450000000000000000000000006020830152604082019050919050565b6000601182527f4c454e4754485f305f52455155495245440000000000000000000000000000006020830152604082019050919050565b60808201600082015161667a60008501826167d6565b50602082015161668d60208501826167d6565b5060408201516166a060408501826167d6565b5060608201516166b360608501826167d6565b50505050565b6080820160008201516166cf60008501826167d6565b5060208201516166e260208501826167d6565b5060408201516166f560408501826167d6565b50606082015161670860608501826167d6565b50505050565b6101208201600082015161672560008501826166b9565b50602082015161673860808501826166b9565b50604082015161674c6101008501826167d6565b50505050565b60608201600082015161676860008501826167e5565b50602082015161677b6020850182615e0c565b50604082015161678e60408501826167d6565b50505050565b6060820160008201516167aa60008501826167e5565b5060208201516167bd6020850182615e0c565b5060408201516167d060408501826167d6565b50505050565b6167df816170a5565b82525050565b6167ee816170af565b82525050565b60006020820190506168096000830184615d93565b92915050565b600061010082019050616825600083018b615d93565b616832602083018a615d93565b61683f60408301896167d6565b61684c60608301886167d6565b61685960808301876167d6565b61686660a08301866167d6565b81810360c08301526168788185615e60565b905081810360e083015261688c8184615e60565b90509998505050505050505050565b60006060820190506168b06000830186615d93565b81810360208301526168c28185615e60565b905081810360408301526168d68184615e60565b9050949350505050565b600060208201905081810360008301526168fa8184615da2565b905092915050565b60006020820190506169176000830184615dfd565b92915050565b60006020820190506169326000830184615e0c565b92915050565b600060608201905061694d6000830186615e0c565b61695a6020830185615d93565b818103604083015261696c8184615e2a565b9050949350505050565b600060408201905061698b6000830185615e0c565b818103602083015261699d8184615e2a565b90509392505050565b60006080820190506169bb6000830187615e0c565b6169c860208301866167e5565b6169d56040830185615e0c565b6169e26060830184615e0c565b95945050505050565b6000604082019050616a006000830185615e1b565b616a0d6020830184615d93565b9392505050565b60006020820190508181036000830152616a2e8184615e60565b905092915050565b6000602082019050616a4b6000830184615e96565b92915050565b60006020820190508181036000830152616a6b8184615ea5565b905092915050565b60006020820190508181036000830152616a8c81615edb565b9050919050565b60006020820190508181036000830152616aac81615f12565b9050919050565b60006020820190508181036000830152616acc81615f49565b9050919050565b60006020820190508181036000830152616aec81615f80565b9050919050565b60006020820190508181036000830152616b0c81615fb7565b9050919050565b60006020820190508181036000830152616b2c81615fee565b9050919050565b60006020820190508181036000830152616b4c8161604b565b9050919050565b60006020820190508181036000830152616b6c81616082565b9050919050565b60006020820190508181036000830152616b8c816160b9565b9050919050565b60006020820190508181036000830152616bac816160f0565b9050919050565b60006020820190508181036000830152616bcc81616127565b9050919050565b60006020820190508181036000830152616bec8161615e565b9050919050565b60006020820190508181036000830152616c0c81616195565b9050919050565b60006020820190508181036000830152616c2c816161cc565b9050919050565b60006020820190508181036000830152616c4c81616203565b9050919050565b60006020820190508181036000830152616c6c8161623a565b9050919050565b60006020820190508181036000830152616c8c81616271565b9050919050565b60006020820190508181036000830152616cac816162a8565b9050919050565b60006020820190508181036000830152616ccc816162df565b9050919050565b60006020820190508181036000830152616cec8161633c565b9050919050565b60006020820190508181036000830152616d0c81616373565b9050919050565b60006020820190508181036000830152616d2c816163aa565b9050919050565b60006020820190508181036000830152616d4c816163e1565b9050919050565b60006020820190508181036000830152616d6c81616418565b9050919050565b60006020820190508181036000830152616d8c8161644f565b9050919050565b60006020820190508181036000830152616dac81616486565b9050919050565b60006020820190508181036000830152616dcc816164bd565b9050919050565b60006020820190508181036000830152616dec816164f4565b9050919050565b60006020820190508181036000830152616e0c81616551565b9050919050565b60006020820190508181036000830152616e2c81616588565b9050919050565b60006020820190508181036000830152616e4c816165bf565b9050919050565b60006020820190508181036000830152616e6c816165f6565b9050919050565b60006020820190508181036000830152616e8c8161662d565b9050919050565b6000608082019050616ea86000830184616664565b92915050565b600061012082019050616ec4600083018461670e565b92915050565b6000606082019050616edf6000830184616752565b92915050565b6000602082019050616efa60008301846167d6565b92915050565b6000604051905081810181811067ffffffffffffffff82111715616f2357600080fd5b8060405250919050565b600067ffffffffffffffff821115616f4457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616f6c57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616f9457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff821115616fbc57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115616fe857600080fd5b601f19601f8301169050602081019050919050565b6000602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600060ff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600061713382617043565b9050919050565b82818337600083830152505050565b60005b8381101561716757808201518184015260208101905061714c565b83811115617176576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a7230582077660df1266e2183c378e8f2513f33170c0994f2c2d9335e426dd87fd4a7c3916c6578706572696d656e74616cf50037" + def filled(fresh1: Bytes32, sender: Address, opt: TransactionOpt): Future[Uint256] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Bytes32]]].encode(TupleType1.apply[Bytes32](fresh1)) + val functionId = Hex.hex2Bytes("288cdc91") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def batchFillOrders(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], takerAssetFillAmounts: DynamicArray[Uint256], signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]](orders, takerAssetFillAmounts, signatures)) + val functionId = Hex.hex2Bytes("297bb70b") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def cancelled(fresh3: Bytes32, sender: Address, opt: TransactionOpt): Future[Bool] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Bytes32]]].encode(TupleType1.apply[Bytes32](fresh3)) + val functionId = Hex.hex2Bytes("2ac12622") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bool]].decode(bytes, 0) + result._1 + } + } + def preSign(hash: Bytes32, signerAddress: Address, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[Bytes32, Address, DynamicBytes]]].encode(TupleType3.apply[Bytes32, Address, DynamicBytes](hash, signerAddress, signature)) + val functionId = Hex.hex2Bytes("3683ef8e") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def matchOrders(leftOrder: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], rightOrder: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], leftSignature: DynamicBytes, rightSignature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType4[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], DynamicBytes, DynamicBytes]]].encode(TupleType4.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], DynamicBytes, DynamicBytes](leftOrder, rightOrder, leftSignature, rightSignature)) + val functionId = Hex.hex2Bytes("3c28d861") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def fillOrderNoThrow(order: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], takerAssetFillAmount: Uint256, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes]]].encode(TupleType3.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes](order, takerAssetFillAmount, signature)) + val functionId = Hex.hex2Bytes("3e228bae") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def assetProxies(fresh5: Bytes4, sender: Address, opt: TransactionOpt): Future[Address] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Bytes4]]].encode(TupleType1.apply[Bytes4](fresh5)) + val functionId = Hex.hex2Bytes("3fd3c997") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Address]].decode(bytes, 0) + result._1 + } + } + def batchCancelOrders(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]]]].encode(TupleType1.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]](orders)) + val functionId = Hex.hex2Bytes("4ac14782") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def batchFillOrKillOrders(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], takerAssetFillAmounts: DynamicArray[Uint256], signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]](orders, takerAssetFillAmounts, signatures)) + val functionId = Hex.hex2Bytes("4d0ae546") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def cancelOrdersUpTo(targetOrderEpoch: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Uint256]]].encode(TupleType1.apply[Uint256](targetOrderEpoch)) + val functionId = Hex.hex2Bytes("4f9559b1") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def batchFillOrdersNoThrow(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], takerAssetFillAmounts: DynamicArray[Uint256], signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], DynamicArray[Uint256], DynamicArray[DynamicBytes]](orders, takerAssetFillAmounts, signatures)) + val functionId = Hex.hex2Bytes("50dde190") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def getAssetProxy(assetProxyId: Bytes4, sender: Address, opt: TransactionOpt): Future[Address] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Bytes4]]].encode(TupleType1.apply[Bytes4](assetProxyId)) + val functionId = Hex.hex2Bytes("60704108") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Address]].decode(bytes, 0) + result._1 + } + } + def transactions(fresh8: Bytes32, sender: Address, opt: TransactionOpt): Future[Bool] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Bytes32]]].encode(TupleType1.apply[Bytes32](fresh8)) + val functionId = Hex.hex2Bytes("642f2eaf") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bool]].decode(bytes, 0) + result._1 + } + } + def fillOrKillOrder(order: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], takerAssetFillAmount: Uint256, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes]]].encode(TupleType3.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes](order, takerAssetFillAmount, signature)) + val functionId = Hex.hex2Bytes("64a3bc15") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def setSignatureValidatorApproval(validatorAddress: Address, approval: Bool, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Bool]]].encode(TupleType2.apply[Address, Bool](validatorAddress, approval)) + val functionId = Hex.hex2Bytes("77fcce68") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def allowedValidators(fresh10: Address, fresh11: Address, sender: Address, opt: TransactionOpt): Future[Bool] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Address]]].encode(TupleType2.apply[Address, Address](fresh10, fresh11)) + val functionId = Hex.hex2Bytes("7b8e3514") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bool]].decode(bytes, 0) + result._1 + } + } + def marketSellOrders(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], takerAssetFillAmount: Uint256, signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]](orders, takerAssetFillAmount, signatures)) + val functionId = Hex.hex2Bytes("7e1d9808") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def getOrdersInfo(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], sender: Address, opt: TransactionOpt): Future[DynamicArray[TupleType3[Uint8, Bytes32, Uint256]]] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]]]].encode(TupleType1.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]](orders)) + val functionId = Hex.hex2Bytes("7e9d74dc") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[DynamicArray[TupleType3[Uint8, Bytes32, Uint256]]]].decode(bytes, 0) + result._1 + } + } + def preSigned(fresh14: Bytes32, fresh15: Address, sender: Address, opt: TransactionOpt): Future[Bool] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Bytes32, Address]]].encode(TupleType2.apply[Bytes32, Address](fresh14, fresh15)) + val functionId = Hex.hex2Bytes("82c174d0") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bool]].decode(bytes, 0) + result._1 + } + } + def owner(sender: Address, opt: TransactionOpt): Future[Address] = { + val encoded = Hex.hex2Bytes("8da5cb5b") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Address]].decode(bytes, 0) + result._1 + } + } + def isValidSignature(hash: Bytes32, signerAddress: Address, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Bool] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[Bytes32, Address, DynamicBytes]]].encode(TupleType3.apply[Bytes32, Address, DynamicBytes](hash, signerAddress, signature)) + val functionId = Hex.hex2Bytes("93634702") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bool]].decode(bytes, 0) + result._1 + } + } + def marketBuyOrdersNoThrow(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], makerAssetFillAmount: Uint256, signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]](orders, makerAssetFillAmount, signatures)) + val functionId = Hex.hex2Bytes("a3e20380") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def fillOrder(order: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], takerAssetFillAmount: Uint256, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes]]].encode(TupleType3.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], Uint256, DynamicBytes](order, takerAssetFillAmount, signature)) + val functionId = Hex.hex2Bytes("b4be83d5") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def executeTransaction(salt: Uint256, signerAddress: Address, data: DynamicBytes, signature: DynamicBytes, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType4[Uint256, Address, DynamicBytes, DynamicBytes]]].encode(TupleType4.apply[Uint256, Address, DynamicBytes, DynamicBytes](salt, signerAddress, data, signature)) + val functionId = Hex.hex2Bytes("bfc8bfce") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def registerAssetProxy(assetProxy: Address, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Address]]].encode(TupleType1.apply[Address](assetProxy)) + val functionId = Hex.hex2Bytes("c585bb93") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def getOrderInfo(order: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], sender: Address, opt: TransactionOpt): Future[TupleType3[Uint8, Bytes32, Uint256]] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]]].encode(TupleType1.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]](order)) + val functionId = Hex.hex2Bytes("c75e0a81") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[TupleType3[Uint8, Bytes32, Uint256]]].decode(bytes, 0) + result._1 + } + } + def cancelOrder(order: TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]]].encode(TupleType1.apply[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]](order)) + val functionId = Hex.hex2Bytes("d46b02c3") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def orderEpoch(fresh18: Address, fresh19: Address, sender: Address, opt: TransactionOpt): Future[Uint256] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Address]]].encode(TupleType2.apply[Address, Address](fresh18, fresh19)) + val functionId = Hex.hex2Bytes("d9bfa73e") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def ZRX_ASSET_DATA(sender: Address, opt: TransactionOpt): Future[DynamicBytes] = { + val encoded = Hex.hex2Bytes("db123b1a") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[DynamicBytes]].decode(bytes, 0) + result._1 + } + } + def marketSellOrdersNoThrow(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], takerAssetFillAmount: Uint256, signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]](orders, takerAssetFillAmount, signatures)) + val functionId = Hex.hex2Bytes("dd1c7d18") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def EIP712_DOMAIN_HASH(sender: Address, opt: TransactionOpt): Future[Bytes32] = { + val encoded = Hex.hex2Bytes("e306f779") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Bytes32]].decode(bytes, 0) + result._1 + } + } + def marketBuyOrders(orders: DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], makerAssetFillAmount: Uint256, signatures: DynamicArray[DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]]]].encode(TupleType3.apply[DynamicArray[TupleType12[Address, Address, Address, Address, Uint256, Uint256, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]], Uint256, DynamicArray[DynamicBytes]](orders, makerAssetFillAmount, signatures)) + val functionId = Hex.hex2Bytes("e5fa431b") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def currentContextAddress(sender: Address, opt: TransactionOpt): Future[Address] = { + val encoded = Hex.hex2Bytes("eea086ba") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Address]].decode(bytes, 0) + result._1 + } + } + def transferOwnership(newOwner: Address, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Address]]].encode(TupleType1.apply[Address](newOwner)) + val functionId = Hex.hex2Bytes("f2fde38b") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def VERSION(sender: Address, opt: TransactionOpt): Future[StringType] = { + val encoded = Hex.hex2Bytes("ffa1ad74") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[StringType]].decode(bytes, 0) + result._1 + } + } + def deploy(_zrxAssetData: DynamicBytes, sender: Address, opt: TransactionOpt): Unit = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[DynamicBytes]]].encode(TupleType1.apply[DynamicBytes](_zrxAssetData)) + val code = Hex.hex2Bytes(binary) + val encoded = code ++ paramsEncoded + impl.deploy(encoded, sender, opt) + } + def decodeSignatureValidatorApproval(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType1[Bool]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeSignatureValidatorApproval: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0xa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba891")) + impl.subscribeLogs(query).map(decodeSignatureValidatorApproval) + } + def decodeFill(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Bytes32]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType8[Address, Address, Uint256, Uint256, Uint256, Uint256, DynamicBytes, DynamicBytes]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeFill: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0x0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c371129")) + impl.subscribeLogs(query).map(decodeFill) + } + def decodeCancel(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Bytes32]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType3[Address, DynamicBytes, DynamicBytes]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeCancel: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0xdc47b3613d9fe400085f6dbdc99453462279057e6207385042827ed6b1a62cf7")) + impl.subscribeLogs(query).map(decodeCancel) + } + def decodeCancelUpTo(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType1[Uint256]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeCancelUpTo: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0x82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f0")) + impl.subscribeLogs(query).map(decodeCancelUpTo) + } + def decodeAssetProxyRegistered(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType2[Bytes4, Address]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeAssetProxyRegistered: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0xd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c03194")) + impl.subscribeLogs(query).map(decodeAssetProxyRegistered) + } + def isDeployed: Boolean = impl.isDeployed + def contractAddress: Address = impl.address.get + def loadFrom(contractAddress: Address) = impl.load(contractAddress) +} \ No newline at end of file diff --git a/examples/src/main/scala/examples/simple/Simple.scala b/examples/src/main/scala/examples/simple/Simple.scala new file mode 100644 index 0000000..956bf2d --- /dev/null +++ b/examples/src/main/scala/examples/simple/Simple.scala @@ -0,0 +1,41 @@ +// AUTO GENERATED, DO NOT EDIT + +package examples.simple +import akka.NotUsed +import akka.stream.scaladsl.Source +import ethabi.util.{ Hex, Hash } +import ethabi.types._ +import ethabi.types.generated._ +import ethabi.protocol.{ Contract, EventValue } +import ethabi.protocol.Request._ +import ethabi.protocol.Response.Log +import scala.concurrent.Future +class Simple(endpoint: String) { self => + private val impl = Contract(endpoint) + import impl.dispatcher + private val binary = "608060405234801561001057600080fd5b50610374806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806385799c3614610046575b600080fd5b34801561005257600080fd5b5061006d600480360361006891908101906101cb565b61006f565b005b806040015181600001517f174e799db4473820d2ac095205358bba921759d7f2fb09509751a40a543842aa836020015184606001516040516100b2929190610242565b60405180910390a350565b600082601f83011215156100d057600080fd5b81356100e36100de826102a6565b610279565b915080825260208301602083018583830111156100ff57600080fd5b61010a8382846102e7565b50505092915050565b60006080828403121561012557600080fd5b61012f6080610279565b9050600061013f848285016101b7565b600083015250602082013567ffffffffffffffff81111561015f57600080fd5b61016b848285016100bd565b602083015250604061017f848285016101b7565b604083015250606082013567ffffffffffffffff81111561019f57600080fd5b6101ab848285016100bd565b60608301525092915050565b60006101c382356102dd565b905092915050565b6000602082840312156101dd57600080fd5b600082013567ffffffffffffffff8111156101f757600080fd5b61020384828501610113565b91505092915050565b6000610217826102d2565b80845261022b8160208601602086016102f6565b61023481610329565b602085010191505092915050565b6000604082019050818103600083015261025c818561020c565b90508181036020830152610270818461020c565b90509392505050565b6000604051905081810181811067ffffffffffffffff8211171561029c57600080fd5b8060405250919050565b600067ffffffffffffffff8211156102bd57600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156103145780820151818401526020810190506102f9565b83811115610323576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a723058201ce538708976bc5eb642066442b9156e9bf442c7f38e3977bac329d2191e7b236c6578706572696d656e74616cf50037" + def trigger(t: TupleType4[Uint256, DynamicBytes, Uint256, DynamicBytes], sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[TupleType4[Uint256, DynamicBytes, Uint256, DynamicBytes]]]].encode(TupleType1.apply[TupleType4[Uint256, DynamicBytes, Uint256, DynamicBytes]](t)) + val functionId = Hex.hex2Bytes("85799c36") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def deploy(sender: Address, opt: TransactionOpt): Unit = { + val encoded = Hex.hex2Bytes(binary) + impl.deploy(encoded, sender, opt) + } + def decodeTestEvent(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Uint256]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Uint256]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType2[DynamicBytes, DynamicBytes]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeTestEvent: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0x174e799db4473820d2ac095205358bba921759d7f2fb09509751a40a543842aa")) + impl.subscribeLogs(query).map(decodeTestEvent) + } + def isDeployed: Boolean = impl.isDeployed + def contractAddress: Address = impl.address.get + def loadFrom(contractAddress: Address) = impl.load(contractAddress) +} \ No newline at end of file diff --git a/examples/src/main/scala/examples/token/SimpleToken.scala b/examples/src/main/scala/examples/token/SimpleToken.scala new file mode 100644 index 0000000..c9dbd56 --- /dev/null +++ b/examples/src/main/scala/examples/token/SimpleToken.scala @@ -0,0 +1,136 @@ +// AUTO GENERATED, DO NOT EDIT + +package examples.token +import akka.NotUsed +import akka.stream.scaladsl.Source +import ethabi.util.{ Hex, Hash } +import ethabi.types._ +import ethabi.types.generated._ +import ethabi.protocol.{ Contract, EventValue } +import ethabi.protocol.Request._ +import ethabi.protocol.Response.Log +import scala.concurrent.Future +class SimpleToken(endpoint: String) { self => + private val impl = Contract(endpoint) + import impl.dispatcher + private val binary = "60806040523480156200001157600080fd5b506040805190810160405280600b81526020017f53696d706c65546f6b656e0000000000000000000000000000000000000000008152506040805190810160405280600381526020017f53494d0000000000000000000000000000000000000000000000000000000000815250601282600390805190602001906200009892919062000293565b508160049080519060200190620000b192919062000293565b5080600560006101000a81548160ff021916908360ff160217905550505050620000f633601260ff16600a0a61271002620000fc640100000000026401000000009004565b62000342565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156200013957600080fd5b6200015e81600254620002716401000000000262001159179091906401000000009004565b600281905550620001c5816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054620002716401000000000262001159179091906401000000009004565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60008082840190508381101515156200028957600080fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002d657805160ff191683800117855562000307565b8280016001018555821562000307579182015b8281111562000306578251825591602001919060010190620002e9565b5b5090506200031691906200031a565b5090565b6200033f91905b808211156200033b57600081600090555060010162000321565b5090565b90565b6111a680620003526000396000f3fe608060405234801561001057600080fd5b50600436106100ec576000357c010000000000000000000000000000000000000000000000000000000090048063313ce567116100a957806395d89b411161008357806395d89b41146103a2578063a457c2d714610425578063a9059cbb1461048b578063dd62ed3e146104f1576100ec565b8063313ce567146102c057806339509351146102e457806370a082311461034a576100ec565b806306fdde03146100f1578063095ea7b31461017457806318160ddd146101da57806323b872dd146101f85780632e0f26251461027e5780632ff2e9dc146102a2575b600080fd5b6100f9610569565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013957808201518184015260208101905061011e565b50505050905090810190601f1680156101665780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101c06004803603604081101561018a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061060b565b604051808215151515815260200191505060405180910390f35b6101e2610738565b6040518082815260200191505060405180910390f35b6102646004803603606081101561020e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610742565b604051808215151515815260200191505060405180910390f35b61028661094a565b604051808260ff1660ff16815260200191505060405180910390f35b6102aa61094f565b6040518082815260200191505060405180910390f35b6102c861095e565b604051808260ff1660ff16815260200191505060405180910390f35b610330600480360360408110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610975565b604051808215151515815260200191505060405180910390f35b61038c6004803603602081101561036057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bac565b6040518082815260200191505060405180910390f35b6103aa610bf4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103ea5780820151818401526020810190506103cf565b50505050905090810190601f1680156104175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104716004803603604081101561043b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c96565b604051808215151515815260200191505060405180910390f35b6104d7600480360360408110156104a157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610ecd565b604051808215151515815260200191505060405180910390f35b6105536004803603604081101561050757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ee4565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106015780601f106105d657610100808354040283529160200191610601565b820191906000526020600020905b8154815290600101906020018083116105e457829003601f168201915b5050505050905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415151561064857600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600254905090565b60006107d382600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061085e848484610f8d565b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600190509392505050565b601281565b601260ff16600a0a6127100281565b6000600560009054906101000a900460ff16905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156109b257600080fd5b610a4182600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461115990919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c8c5780601f10610c6157610100808354040283529160200191610c8c565b820191906000526020600020905b815481529060010190602001808311610c6f57829003601f168201915b5050505050905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610cd357600080fd5b610d6282600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000610eda338484610f8d565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000828211151515610f7c57600080fd5b600082840390508091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610fc957600080fd5b61101a816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f6b90919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110ad816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461115990919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600080828401905083811015151561117057600080fd5b809150509291505056fea165627a7a7230582008f3a090533ddacdd7c8c5ec44ffd7b040994ae055e7f95b00e42d19cbc274e20029" + def name(sender: Address, opt: TransactionOpt): Future[StringType] = { + val encoded = Hex.hex2Bytes("06fdde03") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[StringType]].decode(bytes, 0) + result._1 + } + } + def approve(spender: Address, value: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Uint256]]].encode(TupleType2.apply[Address, Uint256](spender, value)) + val functionId = Hex.hex2Bytes("095ea7b3") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def totalSupply(sender: Address, opt: TransactionOpt): Future[Uint256] = { + val encoded = Hex.hex2Bytes("18160ddd") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def transferFrom(from: Address, to: Address, value: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType3[Address, Address, Uint256]]].encode(TupleType3.apply[Address, Address, Uint256](from, to, value)) + val functionId = Hex.hex2Bytes("23b872dd") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def DECIMALS(sender: Address, opt: TransactionOpt): Future[Uint8] = { + val encoded = Hex.hex2Bytes("2e0f2625") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint8]].decode(bytes, 0) + result._1 + } + } + def INITIAL_SUPPLY(sender: Address, opt: TransactionOpt): Future[Uint256] = { + val encoded = Hex.hex2Bytes("2ff2e9dc") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def decimals(sender: Address, opt: TransactionOpt): Future[Uint8] = { + val encoded = Hex.hex2Bytes("313ce567") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint8]].decode(bytes, 0) + result._1 + } + } + def increaseAllowance(spender: Address, addedValue: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Uint256]]].encode(TupleType2.apply[Address, Uint256](spender, addedValue)) + val functionId = Hex.hex2Bytes("39509351") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def balanceOf(owner: Address, sender: Address, opt: TransactionOpt): Future[Uint256] = { + val paramsEncoded = implicitly[TypeInfo[TupleType1[Address]]].encode(TupleType1.apply[Address](owner)) + val functionId = Hex.hex2Bytes("70a08231") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def symbol(sender: Address, opt: TransactionOpt): Future[StringType] = { + val encoded = Hex.hex2Bytes("95d89b41") + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[StringType]].decode(bytes, 0) + result._1 + } + } + def decreaseAllowance(spender: Address, subtractedValue: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Uint256]]].encode(TupleType2.apply[Address, Uint256](spender, subtractedValue)) + val functionId = Hex.hex2Bytes("a457c2d7") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def transfer(to: Address, value: Uint256, sender: Address, opt: TransactionOpt): Future[Hash] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Uint256]]].encode(TupleType2.apply[Address, Uint256](to, value)) + val functionId = Hex.hex2Bytes("a9059cbb") + val encoded = functionId ++ paramsEncoded + impl.sendTransaction(encoded, sender, opt) + } + def allowance(owner: Address, spender: Address, sender: Address, opt: TransactionOpt): Future[Uint256] = { + val paramsEncoded = implicitly[TypeInfo[TupleType2[Address, Address]]].encode(TupleType2.apply[Address, Address](owner, spender)) + val functionId = Hex.hex2Bytes("dd62ed3e") + val encoded = functionId ++ paramsEncoded + impl.call(encoded, sender, opt).map { bytes => + val result = implicitly[TypeInfo[Uint256]].decode(bytes, 0) + result._1 + } + } + def deploy(sender: Address, opt: TransactionOpt): Unit = { + val encoded = Hex.hex2Bytes(binary) + impl.deploy(encoded, sender, opt) + } + def decodeTransfer(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType1[Uint256]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeTransfer: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")) + impl.subscribeLogs(query).map(decodeTransfer) + } + def decodeApproval(log: Log): EventValue = { + var typeInfos = Seq.empty[TypeInfo[SolType]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[Address]] + typeInfos = typeInfos :+ implicitly[TypeInfo[TupleType1[Uint256]]] + EventValue.decodeEvent(typeInfos, log) + } + def subscribeApproval: Source[EventValue, NotUsed] = { + val query = LogQuery.from(contractAddress, Hash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925")) + impl.subscribeLogs(query).map(decodeApproval) + } + def isDeployed: Boolean = impl.isDeployed + def contractAddress: Address = impl.address.get + def loadFrom(contractAddress: Address) = impl.load(contractAddress) +} \ No newline at end of file diff --git a/examples/src/test/scala/examples/simple/SimpleSpec.scala b/examples/src/test/scala/examples/simple/SimpleSpec.scala new file mode 100644 index 0000000..910c4f0 --- /dev/null +++ b/examples/src/test/scala/examples/simple/SimpleSpec.scala @@ -0,0 +1,40 @@ +package examples.simple + +import akka.actor.ActorSystem +import akka.stream.ActorMaterializer +import org.scalatest.{Matchers, WordSpec} +import ethabi.protocol.Request.TransactionOpt +import ethabi.types.{Address, DynamicBytes} +import ethabi.types.generated.{TupleType4, Uint256} +import scala.util.{Failure, Success} + +class SimpleSpec extends WordSpec with Matchers { + "test simple contract" in { + implicit val system = ActorSystem() + implicit val materializer = ActorMaterializer() + import system.dispatcher + + val sender = Address("0xe538b17ebf20efcf1c426cf1480e8a2a4b87cb1b") + val contract = new Simple("ws://127.0.0.1:8546") + val opt = TransactionOpt(Some(BigInt(1000000)), Some(BigInt(10000)), None, None) + contract.deploy(sender, opt) + while (!contract.isDeployed) { + Thread.sleep(1000) + } + println("deploy succeed, address is: " + contract.contractAddress) + + contract.subscribeTestEvent.runForeach(event => println(event.toString)) + + val a = Uint256(BigInt(1000)) + val b = DynamicBytes(Array[Byte](0x01, 0x02, 0x03, 0x04)) + val c = Uint256(BigInt(3333)) + val d = DynamicBytes(Array[Byte](0x11, 0x22, 0x33, 0x44)) + val t = TupleType4[Uint256, DynamicBytes, Uint256, DynamicBytes](a, b, c, d) + contract.trigger(t, sender, opt) onComplete { + case Success(txHash) => println("work succeed: " + txHash) + case Failure(exception) => println("work failed: " + exception) + } + + Thread.sleep(10000) + } +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala new file mode 100644 index 0000000..ee340bf --- /dev/null +++ b/project/Dependencies.scala @@ -0,0 +1,26 @@ +import sbt._ +import Keys._ + +object Dependencies { + val circeVersion = "0.11.0" + val akkaVersion = "2.5.19" + val scalaMetaVersion = "4.1.0" + + val scalactic = "org.scalactic" %% "scalactic" % "3.0.5" + val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5" % "test" + val scalaMeta = "org.scalameta" %% "scalameta" % scalaMetaVersion + val fastParser = "com.lihaoyi" %% "fastparse" % "2.1.0" + val actor = "com.typesafe.akka" %% "akka-actor" % akkaVersion + val stream = "com.typesafe.akka" %% "akka-stream" % akkaVersion + val akkaHttp = "com.typesafe.akka" %% "akka-http" % "10.1.7" + val scopt = "com.github.scopt" %% "scopt" % "4.0.0-RC2" + val circeCore = "io.circe" %% "circe-core" % circeVersion + val circeGeneric = "io.circe" %% "circe-generic" % circeVersion + val circeParser = "io.circe" %% "circe-parser" % circeVersion + val scrypto = "org.scorexfoundation" %% "scrypto" % "2.0.0" + + val l = libraryDependencies + val deps = l ++= Seq(scalaTest, actor, stream, scrypto, akkaHttp, circeCore, circeGeneric, circeParser) + val codegenDeps = l ++= Seq(scalaMeta, circeCore, circeGeneric, circeParser, fastParser, scopt, scalaTest) + val examplesDpes = l ++= Seq(actor, stream, scalaTest) +} diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..c03cdb8 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version = 1.2.7 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..f299737 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1,3 @@ +addSbtPlugin("io.spray" % "sbt-boilerplate" % "0.6.1") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.4") diff --git a/src/main/boilerplate/ethabi/types/generated/TupleTypes.scala.template b/src/main/boilerplate/ethabi/types/generated/TupleTypes.scala.template new file mode 100644 index 0000000..d208dcc --- /dev/null +++ b/src/main/boilerplate/ethabi/types/generated/TupleTypes.scala.template @@ -0,0 +1,55 @@ + +package ethabi +package types +package generated + +import scala.collection.mutable +import scala.language.implicitConversions + +/* +object TupleType0 extends SolType { + def apply() = TupleType0 + + implicit lazy val typeInfo: TypeInfo[TupleType0.type] = new TypeInfo[TupleType0.type] { + override def name: String = "tuple" + override def isStatic: Boolean = true + override def encode[U >: TupleType0.type](value: U): Array[Byte] = new Array[Byte](0) + override def decode(bytes: Array[Byte], position: Int): (TupleType0.type, Int) = (TupleType0, 0) + } +} +*/ + +[1..22#final case class TupleType1[[#T1 <: SolType#]]([#_1: T1#]) extends TupleType { + override def toList: List[SolType] = List([#_1#]) + override def toString = toList.mkString("[", ", ", "]") +}# +] + +[1..22#object TupleType1 { + // create from a list + // def apply[[#T1 <: SolType#]](values: Seq[SolType]): TupleType1[[#T1#]] = TupleType1([#values(0).asInstanceOf[T1]#]) + + implicit def typeInfo[[#T1 <: SolType#]](implicit [#typeInfo1: TypeInfo[T1]#]): TypeInfo[TupleType1[[#T1#]]] = { + new TypeInfo[TupleType1[[#T1#]]] { + override def name: String = "tuple" + + override def isStatic: Boolean = [#typeInfo1.isStatic# && ] + + override def encode[U >: TupleType1[[#T1#]]](value: U): Array[Byte] = { + val original = value.asInstanceOf[TupleType1[[#T1#]]] + val typeInfos = List([#typeInfo1#]) + val encodedValues = List([#typeInfo1.encode(original._1)#]) + TupleType.encode(typeInfos, encodedValues) + } + + override def decode(bytes: Array[Byte], position: Int): (TupleType1[[#T1#]], Int) = { + val typeInfos = List([#typeInfo1#]) + var index, staticOffset, totalConsumed = ##0 + val (results, consumed) = TupleType.decode(bytes, position, typeInfos) + (TupleType1[[#T1#]]([#results(0).asInstanceOf[T1]#]), consumed) + } + } + } +}# + +] \ No newline at end of file diff --git a/src/main/scala/ethabi/protocol/Contract.scala b/src/main/scala/ethabi/protocol/Contract.scala new file mode 100644 index 0000000..899ff5d --- /dev/null +++ b/src/main/scala/ethabi/protocol/Contract.scala @@ -0,0 +1,106 @@ +package ethabi.protocol + +import scala.concurrent.Future +import scala.concurrent.duration._ +import scala.util.{Failure, Success} +import akka.actor.ActorSystem +import akka.stream.ActorMaterializer +import ethabi.types.{Address, SolType, TupleType, TypeInfo} +import ethabi.util.{Hash, Hex} +import ethabi.protocol.ws.Client +import ethabi.protocol.Request._ +import ethabi.protocol.Response.Log +import ethabi.types.generated.Bytes32 + +class Contract(val endpoint: String) { + private implicit val system = ActorSystem() + private implicit val materializer = ActorMaterializer() + private var contractCreator: Option[Address] = None + private var contractAddress: Option[Address] = None + private val client = Client(endpoint) + + implicit def dispatcher = system.dispatcher + def address: Option[Address] = contractAddress + def creator: Option[Address] = contractCreator + def load(address: Address): Unit = contractAddress = Some(address) + def isDeployed: Boolean = contractAddress.isDefined + + def sendTransaction(data: Array[Byte], sender: Address, opt: TransactionOpt): Future[Hash] = { + if (contractAddress.isEmpty) throw new RuntimeException("contract address is empty when call contract method") + val transaction = Transaction(sender, contractAddress, data, opt) + client.sendTransaction(transaction).map { + case Left(responseError) => throw new RuntimeException(s"send transaction failed, $responseError") + case Right(None) => throw new RuntimeException(s"no transaction hash after send succeed") + case Right(Some(txHash)) => txHash + } + } + + def call(data: Array[Byte], sender: Address, opt: TransactionOpt): Future[Array[Byte]] = { + if (contractAddress.isEmpty) throw new RuntimeException("contract address is empty when call contract method") + val callData = Transaction(sender, contractAddress, data, opt) + client.call(callData).map { + case Left(responseError) => throw new RuntimeException(s"call contract failed, $responseError") + case Right(None) => Array.empty[Byte] + case Right(Some(value)) => value + } + } + + // data include all constructor arguments + def deploy(data: Array[Byte], sender: Address, opt: TransactionOpt): Unit = { + contractCreator = Some(sender) + val transaction = Transaction(sender, None, data, opt) + client.sendTransaction(transaction) onComplete { + case Success(response) => response match { + case Right(Some(txHash)) => afterDeploy(txHash) + case Left(responseError) => throw new RuntimeException(s"deploy contract failed: $responseError") + case Right(None) => throw new RuntimeException("deploy contract failed, no tx hash return") + } + case Failure(exception) => throw new RuntimeException(s"deploy contract failed: $exception") + } + } + + private def afterDeploy(txHash: Hash): Unit = + client.transactionReceipt(txHash) onComplete { + case Success(response) => response match { + case Left(responseError) => throw new RuntimeException(s"deploy contract failed: $responseError") + case Right(None) => system.scheduler.scheduleOnce(2 seconds, () => afterDeploy(txHash)) + case Right(Some(receipt)) => + assert(receipt.contractAddress.isDefined) + // call `get` explicitly + contractAddress = Some(Address(receipt.contractAddress.get)) + } + case Failure(exception) => throw exception + } + + def subscribeLogs(logQuery: LogQuery) = client.subscribeLogs(logQuery) +} + +object Contract { + def apply(endpoint: String) = new Contract(endpoint) +} + +case class EventValue(indexedValues: Seq[SolType], nonIndexedValues: Seq[SolType]) { + override def toString: String = { + s""" + |{ + | indexedValues: ${indexedValues.mkString("[", ", ", "]")}, + | nonIndexedValues: ${nonIndexedValues.mkString("[", ", ", "]")} + |} + """.stripMargin + } +} + +object EventValue { + def decodeEvent(typeInfos: Seq[TypeInfo[_ <: SolType]], log: Log): EventValue = { + val topics = log.topics.slice(1, log.topics.length).map(Hex.hex2Bytes) + val data = Hex.hex2Bytes(log.data) + val indexedValues = topics.zip(typeInfos).map { + case (bytes, typeInfo) => + if (typeInfo.isStatic) typeInfo.decode(bytes, 0)._1 + else Bytes32(bytes) + } + val nonIndexedTypeInfo = typeInfos.slice(topics.length, typeInfos.length).headOption + val nonIndexedValues = nonIndexedTypeInfo.map(_.decode(data, 0)._1.asInstanceOf[TupleType].toList) + EventValue(indexedValues, nonIndexedValues.getOrElse(Seq.empty)) + } +} diff --git a/src/main/scala/ethabi/protocol/Notifier.scala b/src/main/scala/ethabi/protocol/Notifier.scala new file mode 100644 index 0000000..117280e --- /dev/null +++ b/src/main/scala/ethabi/protocol/Notifier.scala @@ -0,0 +1,61 @@ +package ethabi.protocol + +import akka.actor.{ActorRef, Status} +import akka.stream.{Attributes, Outlet, SourceShape} +import akka.stream.stage.{GraphStage, GraphStageLogic, OutHandler} +import io.circe.Decoder +import ethabi.protocol.Subscription.{Notification, SubscriptionId, UpstreamStopped} +import scala.collection.mutable + +class Notifier[T : Decoder](coordinator: ActorRef, request: Request) extends GraphStage[SourceShape[T]] { + import Notifier._ + private val outlet = Outlet[T]("notifier.out") + private val queue = mutable.Queue.empty[T] + override val shape = SourceShape(outlet) + + override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) { + private var subscriptionId: Option[SubscriptionId] = None + implicit def self = stageActor.ref + + setHandler(outlet, new OutHandler { + override def onPull(): Unit = { + if (queue.nonEmpty) { + val element = queue.dequeue() + push(outlet, element) + } + } + }) + + override def preStart(): Unit = { + val target = getStageActor(handler).ref + coordinator ! StartSubscribe(target, request) + } + + override def postStop(): Unit = { + subscriptionId.foreach(coordinator ! Unsubscribe(_)) + } + + private def handler(receive: (ActorRef, Any)): Unit = { + receive match { + case (_, SubscribeSucceed(id)) => subscriptionId = Some(id) + case (_, notification: Notification) => + val element = notification.as[T] + if (isAvailable(outlet) && queue.isEmpty) push(outlet, element) + else queue.enqueue(element.asInstanceOf[T]) + case (_, UpstreamStopped) => + if (queue.nonEmpty) emitMultiple(outlet, queue.toList, () => completeStage()) + else completeStage() + case (_, failure: Status.Failure) => + if (queue.nonEmpty) emitMultiple(outlet, queue.toList, () => fail(outlet, failure.cause)) + else fail(outlet, failure.cause) + case _ => // log + } + } + } +} + +object Notifier { + case class StartSubscribe(target: ActorRef, request: Request) + case class SubscribeSucceed(subscriptionId: SubscriptionId) + case class Unsubscribe(subscriptionId: SubscriptionId) +} diff --git a/src/main/scala/ethabi/protocol/Request.scala b/src/main/scala/ethabi/protocol/Request.scala new file mode 100644 index 0000000..087610b --- /dev/null +++ b/src/main/scala/ethabi/protocol/Request.scala @@ -0,0 +1,214 @@ +package ethabi.protocol + +import io.circe.Json +import io.circe.syntax._ +import ethabi.util.{Hex, Hash} +import ethabi.types.Address +import scala.collection.mutable +import java.util.concurrent.atomic.AtomicLong + +case class Request(jsonrpc: String, id: Long, params: Seq[Json], method: String) { + def withId(id: Long): Request = copy(id = id) +} + +object Request { + private val jsonrpcVersion = "2.0" + private val nextId: AtomicLong = new AtomicLong(1) + + def apply(method: String, params: Seq[Json] = Seq.empty[Json]): Request = { + Request(jsonrpcVersion, nextId.getAndIncrement(), params, method) + } + + sealed trait BlockTag + case object Latest extends BlockTag { + override def toString = "latest" + } + case object Earliest extends BlockTag { + override def toString = "earliest" + } + case object Pending extends BlockTag { + override def toString = "pending" + } + case class BlockNumber(height: Long) extends BlockTag { + override def toString = Hex.long2Hex(height, withPrefix = true) + } + + case class TransactionOpt(gas: Option[BigInt], gasPrice: Option[BigInt], value: Option[BigInt], nonce: Option[Long]) { + def withGas(gas: BigInt): TransactionOpt = copy(gas = Some(gas)) + def withGasPrice(gasPrice: BigInt): TransactionOpt = copy(gasPrice = Some(gasPrice)) + def withValue(value: BigInt): TransactionOpt = copy(value = Some(value)) + def withNonce(nonce: Long): TransactionOpt = copy(nonce = Some(nonce)) + } + + case class Transaction(from: Address, to: Option[Address], data: Array[Byte], opt: TransactionOpt) { + def toJson: Json = { + val json = mutable.Map.empty[String, String] + json("from") = from.toString + if (to.isDefined) json("to") = to.get.toString + if (!data.isEmpty) json("data") = Hex.bytes2Hex(data, withPrefix = true) + if (opt.gas.isDefined) json("gas") = Hex.bigInt2Hex(opt.gas.get, withPrefix = true) + if (opt.gasPrice.isDefined) json("gasPrice") = Hex.bigInt2Hex(opt.gasPrice.get, withPrefix = true) + if (opt.value.isDefined) json("value") = Hex.bigInt2Hex(opt.value.get, withPrefix = true) + if (opt.nonce.isDefined) json("nonce") = Hex.bigInt2Hex(opt.nonce.get, withPrefix = true) + json.asJson + } + override def toString = toJson.spaces2 + } + + case class LogFilter(fromBlock: Option[BlockTag], toBlock: Option[BlockTag], addresses: Seq[Address], topics: Option[Array[Array[Hash]]]) { + def toJson: Json = { + val json = mutable.Map.empty[String, Json] + if (fromBlock.isDefined) json("fromBlock") = Json.fromString(fromBlock.get.toString) + if (toBlock.isDefined) json("toBlock") = Json.fromString(toBlock.get.toString) + json("address") = Json.fromValues(addresses.map(addr => Json.fromString(addr.toString))) + if (topics.isDefined) json("topics") = Json.fromValues(topics.get.map(arr => Json.fromValues(arr.map(hash => Json.fromString(hash.toString))))) + json.asJson + } + override def toString = toJson.spaces2 + } + + case class LogQuery(fromBlock: Option[BlockTag], toBlock: Option[BlockTag], addresses: Seq[Address], topics: Option[Array[Array[Hash]]], blockHash: Option[Hash]) { + def toJson: Json = { + val json = mutable.Map.empty[String, Json] + if (fromBlock.isDefined) json("fromBlock") = Json.fromString(fromBlock.get.toString) + if (toBlock.isDefined) json("toBlock") = Json.fromString(toBlock.get.toString) + json("address") = Json.fromValues(addresses.map(addr => Json.fromString(addr.toString))) + if (topics.isDefined) json("topics") = Json.fromValues(topics.get.map(arr => Json.fromValues(arr.map(hash => Json.fromString(hash.toString))))) + if (blockHash.isDefined) json("blockHash") = Json.fromString(blockHash.get.toString) + json.asJson + } + override def toString = toJson.spaces2 + } + + object LogQuery { + def from(address: Address, topic: Hash): LogQuery = + LogQuery(None, None, Seq(address), Some(Array(Array(topic))), None) + } + + def clientVersion(): Request = Request(method = "web3_clientVersion") + def sha3(data: Array[Byte]): Request = { + Request(method = "web3_sha3", params = Seq(Json.fromString(Hex.bytes2Hex(data, withPrefix = true)))) + } + def netVersion(): Request = Request(method = "net_version") + def netListening(): Request = Request(method = "net_listening") + def netPeerCount(): Request = Request(method = "net_peerCount") + def protocolVersion(): Request = Request(method = "eth_protocolVersion") + def syncing(): Request = Request(method = "eth_syncing") + def coinbase(): Request = Request(method = "eth_coinbase") + def mining(): Request = Request(method = "eth_mining") + def hashRate(): Request = Request(method = "eth_hashrate") + def gasPrice(): Request = Request(method = "eth_gasPrice") + def accounts(): Request = Request(method = "eth_accounts") + def blockNumber(): Request = Request(method = "eth_blockNumber") + def balance(address: Address, blockTag: BlockTag): Request = { + Request(method = "eth_getBalance", params = Seq(address.toString, blockTag.toString).map(Json.fromString)) + } + def storageAt(address: Address, position: Int, blockTag: BlockTag): Request = { + val positionHex = Hex.int2Hex(position, withPrefix = true) + Request(method = "eth_getStorageAt", params = Seq(address.toString, positionHex, blockTag.toString).map(Json.fromString)) + } + def transactionCount(address: Address, blockTag: BlockTag): Request = { + Request(method = "eth_getTransactionCount", params = Seq(address.toString, blockTag.toString).map(Json.fromString)) + } + def blockTransactionCountByHash(blockHash: String): Request = { + Request(method = "eth_getBlockTransactionCountByHash", params = Seq(Json.fromString(blockHash))) + } + def blockTransactionCountByNumber(blockTag: BlockTag = Latest): Request = { + Request(method = "eth_getBlockTransactionCountByNumber", params = Seq(Json.fromString(blockTag.toString))) + } + def blockTransactionCountByNumber(height: Long): Request = { + blockTransactionCountByNumber(BlockNumber(height)) + } + def uncleCountByHash(blockHash: String): Request = { + Request(method = "eth_getUncleCountByBlockHash", params = Seq(Json.fromString(blockHash))) + } + def uncleCountByNumber(blockTag: BlockTag = Latest): Request = { + Request(method = "eth_getUncleCountByBlockNumber", params = Seq(Json.fromString(blockTag.toString))) + } + def uncleCountByNumber(height: Long): Request = { + uncleCountByNumber(BlockNumber(height)) + } + def code(address: Address, blockTag: BlockTag = Latest): Request = { + Request(method = "eth_getCode", params = Seq(address.toString, blockTag.toString).map(Json.fromString)) + } + def code(address: Address, height: Long): Request = { + code(address, BlockNumber(height)) + } + def sign(address: Address, data: String): Request = { + Request(method = "eth_sign", params = Seq(address.toString, data).map(Json.fromString)) + } + def sing(address: Address, data: Array[Byte]): Request = { + val dataHex = Hex.bytes2Hex(data, withPrefix = true) + Request(method = "eth_sign", params = Seq(address.toString, dataHex).map(Json.fromString)) + } + def sendTransaction(transaction: Transaction): Request = { + Request(method = "eth_sendTransaction", params = Seq(transaction.toJson)) + } + def sendRawTransaction(rawTx: Array[Byte]): Request = { + val txHex = Hex.bytes2Hex(rawTx, withPrefix = true) + Request(method = "eth_sendRawTransaction", params = Seq(Json.fromString(txHex))) + } + def call(callData: Transaction, blockTag: BlockTag): Request = + Request(method = "eth_call", params = Seq(callData.toJson, Json.fromString(blockTag.toString))) + def estimateGas(callData: Transaction, blockTag: BlockTag = Latest): Request = + Request(method = "eth_estimateGas", params = Seq(callData.toJson, Json.fromString(blockTag.toString))) + def estimateGas(callData: Transaction, height: Long): Request = estimateGas(callData, BlockNumber(height)) + def blockByHash(hash: Hash, detail: Boolean = false): Request = + Request(method = "eth_getBlockByHash", params = Seq(Json.fromString(hash.toString), Json.fromBoolean(detail))) + def blockByNumber(blockTag: BlockTag = Latest, detail: Boolean = false): Request = { + Request(method = "eth_getBlockByNumber", params = Seq(Json.fromString(blockTag.toString), Json.fromBoolean(detail))) + } + def transactionByHash(hash: String): Request = Request(method = "eth_getTransactionByHash", params = Seq(Json.fromString(hash))) + def transactionByHash(hash: Hash): Request = transactionByHash(hash.toString) + def transactionByBlockHashAndIndex(hash: String, index: Int): Request = { + val indexHex = Hex.int2Hex(index, withPrefix = true) + Request(method = "eth_getTransactionByBlockHashAndIndex", params = Seq(hash, indexHex).map(Json.fromString)) + } + def transactionByBlockHashAndIndex(hash: Hash, index: Int): Request = transactionByBlockHashAndIndex(hash.toString, index) + def transactionByBlockNumberAndIndex(blockTag: BlockTag = Latest, index: Int): Request = { + val indexHex = Hex.int2Hex(index, withPrefix = true) + Request(method = "eth_getTransactionByBlockNumberAndIndex", params = Seq(blockTag.toString, indexHex).map(Json.fromString)) + } + def transactionByBlockNumberAndIndex(height: Long, index: Int): Request = transactionByBlockNumberAndIndex(BlockNumber(height), index) + def transactionReceipt(hash: String): Request = Request(method = "eth_getTransactionReceipt", params = Seq(Json.fromString(hash))) + def transactionReceipt(hash: Hash): Request = transactionReceipt(hash.toString) + def uncleByBlockHashAndIndex(hash: String, index: Int): Request = { + val indexHex = Hex.int2Hex(index, withPrefix = true) + Request(method = "eth_getUncleByBlockHashAndIndex", params = Seq(hash, indexHex).map(Json.fromString)) + } + def uncleByBlockHashAndIndex(hash: Hash, index: Int): Request = uncleByBlockHashAndIndex(hash.toString, index) + def uncleByBlockNumberAndIndex(blockTag: BlockTag = Latest, index: Int): Request = { + val indexHex = Hex.int2Hex(index, withPrefix = true) + Request(method = "eth_getUncleByBlockNumberAndIndex", params = Seq(blockTag.toString, indexHex).map(Json.fromString)) + } + def uncleByBlockNumberAndIndex(height: Long, index: Int): Request = { + uncleByBlockNumberAndIndex(BlockNumber(height), index) + } + def newFilter(logFilter: LogFilter): Request = Request(method = "eth_newFilter", params = Seq(logFilter.toJson)) + def newBlockFilter(): Request = Request(method = "eth_newBlockFilter") + def newPendingTransactionFilter(): Request = Request(method = "eth_newPendingTransactionFilter") + def uninstallFilter(filterId: Int): Request = { + val filterIdHex = Hex.int2Hex(filterId, withPrefix = true) + Request(method = "eth_uninstallFilter", params = Seq(Json.fromString(filterIdHex))) + } + def filterChanges(filterId: Int): Request = { + val filterIdHex = Hex.int2Hex(filterId, withPrefix = true) + Request(method = "eth_getFilterChanges", params = Seq(Json.fromString(filterIdHex))) + } + def filterLogs(filterId: Int): Request = { + val filterIdHex = Hex.int2Hex(filterId, withPrefix = true) + Request(method = "eth_getFilterLogs", params = Seq(Json.fromString(filterIdHex))) + } + def logs(logQuery: LogQuery): Request = Request(method = "eth_getLogs", params = Seq(logQuery.toJson)) + // TODO: more rpc api + + def subscribeNewHeader(includeTransactions: Boolean = false): Request = + Request(method = "eth_subscribe", params = Seq(Json.fromString("newHeads"), Map("includeTransactions" -> includeTransactions).asJson)) + def subscribeLogs(logQuery: LogQuery): Request = + Request(method = "eth_subscribe", params = Seq(Json.fromString("logs"), logQuery.toJson)) + def subscribeNewPendingTransactions(): Request = + Request(method = "eth_subscribe", params = Seq(Json.fromString("newPendingTransactions"))) + def subscribeSyncStatus(): Request = Request(method = "eth_subscribe", params = Seq(Json.fromString("syncing"))) + def unsubscribe(subscriptionId: String): Request = + Request(method = "eth_unsubscribe", params = Seq(Json.fromString(subscriptionId))) +} diff --git a/src/main/scala/ethabi/protocol/Response.scala b/src/main/scala/ethabi/protocol/Response.scala new file mode 100644 index 0000000..5d17597 --- /dev/null +++ b/src/main/scala/ethabi/protocol/Response.scala @@ -0,0 +1,42 @@ +package ethabi.protocol + +import io.circe.{Json, Decoder} + +case class Response(jsonrpc: String, id: Int, result: Json, error: Option[ResponseError]) { + private val response: Either[ResponseError, Json] = if (error.isDefined) Left(error.get) else Right(result) + def as[T : Decoder]: Either[ResponseError, Option[T]] = response.map { json => + if (json.isNull) None + else json.as[T] match { + case Left(decodingFailure) => throw decodingFailure + case Right(value) => Some(value) + } + } + + // auto generated Decoder[Either[A, B]] doesn't work, construct with `either` op manually + def decodeWith[T](decoder: Decoder[T]): Either[ResponseError, Option[T]] = response.map { json => + if (json.isNull) None + else decoder.decodeJson(json) match { + case Left(decodingFailure) => throw decodingFailure + case Right(value) => Some(value) + } + } +} + +case class ResponseError(code: Int, message: String, data: Option[Json]) + +object Response { + case class Syncing(startingBlock: Long, currentBlock: Long, highestBlock: Long) + case class Header(parentHash: String, sha3Uncles: String, miner: String, stateRoot: String, transactionsRoot: String, + receiptsRoot: String, logsBloom: String, difficulty: String, number: String, gasLimit: String, gasUsed: String, + timestamp: String, extraData: String, mixHash: String, nonce: String, hash:String) + case class Log(address: String, topics: Seq[String], data: String, blockNumber: String, transactionHash: String, + transactionIndex: String, blockHash: String, logIndex: String, removed: Boolean) + case class SyncProgress(startingBlock: Long, currentBlock: Long, highestBlock: Long, pulledStates: Long, knownStates: Long) + case class SyncStatus(syncing: Boolean, status: Option[SyncProgress]) + case class TransactionReceipt(transactionHash: String, transactionIndex: String, blockHash: String, blockNumber: String, + cumulativeGasUsed: String, gasUsed: String, contractAddress: Option[String], root: Option[String], + status: Option[String], from: String, to: Option[String], logs: Seq[Log], logsBloom: String) + case class Transaction(blockHash: Option[String], blockNumber: Option[String], from: String, gas: String, gasPrice: String, + hash: String, input: String, nonce: String, to: String, transactionIndex: String, value: String, + v: String, r: String, s: String) +} diff --git a/src/main/scala/ethabi/protocol/Service.scala b/src/main/scala/ethabi/protocol/Service.scala new file mode 100644 index 0000000..d1af5e0 --- /dev/null +++ b/src/main/scala/ethabi/protocol/Service.scala @@ -0,0 +1,53 @@ +package ethabi.protocol + +import io.circe.Decoder +import io.circe.generic.auto._ +import ethabi.protocol.Request.{Transaction => ReqTransaction, _} +import ethabi.protocol.Response._ + +import scala.concurrent.Future +import ethabi.types.Address +import ethabi.util.{Hash, Hex} + +private [protocol] trait Service { + import scala.concurrent.ExecutionContext.Implicits.global + import Service._ + def allowSubscribe: Boolean + def doRequest(req: Request): Future[Response] + + def clientVersion: Result[String] = doRequest(Request.clientVersion()).map(_.as[String]) + def sha3(data: Array[Byte]): Result[Hash] = doRequest(Request.sha3(data)).map(_.as[String].map(_.map(Hash.apply))) + def netVersion: Result[String] = doRequest(Request.netVersion()).map(_.as[String]) + def netListening: Result[Boolean] = doRequest(Request.netListening()).map(_.as[Boolean]) + def peerCount: Result[Int] = doRequest(Request.netPeerCount()).map(_.as[String].map(_.map(Hex.hex2Int))) + def protocolVersion: Result[String] = doRequest(Request.protocolVersion()).map(_.as[String]) + def syncing: Result[Either[Boolean, Response.Syncing]] = doRequest(Request.syncing()).map(_.decodeWith(Decoder[Boolean].either(Decoder[Response.Syncing]))) + def coinbase: Result[Address] = doRequest(Request.coinbase()).map(_.as[String].map(_.map(Address.apply))) + def mining: Result[Boolean] = doRequest(Request.mining()).map(_.as[Boolean]) + def hashRate: Result[Long] = doRequest(Request.hashRate()).map(_.as[String].map(_.map(Hex.hex2Long))) + def gasPrice: Result[BigInt] = doRequest(Request.gasPrice()).map(_.as[String].map(_.map(Hex.hex2BigInt))) + def accounts: Result[Seq[Address]] = doRequest(Request.accounts()).map(_.as[Seq[String]].map(_.map(_.map(Address.apply)))) + def blockNumber: Result[Long] = doRequest(Request.blockNumber()).map(_.as[String].map(_.map(Hex.hex2Long))) + def balance(address: Address, blockTag: BlockTag = Latest): Result[BigInt] = + doRequest(Request.balance(address, blockTag)).map(_.as[String].map(_.map(Hex.hex2BigInt))) + def balance(address: Address, height: Long): Result[BigInt] = balance(address, BlockNumber(height)) + def storageAt(address: Address, position: Int, blockTag: BlockTag = Latest): Result[Array[Byte]] = + doRequest(Request.storageAt(address, position, blockTag)).map(_.as[String].map(_.map(Hex.hex2Bytes))) + def storageAt(address: Address, position: Int, height: Long): Result[Array[Byte]] = storageAt(address, position, BlockNumber(height)) + def transactionCount(address: Address, blockTag: BlockTag = Latest): Result[Int] = + doRequest(Request.transactionCount(address, blockTag)).map(_.as[String].map(_.map(Hex.hex2Int))) + def transactionCount(address: Address, height: Long): Result[Int] = transactionCount(address, BlockNumber(height)) + def blockTransactionCountByHash(blockHash: Hash): Result[Int] = + doRequest(Request.blockTransactionCountByHash(blockHash.toString)).map(_.as[String].map(_.map(Hex.hex2Int))) + + def sendTransaction(transaction: ReqTransaction): Result[Hash] = doRequest(Request.sendTransaction(transaction)).map(_.as[String].map(_.map(Hash.apply))) + def transactionReceipt(txHash: Hash): Result[TransactionReceipt] = doRequest(Request.transactionReceipt(txHash)).map(_.as[TransactionReceipt]) + def call(callData: ReqTransaction, blockTag: BlockTag = Latest): Result[Array[Byte]] = + doRequest(Request.call(callData, blockTag)).map(_.as[String].map(_.map(Hex.hex2Bytes))) + def call(callData: ReqTransaction, height: Long): Result[Array[Byte]] = call(callData, BlockNumber(height)) + def logs(logQuery: LogQuery): Result[Seq[Log]] = doRequest(Request.logs(logQuery)).map(_.as[Seq[Log]]) +} + +object Service { + type Result[T] = Future[Either[ResponseError, Option[T]]] +} \ No newline at end of file diff --git a/src/main/scala/ethabi/protocol/Subscription.scala b/src/main/scala/ethabi/protocol/Subscription.scala new file mode 100644 index 0000000..10e860b --- /dev/null +++ b/src/main/scala/ethabi/protocol/Subscription.scala @@ -0,0 +1,30 @@ +package ethabi.protocol + +import akka.NotUsed +import akka.stream.scaladsl.Source +import io.circe.{Decoder, Json} +import ethabi.protocol.Request.LogQuery +import ethabi.protocol.Response._ + +private [protocol] trait Subscription { self: Service => + def subscribeNewHeaders(includeTransactions: Boolean = false): Source[Header, NotUsed] + def subscribeLogs(logQuery: LogQuery): Source[Log, NotUsed] + def subscribeNewPendingTransaction(): Source[String, NotUsed] + def subscribeSyncStatus(): Source[SyncStatus, NotUsed] +} + +object Subscription { + type SubscriptionId = String + private [protocol] case object UpstreamStopped + + private [protocol] case class NotificationParam(result: Json, subscription: String) + private [protocol] case class Notification(jsonrpc: String, method: String, params: NotificationParam) { + def as[T : Decoder]: T = { + val decoder = implicitly[Decoder[T]] + decoder.decodeJson(params.result) match { + case Left(decodingFailure) => throw decodingFailure + case Right(value) => value + } + } + } +} diff --git a/src/main/scala/ethabi/protocol/http/Client.scala b/src/main/scala/ethabi/protocol/http/Client.scala new file mode 100644 index 0000000..b4887be --- /dev/null +++ b/src/main/scala/ethabi/protocol/http/Client.scala @@ -0,0 +1,31 @@ +package ethabi.protocol.http + +import akka.actor.ActorSystem +import akka.http.scaladsl._ +import akka.http.scaladsl.model._ +import akka.stream.ActorMaterializer +import akka.util.ByteString +import io.circe.jawn.decode +import io.circe.generic.auto._ +import io.circe.syntax._ +import ethabi.protocol.{Request, Response, Service} +import scala.concurrent.Future + +class Client(url: String)(implicit system: ActorSystem, materializer: ActorMaterializer) extends Service { + import system.dispatcher + + override def allowSubscribe: Boolean = false + override def doRequest(req: Request): Future[Response] = { + val entity = HttpEntity(ContentTypes.`application/json`, req.asJson.toString) + val resp = Http().singleRequest(HttpRequest(method = HttpMethods.POST, uri = url, entity = entity)) + resp.flatMap { response => + response.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map { raw => + decode[Response](raw.utf8String).right.get + } + } + } +} + +object Client { + def apply(url: String)(implicit system: ActorSystem, materializer: ActorMaterializer) = new Client(url) +} diff --git a/src/main/scala/ethabi/protocol/ws/Client.scala b/src/main/scala/ethabi/protocol/ws/Client.scala new file mode 100644 index 0000000..9668a66 --- /dev/null +++ b/src/main/scala/ethabi/protocol/ws/Client.scala @@ -0,0 +1,142 @@ +package ethabi.protocol.ws + +import akka.NotUsed +import akka.actor.{Actor, ActorRef, ActorSystem, PoisonPill, Props, Status} +import akka.http.scaladsl.Http +import akka.stream.{ActorMaterializer, OverflowStrategy} +import akka.stream.scaladsl.{Keep, Sink, Source} +import akka.http.scaladsl.model.StatusCodes +import akka.http.scaladsl.model.ws.{Message, TextMessage, WebSocketRequest} +import io.circe.syntax._ +import io.circe.generic.auto._ +import io.circe.{Decoder, jawn} +import ethabi.protocol.Notifier.{StartSubscribe, SubscribeSucceed, Unsubscribe} +import ethabi.protocol.Subscription._ +import ethabi.protocol.Response._ +import ethabi.protocol._ +import ethabi.protocol.ws.Client.NewRequest +import scala.concurrent.{Future, Promise} +import scala.collection.mutable +import scala.util.{Failure, Success} + +class Client(url: String)(implicit system: ActorSystem, materializer: ActorMaterializer) extends Service with Subscription { + import system.dispatcher + + private val listener = system.actorOf(Props(new Listener)) + // TODO: configurable + private val (requestReceiver, upgradeResponse) = Source.actorRef[Message](bufferSize = 1024, overflowStrategy = OverflowStrategy.dropTail) + .viaMat(Http().webSocketClientFlow(WebSocketRequest(url)))(Keep.both) + .to(Sink.actorRef(listener, UpstreamStopped)) + .run() + + upgradeResponse onComplete { + case Success(upgrade) => + if (upgrade.response.status != StatusCodes.SwitchingProtocols) + throw new RuntimeException(s"connect failed: ${upgrade.response.status}") + case Failure(exception) => throw new RuntimeException(s"connect failed: $exception") + } + + // default supervisor strategy is ok + class Listener extends Actor { + private val requests = mutable.Map.empty[Long, Promise[Response]] + private val subscribers = mutable.Map.empty[SubscriptionId, ActorRef] + + override def receive: Receive = { + case message: TextMessage.Strict => onMessage(message) + case UpstreamStopped => + subscribers.values.foreach(_ ! UpstreamStopped) + self ! PoisonPill + case failure: Status.Failure => + subscribers.values.foreach(_ ! failure) + self ! PoisonPill + case StartSubscribe(target, request) => onSubscribe(target, request) + case NewRequest(request, promise) => onNewRequest(request, promise) + case Unsubscribe(id) => onUnsubscribe(id) + case _ => // log + } + + private def onNewRequest(request: Request, promise: Promise[Response]): Unit = { + requests(request.id) = promise + val message = TextMessage(request.asJson.toString) + requestReceiver ! message + } + + private def onMessage(message: TextMessage.Strict): Unit = { + val json = jawn.parse(message.text) match { + case Left(parsingFailure) => throw parsingFailure + case Right(result) => result + } + Decoder[Response].either(Decoder[Notification]).decodeJson(json) match { + case Left(decodingFailure) => throw decodingFailure + case Right(result) => result match { + case Left(response) => onResponse(response) + case Right(notification) => onNotification(notification) + } + } + } + + private def onSubscribe(target: ActorRef, request: Request): Unit = { + val promise = Promise[Response] + self ! NewRequest(request, promise) + promise.future onComplete { + case Success(response) => response.as[String] match { + case Right(Some(id)) => subscribers(id) = target; target ! SubscribeSucceed(id) + case _ => throw new RuntimeException(s"subscribe failed") + } + case Failure(exception) => throw exception + } + } + + private def onUnsubscribe(id: String): Unit = { + subscribers.remove(id) + val promise = Promise[Response] + self ! NewRequest(Request.unsubscribe(id), promise) + promise.future onComplete { + case Success(_) => + case Failure(_) => onUnsubscribe(id) // try again when failed + } + } + + private def onResponse(response: Response): Unit = { + requests(response.id).trySuccess(response) + requests.remove(response.id) + } + + private def onNotification(notification: Notification): Unit = { + subscribers.get(notification.params.subscription).foreach(_ ! notification) + } + } + + override def allowSubscribe: Boolean = true + override def doRequest(req: Request): Future[Response] = { + val promise = Promise[Response] + listener ! NewRequest(req, promise) + promise.future + } + + override def subscribeNewHeaders(includeTransactions: Boolean = false): Source[Header, NotUsed] = { + val request = Request.subscribeNewHeader(includeTransactions) + Source.fromGraph(new Notifier[Header](listener, request)) + } + + override def subscribeLogs(logQuery: Request.LogQuery): Source[Log, NotUsed] = { + val request = Request.subscribeLogs(logQuery) + Source.fromGraph(new Notifier[Log](listener, request)) + } + + override def subscribeNewPendingTransaction(): Source[String, NotUsed] = { + val request = Request.subscribeNewPendingTransactions() + Source.fromGraph(new Notifier[String](listener, request)) + } + + override def subscribeSyncStatus(): Source[SyncStatus, NotUsed] = { + val request = Request.subscribeSyncStatus() + Source.fromGraph(new Notifier[SyncStatus](listener, request)) + } +} + +object Client { + private case class NewRequest(request: Request, promise: Promise[Response]) + + def apply(url: String)(implicit system: ActorSystem, materialzier: ActorMaterializer) = new Client(url) +} diff --git a/src/main/scala/ethabi/types/Address.scala b/src/main/scala/ethabi/types/Address.scala new file mode 100644 index 0000000..df1f105 --- /dev/null +++ b/src/main/scala/ethabi/types/Address.scala @@ -0,0 +1,32 @@ +package ethabi.types + +import java.math.BigInteger +import generated.Uint160 +import ethabi.util.Hex + +final class Address(val value: Array[Byte]) extends SolType { + assert(value.length == 20) + + override def toString: String = Hex.bytes2Hex(value, withPrefix = true) +} + +object Address { + val empty = Address(Array.fill[Byte](20)(0)) + + def apply(address: String): Address = { + Address(Hex.hex2Bytes(address)) + } + def apply(bytes: Array[Byte]): Address = new Address(bytes) + + implicit lazy val typeInfo: TypeInfo[Address] = new TypeInfo[Address] { + override def name: String = "address" + override def isStatic: Boolean = true + override def encode[U >: Address](address: U): Array[Byte] = { + Uint160.typeInfo.encode(Uint160(BigInt(new BigInteger(address.asInstanceOf[Address].value)))) + } + override def decode(bytes: Array[Byte], position: Int): (Address, Int) = { + val (result, consumed) = Uint160.typeInfo.decode(bytes, position) + (Address(result.value.toByteArray), consumed) + } + } +} diff --git a/src/main/scala/ethabi/types/Bool.scala b/src/main/scala/ethabi/types/Bool.scala new file mode 100644 index 0000000..cccddee --- /dev/null +++ b/src/main/scala/ethabi/types/Bool.scala @@ -0,0 +1,24 @@ +package ethabi.types + +import generated.Uint8 + +final case class Bool(value: Boolean) extends SolType { + override def toString = value.toString +} + +object Bool { + implicit lazy val typeInfo: TypeInfo[Bool] = new TypeInfo[Bool] { + override def name: String = "bool" + override def isStatic: Boolean = true + override def encode[U >: Bool](value: U): Array[Byte] = { + val b = value.asInstanceOf[Bool].value + if (b) Uint8.typeInfo.encode(Uint8(BigInt(1))) + else Uint8.typeInfo.encode(Uint8(BigInt(0))) + } + override def decode(bytes: Array[Byte], position: Int): (Bool, Int) = { + val (result, consumed) = Uint8.typeInfo.decode(bytes, position) + if (result.value.toInt == 1) (Bool(true), consumed) + else (Bool(false), consumed) + } + } +} diff --git a/src/main/scala/ethabi/types/DynamicArray.scala b/src/main/scala/ethabi/types/DynamicArray.scala new file mode 100644 index 0000000..a812175 --- /dev/null +++ b/src/main/scala/ethabi/types/DynamicArray.scala @@ -0,0 +1,33 @@ +package ethabi.types + +import generated.Uint256 +import scala.language.implicitConversions + +final class DynamicArray[T <: SolType](val values: List[T]) extends SolType { + def apply(x: Int): T = values(x) + override def toString = values.mkString("[", ", ", "]") +} + +object DynamicArray { + def apply[T <: SolType](values: List[T]) = new DynamicArray[T](values) + + implicit def typeInfo[T <: SolType](implicit typeInfoT: TypeInfo[T]): TypeInfo[DynamicArray[T]] = new TypeInfo[DynamicArray[T]] { + override def name: String = s"${typeInfoT.name}[]" + override def isStatic: Boolean = false + override def encode[U >: DynamicArray[T]](value: U): Array[Byte] = { + val values = value.asInstanceOf[DynamicArray[T]].values + val encodedLength = Uint256.typeInfo.encode(Uint256(BigInt(values.length))) + val encodedValues = values.map(typeInfoT.encode(_)) + val typeInfos = List.fill[TypeInfo[T]](values.length)(typeInfoT) + val bytes = TupleType.encode(typeInfos, encodedValues) + encodedLength ++ bytes + } + override def decode(bytes: Array[Byte], position: Int): (DynamicArray[T], Int) = { + val (length, lengthConsumed) = Uint256.typeInfo.decode(bytes, position) + val typeInfos = List.fill[TypeInfo[T]](length.value.toInt)(typeInfoT) + val (result, consumed) = TupleType.decode(bytes, position + lengthConsumed, typeInfos) + val values = result.map(_.asInstanceOf[T]) + (DynamicArray(values), consumed + lengthConsumed) + } + } +} diff --git a/src/main/scala/ethabi/types/DynamicBytes.scala b/src/main/scala/ethabi/types/DynamicBytes.scala new file mode 100644 index 0000000..4161226 --- /dev/null +++ b/src/main/scala/ethabi/types/DynamicBytes.scala @@ -0,0 +1,51 @@ +package ethabi.types + +import generated.Uint256 +import ethabi.util.Hex + +final class DynamicBytes(val value: Array[Byte]) extends SolType { + override def toString: String = Hex.bytes2Hex(value, withPrefix = true) +} + +object DynamicBytes { + def apply(value: Array[Byte]): DynamicBytes = new DynamicBytes(value) + + // encodedLength don't include prefix 32 bytes length + private def encodedLength(length: Int): Int = { + if (length % 32 == 0) { + length + } else { + (length / 32) * 32 + 32 + } + } + + def encode(value: Array[Byte]): Array[Byte] = { + val length = Uint256(BigInt(value.length)) + val lengthEncoded = Uint256.typeInfo.encode(length) + val totalLength = encodedLength(value.length) + 32 + val result = Array.fill[Byte](totalLength)(0) + Array.copy(lengthEncoded, 0, result, 0, 32) + Array.copy(value, 0, result, 32, value.length) + result + } + + def decode(bytes: Array[Byte], position: Int): (Array[Byte], Int) = { + val (result, consumed) = Uint256.typeInfo.decode(bytes, position) + val offset = position + consumed + val length = result.value.toInt + val encodedLen = encodedLength(length) + (bytes.slice(offset, offset + length), consumed + encodedLen) + } + + implicit lazy val typeInfo: TypeInfo[DynamicBytes] = new TypeInfo[DynamicBytes] { + override def name: String = "bytes" + override def isStatic: Boolean = false + override def encode[U >: DynamicBytes](value: U): Array[Byte] = { + DynamicBytes.encode(value.asInstanceOf[DynamicBytes].value) + } + override def decode(bytes: Array[Byte], position: Int): (DynamicBytes, Int) = { + val (result, consumed) = DynamicBytes.decode(bytes, position) + (DynamicBytes(result), consumed) + } + } +} diff --git a/src/main/scala/ethabi/types/FunctionType.scala b/src/main/scala/ethabi/types/FunctionType.scala new file mode 100644 index 0000000..885b17d --- /dev/null +++ b/src/main/scala/ethabi/types/FunctionType.scala @@ -0,0 +1,35 @@ +package ethabi.types + +import generated.Bytes24 +import ethabi.util.Hex + +final class FunctionType(val selector: Array[Byte], val address: Address) extends SolType { + override def toString: String = Hex.bytes2Hex(selector ++ address.value, withPrefix = true) +} + +object FunctionType { + def apply(selector: Array[Byte], address: Address): FunctionType = new FunctionType(selector, address) + + def encode(function: FunctionType): Array[Byte] = { + val bytes = Array.fill[Byte](24)(0) + Array.copy(function.selector, 0, bytes, 0, 4) + Array.copy(function.address.value, 0, bytes, 4, 20) + Bytes24.typeInfo.encode(Bytes24(bytes)) + } + + def decode(bytes: Array[Byte], position: Int): (FunctionType, Int) = { + val (result, consumed) = Bytes24.typeInfo.decode(bytes, position) + (FunctionType(result.value.slice(0, 4), Address(result.value.slice(4, 24))), consumed) + } + + implicit lazy val typeInfo: TypeInfo[FunctionType] = new TypeInfo[FunctionType] { + override def name: String = "function" + override def isStatic: Boolean = true + override def encode[U >: FunctionType](value: U): Array[Byte] = { + FunctionType.encode(value.asInstanceOf[FunctionType]) + } + override def decode(bytes: Array[Byte], position: Int): (FunctionType, Int) = { + FunctionType.decode(bytes, position) + } + } +} diff --git a/src/main/scala/ethabi/types/IntType.scala b/src/main/scala/ethabi/types/IntType.scala new file mode 100644 index 0000000..31ff2a3 --- /dev/null +++ b/src/main/scala/ethabi/types/IntType.scala @@ -0,0 +1,22 @@ +package ethabi.types + +import java.math.BigInteger + +object IntType { + def encode(value: BigInt): Array[Byte] = { + val encoded = value.toByteArray + val result = paddedBytes(value) + Array.copy(encoded, 0, result, maxByteLength - encoded.length, encoded.length) + result + } + + def decode(bytes: Array[Byte], length: Int, position: Int): BigInt = { + val encoded = bytes.slice(position, position + 32) + val byteLength = length >> 3 + val result = Array.fill[Byte](byteLength + 1)(0) + result(0) = encoded(0) + val offset = maxByteLength - byteLength + Array.copy(encoded, offset, result, 1, byteLength) + BigInt(new BigInteger(result)) + } +} diff --git a/src/main/scala/ethabi/types/SolType.scala b/src/main/scala/ethabi/types/SolType.scala new file mode 100644 index 0000000..52a9e01 --- /dev/null +++ b/src/main/scala/ethabi/types/SolType.scala @@ -0,0 +1,11 @@ +package ethabi.types + +// Mark trait for solidity type +trait SolType + +trait TypeInfo[+T <: SolType] { + def name: String + def isStatic: Boolean + def encode[U >: T](value: U): Array[Byte] + def decode(bytes: Array[Byte], position: Int): (T, Int) +} diff --git a/src/main/scala/ethabi/types/StaticArray.scala b/src/main/scala/ethabi/types/StaticArray.scala new file mode 100644 index 0000000..44fc6bb --- /dev/null +++ b/src/main/scala/ethabi/types/StaticArray.scala @@ -0,0 +1,30 @@ +package ethabi.types + +import scala.language.implicitConversions + +// TODO: it would be better if `length` as type argument, maybe `shapeless` can solve this +final class StaticArray[T <: SolType](val values: List[T]) extends SolType { + def apply(x: Int): T = values(x) + override def toString = values.mkString("[", ", ", "]") +} + +object StaticArray { + def apply[T <: SolType](values: List[T]) = new StaticArray[T](values) + + implicit def typeInfo[T <: SolType](implicit typeInfoT: TypeInfo[T], length: Int): TypeInfo[StaticArray[T]] = new TypeInfo[StaticArray[T]] { + override def name: String = s"${typeInfoT.name}[$length]" + override def isStatic: Boolean = typeInfoT.isStatic + override def encode[U >: StaticArray[T]](value: U): Array[Byte] = { + val values = value.asInstanceOf[StaticArray[T]].values + val encodedValues = values.map(typeInfoT.encode(_)) + val typeInfos = List.fill[TypeInfo[T]](values.length)(typeInfoT) + TupleType.encode(typeInfos, encodedValues) + } + override def decode(bytes: Array[Byte], position: Int): (StaticArray[T], Int) = { + val typeInfos = List.fill[TypeInfo[T]](length)(typeInfoT) + val (result, consumed) = TupleType.decode(bytes, position, typeInfos) + val values = result.map(_.asInstanceOf[T]) + (StaticArray[T](values), consumed) + } + } +} diff --git a/src/main/scala/ethabi/types/StaticBytes.scala b/src/main/scala/ethabi/types/StaticBytes.scala new file mode 100644 index 0000000..ae1bf48 --- /dev/null +++ b/src/main/scala/ethabi/types/StaticBytes.scala @@ -0,0 +1,16 @@ +package ethabi.types + +object StaticBytes { + def encode(value: Array[Byte], length: Int): Array[Byte] = { + val result = Array.fill[Byte](maxByteLength)(0) + Array.copy(value, 0, result, 0, length) + result + } + + def decode(bytes: Array[Byte], length: Int, position: Int): Array[Byte] = { + val encoded = bytes.slice(position, position + 32) + val result = Array.fill[Byte](length)(0) + Array.copy(encoded, 0, result, 0, length) + result + } +} diff --git a/src/main/scala/ethabi/types/StringType.scala b/src/main/scala/ethabi/types/StringType.scala new file mode 100644 index 0000000..c1e04c6 --- /dev/null +++ b/src/main/scala/ethabi/types/StringType.scala @@ -0,0 +1,24 @@ +package ethabi.types + +import java.nio.charset.StandardCharsets + +final class StringType(val value: String) extends SolType { + override def toString: String = value +} + +object StringType { + def apply(value: String): StringType = new StringType(value) + + implicit lazy val typeInfo: TypeInfo[StringType] = new TypeInfo[StringType] { + override def name: String = "string" + override def isStatic: Boolean = false + override def encode[U >: StringType](value: U): Array[Byte] = { + val bytes = value.asInstanceOf[StringType].value.getBytes(StandardCharsets.UTF_8) + DynamicBytes.typeInfo.encode(DynamicBytes(bytes)) + } + override def decode(bytes: Array[Byte], position: Int): (StringType, Int) = { + val (result, consumed) = DynamicBytes.typeInfo.decode(bytes, position) + (StringType(new String(result.value, StandardCharsets.UTF_8)), consumed) + } + } +} diff --git a/src/main/scala/ethabi/types/TupleType.scala b/src/main/scala/ethabi/types/TupleType.scala new file mode 100644 index 0000000..79e1e2a --- /dev/null +++ b/src/main/scala/ethabi/types/TupleType.scala @@ -0,0 +1,63 @@ +package ethabi.types + +import scala.collection.mutable +import generated.Uint256 + +trait TupleType extends SolType { + def toList: List[SolType] +} + +object TupleType { + private [types] def encode(typeInfos: List[TypeInfo[SolType]], encodedValues: List[Array[Byte]]): Array[Byte] = { + assert(typeInfos.length == encodedValues.length) + var index, staticLength, dynamicLength = 0 + typeInfos.zip(encodedValues).foreach { + case (typeInfo, encoded) => + if (typeInfo.isStatic) { + staticLength += encoded.length + } else { + staticLength += 32 + dynamicLength += encoded.length + } + } + val bytes = Array.fill[Byte](staticLength + dynamicLength)(0) + var staticOffset = 0 + var dynamicOffset = staticLength + typeInfos.zip(encodedValues).foreach { + case (typeInfo, encoded) => + if (typeInfo.isStatic) { + Array.copy(encoded, 0, bytes, staticOffset, encoded.length) + staticOffset += encoded.length + } else { + val dynamicOffsetEncoded = Uint256.typeInfo.encode(Uint256(BigInt(dynamicOffset))) + Array.copy(dynamicOffsetEncoded, 0, bytes, staticOffset, 32) + Array.copy(encoded, 0, bytes, dynamicOffset, encoded.length) + staticOffset += 32 + dynamicOffset += encoded.length + } + } + bytes + } + + private [types] def decode(bytes: Array[Byte], position: Int, typeInfos: List[TypeInfo[SolType]]): (List[SolType], Int) = { + var staticOffset, totalConsumed = 0 + val results = new mutable.ListBuffer[SolType]() + typeInfos.foreach(typeInfo => { + if (typeInfo.isStatic) { + val (result, consumed) = typeInfo.decode(bytes, staticOffset + position) + totalConsumed += consumed + staticOffset += consumed + results += result + } else { + val (offset, offsetConsumed) = Uint256.typeInfo.decode(bytes, staticOffset + position) + staticOffset += offsetConsumed + totalConsumed += offsetConsumed + val (result, resultConsumed) = typeInfo.decode(bytes, offset.value.toInt + position) + totalConsumed += resultConsumed + results += result + } + }) + assert(results.length == typeInfos.length) + (results.result(), totalConsumed) + } +} diff --git a/src/main/scala/ethabi/types/UintType.scala b/src/main/scala/ethabi/types/UintType.scala new file mode 100644 index 0000000..5bf845f --- /dev/null +++ b/src/main/scala/ethabi/types/UintType.scala @@ -0,0 +1,25 @@ +package ethabi.types + +import java.math.BigInteger + +object UintType { + def encode(value: BigInt): Array[Byte] = { + val encoded = if (value.bitLength == maxBitLength) { + val bytes = new Array[Byte](maxByteLength) + Array.copy(value.toByteArray, 1, bytes, 0, maxByteLength) + bytes + } else value.toByteArray + val result = Array.fill[Byte](maxByteLength)(0) + Array.copy(encoded, 0, result, maxByteLength - encoded.length, encoded.length) + result + } + + def decode(bytes: Array[Byte], length: Int, position: Int): BigInt = { + val encoded = bytes.slice(position, position + 32) + val byteLength = length >> 3 + val result = Array.fill[Byte](byteLength)(0) + val offset = maxByteLength - byteLength + Array.copy(encoded, offset, result, 0, byteLength) + BigInt(new BigInteger(result)) + } +} diff --git a/src/main/scala/ethabi/types/generated/Bytes1.scala b/src/main/scala/ethabi/types/generated/Bytes1.scala new file mode 100644 index 0000000..6733112 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes1.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes1(val value: Array[Byte]) extends SolType { + assert(value.length <= 1) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes1 { + def apply(value: Array[Byte]): Bytes1 = new Bytes1(value) + implicit lazy val typeInfo: TypeInfo[Bytes1] = new TypeInfo[Bytes1] { + override def name: String = "bytes1" + override def isStatic: Boolean = true + override def encode[U >: Bytes1](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes1].value, 1) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes1, Int) = { + val value = StaticBytes.decode(bytes, 1, position) + (Bytes1(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes10.scala b/src/main/scala/ethabi/types/generated/Bytes10.scala new file mode 100644 index 0000000..abad5e6 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes10.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes10(val value: Array[Byte]) extends SolType { + assert(value.length <= 10) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes10 { + def apply(value: Array[Byte]): Bytes10 = new Bytes10(value) + implicit lazy val typeInfo: TypeInfo[Bytes10] = new TypeInfo[Bytes10] { + override def name: String = "bytes10" + override def isStatic: Boolean = true + override def encode[U >: Bytes10](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes10].value, 10) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes10, Int) = { + val value = StaticBytes.decode(bytes, 10, position) + (Bytes10(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes11.scala b/src/main/scala/ethabi/types/generated/Bytes11.scala new file mode 100644 index 0000000..e072259 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes11.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes11(val value: Array[Byte]) extends SolType { + assert(value.length <= 11) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes11 { + def apply(value: Array[Byte]): Bytes11 = new Bytes11(value) + implicit lazy val typeInfo: TypeInfo[Bytes11] = new TypeInfo[Bytes11] { + override def name: String = "bytes11" + override def isStatic: Boolean = true + override def encode[U >: Bytes11](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes11].value, 11) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes11, Int) = { + val value = StaticBytes.decode(bytes, 11, position) + (Bytes11(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes12.scala b/src/main/scala/ethabi/types/generated/Bytes12.scala new file mode 100644 index 0000000..f9b53ea --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes12.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes12(val value: Array[Byte]) extends SolType { + assert(value.length <= 12) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes12 { + def apply(value: Array[Byte]): Bytes12 = new Bytes12(value) + implicit lazy val typeInfo: TypeInfo[Bytes12] = new TypeInfo[Bytes12] { + override def name: String = "bytes12" + override def isStatic: Boolean = true + override def encode[U >: Bytes12](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes12].value, 12) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes12, Int) = { + val value = StaticBytes.decode(bytes, 12, position) + (Bytes12(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes13.scala b/src/main/scala/ethabi/types/generated/Bytes13.scala new file mode 100644 index 0000000..aa860fd --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes13.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes13(val value: Array[Byte]) extends SolType { + assert(value.length <= 13) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes13 { + def apply(value: Array[Byte]): Bytes13 = new Bytes13(value) + implicit lazy val typeInfo: TypeInfo[Bytes13] = new TypeInfo[Bytes13] { + override def name: String = "bytes13" + override def isStatic: Boolean = true + override def encode[U >: Bytes13](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes13].value, 13) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes13, Int) = { + val value = StaticBytes.decode(bytes, 13, position) + (Bytes13(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes14.scala b/src/main/scala/ethabi/types/generated/Bytes14.scala new file mode 100644 index 0000000..7993e62 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes14.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes14(val value: Array[Byte]) extends SolType { + assert(value.length <= 14) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes14 { + def apply(value: Array[Byte]): Bytes14 = new Bytes14(value) + implicit lazy val typeInfo: TypeInfo[Bytes14] = new TypeInfo[Bytes14] { + override def name: String = "bytes14" + override def isStatic: Boolean = true + override def encode[U >: Bytes14](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes14].value, 14) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes14, Int) = { + val value = StaticBytes.decode(bytes, 14, position) + (Bytes14(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes15.scala b/src/main/scala/ethabi/types/generated/Bytes15.scala new file mode 100644 index 0000000..a4938cc --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes15.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes15(val value: Array[Byte]) extends SolType { + assert(value.length <= 15) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes15 { + def apply(value: Array[Byte]): Bytes15 = new Bytes15(value) + implicit lazy val typeInfo: TypeInfo[Bytes15] = new TypeInfo[Bytes15] { + override def name: String = "bytes15" + override def isStatic: Boolean = true + override def encode[U >: Bytes15](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes15].value, 15) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes15, Int) = { + val value = StaticBytes.decode(bytes, 15, position) + (Bytes15(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes16.scala b/src/main/scala/ethabi/types/generated/Bytes16.scala new file mode 100644 index 0000000..cf89637 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes16.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes16(val value: Array[Byte]) extends SolType { + assert(value.length <= 16) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes16 { + def apply(value: Array[Byte]): Bytes16 = new Bytes16(value) + implicit lazy val typeInfo: TypeInfo[Bytes16] = new TypeInfo[Bytes16] { + override def name: String = "bytes16" + override def isStatic: Boolean = true + override def encode[U >: Bytes16](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes16].value, 16) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes16, Int) = { + val value = StaticBytes.decode(bytes, 16, position) + (Bytes16(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes17.scala b/src/main/scala/ethabi/types/generated/Bytes17.scala new file mode 100644 index 0000000..3737719 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes17.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes17(val value: Array[Byte]) extends SolType { + assert(value.length <= 17) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes17 { + def apply(value: Array[Byte]): Bytes17 = new Bytes17(value) + implicit lazy val typeInfo: TypeInfo[Bytes17] = new TypeInfo[Bytes17] { + override def name: String = "bytes17" + override def isStatic: Boolean = true + override def encode[U >: Bytes17](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes17].value, 17) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes17, Int) = { + val value = StaticBytes.decode(bytes, 17, position) + (Bytes17(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes18.scala b/src/main/scala/ethabi/types/generated/Bytes18.scala new file mode 100644 index 0000000..fc92f27 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes18.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes18(val value: Array[Byte]) extends SolType { + assert(value.length <= 18) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes18 { + def apply(value: Array[Byte]): Bytes18 = new Bytes18(value) + implicit lazy val typeInfo: TypeInfo[Bytes18] = new TypeInfo[Bytes18] { + override def name: String = "bytes18" + override def isStatic: Boolean = true + override def encode[U >: Bytes18](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes18].value, 18) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes18, Int) = { + val value = StaticBytes.decode(bytes, 18, position) + (Bytes18(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes19.scala b/src/main/scala/ethabi/types/generated/Bytes19.scala new file mode 100644 index 0000000..4a934ed --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes19.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes19(val value: Array[Byte]) extends SolType { + assert(value.length <= 19) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes19 { + def apply(value: Array[Byte]): Bytes19 = new Bytes19(value) + implicit lazy val typeInfo: TypeInfo[Bytes19] = new TypeInfo[Bytes19] { + override def name: String = "bytes19" + override def isStatic: Boolean = true + override def encode[U >: Bytes19](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes19].value, 19) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes19, Int) = { + val value = StaticBytes.decode(bytes, 19, position) + (Bytes19(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes2.scala b/src/main/scala/ethabi/types/generated/Bytes2.scala new file mode 100644 index 0000000..31889ef --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes2.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes2(val value: Array[Byte]) extends SolType { + assert(value.length <= 2) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes2 { + def apply(value: Array[Byte]): Bytes2 = new Bytes2(value) + implicit lazy val typeInfo: TypeInfo[Bytes2] = new TypeInfo[Bytes2] { + override def name: String = "bytes2" + override def isStatic: Boolean = true + override def encode[U >: Bytes2](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes2].value, 2) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes2, Int) = { + val value = StaticBytes.decode(bytes, 2, position) + (Bytes2(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes20.scala b/src/main/scala/ethabi/types/generated/Bytes20.scala new file mode 100644 index 0000000..0e36c06 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes20.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes20(val value: Array[Byte]) extends SolType { + assert(value.length <= 20) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes20 { + def apply(value: Array[Byte]): Bytes20 = new Bytes20(value) + implicit lazy val typeInfo: TypeInfo[Bytes20] = new TypeInfo[Bytes20] { + override def name: String = "bytes20" + override def isStatic: Boolean = true + override def encode[U >: Bytes20](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes20].value, 20) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes20, Int) = { + val value = StaticBytes.decode(bytes, 20, position) + (Bytes20(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes21.scala b/src/main/scala/ethabi/types/generated/Bytes21.scala new file mode 100644 index 0000000..fbb16d0 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes21.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes21(val value: Array[Byte]) extends SolType { + assert(value.length <= 21) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes21 { + def apply(value: Array[Byte]): Bytes21 = new Bytes21(value) + implicit lazy val typeInfo: TypeInfo[Bytes21] = new TypeInfo[Bytes21] { + override def name: String = "bytes21" + override def isStatic: Boolean = true + override def encode[U >: Bytes21](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes21].value, 21) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes21, Int) = { + val value = StaticBytes.decode(bytes, 21, position) + (Bytes21(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes22.scala b/src/main/scala/ethabi/types/generated/Bytes22.scala new file mode 100644 index 0000000..4114ddc --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes22.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes22(val value: Array[Byte]) extends SolType { + assert(value.length <= 22) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes22 { + def apply(value: Array[Byte]): Bytes22 = new Bytes22(value) + implicit lazy val typeInfo: TypeInfo[Bytes22] = new TypeInfo[Bytes22] { + override def name: String = "bytes22" + override def isStatic: Boolean = true + override def encode[U >: Bytes22](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes22].value, 22) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes22, Int) = { + val value = StaticBytes.decode(bytes, 22, position) + (Bytes22(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes23.scala b/src/main/scala/ethabi/types/generated/Bytes23.scala new file mode 100644 index 0000000..73c68f1 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes23.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes23(val value: Array[Byte]) extends SolType { + assert(value.length <= 23) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes23 { + def apply(value: Array[Byte]): Bytes23 = new Bytes23(value) + implicit lazy val typeInfo: TypeInfo[Bytes23] = new TypeInfo[Bytes23] { + override def name: String = "bytes23" + override def isStatic: Boolean = true + override def encode[U >: Bytes23](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes23].value, 23) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes23, Int) = { + val value = StaticBytes.decode(bytes, 23, position) + (Bytes23(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes24.scala b/src/main/scala/ethabi/types/generated/Bytes24.scala new file mode 100644 index 0000000..f808dd1 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes24.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes24(val value: Array[Byte]) extends SolType { + assert(value.length <= 24) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes24 { + def apply(value: Array[Byte]): Bytes24 = new Bytes24(value) + implicit lazy val typeInfo: TypeInfo[Bytes24] = new TypeInfo[Bytes24] { + override def name: String = "bytes24" + override def isStatic: Boolean = true + override def encode[U >: Bytes24](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes24].value, 24) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes24, Int) = { + val value = StaticBytes.decode(bytes, 24, position) + (Bytes24(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes25.scala b/src/main/scala/ethabi/types/generated/Bytes25.scala new file mode 100644 index 0000000..5a08332 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes25.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes25(val value: Array[Byte]) extends SolType { + assert(value.length <= 25) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes25 { + def apply(value: Array[Byte]): Bytes25 = new Bytes25(value) + implicit lazy val typeInfo: TypeInfo[Bytes25] = new TypeInfo[Bytes25] { + override def name: String = "bytes25" + override def isStatic: Boolean = true + override def encode[U >: Bytes25](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes25].value, 25) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes25, Int) = { + val value = StaticBytes.decode(bytes, 25, position) + (Bytes25(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes26.scala b/src/main/scala/ethabi/types/generated/Bytes26.scala new file mode 100644 index 0000000..d570906 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes26.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes26(val value: Array[Byte]) extends SolType { + assert(value.length <= 26) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes26 { + def apply(value: Array[Byte]): Bytes26 = new Bytes26(value) + implicit lazy val typeInfo: TypeInfo[Bytes26] = new TypeInfo[Bytes26] { + override def name: String = "bytes26" + override def isStatic: Boolean = true + override def encode[U >: Bytes26](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes26].value, 26) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes26, Int) = { + val value = StaticBytes.decode(bytes, 26, position) + (Bytes26(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes27.scala b/src/main/scala/ethabi/types/generated/Bytes27.scala new file mode 100644 index 0000000..609f8d0 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes27.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes27(val value: Array[Byte]) extends SolType { + assert(value.length <= 27) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes27 { + def apply(value: Array[Byte]): Bytes27 = new Bytes27(value) + implicit lazy val typeInfo: TypeInfo[Bytes27] = new TypeInfo[Bytes27] { + override def name: String = "bytes27" + override def isStatic: Boolean = true + override def encode[U >: Bytes27](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes27].value, 27) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes27, Int) = { + val value = StaticBytes.decode(bytes, 27, position) + (Bytes27(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes28.scala b/src/main/scala/ethabi/types/generated/Bytes28.scala new file mode 100644 index 0000000..a796d62 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes28.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes28(val value: Array[Byte]) extends SolType { + assert(value.length <= 28) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes28 { + def apply(value: Array[Byte]): Bytes28 = new Bytes28(value) + implicit lazy val typeInfo: TypeInfo[Bytes28] = new TypeInfo[Bytes28] { + override def name: String = "bytes28" + override def isStatic: Boolean = true + override def encode[U >: Bytes28](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes28].value, 28) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes28, Int) = { + val value = StaticBytes.decode(bytes, 28, position) + (Bytes28(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes29.scala b/src/main/scala/ethabi/types/generated/Bytes29.scala new file mode 100644 index 0000000..072238b --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes29.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes29(val value: Array[Byte]) extends SolType { + assert(value.length <= 29) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes29 { + def apply(value: Array[Byte]): Bytes29 = new Bytes29(value) + implicit lazy val typeInfo: TypeInfo[Bytes29] = new TypeInfo[Bytes29] { + override def name: String = "bytes29" + override def isStatic: Boolean = true + override def encode[U >: Bytes29](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes29].value, 29) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes29, Int) = { + val value = StaticBytes.decode(bytes, 29, position) + (Bytes29(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes3.scala b/src/main/scala/ethabi/types/generated/Bytes3.scala new file mode 100644 index 0000000..bb56a95 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes3.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes3(val value: Array[Byte]) extends SolType { + assert(value.length <= 3) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes3 { + def apply(value: Array[Byte]): Bytes3 = new Bytes3(value) + implicit lazy val typeInfo: TypeInfo[Bytes3] = new TypeInfo[Bytes3] { + override def name: String = "bytes3" + override def isStatic: Boolean = true + override def encode[U >: Bytes3](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes3].value, 3) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes3, Int) = { + val value = StaticBytes.decode(bytes, 3, position) + (Bytes3(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes30.scala b/src/main/scala/ethabi/types/generated/Bytes30.scala new file mode 100644 index 0000000..b20fb99 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes30.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes30(val value: Array[Byte]) extends SolType { + assert(value.length <= 30) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes30 { + def apply(value: Array[Byte]): Bytes30 = new Bytes30(value) + implicit lazy val typeInfo: TypeInfo[Bytes30] = new TypeInfo[Bytes30] { + override def name: String = "bytes30" + override def isStatic: Boolean = true + override def encode[U >: Bytes30](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes30].value, 30) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes30, Int) = { + val value = StaticBytes.decode(bytes, 30, position) + (Bytes30(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes31.scala b/src/main/scala/ethabi/types/generated/Bytes31.scala new file mode 100644 index 0000000..4a68829 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes31.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes31(val value: Array[Byte]) extends SolType { + assert(value.length <= 31) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes31 { + def apply(value: Array[Byte]): Bytes31 = new Bytes31(value) + implicit lazy val typeInfo: TypeInfo[Bytes31] = new TypeInfo[Bytes31] { + override def name: String = "bytes31" + override def isStatic: Boolean = true + override def encode[U >: Bytes31](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes31].value, 31) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes31, Int) = { + val value = StaticBytes.decode(bytes, 31, position) + (Bytes31(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes32.scala b/src/main/scala/ethabi/types/generated/Bytes32.scala new file mode 100644 index 0000000..c89ff9b --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes32.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes32(val value: Array[Byte]) extends SolType { + assert(value.length <= 32) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes32 { + def apply(value: Array[Byte]): Bytes32 = new Bytes32(value) + implicit lazy val typeInfo: TypeInfo[Bytes32] = new TypeInfo[Bytes32] { + override def name: String = "bytes32" + override def isStatic: Boolean = true + override def encode[U >: Bytes32](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes32].value, 32) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes32, Int) = { + val value = StaticBytes.decode(bytes, 32, position) + (Bytes32(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes4.scala b/src/main/scala/ethabi/types/generated/Bytes4.scala new file mode 100644 index 0000000..171c7af --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes4.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes4(val value: Array[Byte]) extends SolType { + assert(value.length <= 4) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes4 { + def apply(value: Array[Byte]): Bytes4 = new Bytes4(value) + implicit lazy val typeInfo: TypeInfo[Bytes4] = new TypeInfo[Bytes4] { + override def name: String = "bytes4" + override def isStatic: Boolean = true + override def encode[U >: Bytes4](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes4].value, 4) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes4, Int) = { + val value = StaticBytes.decode(bytes, 4, position) + (Bytes4(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes5.scala b/src/main/scala/ethabi/types/generated/Bytes5.scala new file mode 100644 index 0000000..4586046 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes5.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes5(val value: Array[Byte]) extends SolType { + assert(value.length <= 5) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes5 { + def apply(value: Array[Byte]): Bytes5 = new Bytes5(value) + implicit lazy val typeInfo: TypeInfo[Bytes5] = new TypeInfo[Bytes5] { + override def name: String = "bytes5" + override def isStatic: Boolean = true + override def encode[U >: Bytes5](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes5].value, 5) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes5, Int) = { + val value = StaticBytes.decode(bytes, 5, position) + (Bytes5(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes6.scala b/src/main/scala/ethabi/types/generated/Bytes6.scala new file mode 100644 index 0000000..aaaf2d2 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes6.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes6(val value: Array[Byte]) extends SolType { + assert(value.length <= 6) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes6 { + def apply(value: Array[Byte]): Bytes6 = new Bytes6(value) + implicit lazy val typeInfo: TypeInfo[Bytes6] = new TypeInfo[Bytes6] { + override def name: String = "bytes6" + override def isStatic: Boolean = true + override def encode[U >: Bytes6](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes6].value, 6) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes6, Int) = { + val value = StaticBytes.decode(bytes, 6, position) + (Bytes6(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes7.scala b/src/main/scala/ethabi/types/generated/Bytes7.scala new file mode 100644 index 0000000..8db6747 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes7.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes7(val value: Array[Byte]) extends SolType { + assert(value.length <= 7) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes7 { + def apply(value: Array[Byte]): Bytes7 = new Bytes7(value) + implicit lazy val typeInfo: TypeInfo[Bytes7] = new TypeInfo[Bytes7] { + override def name: String = "bytes7" + override def isStatic: Boolean = true + override def encode[U >: Bytes7](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes7].value, 7) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes7, Int) = { + val value = StaticBytes.decode(bytes, 7, position) + (Bytes7(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes8.scala b/src/main/scala/ethabi/types/generated/Bytes8.scala new file mode 100644 index 0000000..d3359cf --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes8.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes8(val value: Array[Byte]) extends SolType { + assert(value.length <= 8) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes8 { + def apply(value: Array[Byte]): Bytes8 = new Bytes8(value) + implicit lazy val typeInfo: TypeInfo[Bytes8] = new TypeInfo[Bytes8] { + override def name: String = "bytes8" + override def isStatic: Boolean = true + override def encode[U >: Bytes8](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes8].value, 8) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes8, Int) = { + val value = StaticBytes.decode(bytes, 8, position) + (Bytes8(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Bytes9.scala b/src/main/scala/ethabi/types/generated/Bytes9.scala new file mode 100644 index 0000000..dc0c3e5 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Bytes9.scala @@ -0,0 +1,24 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +import util.Hex +final class Bytes9(val value: Array[Byte]) extends SolType { + assert(value.length <= 9) + override def toString = Hex.bytes2Hex(value, withPrefix = true) +} +object Bytes9 { + def apply(value: Array[Byte]): Bytes9 = new Bytes9(value) + implicit lazy val typeInfo: TypeInfo[Bytes9] = new TypeInfo[Bytes9] { + override def name: String = "bytes9" + override def isStatic: Boolean = true + override def encode[U >: Bytes9](value: U): Array[Byte] = { + StaticBytes.encode(value.asInstanceOf[Bytes9].value, 9) + } + override def decode(bytes: Array[Byte], position: Int): (Bytes9, Int) = { + val value = StaticBytes.decode(bytes, 9, position) + (Bytes9(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int104.scala b/src/main/scala/ethabi/types/generated/Int104.scala new file mode 100644 index 0000000..8b99a02 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int104.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int104(val value: BigInt) extends SolType { + assert(value.bitLength <= 104) + override def toString = value.toString +} +object Int104 { + def apply(value: BigInt): Int104 = new Int104(value) + implicit lazy val typeInfo: TypeInfo[Int104] = new TypeInfo[Int104] { + override def name: String = "int104" + override def isStatic: Boolean = true + override def encode[U >: Int104](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int104].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int104, Int) = { + val value = IntType.decode(bytes, 104, position) + (Int104(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int112.scala b/src/main/scala/ethabi/types/generated/Int112.scala new file mode 100644 index 0000000..16b9d1d --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int112.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int112(val value: BigInt) extends SolType { + assert(value.bitLength <= 112) + override def toString = value.toString +} +object Int112 { + def apply(value: BigInt): Int112 = new Int112(value) + implicit lazy val typeInfo: TypeInfo[Int112] = new TypeInfo[Int112] { + override def name: String = "int112" + override def isStatic: Boolean = true + override def encode[U >: Int112](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int112].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int112, Int) = { + val value = IntType.decode(bytes, 112, position) + (Int112(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int120.scala b/src/main/scala/ethabi/types/generated/Int120.scala new file mode 100644 index 0000000..f989c2c --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int120.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int120(val value: BigInt) extends SolType { + assert(value.bitLength <= 120) + override def toString = value.toString +} +object Int120 { + def apply(value: BigInt): Int120 = new Int120(value) + implicit lazy val typeInfo: TypeInfo[Int120] = new TypeInfo[Int120] { + override def name: String = "int120" + override def isStatic: Boolean = true + override def encode[U >: Int120](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int120].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int120, Int) = { + val value = IntType.decode(bytes, 120, position) + (Int120(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int128.scala b/src/main/scala/ethabi/types/generated/Int128.scala new file mode 100644 index 0000000..fca7423 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int128.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int128(val value: BigInt) extends SolType { + assert(value.bitLength <= 128) + override def toString = value.toString +} +object Int128 { + def apply(value: BigInt): Int128 = new Int128(value) + implicit lazy val typeInfo: TypeInfo[Int128] = new TypeInfo[Int128] { + override def name: String = "int128" + override def isStatic: Boolean = true + override def encode[U >: Int128](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int128].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int128, Int) = { + val value = IntType.decode(bytes, 128, position) + (Int128(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int136.scala b/src/main/scala/ethabi/types/generated/Int136.scala new file mode 100644 index 0000000..f331fc5 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int136.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int136(val value: BigInt) extends SolType { + assert(value.bitLength <= 136) + override def toString = value.toString +} +object Int136 { + def apply(value: BigInt): Int136 = new Int136(value) + implicit lazy val typeInfo: TypeInfo[Int136] = new TypeInfo[Int136] { + override def name: String = "int136" + override def isStatic: Boolean = true + override def encode[U >: Int136](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int136].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int136, Int) = { + val value = IntType.decode(bytes, 136, position) + (Int136(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int144.scala b/src/main/scala/ethabi/types/generated/Int144.scala new file mode 100644 index 0000000..2a11cae --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int144.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int144(val value: BigInt) extends SolType { + assert(value.bitLength <= 144) + override def toString = value.toString +} +object Int144 { + def apply(value: BigInt): Int144 = new Int144(value) + implicit lazy val typeInfo: TypeInfo[Int144] = new TypeInfo[Int144] { + override def name: String = "int144" + override def isStatic: Boolean = true + override def encode[U >: Int144](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int144].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int144, Int) = { + val value = IntType.decode(bytes, 144, position) + (Int144(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int152.scala b/src/main/scala/ethabi/types/generated/Int152.scala new file mode 100644 index 0000000..240bbaa --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int152.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int152(val value: BigInt) extends SolType { + assert(value.bitLength <= 152) + override def toString = value.toString +} +object Int152 { + def apply(value: BigInt): Int152 = new Int152(value) + implicit lazy val typeInfo: TypeInfo[Int152] = new TypeInfo[Int152] { + override def name: String = "int152" + override def isStatic: Boolean = true + override def encode[U >: Int152](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int152].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int152, Int) = { + val value = IntType.decode(bytes, 152, position) + (Int152(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int16.scala b/src/main/scala/ethabi/types/generated/Int16.scala new file mode 100644 index 0000000..ff89256 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int16.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int16(val value: BigInt) extends SolType { + assert(value.bitLength <= 16) + override def toString = value.toString +} +object Int16 { + def apply(value: BigInt): Int16 = new Int16(value) + implicit lazy val typeInfo: TypeInfo[Int16] = new TypeInfo[Int16] { + override def name: String = "int16" + override def isStatic: Boolean = true + override def encode[U >: Int16](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int16].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int16, Int) = { + val value = IntType.decode(bytes, 16, position) + (Int16(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int160.scala b/src/main/scala/ethabi/types/generated/Int160.scala new file mode 100644 index 0000000..f54ac4c --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int160.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int160(val value: BigInt) extends SolType { + assert(value.bitLength <= 160) + override def toString = value.toString +} +object Int160 { + def apply(value: BigInt): Int160 = new Int160(value) + implicit lazy val typeInfo: TypeInfo[Int160] = new TypeInfo[Int160] { + override def name: String = "int160" + override def isStatic: Boolean = true + override def encode[U >: Int160](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int160].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int160, Int) = { + val value = IntType.decode(bytes, 160, position) + (Int160(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int168.scala b/src/main/scala/ethabi/types/generated/Int168.scala new file mode 100644 index 0000000..655d7e1 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int168.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int168(val value: BigInt) extends SolType { + assert(value.bitLength <= 168) + override def toString = value.toString +} +object Int168 { + def apply(value: BigInt): Int168 = new Int168(value) + implicit lazy val typeInfo: TypeInfo[Int168] = new TypeInfo[Int168] { + override def name: String = "int168" + override def isStatic: Boolean = true + override def encode[U >: Int168](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int168].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int168, Int) = { + val value = IntType.decode(bytes, 168, position) + (Int168(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int176.scala b/src/main/scala/ethabi/types/generated/Int176.scala new file mode 100644 index 0000000..7171006 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int176.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int176(val value: BigInt) extends SolType { + assert(value.bitLength <= 176) + override def toString = value.toString +} +object Int176 { + def apply(value: BigInt): Int176 = new Int176(value) + implicit lazy val typeInfo: TypeInfo[Int176] = new TypeInfo[Int176] { + override def name: String = "int176" + override def isStatic: Boolean = true + override def encode[U >: Int176](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int176].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int176, Int) = { + val value = IntType.decode(bytes, 176, position) + (Int176(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int184.scala b/src/main/scala/ethabi/types/generated/Int184.scala new file mode 100644 index 0000000..46300a1 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int184.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int184(val value: BigInt) extends SolType { + assert(value.bitLength <= 184) + override def toString = value.toString +} +object Int184 { + def apply(value: BigInt): Int184 = new Int184(value) + implicit lazy val typeInfo: TypeInfo[Int184] = new TypeInfo[Int184] { + override def name: String = "int184" + override def isStatic: Boolean = true + override def encode[U >: Int184](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int184].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int184, Int) = { + val value = IntType.decode(bytes, 184, position) + (Int184(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int192.scala b/src/main/scala/ethabi/types/generated/Int192.scala new file mode 100644 index 0000000..feb5421 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int192.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int192(val value: BigInt) extends SolType { + assert(value.bitLength <= 192) + override def toString = value.toString +} +object Int192 { + def apply(value: BigInt): Int192 = new Int192(value) + implicit lazy val typeInfo: TypeInfo[Int192] = new TypeInfo[Int192] { + override def name: String = "int192" + override def isStatic: Boolean = true + override def encode[U >: Int192](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int192].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int192, Int) = { + val value = IntType.decode(bytes, 192, position) + (Int192(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int200.scala b/src/main/scala/ethabi/types/generated/Int200.scala new file mode 100644 index 0000000..0632428 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int200.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int200(val value: BigInt) extends SolType { + assert(value.bitLength <= 200) + override def toString = value.toString +} +object Int200 { + def apply(value: BigInt): Int200 = new Int200(value) + implicit lazy val typeInfo: TypeInfo[Int200] = new TypeInfo[Int200] { + override def name: String = "int200" + override def isStatic: Boolean = true + override def encode[U >: Int200](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int200].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int200, Int) = { + val value = IntType.decode(bytes, 200, position) + (Int200(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int208.scala b/src/main/scala/ethabi/types/generated/Int208.scala new file mode 100644 index 0000000..e5988e6 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int208.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int208(val value: BigInt) extends SolType { + assert(value.bitLength <= 208) + override def toString = value.toString +} +object Int208 { + def apply(value: BigInt): Int208 = new Int208(value) + implicit lazy val typeInfo: TypeInfo[Int208] = new TypeInfo[Int208] { + override def name: String = "int208" + override def isStatic: Boolean = true + override def encode[U >: Int208](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int208].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int208, Int) = { + val value = IntType.decode(bytes, 208, position) + (Int208(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int216.scala b/src/main/scala/ethabi/types/generated/Int216.scala new file mode 100644 index 0000000..9cecf7b --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int216.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int216(val value: BigInt) extends SolType { + assert(value.bitLength <= 216) + override def toString = value.toString +} +object Int216 { + def apply(value: BigInt): Int216 = new Int216(value) + implicit lazy val typeInfo: TypeInfo[Int216] = new TypeInfo[Int216] { + override def name: String = "int216" + override def isStatic: Boolean = true + override def encode[U >: Int216](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int216].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int216, Int) = { + val value = IntType.decode(bytes, 216, position) + (Int216(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int224.scala b/src/main/scala/ethabi/types/generated/Int224.scala new file mode 100644 index 0000000..1895f00 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int224.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int224(val value: BigInt) extends SolType { + assert(value.bitLength <= 224) + override def toString = value.toString +} +object Int224 { + def apply(value: BigInt): Int224 = new Int224(value) + implicit lazy val typeInfo: TypeInfo[Int224] = new TypeInfo[Int224] { + override def name: String = "int224" + override def isStatic: Boolean = true + override def encode[U >: Int224](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int224].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int224, Int) = { + val value = IntType.decode(bytes, 224, position) + (Int224(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int232.scala b/src/main/scala/ethabi/types/generated/Int232.scala new file mode 100644 index 0000000..8315c5b --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int232.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int232(val value: BigInt) extends SolType { + assert(value.bitLength <= 232) + override def toString = value.toString +} +object Int232 { + def apply(value: BigInt): Int232 = new Int232(value) + implicit lazy val typeInfo: TypeInfo[Int232] = new TypeInfo[Int232] { + override def name: String = "int232" + override def isStatic: Boolean = true + override def encode[U >: Int232](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int232].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int232, Int) = { + val value = IntType.decode(bytes, 232, position) + (Int232(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int24.scala b/src/main/scala/ethabi/types/generated/Int24.scala new file mode 100644 index 0000000..ecd5df1 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int24.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int24(val value: BigInt) extends SolType { + assert(value.bitLength <= 24) + override def toString = value.toString +} +object Int24 { + def apply(value: BigInt): Int24 = new Int24(value) + implicit lazy val typeInfo: TypeInfo[Int24] = new TypeInfo[Int24] { + override def name: String = "int24" + override def isStatic: Boolean = true + override def encode[U >: Int24](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int24].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int24, Int) = { + val value = IntType.decode(bytes, 24, position) + (Int24(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int240.scala b/src/main/scala/ethabi/types/generated/Int240.scala new file mode 100644 index 0000000..6f88b1f --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int240.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int240(val value: BigInt) extends SolType { + assert(value.bitLength <= 240) + override def toString = value.toString +} +object Int240 { + def apply(value: BigInt): Int240 = new Int240(value) + implicit lazy val typeInfo: TypeInfo[Int240] = new TypeInfo[Int240] { + override def name: String = "int240" + override def isStatic: Boolean = true + override def encode[U >: Int240](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int240].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int240, Int) = { + val value = IntType.decode(bytes, 240, position) + (Int240(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int248.scala b/src/main/scala/ethabi/types/generated/Int248.scala new file mode 100644 index 0000000..b1d194a --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int248.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int248(val value: BigInt) extends SolType { + assert(value.bitLength <= 248) + override def toString = value.toString +} +object Int248 { + def apply(value: BigInt): Int248 = new Int248(value) + implicit lazy val typeInfo: TypeInfo[Int248] = new TypeInfo[Int248] { + override def name: String = "int248" + override def isStatic: Boolean = true + override def encode[U >: Int248](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int248].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int248, Int) = { + val value = IntType.decode(bytes, 248, position) + (Int248(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int256.scala b/src/main/scala/ethabi/types/generated/Int256.scala new file mode 100644 index 0000000..21251c8 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int256.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int256(val value: BigInt) extends SolType { + assert(value.bitLength <= 256) + override def toString = value.toString +} +object Int256 { + def apply(value: BigInt): Int256 = new Int256(value) + implicit lazy val typeInfo: TypeInfo[Int256] = new TypeInfo[Int256] { + override def name: String = "int256" + override def isStatic: Boolean = true + override def encode[U >: Int256](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int256].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int256, Int) = { + val value = IntType.decode(bytes, 256, position) + (Int256(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int32.scala b/src/main/scala/ethabi/types/generated/Int32.scala new file mode 100644 index 0000000..368cf34 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int32.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int32(val value: BigInt) extends SolType { + assert(value.bitLength <= 32) + override def toString = value.toString +} +object Int32 { + def apply(value: BigInt): Int32 = new Int32(value) + implicit lazy val typeInfo: TypeInfo[Int32] = new TypeInfo[Int32] { + override def name: String = "int32" + override def isStatic: Boolean = true + override def encode[U >: Int32](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int32].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int32, Int) = { + val value = IntType.decode(bytes, 32, position) + (Int32(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int40.scala b/src/main/scala/ethabi/types/generated/Int40.scala new file mode 100644 index 0000000..08bc5d3 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int40.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int40(val value: BigInt) extends SolType { + assert(value.bitLength <= 40) + override def toString = value.toString +} +object Int40 { + def apply(value: BigInt): Int40 = new Int40(value) + implicit lazy val typeInfo: TypeInfo[Int40] = new TypeInfo[Int40] { + override def name: String = "int40" + override def isStatic: Boolean = true + override def encode[U >: Int40](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int40].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int40, Int) = { + val value = IntType.decode(bytes, 40, position) + (Int40(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int48.scala b/src/main/scala/ethabi/types/generated/Int48.scala new file mode 100644 index 0000000..d293497 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int48.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int48(val value: BigInt) extends SolType { + assert(value.bitLength <= 48) + override def toString = value.toString +} +object Int48 { + def apply(value: BigInt): Int48 = new Int48(value) + implicit lazy val typeInfo: TypeInfo[Int48] = new TypeInfo[Int48] { + override def name: String = "int48" + override def isStatic: Boolean = true + override def encode[U >: Int48](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int48].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int48, Int) = { + val value = IntType.decode(bytes, 48, position) + (Int48(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int56.scala b/src/main/scala/ethabi/types/generated/Int56.scala new file mode 100644 index 0000000..9c5e00f --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int56.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int56(val value: BigInt) extends SolType { + assert(value.bitLength <= 56) + override def toString = value.toString +} +object Int56 { + def apply(value: BigInt): Int56 = new Int56(value) + implicit lazy val typeInfo: TypeInfo[Int56] = new TypeInfo[Int56] { + override def name: String = "int56" + override def isStatic: Boolean = true + override def encode[U >: Int56](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int56].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int56, Int) = { + val value = IntType.decode(bytes, 56, position) + (Int56(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int64.scala b/src/main/scala/ethabi/types/generated/Int64.scala new file mode 100644 index 0000000..6ca47a6 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int64.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int64(val value: BigInt) extends SolType { + assert(value.bitLength <= 64) + override def toString = value.toString +} +object Int64 { + def apply(value: BigInt): Int64 = new Int64(value) + implicit lazy val typeInfo: TypeInfo[Int64] = new TypeInfo[Int64] { + override def name: String = "int64" + override def isStatic: Boolean = true + override def encode[U >: Int64](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int64].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int64, Int) = { + val value = IntType.decode(bytes, 64, position) + (Int64(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int72.scala b/src/main/scala/ethabi/types/generated/Int72.scala new file mode 100644 index 0000000..a53631f --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int72.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int72(val value: BigInt) extends SolType { + assert(value.bitLength <= 72) + override def toString = value.toString +} +object Int72 { + def apply(value: BigInt): Int72 = new Int72(value) + implicit lazy val typeInfo: TypeInfo[Int72] = new TypeInfo[Int72] { + override def name: String = "int72" + override def isStatic: Boolean = true + override def encode[U >: Int72](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int72].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int72, Int) = { + val value = IntType.decode(bytes, 72, position) + (Int72(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int8.scala b/src/main/scala/ethabi/types/generated/Int8.scala new file mode 100644 index 0000000..2b7ee7c --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int8.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int8(val value: BigInt) extends SolType { + assert(value.bitLength <= 8) + override def toString = value.toString +} +object Int8 { + def apply(value: BigInt): Int8 = new Int8(value) + implicit lazy val typeInfo: TypeInfo[Int8] = new TypeInfo[Int8] { + override def name: String = "int8" + override def isStatic: Boolean = true + override def encode[U >: Int8](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int8].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int8, Int) = { + val value = IntType.decode(bytes, 8, position) + (Int8(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int80.scala b/src/main/scala/ethabi/types/generated/Int80.scala new file mode 100644 index 0000000..4925f54 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int80.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int80(val value: BigInt) extends SolType { + assert(value.bitLength <= 80) + override def toString = value.toString +} +object Int80 { + def apply(value: BigInt): Int80 = new Int80(value) + implicit lazy val typeInfo: TypeInfo[Int80] = new TypeInfo[Int80] { + override def name: String = "int80" + override def isStatic: Boolean = true + override def encode[U >: Int80](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int80].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int80, Int) = { + val value = IntType.decode(bytes, 80, position) + (Int80(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int88.scala b/src/main/scala/ethabi/types/generated/Int88.scala new file mode 100644 index 0000000..f594835 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int88.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int88(val value: BigInt) extends SolType { + assert(value.bitLength <= 88) + override def toString = value.toString +} +object Int88 { + def apply(value: BigInt): Int88 = new Int88(value) + implicit lazy val typeInfo: TypeInfo[Int88] = new TypeInfo[Int88] { + override def name: String = "int88" + override def isStatic: Boolean = true + override def encode[U >: Int88](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int88].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int88, Int) = { + val value = IntType.decode(bytes, 88, position) + (Int88(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Int96.scala b/src/main/scala/ethabi/types/generated/Int96.scala new file mode 100644 index 0000000..f3a5a54 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Int96.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Int96(val value: BigInt) extends SolType { + assert(value.bitLength <= 96) + override def toString = value.toString +} +object Int96 { + def apply(value: BigInt): Int96 = new Int96(value) + implicit lazy val typeInfo: TypeInfo[Int96] = new TypeInfo[Int96] { + override def name: String = "int96" + override def isStatic: Boolean = true + override def encode[U >: Int96](value: U): Array[Byte] = { + IntType.encode(value.asInstanceOf[Int96].value) + } + override def decode(bytes: Array[Byte], position: Int): (Int96, Int) = { + val value = IntType.decode(bytes, 96, position) + (Int96(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint104.scala b/src/main/scala/ethabi/types/generated/Uint104.scala new file mode 100644 index 0000000..f028cf5 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint104.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint104(val value: BigInt) extends SolType { + assert(value.bitLength <= 104) + override def toString = value.toString +} +object Uint104 { + def apply(value: BigInt): Uint104 = new Uint104(value) + implicit lazy val typeInfo: TypeInfo[Uint104] = new TypeInfo[Uint104] { + override def name: String = "uint104" + override def isStatic: Boolean = true + override def encode[U >: Uint104](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint104].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint104, Int) = { + val value = UintType.decode(bytes, 104, position) + (Uint104(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint112.scala b/src/main/scala/ethabi/types/generated/Uint112.scala new file mode 100644 index 0000000..8d1bfcb --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint112.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint112(val value: BigInt) extends SolType { + assert(value.bitLength <= 112) + override def toString = value.toString +} +object Uint112 { + def apply(value: BigInt): Uint112 = new Uint112(value) + implicit lazy val typeInfo: TypeInfo[Uint112] = new TypeInfo[Uint112] { + override def name: String = "uint112" + override def isStatic: Boolean = true + override def encode[U >: Uint112](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint112].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint112, Int) = { + val value = UintType.decode(bytes, 112, position) + (Uint112(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint120.scala b/src/main/scala/ethabi/types/generated/Uint120.scala new file mode 100644 index 0000000..bf18ea5 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint120.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint120(val value: BigInt) extends SolType { + assert(value.bitLength <= 120) + override def toString = value.toString +} +object Uint120 { + def apply(value: BigInt): Uint120 = new Uint120(value) + implicit lazy val typeInfo: TypeInfo[Uint120] = new TypeInfo[Uint120] { + override def name: String = "uint120" + override def isStatic: Boolean = true + override def encode[U >: Uint120](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint120].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint120, Int) = { + val value = UintType.decode(bytes, 120, position) + (Uint120(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint128.scala b/src/main/scala/ethabi/types/generated/Uint128.scala new file mode 100644 index 0000000..fdccd1f --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint128.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint128(val value: BigInt) extends SolType { + assert(value.bitLength <= 128) + override def toString = value.toString +} +object Uint128 { + def apply(value: BigInt): Uint128 = new Uint128(value) + implicit lazy val typeInfo: TypeInfo[Uint128] = new TypeInfo[Uint128] { + override def name: String = "uint128" + override def isStatic: Boolean = true + override def encode[U >: Uint128](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint128].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint128, Int) = { + val value = UintType.decode(bytes, 128, position) + (Uint128(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint136.scala b/src/main/scala/ethabi/types/generated/Uint136.scala new file mode 100644 index 0000000..fd22b71 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint136.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint136(val value: BigInt) extends SolType { + assert(value.bitLength <= 136) + override def toString = value.toString +} +object Uint136 { + def apply(value: BigInt): Uint136 = new Uint136(value) + implicit lazy val typeInfo: TypeInfo[Uint136] = new TypeInfo[Uint136] { + override def name: String = "uint136" + override def isStatic: Boolean = true + override def encode[U >: Uint136](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint136].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint136, Int) = { + val value = UintType.decode(bytes, 136, position) + (Uint136(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint144.scala b/src/main/scala/ethabi/types/generated/Uint144.scala new file mode 100644 index 0000000..7db5d21 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint144.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint144(val value: BigInt) extends SolType { + assert(value.bitLength <= 144) + override def toString = value.toString +} +object Uint144 { + def apply(value: BigInt): Uint144 = new Uint144(value) + implicit lazy val typeInfo: TypeInfo[Uint144] = new TypeInfo[Uint144] { + override def name: String = "uint144" + override def isStatic: Boolean = true + override def encode[U >: Uint144](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint144].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint144, Int) = { + val value = UintType.decode(bytes, 144, position) + (Uint144(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint152.scala b/src/main/scala/ethabi/types/generated/Uint152.scala new file mode 100644 index 0000000..a5ba915 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint152.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint152(val value: BigInt) extends SolType { + assert(value.bitLength <= 152) + override def toString = value.toString +} +object Uint152 { + def apply(value: BigInt): Uint152 = new Uint152(value) + implicit lazy val typeInfo: TypeInfo[Uint152] = new TypeInfo[Uint152] { + override def name: String = "uint152" + override def isStatic: Boolean = true + override def encode[U >: Uint152](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint152].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint152, Int) = { + val value = UintType.decode(bytes, 152, position) + (Uint152(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint16.scala b/src/main/scala/ethabi/types/generated/Uint16.scala new file mode 100644 index 0000000..1402f08 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint16.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint16(val value: BigInt) extends SolType { + assert(value.bitLength <= 16) + override def toString = value.toString +} +object Uint16 { + def apply(value: BigInt): Uint16 = new Uint16(value) + implicit lazy val typeInfo: TypeInfo[Uint16] = new TypeInfo[Uint16] { + override def name: String = "uint16" + override def isStatic: Boolean = true + override def encode[U >: Uint16](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint16].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint16, Int) = { + val value = UintType.decode(bytes, 16, position) + (Uint16(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint160.scala b/src/main/scala/ethabi/types/generated/Uint160.scala new file mode 100644 index 0000000..edeb839 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint160.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint160(val value: BigInt) extends SolType { + assert(value.bitLength <= 160) + override def toString = value.toString +} +object Uint160 { + def apply(value: BigInt): Uint160 = new Uint160(value) + implicit lazy val typeInfo: TypeInfo[Uint160] = new TypeInfo[Uint160] { + override def name: String = "uint160" + override def isStatic: Boolean = true + override def encode[U >: Uint160](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint160].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint160, Int) = { + val value = UintType.decode(bytes, 160, position) + (Uint160(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint168.scala b/src/main/scala/ethabi/types/generated/Uint168.scala new file mode 100644 index 0000000..a33d711 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint168.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint168(val value: BigInt) extends SolType { + assert(value.bitLength <= 168) + override def toString = value.toString +} +object Uint168 { + def apply(value: BigInt): Uint168 = new Uint168(value) + implicit lazy val typeInfo: TypeInfo[Uint168] = new TypeInfo[Uint168] { + override def name: String = "uint168" + override def isStatic: Boolean = true + override def encode[U >: Uint168](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint168].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint168, Int) = { + val value = UintType.decode(bytes, 168, position) + (Uint168(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint176.scala b/src/main/scala/ethabi/types/generated/Uint176.scala new file mode 100644 index 0000000..83f98ea --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint176.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint176(val value: BigInt) extends SolType { + assert(value.bitLength <= 176) + override def toString = value.toString +} +object Uint176 { + def apply(value: BigInt): Uint176 = new Uint176(value) + implicit lazy val typeInfo: TypeInfo[Uint176] = new TypeInfo[Uint176] { + override def name: String = "uint176" + override def isStatic: Boolean = true + override def encode[U >: Uint176](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint176].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint176, Int) = { + val value = UintType.decode(bytes, 176, position) + (Uint176(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint184.scala b/src/main/scala/ethabi/types/generated/Uint184.scala new file mode 100644 index 0000000..b7d9cde --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint184.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint184(val value: BigInt) extends SolType { + assert(value.bitLength <= 184) + override def toString = value.toString +} +object Uint184 { + def apply(value: BigInt): Uint184 = new Uint184(value) + implicit lazy val typeInfo: TypeInfo[Uint184] = new TypeInfo[Uint184] { + override def name: String = "uint184" + override def isStatic: Boolean = true + override def encode[U >: Uint184](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint184].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint184, Int) = { + val value = UintType.decode(bytes, 184, position) + (Uint184(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint192.scala b/src/main/scala/ethabi/types/generated/Uint192.scala new file mode 100644 index 0000000..2d31de6 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint192.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint192(val value: BigInt) extends SolType { + assert(value.bitLength <= 192) + override def toString = value.toString +} +object Uint192 { + def apply(value: BigInt): Uint192 = new Uint192(value) + implicit lazy val typeInfo: TypeInfo[Uint192] = new TypeInfo[Uint192] { + override def name: String = "uint192" + override def isStatic: Boolean = true + override def encode[U >: Uint192](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint192].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint192, Int) = { + val value = UintType.decode(bytes, 192, position) + (Uint192(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint200.scala b/src/main/scala/ethabi/types/generated/Uint200.scala new file mode 100644 index 0000000..73447d5 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint200.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint200(val value: BigInt) extends SolType { + assert(value.bitLength <= 200) + override def toString = value.toString +} +object Uint200 { + def apply(value: BigInt): Uint200 = new Uint200(value) + implicit lazy val typeInfo: TypeInfo[Uint200] = new TypeInfo[Uint200] { + override def name: String = "uint200" + override def isStatic: Boolean = true + override def encode[U >: Uint200](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint200].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint200, Int) = { + val value = UintType.decode(bytes, 200, position) + (Uint200(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint208.scala b/src/main/scala/ethabi/types/generated/Uint208.scala new file mode 100644 index 0000000..f62a469 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint208.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint208(val value: BigInt) extends SolType { + assert(value.bitLength <= 208) + override def toString = value.toString +} +object Uint208 { + def apply(value: BigInt): Uint208 = new Uint208(value) + implicit lazy val typeInfo: TypeInfo[Uint208] = new TypeInfo[Uint208] { + override def name: String = "uint208" + override def isStatic: Boolean = true + override def encode[U >: Uint208](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint208].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint208, Int) = { + val value = UintType.decode(bytes, 208, position) + (Uint208(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint216.scala b/src/main/scala/ethabi/types/generated/Uint216.scala new file mode 100644 index 0000000..8f2d7b0 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint216.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint216(val value: BigInt) extends SolType { + assert(value.bitLength <= 216) + override def toString = value.toString +} +object Uint216 { + def apply(value: BigInt): Uint216 = new Uint216(value) + implicit lazy val typeInfo: TypeInfo[Uint216] = new TypeInfo[Uint216] { + override def name: String = "uint216" + override def isStatic: Boolean = true + override def encode[U >: Uint216](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint216].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint216, Int) = { + val value = UintType.decode(bytes, 216, position) + (Uint216(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint224.scala b/src/main/scala/ethabi/types/generated/Uint224.scala new file mode 100644 index 0000000..4480df9 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint224.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint224(val value: BigInt) extends SolType { + assert(value.bitLength <= 224) + override def toString = value.toString +} +object Uint224 { + def apply(value: BigInt): Uint224 = new Uint224(value) + implicit lazy val typeInfo: TypeInfo[Uint224] = new TypeInfo[Uint224] { + override def name: String = "uint224" + override def isStatic: Boolean = true + override def encode[U >: Uint224](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint224].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint224, Int) = { + val value = UintType.decode(bytes, 224, position) + (Uint224(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint232.scala b/src/main/scala/ethabi/types/generated/Uint232.scala new file mode 100644 index 0000000..76053bf --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint232.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint232(val value: BigInt) extends SolType { + assert(value.bitLength <= 232) + override def toString = value.toString +} +object Uint232 { + def apply(value: BigInt): Uint232 = new Uint232(value) + implicit lazy val typeInfo: TypeInfo[Uint232] = new TypeInfo[Uint232] { + override def name: String = "uint232" + override def isStatic: Boolean = true + override def encode[U >: Uint232](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint232].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint232, Int) = { + val value = UintType.decode(bytes, 232, position) + (Uint232(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint24.scala b/src/main/scala/ethabi/types/generated/Uint24.scala new file mode 100644 index 0000000..c4be109 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint24.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint24(val value: BigInt) extends SolType { + assert(value.bitLength <= 24) + override def toString = value.toString +} +object Uint24 { + def apply(value: BigInt): Uint24 = new Uint24(value) + implicit lazy val typeInfo: TypeInfo[Uint24] = new TypeInfo[Uint24] { + override def name: String = "uint24" + override def isStatic: Boolean = true + override def encode[U >: Uint24](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint24].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint24, Int) = { + val value = UintType.decode(bytes, 24, position) + (Uint24(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint240.scala b/src/main/scala/ethabi/types/generated/Uint240.scala new file mode 100644 index 0000000..f39bdcc --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint240.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint240(val value: BigInt) extends SolType { + assert(value.bitLength <= 240) + override def toString = value.toString +} +object Uint240 { + def apply(value: BigInt): Uint240 = new Uint240(value) + implicit lazy val typeInfo: TypeInfo[Uint240] = new TypeInfo[Uint240] { + override def name: String = "uint240" + override def isStatic: Boolean = true + override def encode[U >: Uint240](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint240].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint240, Int) = { + val value = UintType.decode(bytes, 240, position) + (Uint240(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint248.scala b/src/main/scala/ethabi/types/generated/Uint248.scala new file mode 100644 index 0000000..2e71139 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint248.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint248(val value: BigInt) extends SolType { + assert(value.bitLength <= 248) + override def toString = value.toString +} +object Uint248 { + def apply(value: BigInt): Uint248 = new Uint248(value) + implicit lazy val typeInfo: TypeInfo[Uint248] = new TypeInfo[Uint248] { + override def name: String = "uint248" + override def isStatic: Boolean = true + override def encode[U >: Uint248](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint248].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint248, Int) = { + val value = UintType.decode(bytes, 248, position) + (Uint248(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint256.scala b/src/main/scala/ethabi/types/generated/Uint256.scala new file mode 100644 index 0000000..29c2c30 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint256.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint256(val value: BigInt) extends SolType { + assert(value.bitLength <= 256) + override def toString = value.toString +} +object Uint256 { + def apply(value: BigInt): Uint256 = new Uint256(value) + implicit lazy val typeInfo: TypeInfo[Uint256] = new TypeInfo[Uint256] { + override def name: String = "uint256" + override def isStatic: Boolean = true + override def encode[U >: Uint256](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint256].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint256, Int) = { + val value = UintType.decode(bytes, 256, position) + (Uint256(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint32.scala b/src/main/scala/ethabi/types/generated/Uint32.scala new file mode 100644 index 0000000..09130ef --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint32.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint32(val value: BigInt) extends SolType { + assert(value.bitLength <= 32) + override def toString = value.toString +} +object Uint32 { + def apply(value: BigInt): Uint32 = new Uint32(value) + implicit lazy val typeInfo: TypeInfo[Uint32] = new TypeInfo[Uint32] { + override def name: String = "uint32" + override def isStatic: Boolean = true + override def encode[U >: Uint32](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint32].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint32, Int) = { + val value = UintType.decode(bytes, 32, position) + (Uint32(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint40.scala b/src/main/scala/ethabi/types/generated/Uint40.scala new file mode 100644 index 0000000..21a0808 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint40.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint40(val value: BigInt) extends SolType { + assert(value.bitLength <= 40) + override def toString = value.toString +} +object Uint40 { + def apply(value: BigInt): Uint40 = new Uint40(value) + implicit lazy val typeInfo: TypeInfo[Uint40] = new TypeInfo[Uint40] { + override def name: String = "uint40" + override def isStatic: Boolean = true + override def encode[U >: Uint40](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint40].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint40, Int) = { + val value = UintType.decode(bytes, 40, position) + (Uint40(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint48.scala b/src/main/scala/ethabi/types/generated/Uint48.scala new file mode 100644 index 0000000..f6e0b7a --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint48.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint48(val value: BigInt) extends SolType { + assert(value.bitLength <= 48) + override def toString = value.toString +} +object Uint48 { + def apply(value: BigInt): Uint48 = new Uint48(value) + implicit lazy val typeInfo: TypeInfo[Uint48] = new TypeInfo[Uint48] { + override def name: String = "uint48" + override def isStatic: Boolean = true + override def encode[U >: Uint48](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint48].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint48, Int) = { + val value = UintType.decode(bytes, 48, position) + (Uint48(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint56.scala b/src/main/scala/ethabi/types/generated/Uint56.scala new file mode 100644 index 0000000..137f0eb --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint56.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint56(val value: BigInt) extends SolType { + assert(value.bitLength <= 56) + override def toString = value.toString +} +object Uint56 { + def apply(value: BigInt): Uint56 = new Uint56(value) + implicit lazy val typeInfo: TypeInfo[Uint56] = new TypeInfo[Uint56] { + override def name: String = "uint56" + override def isStatic: Boolean = true + override def encode[U >: Uint56](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint56].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint56, Int) = { + val value = UintType.decode(bytes, 56, position) + (Uint56(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint64.scala b/src/main/scala/ethabi/types/generated/Uint64.scala new file mode 100644 index 0000000..b7fd16f --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint64.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint64(val value: BigInt) extends SolType { + assert(value.bitLength <= 64) + override def toString = value.toString +} +object Uint64 { + def apply(value: BigInt): Uint64 = new Uint64(value) + implicit lazy val typeInfo: TypeInfo[Uint64] = new TypeInfo[Uint64] { + override def name: String = "uint64" + override def isStatic: Boolean = true + override def encode[U >: Uint64](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint64].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint64, Int) = { + val value = UintType.decode(bytes, 64, position) + (Uint64(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint72.scala b/src/main/scala/ethabi/types/generated/Uint72.scala new file mode 100644 index 0000000..1789dfd --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint72.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint72(val value: BigInt) extends SolType { + assert(value.bitLength <= 72) + override def toString = value.toString +} +object Uint72 { + def apply(value: BigInt): Uint72 = new Uint72(value) + implicit lazy val typeInfo: TypeInfo[Uint72] = new TypeInfo[Uint72] { + override def name: String = "uint72" + override def isStatic: Boolean = true + override def encode[U >: Uint72](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint72].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint72, Int) = { + val value = UintType.decode(bytes, 72, position) + (Uint72(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint8.scala b/src/main/scala/ethabi/types/generated/Uint8.scala new file mode 100644 index 0000000..a37dc48 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint8.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint8(val value: BigInt) extends SolType { + assert(value.bitLength <= 8) + override def toString = value.toString +} +object Uint8 { + def apply(value: BigInt): Uint8 = new Uint8(value) + implicit lazy val typeInfo: TypeInfo[Uint8] = new TypeInfo[Uint8] { + override def name: String = "uint8" + override def isStatic: Boolean = true + override def encode[U >: Uint8](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint8].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint8, Int) = { + val value = UintType.decode(bytes, 8, position) + (Uint8(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint80.scala b/src/main/scala/ethabi/types/generated/Uint80.scala new file mode 100644 index 0000000..f1ede33 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint80.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint80(val value: BigInt) extends SolType { + assert(value.bitLength <= 80) + override def toString = value.toString +} +object Uint80 { + def apply(value: BigInt): Uint80 = new Uint80(value) + implicit lazy val typeInfo: TypeInfo[Uint80] = new TypeInfo[Uint80] { + override def name: String = "uint80" + override def isStatic: Boolean = true + override def encode[U >: Uint80](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint80].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint80, Int) = { + val value = UintType.decode(bytes, 80, position) + (Uint80(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint88.scala b/src/main/scala/ethabi/types/generated/Uint88.scala new file mode 100644 index 0000000..e201c65 --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint88.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint88(val value: BigInt) extends SolType { + assert(value.bitLength <= 88) + override def toString = value.toString +} +object Uint88 { + def apply(value: BigInt): Uint88 = new Uint88(value) + implicit lazy val typeInfo: TypeInfo[Uint88] = new TypeInfo[Uint88] { + override def name: String = "uint88" + override def isStatic: Boolean = true + override def encode[U >: Uint88](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint88].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint88, Int) = { + val value = UintType.decode(bytes, 88, position) + (Uint88(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/generated/Uint96.scala b/src/main/scala/ethabi/types/generated/Uint96.scala new file mode 100644 index 0000000..ecc2d5b --- /dev/null +++ b/src/main/scala/ethabi/types/generated/Uint96.scala @@ -0,0 +1,23 @@ +// AUTO GENERATED, DO NOT EDIT + +package ethabi +package types +package generated +final class Uint96(val value: BigInt) extends SolType { + assert(value.bitLength <= 96) + override def toString = value.toString +} +object Uint96 { + def apply(value: BigInt): Uint96 = new Uint96(value) + implicit lazy val typeInfo: TypeInfo[Uint96] = new TypeInfo[Uint96] { + override def name: String = "uint96" + override def isStatic: Boolean = true + override def encode[U >: Uint96](value: U): Array[Byte] = { + UintType.encode(value.asInstanceOf[Uint96].value) + } + override def decode(bytes: Array[Byte], position: Int): (Uint96, Int) = { + val value = UintType.decode(bytes, 96, position) + (Uint96(value), 32) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ethabi/types/package.scala b/src/main/scala/ethabi/types/package.scala new file mode 100644 index 0000000..9804e3f --- /dev/null +++ b/src/main/scala/ethabi/types/package.scala @@ -0,0 +1,11 @@ +package ethabi + +package object types { + private [types] val maxBitLength = 256 + private [types] val maxByteLength = 32 + + private [types] def paddedBytes(value: BigInt): Array[Byte] = { + val paddedValue = if (value.signum == -1) 0xff else 0x00 + Array.fill[Byte](maxByteLength)(paddedValue.toByte) + } +} diff --git a/src/main/scala/ethabi/util/Hash.scala b/src/main/scala/ethabi/util/Hash.scala new file mode 100644 index 0000000..ef79ed6 --- /dev/null +++ b/src/main/scala/ethabi/util/Hash.scala @@ -0,0 +1,13 @@ +package ethabi.util + +import scorex.crypto.hash.Keccak256 + +case class Hash(bytes: Array[Byte]) { + assert(bytes.length == 32) + override def toString: String = Hex.bytes2Hex(bytes, withPrefix = true) +} + +object Hash { + def hash(bytes: Array[Byte]): Hash = Hash(Keccak256.hash(bytes)) + def apply(hex: String): Hash = Hash(Hex.hex2Bytes(hex)) +} diff --git a/src/main/scala/ethabi/util/Hex.scala b/src/main/scala/ethabi/util/Hex.scala new file mode 100644 index 0000000..1f59270 --- /dev/null +++ b/src/main/scala/ethabi/util/Hex.scala @@ -0,0 +1,52 @@ +package ethabi.util + +import java.math.BigInteger + +object Hex { + private def removePrefix(hex: String): String = { + if (hex.startsWith("0x") || hex.startsWith("0X")) hex.slice(2, hex.length) + else hex + } + + def hex2Bytes(hex: String): Array[Byte] = { + val slice = removePrefix(hex) + slice.sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte) + } + + def bytes2Hex(bytes: Array[Byte], withPrefix: Boolean = false): String = { + val hex = bytes.map("%02x" format _).mkString + if (withPrefix) "0x" + hex + else hex + } + + def bigInt2Hex(value: BigInt, withPrefix: Boolean = false): String = { + // NOTE: remove the leading zeros + val hex = bytes2Hex(value.toByteArray).replaceFirst("^0+(?!$)", "") + if (withPrefix) "0x" + hex else hex + } + + def hex2BigInt(hex: String): BigInt = { + val bytes = hex2Bytes(hex) + BigInt(new BigInteger(bytes)) + } + + def int2Hex(value: Int, withPrefix: Boolean = false): String = { + if (withPrefix) "0x" + value.toHexString + else value.toHexString + } + + def hex2Int(hex: String): Int = { + val slice = removePrefix(hex) + java.lang.Integer.parseInt(slice, 16) + } + + def long2Hex(value: Long, withPrefix: Boolean = false): String = { + if (withPrefix) "0x" + value.toHexString + else value.toHexString + } + + def hex2Long(hex: String): Long = { + val slice = removePrefix(hex) + java.lang.Long.parseLong(slice, 16) + } +} diff --git a/src/test/scala/ethabi/types/AddressSpec.scala b/src/test/scala/ethabi/types/AddressSpec.scala new file mode 100644 index 0000000..b6a81f1 --- /dev/null +++ b/src/test/scala/ethabi/types/AddressSpec.scala @@ -0,0 +1,20 @@ +package ethabi.types + +import org.scalatest.{WordSpec, Matchers} +import ethabi.util.Hex + +class AddressSpec extends WordSpec with Matchers { + "test address encode" in { + val bytes = Array.fill[Byte](20)(0x24) + // 0000000000000000000000002424242424242424242424242424242424242424 + Hex.bytes2Hex(Address.typeInfo.encode(Address(bytes))) shouldBe "0000000000000000000000002424242424242424242424242424242424242424" + } + + "test address decode" in { + val bytes = Array.fill[Byte](20)(0x24) + val encoded = Hex.hex2Bytes("0000000000000000000000002424242424242424242424242424242424242424") + val (result, consumed) = Address.typeInfo.decode(encoded, 0) + result.value shouldBe bytes + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/DynamicArraySpec.scala b/src/test/scala/ethabi/types/DynamicArraySpec.scala new file mode 100644 index 0000000..89ec738 --- /dev/null +++ b/src/test/scala/ethabi/types/DynamicArraySpec.scala @@ -0,0 +1,35 @@ +package ethabi.types + +import org.scalatest.{WordSpec, Matchers} +import ethabi.util.Hex + +class DynamicArraySpec extends WordSpec with Matchers { + import DynamicBytes._ + val bytes = DynamicBytes(Array.fill[Byte](50)(0x24)) + "test bytes[] encode" in { + val typeInfo = implicitly[TypeInfo[DynamicArray[DynamicBytes]]] + // 0000000000000000000000000000000000000000000000000000000000000003 + + // 0000000000000000000000000000000000000000000000000000000000000060 + + // 00000000000000000000000000000000000000000000000000000000000000c0 + + // 0000000000000000000000000000000000000000000000000000000000000120 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + Hex.bytes2Hex(typeInfo.encode(DynamicArray(List.fill[DynamicBytes](3)(bytes)))) shouldBe "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000" + } + + "test bytes[] decode" in { + val encoded = Hex.hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000") + val typeInfo = implicitly[TypeInfo[DynamicArray[DynamicBytes]]] + val (result, consumed) = typeInfo.decode(encoded, 0) + result.values.length shouldBe 3 + result.values.map(_.value).foreach(_ shouldBe bytes.value) + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/DynamicBytesSpec.scala b/src/test/scala/ethabi/types/DynamicBytesSpec.scala new file mode 100644 index 0000000..5f96292 --- /dev/null +++ b/src/test/scala/ethabi/types/DynamicBytesSpec.scala @@ -0,0 +1,37 @@ +package ethabi.types + +import org.scalatest.{Matchers, WordSpec} +import ethabi.util.Hex + +class DynamicBytesSpec extends WordSpec with Matchers { + "test dynamic bytes encode(length = 20)" in { + val bytes = Array.fill[Byte](20)(0x24) + // 0000000000000000000000000000000000000000000000000000000000000014 + + // 2424242424242424242424242424242424242424000000000000000000000000 + Hex.bytes2Hex(DynamicBytes.typeInfo.encode(DynamicBytes(bytes))) shouldBe "00000000000000000000000000000000000000000000000000000000000000142424242424242424242424242424242424242424000000000000000000000000" + } + + "test dynamic bytes decode(length = 20)" in { + val bytes = Array.fill[Byte](20)(0x24) + val encoded = Hex.hex2Bytes("00000000000000000000000000000000000000000000000000000000000000142424242424242424242424242424242424242424000000000000000000000000") + val (result, consumed) = DynamicBytes.typeInfo.decode(encoded, 0) + result.value shouldBe bytes + consumed shouldBe 64 + } + + "test dynamic bytes encode(length = 50)" in { + val bytes = Array.fill[Byte](50)(0x24) + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + Hex.bytes2Hex(DynamicBytes.typeInfo.encode(DynamicBytes(bytes))) shouldBe "000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000" + } + + "test dynamic bytes decode(length = 50)" in { + val bytes = Array.fill[Byte](50)(0x24) + val encoded = Hex.hex2Bytes("000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000") + val (result, consumed) = DynamicBytes.typeInfo.decode(encoded, 0) + result.value shouldBe bytes + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/IntTypeSpec.scala b/src/test/scala/ethabi/types/IntTypeSpec.scala new file mode 100644 index 0000000..adf6f6c --- /dev/null +++ b/src/test/scala/ethabi/types/IntTypeSpec.scala @@ -0,0 +1,30 @@ +package ethabi.types + +import org.scalatest.{WordSpec, Matchers} +import ethabi.types.generated._ + +class IntTypeSpec extends WordSpec with Matchers { + "test int8 encode" in { + // fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 + Int8.typeInfo.encode(Int8(BigInt(-12))).map("%02x" format _).mkString shouldBe "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4" + } + + "test int8 decode" in { + val encoded = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4".sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte) + val (result, consumed) = Int8.typeInfo.decode(encoded, 0) + result.value.toInt shouldBe -12 + consumed shouldBe 32 + } + + "test int16 encode" in { + // 0000000000000000000000000000000000000000000000000000000000002710 + Int16.typeInfo.encode(Int16(BigInt(10000))).map("%02x" format _).mkString shouldBe "0000000000000000000000000000000000000000000000000000000000002710" + } + + "test int16 decode" in { + val encoded = "0000000000000000000000000000000000000000000000000000000000002710".sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte) + val (result, consumed) = Int16.typeInfo.decode(encoded, 0) + result.value.toInt shouldBe 10000 + consumed shouldBe 32 + } +} diff --git a/src/test/scala/ethabi/types/StaticArraySpec.scala b/src/test/scala/ethabi/types/StaticArraySpec.scala new file mode 100644 index 0000000..1eccaca --- /dev/null +++ b/src/test/scala/ethabi/types/StaticArraySpec.scala @@ -0,0 +1,56 @@ +package ethabi.types + +import org.scalatest.{WordSpec, Matchers} +import ethabi.util.Hex + +class StaticArraySpec extends WordSpec with Matchers { + val bytes = DynamicBytes(Array.fill[Byte](50)(0x24)) + "test bytes[3] encode" in { + implicit val length: Int = 3 + val typeInfo = implicitly[TypeInfo[StaticArray[DynamicBytes]]] + // 0000000000000000000000000000000000000000000000000000000000000060 + + // 00000000000000000000000000000000000000000000000000000000000000c0 + + // 0000000000000000000000000000000000000000000000000000000000000120 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + + // 0000000000000000000000000000000000000000000000000000000000000032 + + // 2424242424242424242424242424242424242424242424242424242424242424 + + // 2424242424242424242424242424242424240000000000000000000000000000 + Hex.bytes2Hex(typeInfo.encode(StaticArray(List.fill[DynamicBytes](3)(bytes)))) shouldBe "000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000" + } + + "test bytes[3] decode" in { + val encoded = Hex.hex2Bytes("000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003224242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424240000000000000000000000000000") + implicit val length: Int = 3 + val typeInfo = implicitly[TypeInfo[StaticArray[DynamicBytes]]] + val (result, consumed) = typeInfo.decode(encoded, 0) + result.values.length shouldBe length + result.values.map(_.value).foreach(_ shouldBe bytes.value) + consumed shouldBe encoded.length + } + + val address = Address(Array.fill[Byte](20)(0x24)) + "test address[4] encode" in { + implicit val length: Int = 4 + val typeInfo = implicitly[TypeInfo[StaticArray[Address]]] + // 0000000000000000000000002424242424242424242424242424242424242424 + + // 0000000000000000000000002424242424242424242424242424242424242424 + + // 0000000000000000000000002424242424242424242424242424242424242424 + + // 0000000000000000000000002424242424242424242424242424242424242424 + Hex.bytes2Hex(typeInfo.encode(StaticArray(List.fill[Address](4)(address)))) shouldBe "0000000000000000000000002424242424242424242424242424242424242424000000000000000000000000242424242424242424242424242424242424242400000000000000000000000024242424242424242424242424242424242424240000000000000000000000002424242424242424242424242424242424242424" + } + + "test address[4] decode" in { + implicit val length: Int = 4 + val typeInfo = implicitly[TypeInfo[StaticArray[Address]]] + val encoded = Hex.hex2Bytes("0000000000000000000000002424242424242424242424242424242424242424000000000000000000000000242424242424242424242424242424242424242400000000000000000000000024242424242424242424242424242424242424240000000000000000000000002424242424242424242424242424242424242424") + val (result, consumed) = typeInfo.decode(encoded, 0) + result.values.length shouldBe length + result.values.map(_.value).foreach(_ shouldBe address.value) + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/StaticBytesSpec.scala b/src/test/scala/ethabi/types/StaticBytesSpec.scala new file mode 100644 index 0000000..257cc0b --- /dev/null +++ b/src/test/scala/ethabi/types/StaticBytesSpec.scala @@ -0,0 +1,21 @@ +package ethabi.types + +import org.scalatest.{Matchers, WordSpec} +import ethabi.types.generated._ +import ethabi.util.Hex + +class StaticBytesSpec extends WordSpec with Matchers { + "test bytes5 encode" in { + val bytes = Array[Byte](0x01, 0x02, 0x03, 0x04, 0x05) + // 0102030405000000000000000000000000000000000000000000000000000000 + Hex.bytes2Hex(Bytes5.typeInfo.encode(Bytes5(bytes))) shouldBe "0102030405000000000000000000000000000000000000000000000000000000" + } + + "test bytes5 decode" in { + val bytes = Array[Byte](0x01, 0x02, 0x03, 0x04, 0x05) + val encoded = Hex.hex2Bytes("0102030405000000000000000000000000000000000000000000000000000000") + val (result, consumed) = Bytes5.typeInfo.decode(encoded, 0) + result.value shouldBe bytes + consumed shouldBe 32 + } +} diff --git a/src/test/scala/ethabi/types/StringTypeSpec.scala b/src/test/scala/ethabi/types/StringTypeSpec.scala new file mode 100644 index 0000000..5879a82 --- /dev/null +++ b/src/test/scala/ethabi/types/StringTypeSpec.scala @@ -0,0 +1,20 @@ +package ethabi.types + +import org.scalatest.{WordSpec, Matchers} +import ethabi.util.Hex + +class StringTypeSpec extends WordSpec with Matchers { + "test utf8 string encode" in { + val value = StringType("以太坊") + // 0000000000000000000000000000000000000000000000000000000000000009 + + // e4bba5e5a4aae59d8a0000000000000000000000000000000000000000000000 + Hex.bytes2Hex(StringType.typeInfo.encode(value)) shouldBe "0000000000000000000000000000000000000000000000000000000000000009e4bba5e5a4aae59d8a0000000000000000000000000000000000000000000000" + } + + "test utf8 string decode" in { + val encoded = Hex.hex2Bytes("0000000000000000000000000000000000000000000000000000000000000009e4bba5e5a4aae59d8a0000000000000000000000000000000000000000000000") + val (result, consumed) = StringType.typeInfo.decode(encoded, 0) + result.value shouldBe "以太坊" + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/TupleTypeSpec.scala b/src/test/scala/ethabi/types/TupleTypeSpec.scala new file mode 100644 index 0000000..575980f --- /dev/null +++ b/src/test/scala/ethabi/types/TupleTypeSpec.scala @@ -0,0 +1,63 @@ +package ethabi.types + +import org.scalatest.{Matchers, WordSpec} +import ethabi.types.generated._ +import ethabi.util.Hex + +class TupleTypeSpec extends WordSpec with Matchers { + import Uint256._ + import Address._ + import DynamicBytes._ + + val number = Uint256(BigInt(10000)) + val address = Address(Array.fill[Byte](20)(0x24)) + val bytes = DynamicBytes(Array.fill[Byte](20)(0x13)) + + "test tuple3(uint256, address, bytes) encode" in { + val tuple = TupleType3[Uint256, Address, DynamicBytes](number, address, bytes) + val tupleTypeInfo = implicitly[TypeInfo[TupleType3[Uint256, Address, DynamicBytes]]] + // 0000000000000000000000000000000000000000000000000000000000002710 + + // 0000000000000000000000002424242424242424242424242424242424242424 + + // 0000000000000000000000000000000000000000000000000000000000000060 + + // 0000000000000000000000000000000000000000000000000000000000000014 + + // 1313131313131313131313131313131313131313000000000000000000000000 + Hex.bytes2Hex(tupleTypeInfo.encode(tuple)) shouldBe "00000000000000000000000000000000000000000000000000000000000027100000000000000000000000002424242424242424242424242424242424242424000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000141313131313131313131313131313131313131313000000000000000000000000" + } + + "test tuple3(uint256, address, bytes) decode" in { + val encoded = Hex.hex2Bytes("00000000000000000000000000000000000000000000000000000000000027100000000000000000000000002424242424242424242424242424242424242424000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000141313131313131313131313131313131313131313000000000000000000000000") + val tupleTypeInfo = implicitly[TypeInfo[TupleType3[Uint256, Address, DynamicBytes]]] + val (result, consumed) = tupleTypeInfo.decode(encoded, 0) + result._1.value.toInt shouldBe number.value.toInt + result._2.value shouldBe address.value + result._3.value shouldBe bytes.value + consumed shouldBe encoded.length + } + + "test tuple3(tuple2(bytes, address), uint256, bytes) encode" in { + val tuple2 = TupleType2[DynamicBytes, Address](bytes, address) + val tuple3 = TupleType3[TupleType2[DynamicBytes, Address], Uint256, DynamicBytes](tuple2, number, bytes) + val tupleTypeInfo = implicitly[TypeInfo[TupleType3[TupleType2[DynamicBytes, Address], Uint256, DynamicBytes]]] + // 0000000000000000000000000000000000000000000000000000000000000060 + + // 0000000000000000000000000000000000000000000000000000000000002710 + + // 00000000000000000000000000000000000000000000000000000000000000e0 + + // 0000000000000000000000000000000000000000000000000000000000000040 + + // 0000000000000000000000002424242424242424242424242424242424242424 + + // 0000000000000000000000000000000000000000000000000000000000000014 + + // 1313131313131313131313131313131313131313000000000000000000000000 + + // 0000000000000000000000000000000000000000000000000000000000000014 + + // 1313131313131313131313131313131313131313000000000000000000000000 + Hex.bytes2Hex(tupleTypeInfo.encode(tuple3)) shouldBe "0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000024242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000014131313131313131313131313131313131313131300000000000000000000000000000000000000000000000000000000000000000000000000000000000000141313131313131313131313131313131313131313000000000000000000000000" + } + + "test tuple3(tuple2(bytes, address), uint256, bytes) decode" in { + val encoded = Hex.hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000024242424242424242424242424242424242424240000000000000000000000000000000000000000000000000000000000000014131313131313131313131313131313131313131300000000000000000000000000000000000000000000000000000000000000000000000000000000000000141313131313131313131313131313131313131313000000000000000000000000") + val tupleTypeInfo = implicitly[TypeInfo[TupleType3[TupleType2[DynamicBytes, Address], Uint256, DynamicBytes]]] + val (result, consumed) = tupleTypeInfo.decode(encoded, 0) + result._1._1.value shouldBe bytes.value + result._1._2.value shouldBe address.value + result._2.value.toInt shouldBe number.value.toInt + result._3.value shouldBe bytes.value + consumed shouldBe encoded.length + } +} diff --git a/src/test/scala/ethabi/types/UintTypeSpec.scala b/src/test/scala/ethabi/types/UintTypeSpec.scala new file mode 100644 index 0000000..a949939 --- /dev/null +++ b/src/test/scala/ethabi/types/UintTypeSpec.scala @@ -0,0 +1,30 @@ +package ethabi.types + +import org.scalatest.{Matchers, WordSpec} +import ethabi.types.generated._ + +class UintTypeSpec extends WordSpec with Matchers { + // 000000000000000000000000000000000000000000000000000000000000000c + "test uint8 encode" in { + Uint8.typeInfo.encode(Uint8(BigInt(12))).map("%02x" format _).mkString shouldBe "000000000000000000000000000000000000000000000000000000000000000c" + } + + "test uint8 decode" in { + val encoded = "000000000000000000000000000000000000000000000000000000000000000c".sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte) + val (result, consumed) = Uint8.typeInfo.decode(encoded, 0) + result.value.toInt shouldBe 12 + consumed shouldBe 32 + } + + "test uint16 encode" in { + // 0000000000000000000000000000000000000000000000000000000000002710 + Uint16.typeInfo.encode(Uint16(BigInt(10000))).map("%02x" format _).mkString shouldBe "0000000000000000000000000000000000000000000000000000000000002710" + } + + "test uint16 decode" in { + val encoded = "0000000000000000000000000000000000000000000000000000000000002710".sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte) + val (result, consumed) = Uint16.typeInfo.decode(encoded, 0) + result.value.toInt shouldBe 10000 + consumed shouldBe 32 + } +} diff --git a/src/test/scala/ethabi/util/HexSpec.scala b/src/test/scala/ethabi/util/HexSpec.scala new file mode 100644 index 0000000..eca0e07 --- /dev/null +++ b/src/test/scala/ethabi/util/HexSpec.scala @@ -0,0 +1,10 @@ +package ethabi.util + +import org.scalatest.{WordSpec, Matchers} + +class HexSpec extends WordSpec with Matchers { + "test empty hex to bytes" in { + val bytes = Hex.hex2Bytes("") + bytes.length shouldBe 0 + } +}