From 88546a88a228f3ca73259957d062802a0ac93ed0 Mon Sep 17 00:00:00 2001 From: lash Date: Tue, 30 May 2023 17:42:53 +0100 Subject: [PATCH] Initial commit --- .gitignore | 6 + python/LICENSE | 661 ++++++++++++++++++ python/MANIFEST.in | 1 + python/ge_capped_token/__init__.py | 25 + python/ge_capped_token/data/CappedToken.bin | 1 + python/ge_capped_token/data/CappedToken.json | 1 + .../data/CappedToken.metadata.json | 1 + python/ge_capped_token/data/__init__.py | 3 + python/ge_capped_token/unittest/__init__.py | 51 ++ python/requirements.txt | 5 + python/run_tests.sh | 15 + python/setup.cfg | 51 ++ python/setup.py | 32 + python/test_requirements.txt | 3 + python/tests/test_erc20_interface.py | 14 + python/tests/test_giftable.py | 123 ++++ solidity/CappedToken.sol | 278 ++++++++ solidity/Makefile | 12 + 18 files changed, 1283 insertions(+) create mode 100644 .gitignore create mode 100644 python/LICENSE create mode 100644 python/MANIFEST.in create mode 100644 python/ge_capped_token/__init__.py create mode 100644 python/ge_capped_token/data/CappedToken.bin create mode 100644 python/ge_capped_token/data/CappedToken.json create mode 100644 python/ge_capped_token/data/CappedToken.metadata.json create mode 100644 python/ge_capped_token/data/__init__.py create mode 100644 python/ge_capped_token/unittest/__init__.py create mode 100644 python/requirements.txt create mode 100755 python/run_tests.sh create mode 100644 python/setup.cfg create mode 100644 python/setup.py create mode 100644 python/test_requirements.txt create mode 100644 python/tests/test_erc20_interface.py create mode 100644 python/tests/test_giftable.py create mode 100644 solidity/CappedToken.sol create mode 100644 solidity/Makefile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cdbaee --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__ +*.pyc +*.egg-info +build/ +solidity/*.bin +solidity/*.json diff --git a/python/LICENSE b/python/LICENSE new file mode 100644 index 0000000..be3f7b2 --- /dev/null +++ b/python/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/python/MANIFEST.in b/python/MANIFEST.in new file mode 100644 index 0000000..e14e43a --- /dev/null +++ b/python/MANIFEST.in @@ -0,0 +1 @@ +include **/data/ERC20.json **/data/GiftableToken.json **/data/GiftableToken.bin *requirements.txt CHANGELOG LICENSE WAIVER WAIVER.asc **/data/.chainlib diff --git a/python/ge_capped_token/__init__.py b/python/ge_capped_token/__init__.py new file mode 100644 index 0000000..c74be6f --- /dev/null +++ b/python/ge_capped_token/__init__.py @@ -0,0 +1,25 @@ +# external imports +from giftable_erc20_token import GiftableToken + +# local imports +from ge_capped_token.data import data_dir + + +class CappedToken(GiftableToken): + + @staticmethod + def abi(): + if CappedToken.__abi == None: + f = open(os.path.join(data_dir, 'CappedToken.json'), 'r') + CappedToken.__abi = json.load(f) + f.close() + return CappedToken.__abi + + + @staticmethod + def bytecode(version=None): + if CappedToken.__bytecode == None: + f = open(os.path.join(data_dir, 'CappedToken.bin')) + CappedToken.__bytecode = f.read() + f.close() + return CappedToken.__bytecode diff --git a/python/ge_capped_token/data/CappedToken.bin b/python/ge_capped_token/data/CappedToken.bin new file mode 100644 index 0000000..222a144 --- /dev/null +++ b/python/ge_capped_token/data/CappedToken.bin @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b5060405162002bdc38038062002bdc8339818101604052810190620000379190620002d3565b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360029081620000889190620005ca565b5082600390816200009a9190620005ca565b5081600460006101000a81548160ff021916908360ff1602179055508060098190555050505050620006b1565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200013082620000e5565b810181811067ffffffffffffffff82111715620001525762000151620000f6565b5b80604052505050565b600062000167620000c7565b905062000175828262000125565b919050565b600067ffffffffffffffff821115620001985762000197620000f6565b5b620001a382620000e5565b9050602081019050919050565b60005b83811015620001d0578082015181840152602081019050620001b3565b60008484015250505050565b6000620001f3620001ed846200017a565b6200015b565b905082815260208101848484011115620002125762000211620000e0565b5b6200021f848285620001b0565b509392505050565b600082601f8301126200023f576200023e620000db565b5b815162000251848260208601620001dc565b91505092915050565b600060ff82169050919050565b62000272816200025a565b81146200027e57600080fd5b50565b600081519050620002928162000267565b92915050565b6000819050919050565b620002ad8162000298565b8114620002b957600080fd5b50565b600081519050620002cd81620002a2565b92915050565b60008060008060808587031215620002f057620002ef620000d1565b5b600085015167ffffffffffffffff811115620003115762000310620000d6565b5b6200031f8782880162000227565b945050602085015167ffffffffffffffff811115620003435762000342620000d6565b5b620003518782880162000227565b9350506040620003648782880162000281565b92505060606200037787828801620002bc565b91505092959194509250565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003d657607f821691505b602082108103620003ec57620003eb6200038e565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b60008160020a8302905092915050565b600060088302620004597fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000417565b62000465868362000417565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620004a8620004a26200049c8462000298565b6200047d565b62000298565b9050919050565b6000819050919050565b620004c48362000487565b620004dc620004d382620004af565b84845462000427565b825550505050565b600090565b620004f3620004e4565b62000500818484620004b9565b505050565b5b8181101562000528576200051c600082620004e9565b60018101905062000506565b5050565b601f82111562000577576200054181620003f2565b6200054c8462000407565b810160208510156200055c578190505b620005746200056b8562000407565b83018262000505565b50505b505050565b60008160020a8304905092915050565b60006200059f600019846008026200057c565b1980831691505092915050565b6000620005ba83836200058c565b9150826002028217905092915050565b620005d58262000383565b67ffffffffffffffff811115620005f157620005f0620000f6565b5b620005fd8254620003bd565b6200060a8282856200052c565b600060209050601f8311600181146200064257600084156200062d578287015190505b620006398582620005ac565b865550620006a9565b601f1984166200065286620003f2565b60005b828110156200067c5784890151825560018201915060208501945060208101905062000655565b868310156200069c578489015162000698601f8916826200058c565b8355505b6001600288020188555050505b505050505050565b61251b80620006c16000396000f3fe608060405234801561001057600080fd5b5060043610610202576000357c0100000000000000000000000000000000000000000000000000000000900480635ae06f7e1161012c578063a2309ff8116100bf578063d89135cd1161008e578063d89135cd146105ef578063da2824a81461060d578063dd62ed3e1461063d578063f2fde38b1461066d57610202565b8063a2309ff814610565578063a9059cbb14610583578063b1cb0db3146105b3578063d5abeb01146105d157610202565b806386fe212d116100fb57806386fe212d146104dd5780638da5cb5b1461050d57806394d008ef1461052b57806395d89b411461054757610202565b80635ae06f7e146104435780635f408c04146104735780636f8b44b01461049157806370a08231146104ad57610202565b80632c1758c1116101a457806342966c681161017357806342966c68146103a9578063449a52f8146103d957806344d171871461040957806344df8e701461042557610202565b80632c1758c114610321578063313ce5671461035157806331a5995d1461036f57806332c270521461038d57610202565b806318160ddd116101e057806318160ddd1461028557806318cbbcfc146102a357806323b872dd146102c15780632b29ba23146102f157610202565b806301ffc9a71461020757806306fdde0314610237578063095ea7b314610255575b600080fd5b610221600480360381019061021c9190611cc0565b61069d565b60405161022e9190611d08565b60405180910390f35b61023f6108e7565b60405161024c9190611db3565b60405180910390f35b61026f600480360381019061026a9190611e69565b610975565b60405161027c9190611d08565b60405180910390f35b61028d610b10565b60405161029a9190611eb8565b60405180910390f35b6102ab610b27565b6040516102b89190611eb8565b60405180910390f35b6102db60048036038101906102d69190611ed3565b610b2c565b6040516102e89190611d08565b60405180910390f35b61030b60048036038101906103069190611f26565b610e54565b6040516103189190611d08565b60405180910390f35b61033b60048036038101906103369190611f53565b610f00565b6040516103489190611d08565b60405180910390f35b610359610f33565b6040516103669190611f9c565b60405180910390f35b610377610f46565b6040516103849190611eb8565b60405180910390f35b6103a760048036038101906103a29190611f53565b610f4c565b005b6103c360048036038101906103be9190611f53565b611027565b6040516103d09190611d08565b60405180910390f35b6103f360048036038101906103ee9190611e69565b6111e9565b6040516104009190611d08565b60405180910390f35b610423600480360381019061041e919061201c565b6113b9565b005b61042d611437565b60405161043a9190611d08565b60405180910390f35b61045d60048036038101906104589190611f26565b611486565b60405161046a9190611d08565b60405180910390f35b61047b6115c4565b6040516104889190611f9c565b60405180910390f35b6104ab60048036038101906104a69190611f53565b611662565b005b6104c760048036038101906104c29190611f26565b611728565b6040516104d49190611eb8565b60405180910390f35b6104f760048036038101906104f29190611f53565b611740565b6040516105049190611eb8565b60405180910390f35b610515611833565b604051610522919061209f565b60405180910390f35b6105456004803603810190610540919061201c565b611857565b005b61054f611868565b60405161055c9190611db3565b60405180910390f35b61056d6118f6565b60405161057a9190611eb8565b60405180910390f35b61059d60048036038101906105989190611e69565b6118fc565b6040516105aa9190611d08565b60405180910390f35b6105bb611a7b565b6040516105c89190611eb8565b60405180910390f35b6105d9611a81565b6040516105e69190611eb8565b60405180910390f35b6105f7611a87565b6040516106049190611eb8565b60405180910390f35b61062760048036038101906106229190611f26565b611a8d565b6040516106349190611d08565b60405180910390f35b610657600480360381019061065291906120ba565b611b95565b6040516106649190611eb8565b60405180910390f35b61068760048036038101906106829190611f26565b611bba565b6040516106949190611d08565b60405180910390f35b600063b61bc9417c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036106f157600190506108e2565b63449a52f87c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361074357600190506108e2565b6301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361079557600190506108e2565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036107e757600190506108e2565b63abe1f1f57c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361083957600190506108e2565b63b1110c1b7c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361088b57600190506108e2565b63841a0e947c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036108dd57600190506108e2565b600090505b919050565b600280546108f490612129565b80601f016020809104026020016040519081016040528092919081815260200182805461092090612129565b801561096d5780601f106109425761010080835404028352916020019161096d565b820191906000526020600020905b81548152906001019060200180831161095057829003601f168201915b505050505081565b6000806109806115c4565b60ff161461098d57600080fd5b6000821115610a20576000600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414610a1f57600080fd5b5b81600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610afe9190611eb8565b60405180910390a36001905092915050565b6000600854600754610b229190612189565b905090565b600f81565b600080610b376115c4565b60ff1614610b4457600080fd5b81600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610bcd57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015610c1957600080fd5b81600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610ca19190612189565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610d709190612189565b9250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610dc691906121bd565b925050819055503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f5f7542858008eeb041631f30e6109ae94b83a58e9a58261dd2c42c508850f93985604051610e419190611eb8565b60405180910390a4600190509392505050565b6000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680610ef9575060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b9050919050565b6000600f8210610f0f57600080fd5b60008203610f2457600f600d54149050610f2e565b81600d5483161490505b919050565b600460009054906101000a900460ff1681565b600d5481565b610f59600460ff16610f00565b15610f99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f909061223d565b60405180910390fd5b428110610fdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd2906122a9565b60405180910390fd5b6000600954905081600981905550807ff5bd6cb27a0006b5ea8618058a0d84719695cb6d984f4840bc1a54ca12ae4b7c60095460405161101b9190611eb8565b60405180910390a25050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110af90612315565b60405180910390fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561113a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161113190612381565b60405180910390fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546111899190612189565b9250508190555081600860008282546111a291906121bd565b925050819055507fb90306ad06b2a6ff86ddc9327db583062895ef6540e62dc50add009db5b356eb826040516111d89190611eb8565b60405180910390a160019050919050565b6000600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061128e575060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61129757600080fd5b60006112a16115c4565b60ff16146112ae57600080fd5b6000600b5411156112db57600b54826112c5610b10565b6112cf91906121bd565b11156112da57600080fd5b5b81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461132a91906121bd565b92505081905550816007600082825461134391906121bd565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8846040516113a79190611eb8565b60405180910390a36001905092915050565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611427576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141e906123ed565b60405180910390fd5b61143083611027565b5050505050565b6000611481600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611027565b905090565b6000611495600160ff16610f00565b156114d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114cc9061223d565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061155a57508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61156357600080fd5b6000600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b600080600954036115d8576000905061165f565b600a60009054906101000a900460ff16156115f6576001905061165f565b600954421061165a576001600a60006101000a81548160ff0219169083151502179055507ff80dbaea4785589e52984ca36a31de106adc77759539a5c7d92883bf49692fe9426040516116499190611eb8565b60405180910390a16002905061165f565b600090505b90565b61166f600260ff16610f00565b1561167957600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116d157600080fd5b6116d9610b10565b81116116e457600080fd5b600b547f9722adea12ab7ef86fc45b88f0e0b567639e8dddaae60261e08c03d747fbbfe6826040516117169190611eb8565b60405180910390a280600b8190555050565b60056020528060005260406000206000915090505481565b60006001600f61175091906121bd565b8210611791576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178890612459565b60405180910390fd5b6000600d548316146117d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117cf906124c5565b60405180910390fd5b81600d60008282541792505081905550600f600d541415157f6b7e2e653f93b645d4ed7292d6429f96637084363e477c8aaea1a43ed13c284e600d546040516118219190611eb8565b60405180910390a2600d549050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61186184846111e9565b5050505050565b6003805461187590612129565b80601f01602080910402602001604051908101604052809291908181526020018280546118a190612129565b80156118ee5780601f106118c3576101008083540402835291602001916118ee565b820191906000526020600020905b8154815290600101906020018083116118d157829003601f168201915b505050505081565b60075481565b6000806119076115c4565b60ff161461191457600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561196057600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546119af9190612189565b9250508190555081600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611a0591906121bd565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a699190611eb8565b60405180910390a36001905092915050565b60095481565b600b5481565b60085481565b6000611a9c600160ff16610f00565b15611adc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad39061223d565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b3457600080fd5b6001600c60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060019050919050565b6006602052816000526040600020602052806000526040600020600091509150505481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c1557600080fd5b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060019050919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611c9d81611c68565b8114611ca857600080fd5b50565b600081359050611cba81611c94565b92915050565b600060208284031215611cd657611cd5611c5e565b5b6000611ce484828501611cab565b91505092915050565b60008115159050919050565b611d0281611ced565b82525050565b6000602082019050611d1d6000830184611cf9565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611d5d578082015181840152602081019050611d42565b60008484015250505050565b6000601f19601f8301169050919050565b6000611d8582611d23565b611d8f8185611d2e565b9350611d9f818560208601611d3f565b611da881611d69565b840191505092915050565b60006020820190508181036000830152611dcd8184611d7a565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611e0082611dd5565b9050919050565b611e1081611df5565b8114611e1b57600080fd5b50565b600081359050611e2d81611e07565b92915050565b6000819050919050565b611e4681611e33565b8114611e5157600080fd5b50565b600081359050611e6381611e3d565b92915050565b60008060408385031215611e8057611e7f611c5e565b5b6000611e8e85828601611e1e565b9250506020611e9f85828601611e54565b9150509250929050565b611eb281611e33565b82525050565b6000602082019050611ecd6000830184611ea9565b92915050565b600080600060608486031215611eec57611eeb611c5e565b5b6000611efa86828701611e1e565b9350506020611f0b86828701611e1e565b9250506040611f1c86828701611e54565b9150509250925092565b600060208284031215611f3c57611f3b611c5e565b5b6000611f4a84828501611e1e565b91505092915050565b600060208284031215611f6957611f68611c5e565b5b6000611f7784828501611e54565b91505092915050565b600060ff82169050919050565b611f9681611f80565b82525050565b6000602082019050611fb16000830184611f8d565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112611fdc57611fdb611fb7565b5b8235905067ffffffffffffffff811115611ff957611ff8611fbc565b5b60208301915083600182028301111561201557612014611fc1565b5b9250929050565b6000806000806060858703121561203657612035611c5e565b5b600061204487828801611e1e565b945050602061205587828801611e54565b935050604085013567ffffffffffffffff81111561207657612075611c63565b5b61208287828801611fc6565b925092505092959194509250565b61209981611df5565b82525050565b60006020820190506120b46000830184612090565b92915050565b600080604083850312156120d1576120d0611c5e565b5b60006120df85828601611e1e565b92505060206120f085828601611e1e565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061214157607f821691505b602082108103612154576121536120fa565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061219482611e33565b915061219f83611e33565b92508282039050818111156121b7576121b661215a565b5b92915050565b60006121c882611e33565b91506121d383611e33565b92508282019050808211156121eb576121ea61215a565b5b92915050565b7f4552525f5345414c454400000000000000000000000000000000000000000000600082015250565b6000612227600a83611d2e565b9150612232826121f1565b602082019050919050565b600060208201905081810360008301526122568161221a565b9050919050565b7f4552525f4558504952455f504153540000000000000000000000000000000000600082015250565b6000612293600f83611d2e565b915061229e8261225d565b602082019050919050565b600060208201905081810360008301526122c281612286565b9050919050565b7f4552525f41434345535300000000000000000000000000000000000000000000600082015250565b60006122ff600a83611d2e565b915061230a826122c9565b602082019050919050565b6000602082019050818103600083015261232e816122f2565b9050919050565b7f4552525f46554e44530000000000000000000000000000000000000000000000600082015250565b600061236b600983611d2e565b915061237682612335565b602082019050919050565b6000602082019050818103600083015261239a8161235e565b9050919050565b7f4552525f4e4f545f53454c460000000000000000000000000000000000000000600082015250565b60006123d7600c83611d2e565b91506123e2826123a1565b602082019050919050565b60006020820190508181036000830152612406816123ca565b9050919050565b7f4552525f494e56414c49445f5354415445000000000000000000000000000000600082015250565b6000612443601183611d2e565b915061244e8261240d565b602082019050919050565b6000602082019050818103600083015261247281612436565b9050919050565b7f4552525f414c52454144595f4c4f434b45440000000000000000000000000000600082015250565b60006124af601283611d2e565b91506124ba82612479565b602082019050919050565b600060208201905081810360008301526124de816124a2565b905091905056fea2646970667358221220200054cdf1385e20d7db57cc26c03b18a42ad20bf32b991a378fc17e916091d064736f6c63430008130033 \ No newline at end of file diff --git a/python/ge_capped_token/data/CappedToken.json b/python/ge_capped_token/data/CappedToken.json new file mode 100644 index 0000000..2f9dfb5 --- /dev/null +++ b/python/ge_capped_token/data/CappedToken.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"uint256","name":"_expireTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_oldCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newCap","type":"uint256"}],"name":"Cap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"Expired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTimestamp","type":"uint256"}],"name":"ExpiryChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"_final","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_sealState","type":"uint256"}],"name":"SealStateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_writer","type":"address"}],"name":"WriterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_writer","type":"address"}],"name":"WriterRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"addWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"applyExpiry","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"deleteWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expires","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_state","type":"uint256"}],"name":"isSealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"isWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSealState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"mintTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_state","type":"uint256"}],"name":"seal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sealState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"setExpire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] diff --git a/python/ge_capped_token/data/CappedToken.metadata.json b/python/ge_capped_token/data/CappedToken.metadata.json new file mode 100644 index 0000000..51c02aa --- /dev/null +++ b/python/ge_capped_token/data/CappedToken.metadata.json @@ -0,0 +1 @@ +{"compiler":{"version":"0.8.19+commit.7dd6d404"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"uint256","name":"_expireTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_oldCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newCap","type":"uint256"}],"name":"Cap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"Expired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_oldTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTimestamp","type":"uint256"}],"name":"ExpiryChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"_final","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_sealState","type":"uint256"}],"name":"SealStateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferFrom","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_writer","type":"address"}],"name":"WriterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_writer","type":"address"}],"name":"WriterRemoved","type":"event"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"addWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"applyExpiry","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"deleteWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expires","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_state","type":"uint256"}],"name":"isSealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"isWriter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSealState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"mintTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_state","type":"uint256"}],"name":"seal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sealState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"setExpire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"CappedToken.sol":"CappedToken"},"evmVersion":"byzantium","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"CappedToken.sol":{"keccak256":"0x8d201af84af68db58fccc746718b4abfe7d649e84a1f1bd1949ba378bf03fcb7","license":"AGPL-3.0-or-later","urls":["bzz-raw://7b3adbbcca0f48c6eee68fc88923d2d3446db2221231315cdbda6919d0fc0c6f","dweb:/ipfs/QmRTY3LPX7ef7GTL6HxuDFm3A6tYMqB3QSnEDHXj4TmgRR"]}},"version":1} diff --git a/python/ge_capped_token/data/__init__.py b/python/ge_capped_token/data/__init__.py new file mode 100644 index 0000000..01ec837 --- /dev/null +++ b/python/ge_capped_token/data/__init__.py @@ -0,0 +1,3 @@ +import os + +data_dir = os.path.realpath(os.path.dirname(__file__)) diff --git a/python/ge_capped_token/unittest/__init__.py b/python/ge_capped_token/unittest/__init__.py new file mode 100644 index 0000000..ddee7c8 --- /dev/null +++ b/python/ge_capped_token/unittest/__init__.py @@ -0,0 +1,51 @@ +# standard imports +import logging +import time + +# external imports +from chainlib.eth.unittest.ethtester import EthTesterCase +from chainlib.connection import RPCConnection +from chainlib.eth.nonce import RPCNonceOracle +from chainlib.eth.tx import receipt +from chainlib.eth.address import to_checksum_address + +# local imports +from ge_capped_token import CappedToken + +logg = logging.getLogger(__name__) + + +class TestCappedToken(EthTesterCase): + + expire = 0 + + def setUp(self): + super(TestCappedToken, self).setUp() + self.conn = RPCConnection.connect(self.chain_spec, 'default') + nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.conn) + c = CappedToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + self.symbol = 'FOO' + self.name = 'Foo Token' + self.decimals = 16 + (tx_hash, o) = c.constructor(self.accounts[0], self.name, self.symbol, self.decimals, expire=self.expire) + self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 1) + self.address = to_checksum_address(r['contract_address']) + logg.debug('published on address {} with hash {}'.format(self.address, tx_hash)) + + self.initial_supply = 1 << 40 + (tx_hash, o) = c.mint_to(self.address, self.accounts[0], self.accounts[0], self.initial_supply) + r = self.conn.do(o) + o = receipt(tx_hash) + r = self.conn.do(o) + self.assertEqual(r['status'], 1) + + +class TestCappedExpireToken(TestCappedToken): + + expire = int(time.time()) + 100000 + + def setUp(self): + super(TestCappedExpireToken, self).setUp() diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..ae7c0ec --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,5 @@ +confini~=0.6.1 +chainlib-eth~=0.4.17 +chainlib~=0.4.12 +potaahto~=0.1.1 +eth_erc20~=0.7.4 diff --git a/python/run_tests.sh b/python/run_tests.sh new file mode 100755 index 0000000..926a9eb --- /dev/null +++ b/python/run_tests.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +export PYTHONPATH=${PYTHONPATH}:. +>&2 echo "using pythonpath $PYTHONPATH" + +set -e +set -x +for f in `ls tests/*.py`; do + python $f + if [ $? -gt 0 ]; then + exit 1 + fi +done +set +x +set +e diff --git a/python/setup.cfg b/python/setup.cfg new file mode 100644 index 0000000..b077332 --- /dev/null +++ b/python/setup.cfg @@ -0,0 +1,51 @@ +[metadata] +name = ge-capped-token +version = 0.0.1 +description = ERC20 token that can be minted, capped and expired. +author = Louis Holbrook +author_email = dev@holbrook.no +url = https://git.grassecon.net/grassrootseconomics/ge-capped-token +keywords = + dlt + ethereum + token + blockchain + cryptocurrency +classifiers = + Programming Language :: Python :: 3 + Operating System :: OS Independent + Development Status :: 4 - Beta + Environment :: Console + Intended Audience :: Developers + License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) + Topic :: Internet + Topic :: Software Development :: Libraries + #Topic :: Blockchain :: EVM +license = AGPLv3+ +licence_files = + LICENSE + +[options] +include_package_data = True +python_requires = >= 3.8 +packages = + giftable_erc20_token + giftable_erc20_token.runnable + giftable_erc20_token.unittest + giftable_erc20_token.data + eth_erc20 + eth_erc20.data + eth_erc20.runnable + static_token.data + +[options.package_data] +* = + data/GiftableToken.json + data/GiftableToken.bin + data/StaticToken.json + data/StaticToken.bin + data/ERC20.json + +[options.entry_points] +console_scripts = + capped-token-publish = giftable_erc20_token.runnable.publish:main diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000..8203876 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup + +requirements = [] +f = open('requirements.txt', 'r') +while True: + l = f.readline() + if l == '': + break + requirements.append(l.rstrip()) +f.close() + +test_requirements = [] +f = open('test_requirements.txt', 'r') +while True: + l = f.readline() + if l == '': + break + test_requirements.append(l.rstrip()) +f.close() + + +setup( + package_data={ + '': [ + 'data/GiftableToken.abi.json', + 'data/GiftableToken.bin', + ], + }, + include_package_data=True, + install_requires=requirements, + tests_require=test_requirements, + ) diff --git a/python/test_requirements.txt b/python/test_requirements.txt new file mode 100644 index 0000000..88fa46d --- /dev/null +++ b/python/test_requirements.txt @@ -0,0 +1,3 @@ +eth_tester==0.5.0b3 +py-evm==0.3.0a20 +pytest==6.0.1 diff --git a/python/tests/test_erc20_interface.py b/python/tests/test_erc20_interface.py new file mode 100644 index 0000000..196b37f --- /dev/null +++ b/python/tests/test_erc20_interface.py @@ -0,0 +1,14 @@ +# import logging +import unittest + +# local imports +from ge_capped_token.unittest import TestCappedToken +from eth_erc20.unittest import TestInterface + + +class TestBasic(TestCappedToken, TestInterface): + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/python/tests/test_giftable.py b/python/tests/test_giftable.py new file mode 100644 index 0000000..944977d --- /dev/null +++ b/python/tests/test_giftable.py @@ -0,0 +1,123 @@ +# standard imports +import os +import unittest +import json +import logging +import datetime + +# external imports +from chainlib.eth.constant import ZERO_ADDRESS +from chainlib.eth.nonce import RPCNonceOracle +from chainlib.eth.tx import receipt +from chainlib.eth.block import ( + block_latest, + block_by_number, + ) + +# local imports +from giftable_erc20_token import GiftableToken +from giftable_erc20_token.unittest import TestGiftableExpireToken + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() + +testdir = os.path.dirname(__file__) + + +class TestExpire(TestGiftableExpireToken): + + def setUp(self): + super(TestExpire, self).setUp() + + + def test_expires(self): + mint_amount = self.initial_supply + nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) + c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + + (tx_hash, o) = c.transfer(self.address, self.accounts[0], self.accounts[1], int(mint_amount / 2)) + r = self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 1) + + self.backend.time_travel(self.expire + 60) + o = block_latest() + r = self.rpc.do(o) + o = block_by_number(r) + r = self.rpc.do(o) + self.assertGreaterEqual(r['timestamp'], self.expire) + + nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) + c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash, o) = c.transfer(self.address, self.accounts[0], self.accounts[1], 1) + r = self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 0) + + nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc) + c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash, o) = c.transfer(self.address, self.accounts[1], self.accounts[0], 1) + r = self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 0) + + o = c.balance_of(self.address, self.accounts[0], sender_address=self.accounts[0]) + r = self.rpc.do(o) + balance = c.parse_balance(r) + self.assertEqual(balance, int(mint_amount / 2)) + + o = c.balance_of(self.address, self.accounts[1], sender_address=self.accounts[0]) + r = self.rpc.do(o) + balance += c.parse_balance(r) + self.assertEqual(balance, mint_amount) + + o = c.total_supply(self.address, sender_address=self.accounts[0]) + r = self.rpc.do(o) + supply = c.parse_balance(r) + self.assertEqual(supply, mint_amount) + + + def test_burn(self): + mint_amount = self.initial_supply + nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc) + c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash, o) = c.burn(self.address, self.accounts[1], int(mint_amount / 4)) + self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 0) + + nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) + c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash, o) = c.burn(self.address, self.accounts[0], int(mint_amount / 4)) + self.rpc.do(o) + o = receipt(tx_hash) + r = self.rpc.do(o) + self.assertEqual(r['status'], 1) + + o = c.burned(self.address, sender_address=self.accounts[0]) + r = self.rpc.do(o) + burned = c.parse_balance(r) + self.assertEqual(burned, int(mint_amount / 4)) + + o = c.balance_of(self.address, self.accounts[0], sender_address=self.accounts[0]) + r = self.rpc.do(o) + balance = c.parse_balance(r) + self.assertEqual(balance, mint_amount - burned) + + o = c.total_supply(self.address, sender_address=self.accounts[0]) + r = self.rpc.do(o) + balance = c.parse_balance(r) + self.assertEqual(balance, mint_amount - burned) + + o = c.total_minted(self.address, sender_address=self.accounts[0]) + r = self.rpc.do(o) + balance = c.parse_balance(r) + self.assertEqual(balance, mint_amount) + + +if __name__ == '__main__': + unittest.main() diff --git a/solidity/CappedToken.sol b/solidity/CappedToken.sol new file mode 100644 index 0000000..eec15b9 --- /dev/null +++ b/solidity/CappedToken.sol @@ -0,0 +1,278 @@ +pragma solidity >=0.8.0; + +// SPDX-License-Identifier: AGPL-3.0-or-later +// File-Version: 1 + +contract CappedToken { + + // Implements EIP173 + address public owner; + + // Implements Writer + mapping(address => bool) writer; + + // Implements ERC20 + string public name; + // Implements ERC20 + string public symbol; + // Implements ERC20 + uint8 public decimals; + // Implements ERC20 + mapping (address => uint256) public balanceOf; + // Implements ERC20 + mapping (address => mapping (address => uint256)) public allowance; + + // Implements Burner + uint256 public totalMinted; + // Implements Burner + uint256 public totalBurned; + + // Implements Expire + uint256 public expires; + bool expired; + + // Implements Cap + uint256 public maxSupply; + + mapping(address => bool) writers; + + // Implements ERC20 + event Transfer(address indexed _from, address indexed _to, uint256 _value); + // Implements ERC20 + event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value); + // Implements ERC20 + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + + // Implements Minter + event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value); + + // Implement Expire + event Expired(uint256 _timestamp); + event ExpiryChange(uint256 indexed _oldTimestamp, uint256 _newTimestamp); + + // Implements Writer + event WriterAdded(address _writer); + // Implements Writer + event WriterRemoved(address _writer); + + // Implements Burner + event Burn(uint256 _value); + + // Implements Cap + event Cap(uint256 indexed _oldCap, uint256 _newCap); + + // Implements Seal + event SealStateChange(bool indexed _final, uint256 _sealState); + + // Implements Seal + uint256 public sealState; + uint8 constant WRITER_STATE = 1; + uint8 constant CAP_STATE = 2; + uint8 constant EXPIRY_STATE = 4; + uint256 constant public maxSealState = 15; + + constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _expireTimestamp) { + owner = msg.sender; + name = _name; + symbol = _symbol; + decimals = _decimals; + expires = _expireTimestamp; + } + + // Change max token supply. + // Can only increase supply cap, not decrease. + function setMaxSupply(uint256 _cap) public { + require(!isSealed(CAP_STATE)); + require(msg.sender == owner); + require(_cap > totalSupply()); + emit Cap(maxSupply, _cap); + maxSupply = _cap; + } + + function seal(uint256 _state) public returns(uint256) { + require(_state < maxSealState + 1, 'ERR_INVALID_STATE'); + require(_state & sealState == 0, 'ERR_ALREADY_LOCKED'); + sealState |= _state; + emit SealStateChange(sealState == maxSealState, sealState); + return uint256(sealState); + } + + function isSealed(uint256 _state) public view returns(bool) { + require(_state < maxSealState); + if (_state == 0) { + return sealState == maxSealState; + } + return _state & sealState == _state; + } + + function setExpire(uint256 _timestamp) public { + require(!isSealed(EXPIRY_STATE), "ERR_SEALED"); + require(_timestamp < block.timestamp, "ERR_EXPIRE_PAST"); + uint256 oldTimestamp; + + oldTimestamp = expires; + expires = _timestamp; + emit ExpiryChange(oldTimestamp, expires); + } + + // Implements ERC20 + function totalSupply() public view returns (uint256) { + return totalMinted - totalBurned; + } + + // Implements Minter + function mintTo(address _to, uint256 _value) public returns (bool) { + require(writers[msg.sender] || msg.sender == owner); + require(applyExpiry() == 0); + if (maxSupply > 0) { + require(totalSupply() + _value <= maxSupply); + } + + balanceOf[_to] += _value; + totalMinted += _value; + + emit Mint(msg.sender, _to, _value); + + return true; + } + + // Implements Minter + // Implements ERC5679Ext20 + function mint(address _to, uint256 _value, bytes calldata _data) public { + _data; + mintTo(_to, _value); + } + + // Implements Writer + function addWriter(address _minter) public returns (bool) { + require(!isSealed(WRITER_STATE), "ERR_SEALED"); + require(msg.sender == owner); + + writers[_minter] = true; + + return true; + } + + // Implements Writer + function deleteWriter(address _minter) public returns (bool) { + require(!isSealed(WRITER_STATE), "ERR_SEALED"); + require(msg.sender == owner || msg.sender == _minter); + + writers[_minter] = false; + + return true; + } + + // Implements Writer + function isWriter(address _minter) public view returns(bool) { + return writers[_minter] || _minter == owner; + } + + // Implements Expire + function applyExpiry() public returns(uint8) { + if (expires == 0) { + return 0; + } + if (expired) { + return 1; + } + if (block.timestamp >= expires) { + expired = true; + emit Expired(block.timestamp); + return 2; + } + return 0; + + } + + // Implements ERC20 + function transfer(address _to, uint256 _value) public returns (bool) { + require(applyExpiry() == 0); + require(balanceOf[msg.sender] >= _value); + balanceOf[msg.sender] -= _value; + balanceOf[_to] += _value; + emit Transfer(msg.sender, _to, _value); + return true; + } + + // Implements Burner + function burn(uint256 _value) public returns (bool) { + require(msg.sender == owner, 'ERR_ACCESS'); + require(balanceOf[msg.sender] >= _value, 'ERR_FUNDS'); + + balanceOf[msg.sender] -= _value; + totalBurned += _value; + + emit Burn(_value); + return true; + } + + // Implements Burner + function burn() public returns(bool) { + return burn(balanceOf[msg.sender]); + } + + // Implements Burner + // Implements ERC5679Ext20 + function burn(address _from, uint256 _value, bytes calldata _data) public { + require(msg.sender == _from, 'ERR_NOT_SELF'); + _data; + burn(_value); + } + + // Implements ERC20 + function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { + require(applyExpiry() == 0); + require(allowance[_from][msg.sender] >= _value); + require(balanceOf[_from] >= _value); + allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value; + balanceOf[_from] -= _value; + balanceOf[_to] += _value; + emit TransferFrom(_from, _to, msg.sender, _value); + return true; + } + + // Implements ERC20 + function approve(address _spender, uint256 _value) public returns (bool) { + require(applyExpiry() == 0); + if (_value > 0) { + require(allowance[msg.sender][_spender] == 0); + } + allowance[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + // Implements EIP173 + function transferOwnership(address _newOwner) public returns (bool) { + require(msg.sender == owner); + owner = _newOwner; + return true; + } + + // Implements EIP165 + function supportsInterface(bytes4 _sum) public pure returns (bool) { + if (_sum == 0xb61bc941) { // ERC20 + return true; + } + if (_sum == 0x449a52f8) { // Minter + return true; + } + if (_sum == 0x01ffc9a7) { // EIP165 + return true; + } + if (_sum == 0x9493f8b2) { // EIP173 + return true; + } + if (_sum == 0xabe1f1f5) { // Writer + return true; + } + if (_sum == 0xb1110c1b) { // Burner + return true; + } + if (_sum == 0x841a0e94) { // Expire + return true; + } + return false; + } +} diff --git a/solidity/Makefile b/solidity/Makefile new file mode 100644 index 0000000..2b7e47e --- /dev/null +++ b/solidity/Makefile @@ -0,0 +1,12 @@ +SOLC = /usr/bin/solc + +all: + $(SOLC) --bin CappedToken.sol --evm-version byzantium | awk 'NR>3' > CappedToken.bin + $(SOLC) --abi CappedToken.sol --evm-version byzantium | awk 'NR>3' > CappedToken.json + $(SOLC) --metadata CappedToken.sol --evm-version byzantium | awk 'NR>3' > CappedToken.metadata.json + truncate -s -1 CappedToken.bin + +install: all + cp -v *.json ../python/ge_capped_token/data/ + cp -v *.bin ../python/ge_capped_token/data/ +