diff --git a/.eslintignore b/.eslintignore index dfd3a0917..8a2103827 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,5 @@ cache coverage* gasReporterOutput.json typechain +artifacts-zk +cache-zk diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6ddaa2abf..67ffa2bcc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,3 +1,13 @@ +# When making a release, please keep in mind that this action expects and validates a few things: +# - Releases marked as drafts will be ignored (ie. they will not publish). +# - Ensure that package.json has a version. +# - Ensure the git tag you create during the release process starts with a v (ie. v1.2.3). +# - Ensure that the version in package.json matches the release tag created. +# - Ensure versions are valid semver format. +# - Ensure the GitHub release is marked as a pre-release if the semver version has a pre-release tag. + +# This script was inspired by this README: https://github.com/marketplace/actions/github-releases-for-automated-package-publishing + name: Publish Package to npmjs on: release: @@ -7,12 +17,48 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + + # Note we set an `id` called `release`. We'll use that later... + - name: Validate and extract release information + id: release + uses: manovotny/github-releases-for-automated-package-publishing-action@v2.0.1 + # Setup .npmrc file to publish to npm - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 with: node-version: "16.x" + always-auth: true registry-url: "https://registry.npmjs.org" + + # Perform installs, run tests, run a build step, etc. here, as needed. - run: yarn - - run: yarn publish + + # The last two steps will publish the package. Note that we're using + # information from the `release` step above (I told you we'd use it + # later). Notice the `if` statements on both steps... + # + # If there *is* a tag (ie. `beta`, `canary`, etc.), we publish a + # "pre-release" or "tagged" version of a package (ie. 1.2.3-beta.1). + # + # If there *is not* a tag (ie. `beta`, `canary`, etc.), we publish a + # version of a package (ie. 1.2.3). + # + # This example is using npm to publish, but you could just as easily + # use yarn, if you prefer. It's also publishing to the NPM registry, + # thus, it's using `NPM_TOKEN`, but you could just as easily use + # `GITHUB_TOKEN` if you were publishing to the GitHub Package registry. + + # This will publish a "pre-release" or "tagged" version of a package. + + # This will publish a version of a package. + - name: Publish version + if: steps.release.outputs.tag == '' + run: yarn publish + env: + NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish tagged version + if: steps.release.outputs.tag != '' + run: yarn publish --tag ${{ steps.release.outputs.tag }} env: NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.npmignore b/.npmignore index c4ff6d397..f6ef6a5b9 100644 --- a/.npmignore +++ b/.npmignore @@ -1,2 +1,3 @@ hardhat.config.ts cache +cache-zk \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 77d708c34..59766e79e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,5 @@ coverage* gasReporterOutput.json typechain dist +artifacts-zk +cache-zk diff --git a/LICENSE b/LICENSE index 0ad25db4b..c1f149e94 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,99 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 +Business Source License 1.1 - 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. +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. - 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. +Parameters - 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. +Licensor: Risk Labs - 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. +Licensed Work: Across V2 Contracts and Design + The Licensed Work is (c) 2023 Risk Labs - 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. +Additional Use Grant: None. - 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. +Change Date: The earlier of 2027-07-27 or earlier if Risk Labs + modifies this license. - 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. +Change License: GNU General Public License v3.0 or later - 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 - TERMS AND CONDITIONS +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. - 0. Definitions. +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. - "This License" refers to version 3 of the GNU Affero General Public License. +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. - "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. +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. - 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. +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. - A "covered work" means either the unmodified Program or a work based -on the Program. +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). - 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 THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. - 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. +MariaDB hereby grants you permission to use this License’s text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. - 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. +Covenants of Licensor - 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. +In consideration of the right to use this License’s text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: - 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. +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. - 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. +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". - 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. +3. To specify a Change Date. - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. +4. Not to modify this License in any other way. - The Corresponding Source for a work in source code form is that -same work. +----------------------------------------------------------------------------- - 2. Basic Permissions. +Notice - 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 -. +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. \ No newline at end of file diff --git a/README.md b/README.md index c5193ba28..0c16329ff 100644 --- a/README.md +++ b/README.md @@ -69,3 +69,10 @@ These are special instructions for compiling and deploying contracts on `zksync` This step requires [Docker Desktop](https://www.docker.com/products/docker-desktop/) to be running, as the `solc` docker image is fetched as a prerequisite. `yarn compile-zksync` + +## License + +All code in this repository is licensed under BUSL-1.1 unless specified differently in the file. +Individual exceptions to this license can be made by Risk Labs, which holds the rights to this +software and design. If you are interested in using the code or designs in a derivative work, +feel free to reach out to licensing@risklabs.foundation. diff --git a/contracts/AcrossConfigStore.sol b/contracts/AcrossConfigStore.sol index 54eb1a105..00e71ca60 100644 --- a/contracts/AcrossConfigStore.sol +++ b/contracts/AcrossConfigStore.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@uma/core/contracts/common/implementation/MultiCaller.sol"; diff --git a/contracts/Arbitrum_SpokePool.sol b/contracts/Arbitrum_SpokePool.sol index 585f5f051..4fbbea840 100644 --- a/contracts/Arbitrum_SpokePool.sol +++ b/contracts/Arbitrum_SpokePool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; diff --git a/contracts/Boba_SpokePool.sol b/contracts/Boba_SpokePool.sol index 865f81890..d8406303a 100644 --- a/contracts/Boba_SpokePool.sol +++ b/contracts/Boba_SpokePool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Ovm_SpokePool.sol"; diff --git a/contracts/BondToken.sol b/contracts/BondToken.sol index c91e56942..019c24a7c 100644 --- a/contracts/BondToken.sol +++ b/contracts/BondToken.sol @@ -1,14 +1,14 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; -import "./HubPoolInterface.sol"; +import "./interfaces/HubPoolInterface.sol"; import "./external/WETH9.sol"; interface ExtendedHubPoolInterface is HubPoolInterface { - // Specify the automatically-implemented rootBundleProposer() getter. + // Specify the automatically-implemented rootBundleProposal() getter. function rootBundleProposal() external pure returns (HubPoolInterface.RootBundle memory); } @@ -18,7 +18,7 @@ interface ExtendedHubPoolInterface is HubPoolInterface { * imposes address-based permissioning on the WETH9 transferFrom() function in order to constrain the movement of ABT * into the Across v2 HubPool contract. When configured as the required HubPool bond token, ABT can dramatically reduce * the attack surface of the HubPool by requiring that addresses are explicitly approved before they can successfully - * submit a root bundle proposal. The address-based permissiong does not constrain transfers that are needed to dispute + * submit a root bundle proposal. The address-based permissioning does not constrain transfers that are needed to dispute * a root bundle proposal, so the ability of decentralised/unknown actors to dispute is unaffected. */ contract BondToken is WETH9, Ownable { diff --git a/contracts/Ethereum_SpokePool.sol b/contracts/Ethereum_SpokePool.sol index d6c491789..af77db942 100644 --- a/contracts/Ethereum_SpokePool.sol +++ b/contracts/Ethereum_SpokePool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; diff --git a/contracts/HubPool.sol b/contracts/HubPool.sol index 8ea409320..33fa6d85c 100644 --- a/contracts/HubPool.sol +++ b/contracts/HubPool.sol @@ -1,12 +1,12 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./MerkleLib.sol"; -import "./HubPoolInterface.sol"; +import "./interfaces/HubPoolInterface.sol"; import "./Lockable.sol"; import "./interfaces/LpTokenFactoryInterface.sol"; -import "./interfaces/WETH9Interface.sol"; +import "./external/interfaces/WETH9Interface.sol"; import "@uma/core/contracts/common/implementation/Testable.sol"; import "@uma/core/contracts/common/implementation/MultiCaller.sol"; diff --git a/contracts/Lockable.sol b/contracts/Lockable.sol index bb86571f9..75cbd70f6 100644 --- a/contracts/Lockable.sol +++ b/contracts/Lockable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** diff --git a/contracts/LpTokenFactory.sol b/contracts/LpTokenFactory.sol index f947805b1..4e06978ef 100644 --- a/contracts/LpTokenFactory.sol +++ b/contracts/LpTokenFactory.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./interfaces/LpTokenFactoryInterface.sol"; diff --git a/contracts/MerkleLib.sol b/contracts/MerkleLib.sol index 9e214a3a6..e5310edb4 100644 --- a/contracts/MerkleLib.sol +++ b/contracts/MerkleLib.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "./SpokePoolInterface.sol"; -import "./HubPoolInterface.sol"; +import "./interfaces/SpokePoolInterface.sol"; +import "./interfaces/HubPoolInterface.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; @@ -102,6 +102,6 @@ library MerkleLib { * @return uint256 representing the modified input claimedBitMap with the index set to true. */ function setClaimed1D(uint256 claimedBitMap, uint8 index) internal pure returns (uint256) { - return claimedBitMap | (1 << index % 256); + return claimedBitMap | (1 << index); } } diff --git a/contracts/Optimism_SpokePool.sol b/contracts/Optimism_SpokePool.sol index fd70342a6..fce8a86b3 100644 --- a/contracts/Optimism_SpokePool.sol +++ b/contracts/Optimism_SpokePool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; diff --git a/contracts/Ovm_SpokePool.sol b/contracts/Ovm_SpokePool.sol index d13d7f512..6e6c60e7c 100644 --- a/contracts/Ovm_SpokePool.sol +++ b/contracts/Ovm_SpokePool.sol @@ -1,18 +1,28 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; -import "./interfaces/WETH9Interface.sol"; +import "./external/interfaces/WETH9Interface.sol"; import "@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol"; import "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; -import "@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol"; // https://github.com/Synthetixio/synthetix/blob/5ca27785fad8237fb0710eac01421cafbbd69647/contracts/SynthetixBridgeToBase.sol#L50 interface SynthetixBridgeToBase { function withdrawTo(address to, uint256 amount) external; } +// https://github.com/ethereum-optimism/optimism/blob/bf51c4935261634120f31827c3910aa631f6bf9c/packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol +interface IL2ERC20Bridge { + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _extraData + ) external payable; +} + /** * @notice OVM specific SpokePool. Uses OVM cross-domain-enabled logic to implement admin only access to functions. * Optimism and Boba each implement this spoke pool and set their chain specific contract addresses for l2Eth and l2Weth. */ @@ -27,6 +37,12 @@ contract Ovm_SpokePool is SpokePool { // Address of the Optimism L2 messenger. address public messenger; + // Address of custom bridge used to bridge Synthetix-related assets like SNX. + address private constant SYNTHETIX_BRIDGE = 0x136b1EC699c62b0606854056f02dC7Bb80482d63; + + // Address of SNX ERC20 + address private constant SNX = 0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4; + // Stores alternative token bridges to use for L2 tokens that don't go over the standard bridge. This is needed // to support non-standard ERC20 tokens on Optimism, such as DIA and SNX which both use custom bridges. mapping(address => address) public tokenBridges; @@ -155,10 +171,19 @@ contract Ovm_SpokePool is SpokePool { if (relayerRefundLeaf.l2TokenAddress == address(wrappedNativeToken)) { WETH9Interface(relayerRefundLeaf.l2TokenAddress).withdraw(relayerRefundLeaf.amountToReturn); // Unwrap into ETH. relayerRefundLeaf.l2TokenAddress = l2Eth; // Set the l2TokenAddress to ETH. + IL2ERC20Bridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo{ + value: relayerRefundLeaf.amountToReturn + }( + relayerRefundLeaf.l2TokenAddress, // _l2Token. Address of the L2 token to bridge over. + hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract. + relayerRefundLeaf.amountToReturn, // _amount. + l1Gas, // _l1Gas. Unused, but included for potential forward compatibility considerations + "" // _data. We don't need to send any data for the bridging action. + ); } // Handle custom SNX bridge which doesn't conform to the standard bridge interface. - if (relayerRefundLeaf.l2TokenAddress == 0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4) - SynthetixBridgeToBase(0x136b1EC699c62b0606854056f02dC7Bb80482d63).withdrawTo( + else if (relayerRefundLeaf.l2TokenAddress == SNX) + SynthetixBridgeToBase(SYNTHETIX_BRIDGE).withdrawTo( hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract. relayerRefundLeaf.amountToReturn // _amount. ); diff --git a/contracts/PolygonTokenBridger.sol b/contracts/PolygonTokenBridger.sol index 883cf95d7..4190031fb 100644 --- a/contracts/PolygonTokenBridger.sol +++ b/contracts/PolygonTokenBridger.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./Lockable.sol"; -import "./interfaces/WETH9Interface.sol"; +import "./external/interfaces/WETH9Interface.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; diff --git a/contracts/Polygon_SpokePool.sol b/contracts/Polygon_SpokePool.sol index 85697f66b..5e0f099b1 100644 --- a/contracts/Polygon_SpokePool.sol +++ b/contracts/Polygon_SpokePool.sol @@ -1,13 +1,25 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; import "./PolygonTokenBridger.sol"; -import "./interfaces/WETH9Interface.sol"; -import "./SpokePoolInterface.sol"; +import "./external/interfaces/WETH9Interface.sol"; +import "./interfaces/SpokePoolInterface.sol"; -// IFxMessageProcessor represents interface to process messages. +/** + * @notice IFxMessageProcessor represents interface to process messages. + */ interface IFxMessageProcessor { + /** + * @notice Called by FxChild upon receiving L1 message that targets this contract. Performs an additional check + * that the L1 caller was the expected cross domain admin, and then delegate calls. + * @notice Polygon bridge only executes this external function on the target Polygon contract when relaying + * messages from L1, so all functions on this SpokePool are expected to originate via this call. + * @dev stateId value isn't used because it isn't relevant for this method. It doesn't care what state sync + * triggered this call. + * @param rootMessageSender Original L1 sender of data. + * @param data ABI encoded function call to execute on this contract. + */ function processMessageFromRoot( uint256 stateId, address rootMessageSender, @@ -35,6 +47,7 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool { event PolygonTokensBridged(address indexed token, address indexed receiver, uint256 amount); event SetFxChild(address indexed newFxChild); event SetPolygonTokenBridger(address indexed polygonTokenBridger); + event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender); // Note: validating calls this way ensures that strange calls coming from the fxChild won't be misinterpreted. // Put differently, just checking that msg.sender == fxChild is not sufficient. @@ -48,7 +61,7 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool { // This sets a variable indicating that we're now inside a validated call. // Note: this is used by other methods to ensure that this call has been validated by this method and is not - // spoofed. See + // spoofed. See comment for `_requireAdminSender` for more details. callValidated = true; _; @@ -132,12 +145,15 @@ contract Polygon_SpokePool is IFxMessageProcessor, SpokePool { (bool success, ) = address(this).delegatecall(data); //slither-disable-end low-level-calls require(success, "delegatecall failed"); + + emit ReceivedMessageFromL1(msg.sender, rootMessageSender); } /** * @notice Allows the caller to trigger the wrapping of any unwrapped matic tokens. - * @dev Matic sends via L1 -> L2 bridging actions don't call into the contract receiving the tokens, so wrapping - * must be done via a separate transaction. + * @dev Unlike other ERC20 transfers, Matic transfers from L1 -> L2 bridging don't result in an L2 call into + * the contract receiving the tokens, so wrapping must be done via a separate transaction. In other words, + * we can't rely upon a `fallback()` method being triggered to wrap MATIC upon receiving it. */ function wrap() public nonReentrant { _wrap(); diff --git a/contracts/SpokePool.sol b/contracts/SpokePool.sol index 79488dee6..58e9f8d93 100644 --- a/contracts/SpokePool.sol +++ b/contracts/SpokePool.sol @@ -1,16 +1,15 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./MerkleLib.sol"; -import "./interfaces/WETH9Interface.sol"; -import "./SpokePoolInterface.sol"; +import "./external/interfaces/WETH9Interface.sol"; +import "./interfaces/SpokePoolInterface.sol"; import "./upgradeable/MultiCallerUpgradeable.sol"; import "./upgradeable/EIP712CrossChainUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; @@ -21,6 +20,8 @@ interface AcrossMessageHandler { function handleAcrossMessage( address tokenSent, uint256 amount, + bool fillCompleted, + address relayer, bytes memory message ) external; } @@ -88,8 +89,21 @@ abstract contract SpokePool is // frontrunning that might change their worst-case quote. mapping(address => uint256) public depositCounter; + // This tracks the number of identical refunds that have been requested. + // The intention is to allow an off-chain system to know when this could be a duplicate and ensure that the other + // requests are known and accounted for. + mapping(bytes32 => uint256) public refundsRequested; + uint256 public constant MAX_TRANSFER_SIZE = 1e36; + // Note: this needs to be larger than the max transfer size to ensure that all slow fills are fillable, even if + // their fees are negative. + // It's important that it isn't too large, however, as it should be multipliable by ~2e18 without overflowing. + // 1e40 * 2e18 = 2e58 << 2^255 ~= 5e76 + uint256 public constant SLOW_FILL_MAX_TOKENS_TO_SEND = 1e40; + + // Set max payout adjustment to something + bytes32 public constant UPDATE_DEPOSIT_DETAILS_HASH = keccak256( "UpdateDepositDetails(uint32 depositId,uint256 originChainId,int64 updatedRelayerFeePct,address updatedRecipient,bytes updatedMessage)" @@ -105,11 +119,11 @@ abstract contract SpokePool is event FundsDeposited( uint256 amount, uint256 originChainId, - uint256 destinationChainId, + uint256 indexed destinationChainId, int64 relayerFeePct, uint32 indexed depositId, uint32 quoteTimestamp, - address indexed originToken, + address originToken, address recipient, address indexed depositor, bytes message @@ -127,19 +141,29 @@ abstract contract SpokePool is uint256 totalFilledAmount, uint256 fillAmount, uint256 repaymentChainId, - uint256 originChainId, + uint256 indexed originChainId, uint256 destinationChainId, int64 relayerFeePct, int64 realizedLpFeePct, uint32 indexed depositId, address destinationToken, - address indexed relayer, + address relayer, address indexed depositor, address recipient, bytes message, RelayExecutionInfo updatableRelayData ); - + event RefundRequested( + address indexed relayer, + address refundToken, + uint256 amount, + uint256 indexed originChainId, + uint256 destinationChainId, + int64 realizedLpFeePct, + uint32 indexed depositId, + uint256 fillBlock, + uint256 previousIdenticalRequests + ); event RelayedRootBundle( uint32 indexed rootBundleId, bytes32 indexed relayerRefundRoot, @@ -166,6 +190,21 @@ abstract contract SpokePool is event PausedDeposits(bool isPaused); event PausedFills(bool isPaused); + /** + * @notice Represents data used to fill a deposit. + * @param relay Relay containing original data linked to deposit. Contains fields that can be + * overridden by other parameters in the RelayExecution struct. + * @param relayHash Hash of the relay data. + * @param updatedRelayerFeePct Actual relayer fee pct to use for this relay. + * @param updatedRecipient Actual recipient to use for this relay. + * @param updatedMessage Actual message to use for this relay. + * @param repaymentChainId Chain ID of the network that the relayer will receive refunds on. + * @param maxTokensToSend Max number of tokens to pull from relayer. + * @param maxCount Max count to protect the relayer from frontrunning. + * @param slowFill Whether this is a slow fill. + * @param payoutAdjustmentPct Adjustment to the payout amount. Can be used to increase or decrease the payout to + * allow for rewards or penalties. Used in slow fills. + */ struct RelayExecution { RelayData relay; bytes32 relayHash; @@ -179,6 +218,16 @@ abstract contract SpokePool is int256 payoutAdjustmentPct; } + /** + * @notice Packs together information to include in FilledRelay event. + * @dev This struct is emitted as opposed to its constituent parameters due to the limit on number of + * parameters in an event. + * @param recipient Recipient of the relayed funds. + * @param message Message included in the relay. + * @param relayerFeePct Relayer fee pct used for this relay. + * @param isSlowRelay Whether this is a slow relay. + * @param payoutAdjustmentPct Adjustment to the payout amount. + */ struct RelayExecutionInfo { address recipient; bytes message; @@ -187,14 +236,6 @@ abstract contract SpokePool is int256 payoutAdjustmentPct; } - struct DepositUpdate { - uint32 depositId; - uint256 originChainId; - int64 updatedRelayerFeePct; - address updatedRecipient; - bytes updatedMessage; - } - /** * Do not leave an implementation contract uninitialized. An uninitialized implementation contract can be * taken over by an attacker, which may impact the proxy. To prevent the implementation contract from being @@ -262,8 +303,10 @@ abstract contract SpokePool is function _authorizeUpgrade(address newImplementation) internal override onlyAdmin {} /** - * @notice Pauses deposit and fill functions. This is intended to be used during upgrades or when + * @notice Pauses deposit-related functions. This is intended to be used if this contract is deprecated or when * something goes awry. + * @dev Affects `deposit()` but not `speedUpDeposit()`, so that existing deposits can be sped up and still + * relayed. * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it. */ function pauseDeposits(bool pause) public override onlyAdmin nonReentrant { @@ -271,6 +314,12 @@ abstract contract SpokePool is emit PausedDeposits(pause); } + /** + * @notice Pauses fill-related functions. This is intended to be used if this contract is deprecated or when + * something goes awry. + * @dev Affects fillRelayWithUpdatedDeposit() and fillRelay(). + * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it. + */ function pauseFills(bool pause) public override onlyAdmin nonReentrant { pausedFills = pause; emit PausedFills(pause); @@ -417,7 +466,7 @@ abstract contract SpokePool is // In this case the msg.value will be set to 0, indicating a "normal" ERC20 bridging action. } else IERC20Upgradeable(originToken).safeTransferFrom(msg.sender, address(this), amount); - _emitDeposit( + emit FundsDeposited( amount, chainId(), destinationChainId, @@ -460,7 +509,7 @@ abstract contract SpokePool is bytes memory updatedMessage, bytes memory depositorSignature ) public override nonReentrant { - require(updatedRelayerFeePct < 0.5e18, "invalid relayer fee"); + require(SignedMath.abs(updatedRelayerFeePct) < 0.5e18, "Invalid relayer fee"); _verifyUpdateDepositMessage( depositor, @@ -564,7 +613,7 @@ abstract contract SpokePool is /** * @notice Called by relayer to execute same logic as calling fillRelay except that relayer is using an updated * relayer fee %. The fee % must have been emitted in a message cryptographically signed by the depositor. - * @notice By design, the depositor probably emitted the message with the updated fee by calling speedUpRelay(). + * @notice By design, the depositor probably emitted the message with the updated fee by calling speedUpDeposit(). * @param depositor Depositor on origin chain who set this chain as the destination chain. * @param recipient Specified recipient on this chain. * @param destinationToken Token to send to recipient. Should be mapped to the origin token, origin chain ID @@ -643,6 +692,92 @@ abstract contract SpokePool is _emitFillRelay(relayExecution, fillAmountPreFees); } + /** + * @notice Caller signals to the system that they want a refund on this chain, which they set as the + * `repaymentChainId` on the original fillRelay() call on the `destinationChainId`. An observer should be + * be able to 1-to-1 match the emitted RefundRequested event with the FilledRelay event on the `destinationChainId`. + * @dev This function could be used to artificially inflate the `fillCounter`, allowing the caller to "frontrun" + * and cancel pending fills in the mempool. This would in the worst case censor fills at the cost of the caller's + * gas costs. We don't view this as a major issue as the fill can be resubmitted and obtain the same incentive, + * since incentives are based on validated refunds and would ignore these censoring attempts. This is no + * different from calling `fillRelay` and setting msg.sender = recipient. + * @dev Caller needs to pass in `fillBlock` that the FilledRelay event was emitted on the `destinationChainId`. + * This is to make it hard to request a refund before a fill has been mined and to make lookups of the original + * fill as simple as possible. + * @param refundToken This chain's token equivalent for original fill destination token. + * @param amount Original deposit amount. + * @param originChainId Original origin chain ID. + * @param destinationChainId Original destination chain ID. + * @param realizedLpFeePct Original realized LP fee %. + * @param depositId Original deposit ID. + * @param maxCount Max count to protect the refund recipient from frontrunning. + */ + function requestRefund( + address refundToken, + uint256 amount, + uint256 originChainId, + uint256 destinationChainId, + int64 realizedLpFeePct, + uint32 depositId, + uint256 fillBlock, + uint256 maxCount + ) external nonReentrant { + // Prevent unrealistic amounts from increasing fill counter too high. + require(amount <= MAX_TRANSFER_SIZE, "Amount too large"); + + // This allows the caller to add in frontrunning protection for quote validity. + require(fillCounter[refundToken] <= maxCount, "Above max count"); + + // Track duplicate refund requests. + bytes32 refundHash = keccak256( + abi.encode( + msg.sender, + refundToken, + amount, + originChainId, + destinationChainId, + realizedLpFeePct, + depositId, + fillBlock + ) + ); + + // Track duplicate requests so that an offchain actor knows if an identical request has already been made. + // If so, it can check to ensure that that request was thrown out as invalid before honoring the duplicate. + // In particular, this is meant to handle odd cases where an initial request is invalidated based on + // timing, but can be validated by a later, identical request. + uint256 previousIdenticalRequests = refundsRequested[refundHash]++; + + // Refund will take tokens out of this pool, increment the fill counter. This function should only be + // called if a relayer from destinationChainId wants to take a refund on this chain, a different chain. + // This type of repayment should only be possible for full fills, so the starting fill amount should + // always be 0. Also, just like in _fillRelay we should revert if the first fill pre fees rounds to 0, + // and in this case `amount` == `fillAmountPreFees`. + require(amount > 0, "Amount must be > 0"); + _updateCountFromFill( + 0, + true, // The refund is being requested here, so it is local. + amount, + realizedLpFeePct, + refundToken, + false // Slow fills should never match with a Refund. This should be enforced by off-chain bundle builders. + ); + + emit RefundRequested( + // Set caller as relayer. If caller is not relayer from destination chain that originally sent + // fill, then off-chain validator should discard this refund attempt. + msg.sender, + refundToken, + amount, + originChainId, + destinationChainId, + realizedLpFeePct, + depositId, + fillBlock, + previousIdenticalRequests + ); + } + /************************************** * DATA WORKER FUNCTIONS * **************************************/ @@ -843,7 +978,7 @@ abstract contract SpokePool is updatedRecipient: recipient, updatedMessage: message, repaymentChainId: 0, - maxTokensToSend: amount, + maxTokensToSend: SLOW_FILL_MAX_TOKENS_TO_SEND, slowFill: true, payoutAdjustmentPct: payoutAdjustmentPct, maxCount: type(uint256).max @@ -1000,47 +1135,70 @@ abstract contract SpokePool is // This allows the caller to add in frontrunning protection for quote validity. require(fillCounter[relayData.destinationToken] <= relayExecution.maxCount, "Above max count"); - // Stores the equivalent amount to be sent by the relayer before fees have been taken out. - if (relayExecution.maxTokensToSend == 0) return 0; - // Derive the amount of the relay filled if the caller wants to send exactly maxTokensToSend tokens to // the recipient. For example, if the user wants to send 10 tokens to the recipient, the full relay amount // is 100, and the fee %'s total 5%, then this computation would return ~10.5, meaning that to fill 10.5/100 // of the full relay size, the caller would need to send 10 tokens to the user. + // This is equivalent to the amount to be sent by the relayer before fees have been taken out. fillAmountPreFees = _computeAmountPreFees( relayExecution.maxTokensToSend, (relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct) ); + // If fill amount minus fees, which is possible with small fill amounts and negative fees, then + // revert. + require(fillAmountPreFees > 0, "fill amount pre fees is 0"); + // If user's specified max amount to send is greater than the amount of the relay remaining pre-fees, // we'll pull exactly enough tokens to complete the relay. - uint256 amountToSend = relayExecution.maxTokensToSend; uint256 amountRemainingInRelay = relayData.amount - relayFills[relayExecution.relayHash]; if (amountRemainingInRelay < fillAmountPreFees) { fillAmountPreFees = amountRemainingInRelay; + } - // The user will fulfill the remainder of the relay, so we need to compute exactly how many tokens post-fees - // that they need to send to the recipient. Note that if the relayer is filled using contract funds then - // this is a slow relay. - amountToSend = _computeAmountPostFees( - fillAmountPreFees, - relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct - ); + // Apply post-fees computation to amount that relayer will send to user. Rounding errors are possible + // when computing fillAmountPreFees and then amountToSend, and we just want to enforce that + // the error added to amountToSend is consistently applied to partial and full fills. + uint256 amountToSend = _computeAmountPostFees( + fillAmountPreFees, + relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct + ); - if (relayExecution.payoutAdjustmentPct != 0) { - // If payoutAdjustmentPct is positive, then the recipient will receive more than the amount they - // were originally expecting. If it is negative, then the recipient will receive less. - // -1e18 is -100%. Because we cannot pay out negative values, that is the minimum. - require(relayExecution.payoutAdjustmentPct >= -1e18, "payoutAdjustmentPct too small"); + // This can only happen in a slow fill, where the contract is funding the relay. + if (relayExecution.payoutAdjustmentPct != 0) { + // If payoutAdjustmentPct is positive, then the recipient will receive more than the amount they + // were originally expecting. If it is negative, then the recipient will receive less. + // -1e18 is -100%. Because we cannot pay out negative values, that is the minimum. + require(relayExecution.payoutAdjustmentPct >= -1e18, "payoutAdjustmentPct too small"); - // Note: since _computeAmountPostFees is typicaly intended for fees, the signage must be reversed. - amountToSend = _computeAmountPostFees(amountToSend, -relayExecution.payoutAdjustmentPct); - } + // Allow the payout adjustment to go up to 1000% (i.e. 11x). + // This is a sanity check to ensure the payouts do not grow too large via some sort of issue in bundle + // construction. + require(relayExecution.payoutAdjustmentPct <= 100e18, "payoutAdjustmentPct too large"); + + // Note: since _computeAmountPostFees is typically intended for fees, the signage must be reversed. + amountToSend = _computeAmountPostFees(amountToSend, -relayExecution.payoutAdjustmentPct); + + // Note: this error should never happen, since the maxTokensToSend is expected to be set much higher than + // the amount, but it is here as a sanity check. + require(amountToSend <= relayExecution.maxTokensToSend, "Somehow hit maxTokensToSend!"); } + // Since the first partial fill is used to update the fill counter for the entire refund amount, we don't have + // a simple way to handle the case where follow-up partial fills take repayment on different chains. We'd + // need a way to decrement the fill counter in this case (or increase deposit counter) to ensure that users + // have adequate frontrunning protections. + // Instead of adding complexity, we require that all partial fills set repayment chain equal to destination chain. + // Note: .slowFill is checked because slow fills set repaymentChainId to 0. + bool localRepayment = relayExecution.repaymentChainId == relayExecution.relay.destinationChainId; + require( + localRepayment || relayExecution.relay.amount == fillAmountPreFees || relayExecution.slowFill, + "invalid repayment chain" + ); + // Update fill counter. _updateCountFromFill( relayFills[relayExecution.relayHash], - relayFills[relayExecution.relayHash] + fillAmountPreFees, + localRepayment, relayData.amount, relayData.realizedLpFeePct, relayData.destinationToken, @@ -1056,7 +1214,7 @@ abstract contract SpokePool is // net movement of funds. // Note: this is important because it means that relayers can intentionally self-relay in a capital efficient // way (no need to have funds on the destination). - if (msg.sender == relayData.recipient) return fillAmountPreFees; + if (msg.sender == relayExecution.updatedRecipient) return fillAmountPreFees; // If relay token is wrappedNativeToken then unwrap and send native token. if (relayData.destinationToken == address(wrappedNativeToken)) { @@ -1067,43 +1225,48 @@ abstract contract SpokePool is // need to unwrap it to native token before sending to the user. if (!relayExecution.slowFill) IERC20Upgradeable(relayData.destinationToken).safeTransferFrom(msg.sender, address(this), amountToSend); - _unwrapwrappedNativeTokenTo(payable(relayData.recipient), amountToSend); + _unwrapwrappedNativeTokenTo(payable(relayExecution.updatedRecipient), amountToSend); // Else, this is a normal ERC20 token. Send to recipient. } else { // Note: Similar to note above, send token directly from the contract to the user in the slow relay case. if (!relayExecution.slowFill) IERC20Upgradeable(relayData.destinationToken).safeTransferFrom( msg.sender, - relayData.recipient, + relayExecution.updatedRecipient, + amountToSend + ); + else + IERC20Upgradeable(relayData.destinationToken).safeTransfer( + relayExecution.updatedRecipient, amountToSend ); - else IERC20Upgradeable(relayData.destinationToken).safeTransfer(relayData.recipient, amountToSend); } - if (relayData.recipient.isContract() && relayData.message.length > 0) { - AcrossMessageHandler(relayData.recipient).handleAcrossMessage( + if (relayExecution.updatedRecipient.isContract() && relayExecution.updatedMessage.length > 0) { + AcrossMessageHandler(relayExecution.updatedRecipient).handleAcrossMessage( relayData.destinationToken, amountToSend, - relayData.message + relayFills[relayExecution.relayHash] >= relayData.amount, + msg.sender, + relayExecution.updatedMessage ); } } function _updateCountFromFill( uint256 startingFillAmount, - uint256 endingFillAmount, + bool localRepayment, uint256 totalFillAmount, int64 realizedLPFeePct, address token, bool useContractFunds ) internal { - // If this is a slow fill, it's an initial 0-fill, or a partial fill has already happened, do nothing, as these - // should not impact the count. - if (useContractFunds || endingFillAmount == 0 || startingFillAmount > 0) return; + // If this is a slow fill, a first partial fill with repayment on another chain, or a partial fill has already happened, do nothing, as these + // should not impact the count. Initial 0-fills will not reach this part of the code. + if (useContractFunds || startingFillAmount > 0 || !localRepayment) return; fillCounter[token] += _computeAmountPostFees(totalFillAmount, realizedLPFeePct); } - // The following internal methods emit events with many params to overcome solidity stack too deep issues. function _emitFillRelay(RelayExecution memory relayExecution, uint256 fillAmountPreFees) internal { RelayExecutionInfo memory relayExecutionInfo = RelayExecutionInfo({ relayerFeePct: relayExecution.updatedRelayerFeePct, @@ -1132,32 +1295,6 @@ abstract contract SpokePool is ); } - function _emitDeposit( - uint256 amount, - uint256 originChainId, - uint256 destinationChainId, - int64 relayerFeePct, - uint32 depositId, - uint32 quoteTimestamp, - address originToken, - address recipient, - address depositor, - bytes memory message - ) internal { - emit FundsDeposited( - amount, - originChainId, - destinationChainId, - relayerFeePct, - depositId, - quoteTimestamp, - originToken, - recipient, - depositor, - message - ); - } - // Implementing contract needs to override this to ensure that only the appropriate cross chain admin can execute // certain admin functions. For L2 contracts, the cross chain admin refers to some L1 address or contract, and for // L1, this would just be the same admin of the HubPool. @@ -1168,6 +1305,6 @@ abstract contract SpokePool is // Reserve storage slots for future versions of this base contract to add state variables without // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables - // are added. This is at bottom of contract to make sure its always at the end of storage. + // are added. This is at bottom of contract to make sure it's always at the end of storage. uint256[1000] private __gap; } diff --git a/contracts/Succinct_SpokePool.sol b/contracts/Succinct_SpokePool.sol index f25c2721f..b4c7de7c6 100644 --- a/contracts/Succinct_SpokePool.sol +++ b/contracts/Succinct_SpokePool.sol @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; -import "./interfaces/WETH9Interface.sol"; -import "./external/SuccinctInterfaces.sol"; +import "./external/interfaces/WETH9Interface.sol"; +import "./external/interfaces/SuccinctInterfaces.sol"; /** * @notice Succinct Spoke pool. @@ -19,13 +19,16 @@ contract Succinct_SpokePool is SpokePool, ITelepathyHandler { // private. Leaving it set to true can permanently disable admin calls. bool private adminCallValidated; - // Note: validating calls this way ensures that strange calls coming from the succinctTargetAmb won't be misinterpreted. - // Put differently, just checking that msg.sender == succinctTargetAmb is not sufficient. + event SetSuccinctTargetAmb(address indexed newSuccinctTargetAmb); + event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender); + + // Note: validating calls this way ensures that strange calls coming from the succinctTargetAmb won't be + // misinterpreted. Put differently, just checking that msg.sender == succinctTargetAmb is not sufficient. // All calls that have admin privileges must be fired from within the handleTelepathy method that's gone // through validation where the sender is checked and the sender from the other chain is also validated. - // This modifier sets the callValidated variable so this condition can be checked in _requireAdminSender(). + // This modifier sets the adminCallValidated variable so this condition can be checked in _requireAdminSender(). modifier validateInternalCalls() { - // Make sure callValidated is set to True only once at beginning of processMessageFromRoot, which prevents + // Make sure adminCallValidated is set to True only once at beginning of processMessageFromRoot, which prevents // processMessageFromRoot from being re-entered. require(!adminCallValidated, "adminCallValidated already set"); @@ -36,7 +39,7 @@ contract Succinct_SpokePool is SpokePool, ITelepathyHandler { _; - // Reset callValidated to false to disallow admin calls after this method exits. + // Reset adminCallValidated to false to disallow admin calls after this method exits. adminCallValidated = false; } @@ -68,6 +71,7 @@ contract Succinct_SpokePool is SpokePool, ITelepathyHandler { */ function setSuccinctTargetAmb(address _succinctTargetAmb) external onlyAdmin { succinctTargetAmb = _succinctTargetAmb; + emit SetSuccinctTargetAmb(_succinctTargetAmb); } /** @@ -83,14 +87,15 @@ contract Succinct_SpokePool is SpokePool, ITelepathyHandler { ) external override validateInternalCalls returns (bytes4) { // Validate msg.sender as succinct, the x-chain sender as being the hubPool (the admin) and the source chain as // 1 (mainnet). - require( - msg.sender == succinctTargetAmb && _senderAddress == hubPool && _sourceChainId == hubChainId, - "Invalid message" - ); + require(msg.sender == succinctTargetAmb, "caller not succinct AMB"); + require(_senderAddress == hubPool, "sender not hubPool"); + require(_sourceChainId == hubChainId, "source chain not hub chain"); /// @custom:oz-upgrades-unsafe-allow delegatecall (bool success, ) = address(this).delegatecall(_data); require(success, "delegatecall failed"); + + emit ReceivedMessageFromL1(msg.sender, _senderAddress); return ITelepathyHandler.handleTelepathy.selector; } diff --git a/contracts/ZkSync_SpokePool.sol b/contracts/ZkSync_SpokePool.sol index eb11e17bb..60e8a1d98 100644 --- a/contracts/ZkSync_SpokePool.sol +++ b/contracts/ZkSync_SpokePool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "./SpokePool.sol"; diff --git a/contracts/chain-adapters/Arbitrum_Adapter.sol b/contracts/chain-adapters/Arbitrum_Adapter.sol index 9cb6ccfcf..f220c4f93 100644 --- a/contracts/chain-adapters/Arbitrum_Adapter.sol +++ b/contracts/chain-adapters/Arbitrum_Adapter.sol @@ -1,38 +1,91 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +/** + * @notice Interface for Arbitrum's L1 Inbox contract used to send messages to Arbitrum. + */ interface ArbitrumL1InboxLike { + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @dev Caller must set msg.value equal to at least `maxSubmissionCost + maxGas * gasPriceBid`. + * all msg.value will deposited to callValueRefundAddress on L2 + * @dev More details can be found here: https://developer.arbitrum.io/arbos/l1-to-l2-messaging + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ function createRetryableTicket( - address destAddr, - uint256 arbTxCallValue, + address to, + uint256 l2CallValue, uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, bytes calldata data ) external payable returns (uint256); + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed + * funds come from the deposit alone, rather than falling back on the user's L2 balance + * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). + * createRetryableTicket method is the recommended standard. + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ function unsafeCreateRetryableTicket( - address destAddr, - uint256 arbTxCallValue, + address to, + uint256 l2CallValue, uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, bytes calldata data ) external payable returns (uint256); } +/** + * @notice Layer 1 Gateway contract for bridging standard ERC20s to Arbitrum. + */ interface ArbitrumL1ERC20GatewayLike { + /** + * @notice Deprecated in favor of outboundTransferCustomRefund but still used in custom bridges + * like the DAI bridge. + * @dev Refunded to aliased L2 address of sender if sender has code on L1, otherwise to to sender's EOA on L2. + * @param _l1Token L1 address of ERC20 + * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), + * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to + * cancel the retryable ticket and receive callvalue refund + * @param _amount Token Amount + * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution + * @param _gasPriceBid Gas price for L2 execution + * @param _data encoded data from router and user + * @return res abi encoded inbox sequence number + */ function outboundTransfer( - address _token, + address _l1Token, address _to, uint256 _amount, uint256 _maxGas, @@ -40,8 +93,26 @@ interface ArbitrumL1ERC20GatewayLike { bytes calldata _data ) external payable returns (bytes memory); + /** + * @notice Deposit ERC20 token from Ethereum into Arbitrum. + * @dev L2 address alias will not be applied to the following types of addresses on L1: + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * @param _l1Token L1 address of ERC20 + * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 + * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), + * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to + * cancel the retryable ticket and receive callvalue refund + * @param _amount Token Amount + * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution + * @param _gasPriceBid Gas price for L2 execution + * @param _data encoded data from router and user + * @return res abi encoded inbox sequence number + */ function outboundTransferCustomRefund( - address _token, + address _l1Token, address _refundTo, address _to, uint256 _amount, @@ -50,6 +121,11 @@ interface ArbitrumL1ERC20GatewayLike { bytes calldata _data ) external payable returns (bytes memory); + /** + * @notice get ERC20 gateway for token. + * @param _token ERC20 address. + * @return address of ERC20 gateway. + */ function getGateway(address _token) external view returns (address); } diff --git a/contracts/chain-adapters/Arbitrum_RescueAdapter.sol b/contracts/chain-adapters/Arbitrum_RescueAdapter.sol index b39125835..1a66e5133 100644 --- a/contracts/chain-adapters/Arbitrum_RescueAdapter.sol +++ b/contracts/chain-adapters/Arbitrum_RescueAdapter.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import "./Arbitrum_Adapter.sol"; // Used to import `ArbitrumL1ERC20GatewayLike` and `ArbitrumL1InboxLike` import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol b/contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol index 0e45f9f5f..944dd5baa 100644 --- a/contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol +++ b/contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import { ArbitrumL1ERC20GatewayLike } from "./Arbitrum_Adapter.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/chain-adapters/Boba_Adapter.sol b/contracts/chain-adapters/Boba_Adapter.sol index 6bbcdfacd..0b2a73841 100644 --- a/contracts/chain-adapters/Boba_Adapter.sol +++ b/contracts/chain-adapters/Boba_Adapter.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; -import "../interfaces/WETH9Interface.sol"; +import "./interfaces/AdapterInterface.sol"; +import "../external/interfaces/WETH9Interface.sol"; // @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need // this contract's state variables to be `immutable` because of the delegateCall call. diff --git a/contracts/chain-adapters/Ethereum_Adapter.sol b/contracts/chain-adapters/Ethereum_Adapter.sol index c94ddf161..c97b9dd30 100644 --- a/contracts/chain-adapters/Ethereum_Adapter.sol +++ b/contracts/chain-adapters/Ethereum_Adapter.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/chain-adapters/Ethereum_RescueAdapter.sol b/contracts/chain-adapters/Ethereum_RescueAdapter.sol index d779eecae..c8fc200ac 100644 --- a/contracts/chain-adapters/Ethereum_RescueAdapter.sol +++ b/contracts/chain-adapters/Ethereum_RescueAdapter.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/chain-adapters/Mock_Adapter.sol b/contracts/chain-adapters/Mock_Adapter.sol index 3e5f209fd..3095ab138 100644 --- a/contracts/chain-adapters/Mock_Adapter.sol +++ b/contracts/chain-adapters/Mock_Adapter.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; +import "./interfaces/AdapterInterface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** diff --git a/contracts/chain-adapters/Optimism_Adapter.sol b/contracts/chain-adapters/Optimism_Adapter.sol index f031e0f63..ff92d3d32 100644 --- a/contracts/chain-adapters/Optimism_Adapter.sol +++ b/contracts/chain-adapters/Optimism_Adapter.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; -import "../interfaces/WETH9Interface.sol"; +import "./interfaces/AdapterInterface.sol"; +import "../external/interfaces/WETH9Interface.sol"; // @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need // this contract's state variables to be `immutable` because of the delegateCall call. @@ -12,7 +12,15 @@ import "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +/** + * @notice Interface for Synthetix custom bridge to Optimism. + */ interface SynthetixBridgeToOptimism is IL1StandardBridge { + /** + * @notice Send tokens to Optimism. + * @param to Address to send tokens to on L2. + * @param amount Amount of tokens to send. + */ function depositTo(address to, uint256 amount) external; } @@ -20,7 +28,7 @@ interface SynthetixBridgeToOptimism is IL1StandardBridge { * @notice Contract containing logic to send messages from L1 to Optimism. * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be * called via delegatecall, which will execute this contract's logic within the context of the originating contract. - * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods + * For example, the HubPool will delegatecall these functions, therefore it's only necessary that the HubPool's methods * that call this contract's logic guard against reentrancy. */ diff --git a/contracts/chain-adapters/Polygon_Adapter.sol b/contracts/chain-adapters/Polygon_Adapter.sol index 1da8b8d52..53975a12c 100644 --- a/contracts/chain-adapters/Polygon_Adapter.sol +++ b/contracts/chain-adapters/Polygon_Adapter.sol @@ -1,15 +1,28 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; -import "../interfaces/WETH9Interface.sol"; +import "./interfaces/AdapterInterface.sol"; +import "../external/interfaces/WETH9Interface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +/** + * @notice Send tokens to Polygon. + */ interface IRootChainManager { + /** + * @notice Send msg.value of ETH to Polygon + * @param user Recipient of ETH on Polygon. + */ function depositEtherFor(address user) external payable; + /** + * @notice Send ERC20 tokens to Polygon. + * @param user Recipient of L2 equivalent tokens on Polygon. + * @param rootToken L1 Address of token to send. + * @param depositData Data to pass to L2 including amount of tokens to send. Should be abi.encode(amount). + */ function depositFor( address user, address rootToken, @@ -17,11 +30,28 @@ interface IRootChainManager { ) external; } +/** + * @notice Send arbitrary messages to Polygon. + */ interface IFxStateSender { + /** + * @notice Send arbitrary message to Polygon. + * @param _receiver Address on Polygon to receive message. + * @param _data Message to send to `_receiver` on Polygon. + */ function sendMessageToChild(address _receiver, bytes calldata _data) external; } +/** + * @notice Similar to RootChainManager, but for Matic (Plasma) bridge. + */ interface DepositManager { + /** + * @notice Send tokens to Polygon. Only used to send MATIC in this Polygon_Adapter. + * @param token L1 token to send. Should be MATIC. + * @param user Recipient of L2 equivalent tokens on Polygon. + * @param amount Amount of `token` to send. + */ function depositERC20ForUser( address token, address user, diff --git a/contracts/chain-adapters/Succinct_Adapter.sol b/contracts/chain-adapters/Succinct_Adapter.sol index 0fcd71689..511a1f24b 100644 --- a/contracts/chain-adapters/Succinct_Adapter.sol +++ b/contracts/chain-adapters/Succinct_Adapter.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; -import "../external/SuccinctInterfaces.sol"; +import "./interfaces/AdapterInterface.sol"; +import "../external/interfaces/SuccinctInterfaces.sol"; // solhint-disable-next-line contract-name-camelcase contract Succinct_Adapter is AdapterInterface { @@ -24,7 +24,7 @@ contract Succinct_Adapter is AdapterInterface { /** * @notice Send cross-chain message to target on the destination. - * @param target Contract on the destinatipn that will receive the message.. + * @param target Contract on the destination that will receive the message. * @param message Data to send to target. */ function relayMessage(address target, bytes calldata message) external payable override { diff --git a/contracts/chain-adapters/ZkSync_Adapter.sol b/contracts/chain-adapters/ZkSync_Adapter.sol index 7b6305eb2..ad842537f 100644 --- a/contracts/chain-adapters/ZkSync_Adapter.sol +++ b/contracts/chain-adapters/ZkSync_Adapter.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "../interfaces/AdapterInterface.sol"; -import "../interfaces/WETH9Interface.sol"; +import "./interfaces/AdapterInterface.sol"; +import "../external/interfaces/WETH9Interface.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/chain-adapters/interfaces/AdapterInterface.sol b/contracts/chain-adapters/interfaces/AdapterInterface.sol new file mode 100644 index 000000000..f8143e0c6 --- /dev/null +++ b/contracts/chain-adapters/interfaces/AdapterInterface.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/** + * @notice Sends cross chain messages and tokens to contracts on a specific L2 network. + * This interface is implemented by an adapter contract that is deployed on L1. + */ + +interface AdapterInterface { + event MessageRelayed(address target, bytes message); + + event TokensRelayed(address l1Token, address l2Token, uint256 amount, address to); + + /** + * @notice Send message to `target` on L2. + * @dev This method is marked payable because relaying the message might require a fee + * to be paid by the sender to forward the message to L2. However, it will not send msg.value + * to the target contract on L2. + * @param target L2 address to send message to. + * @param message Message to send to `target`. + */ + function relayMessage(address target, bytes calldata message) external payable; + + /** + * @notice Send `amount` of `l1Token` to `to` on L2. `l2Token` is the L2 address equivalent of `l1Token`. + * @dev This method is marked payable because relaying the message might require a fee + * to be paid by the sender to forward the message to L2. However, it will not send msg.value + * to the target contract on L2. + * @param l1Token L1 token to bridge. + * @param l2Token L2 token to receive. + * @param amount Amount of `l1Token` to bridge. + * @param to Bridge recipient. + */ + function relayTokens( + address l1Token, + address l2Token, + uint256 amount, + address to + ) external payable; +} diff --git a/contracts/erc1155/MintableERC1155.sol b/contracts/erc1155/MintableERC1155.sol new file mode 100644 index 000000000..7603c9b4d --- /dev/null +++ b/contracts/erc1155/MintableERC1155.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; + +/** + * @title MintableERC1155 + * @notice Ownable contract enabling owner to airdrop many recipients the same token ID at once + */ +contract MintableERC1155 is ERC1155, Ownable { + // Maps `tokenId` to metadata URI `tokenURI` + mapping(uint256 => string) public _tokenURIs; + + event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount); + + // We are passing an empty string as the `baseURI` because we use `_tokenURIs` instead + // to allow for IPFS URIs. + // solhint-disable-next-line + constructor() ERC1155("") {} + + /** + * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`. + * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list. + * @param recipients List of airdrop recipients. + * @param tokenId Token type to airdrop. + * @param amount Amount of token types to airdrop. + */ + function airdrop( + uint256 tokenId, + address[] memory recipients, + uint256 amount + ) public onlyOwner { + for (uint256 i = 0; i < recipients.length; i++) { + _mint(recipients[i], tokenId, amount, ""); + } + emit Airdrop(_msgSender(), tokenId, recipients, amount); + } + + /** + * @notice Sets the URI for token of type `tokenId` to `tokenURI`. + * @param tokenId Token type to set `tokenURI` for. + * @param tokenURI URI of token metadata. + */ + function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner { + require(bytes(_tokenURIs[tokenId]).length == 0, "uri already set"); + + _tokenURIs[tokenId] = tokenURI; + emit URI(tokenURI, tokenId); + } + + /** + * @notice Returns metadata URI of token type `tokenId`. + * @dev Instead of returning the same URI for *all* token types, we return the uri set by + * `setTokenURI` to allow IPFS URIs for all token types. + * @param tokenId Token type to retrieve metadata URI for. + */ + function uri(uint256 tokenId) public view override returns (string memory) { + return _tokenURIs[tokenId]; + } +} diff --git a/contracts/external/SuccinctInterfaces.sol b/contracts/external/interfaces/SuccinctInterfaces.sol similarity index 100% rename from contracts/external/SuccinctInterfaces.sol rename to contracts/external/interfaces/SuccinctInterfaces.sol diff --git a/contracts/external/interfaces/WETH9Interface.sol b/contracts/external/interfaces/WETH9Interface.sol new file mode 100644 index 000000000..3dcd8d515 --- /dev/null +++ b/contracts/external/interfaces/WETH9Interface.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/** + * @notice Interface for the WETH9 contract. + */ +interface WETH9Interface { + /** + * @notice Burn Wrapped Ether and receive native Ether. + * @param wad Amount of WETH to unwrap and send to caller. + */ + function withdraw(uint256 wad) external; + + /** + * @notice Lock native Ether and mint Wrapped Ether ERC20 + * @dev msg.value is amount of Wrapped Ether to mint/Ether to lock. + */ + function deposit() external payable; + + /** + * @notice Get balance of WETH held by `guy`. + * @param guy Address to get balance of. + * @return wad Amount of WETH held by `guy`. + */ + function balanceOf(address guy) external view returns (uint256 wad); + + /** + * @notice Transfer `wad` of WETH from caller to `guy`. + * @param guy Address to send WETH to. + * @param wad Amount of WETH to send. + * @return ok True if transfer succeeded. + */ + function transfer(address guy, uint256 wad) external returns (bool); +} diff --git a/contracts/interfaces/AdapterInterface.sol b/contracts/interfaces/AdapterInterface.sol deleted file mode 100644 index c40f71f6a..000000000 --- a/contracts/interfaces/AdapterInterface.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity ^0.8.0; - -/** - * @notice Sends cross chain messages and tokens to contracts on a specific L2 network. - */ - -interface AdapterInterface { - event MessageRelayed(address target, bytes message); - - event TokensRelayed(address l1Token, address l2Token, uint256 amount, address to); - - function relayMessage(address target, bytes calldata message) external payable; - - function relayTokens( - address l1Token, - address l2Token, - uint256 amount, - address to - ) external payable; -} diff --git a/contracts/HubPoolInterface.sol b/contracts/interfaces/HubPoolInterface.sol similarity index 98% rename from contracts/HubPoolInterface.sol rename to contracts/interfaces/HubPoolInterface.sol index 1d72360ea..49292e215 100644 --- a/contracts/HubPoolInterface.sol +++ b/contracts/interfaces/HubPoolInterface.sol @@ -1,8 +1,6 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import "./interfaces/AdapterInterface.sol"; - import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** diff --git a/contracts/interfaces/LpTokenFactoryInterface.sol b/contracts/interfaces/LpTokenFactoryInterface.sol index 92b7bf9e8..6e8012ff8 100644 --- a/contracts/interfaces/LpTokenFactoryInterface.sol +++ b/contracts/interfaces/LpTokenFactoryInterface.sol @@ -1,6 +1,15 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; +/** + * @notice Factory to create new LP ERC20 tokens that represent a liquidity provider's position. HubPool is the + * intended client of this contract. + */ interface LpTokenFactoryInterface { + /** + * @notice Deploys new LP token for L1 token. Sets caller as minter and burner of token. + * @param l1Token L1 token to name in LP token name. + * @return address of new LP token. + */ function createLpToken(address l1Token) external returns (address); } diff --git a/contracts/SpokePoolInterface.sol b/contracts/interfaces/SpokePoolInterface.sol similarity index 99% rename from contracts/SpokePoolInterface.sol rename to contracts/interfaces/SpokePoolInterface.sol index 6d43bf6cf..1ba0edcb1 100644 --- a/contracts/SpokePoolInterface.sol +++ b/contracts/interfaces/SpokePoolInterface.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** diff --git a/contracts/interfaces/WETH9Interface.sol b/contracts/interfaces/WETH9Interface.sol deleted file mode 100644 index b13caf788..000000000 --- a/contracts/interfaces/WETH9Interface.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity ^0.8.0; - -interface WETH9Interface { - function withdraw(uint256 wad) external; - - function deposit() external payable; - - function balanceOf(address guy) external view returns (uint256 wad); - - function transfer(address guy, uint256 wad) external returns (bool); -} diff --git a/contracts/merkle-distributor/AcrossMerkleDistributor.sol b/contracts/merkle-distributor/AcrossMerkleDistributor.sol index 5f4ff9553..f881b8380 100644 --- a/contracts/merkle-distributor/AcrossMerkleDistributor.sol +++ b/contracts/merkle-distributor/AcrossMerkleDistributor.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol"; diff --git a/contracts/test/AcrossMessageHandlerMock.sol b/contracts/test/AcrossMessageHandlerMock.sol index cda26868c..f2eb6e84b 100644 --- a/contracts/test/AcrossMessageHandlerMock.sol +++ b/contracts/test/AcrossMessageHandlerMock.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../SpokePool.sol"; @@ -7,6 +7,8 @@ contract AcrossMessageHandlerMock is AcrossMessageHandler { function handleAcrossMessage( address tokenSent, uint256 amount, + bool fillCompleted, + address relayer, bytes memory message ) external override {} } diff --git a/contracts/test/ArbitrumMocks.sol b/contracts/test/ArbitrumMocks.sol index 43a87bb8f..b80229ab4 100644 --- a/contracts/test/ArbitrumMocks.sol +++ b/contracts/test/ArbitrumMocks.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; contract ArbitrumMockErc20GatewayRouter { diff --git a/contracts/test/MerkleLibTest.sol b/contracts/test/MerkleLibTest.sol index 1a1abf9dc..efc9228ba 100644 --- a/contracts/test/MerkleLibTest.sol +++ b/contracts/test/MerkleLibTest.sol @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../MerkleLib.sol"; -import "../HubPoolInterface.sol"; -import "../SpokePoolInterface.sol"; +import "../interfaces/HubPoolInterface.sol"; +import "../interfaces/SpokePoolInterface.sol"; /** * @notice Contract to test the MerkleLib. diff --git a/contracts/test/MockBedrockStandardBridge.sol b/contracts/test/MockBedrockStandardBridge.sol new file mode 100644 index 000000000..8e712628f --- /dev/null +++ b/contracts/test/MockBedrockStandardBridge.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import "../Ovm_SpokePool.sol"; + +// Provides payable withdrawTo interface introduced on Bedrock +contract MockBedrockL2StandardBridge is IL2ERC20Bridge { + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _extraData + ) external payable { + // do nothing + } +} diff --git a/contracts/test/MockOptimism_SpokePool.sol b/contracts/test/MockOptimism_SpokePool.sol new file mode 100644 index 000000000..0ca6f8dc5 --- /dev/null +++ b/contracts/test/MockOptimism_SpokePool.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; +import "../Ovm_SpokePool.sol"; + +/** + * @notice Mock Optimism Spoke pool allowing deployer to override constructor params. + */ +contract MockOptimism_SpokePool is Ovm_SpokePool { + function initialize( + address l2Weth, + address l2Eth, + uint32 _initialDepositId, + address _crossDomainAdmin, + address _hubPool + ) public initializer { + __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, l2Eth, l2Weth); + } +} diff --git a/contracts/test/PolygonERC20Test.sol b/contracts/test/PolygonERC20Test.sol index 07b439abe..a0b3d8b18 100644 --- a/contracts/test/PolygonERC20Test.sol +++ b/contracts/test/PolygonERC20Test.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@uma/core/contracts/common/implementation/ExpandedERC20.sol"; diff --git a/contracts/test/PolygonMocks.sol b/contracts/test/PolygonMocks.sol index 8c8a73e54..69fbf567e 100644 --- a/contracts/test/PolygonMocks.sol +++ b/contracts/test/PolygonMocks.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/contracts/test/SuccinctMocks.sol b/contracts/test/SuccinctMocks.sol index 9ec3fb87b..b3f4365b3 100644 --- a/contracts/test/SuccinctMocks.sol +++ b/contracts/test/SuccinctMocks.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; contract TelepathyBroadcasterMock { diff --git a/contracts/upgradeable/EIP712CrossChainUpgradeable.sol b/contracts/upgradeable/EIP712CrossChainUpgradeable.sol index d8003fe7a..7007f61aa 100644 --- a/contracts/upgradeable/EIP712CrossChainUpgradeable.sol +++ b/contracts/upgradeable/EIP712CrossChainUpgradeable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; @@ -80,6 +80,6 @@ abstract contract EIP712CrossChainUpgradeable is Initializable { // Reserve storage slots for future versions of this base contract to add state variables without // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables - // are added. This is at bottom of contract to make sure its always at the end of storage. + // are added. This is at bottom of contract to make sure it's always at the end of storage. uint256[1000] private __gap; } diff --git a/contracts/upgradeable/MultiCallerUpgradeable.sol b/contracts/upgradeable/MultiCallerUpgradeable.sol index 3016ceabd..d907dbf1d 100644 --- a/contracts/upgradeable/MultiCallerUpgradeable.sol +++ b/contracts/upgradeable/MultiCallerUpgradeable.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** - * @title MockSpokePool + * @title MultiCallerUpgradeable * @notice Logic is 100% copied from "@uma/core/contracts/common/implementation/MultiCaller.sol" but one * comment is added to clarify why we allow delegatecall() in this contract, which is typically unsafe for use in * upgradeable implementation contracts. diff --git a/deploy/001_deploy_hubpool.ts b/deploy/001_deploy_hubpool.ts index 6fed96b4b..6e9aac8c5 100644 --- a/deploy/001_deploy_hubpool.ts +++ b/deploy/001_deploy_hubpool.ts @@ -1,9 +1,9 @@ import { L1_ADDRESS_MAP } from "./consts"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/002_deploy_optimism_adapter.ts b/deploy/002_deploy_optimism_adapter.ts index 038bf45be..a9a2d5624 100644 --- a/deploy/002_deploy_optimism_adapter.ts +++ b/deploy/002_deploy_optimism_adapter.ts @@ -1,9 +1,8 @@ import { L1_ADDRESS_MAP } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/003_deploy_optimism_spokepool.ts b/deploy/003_deploy_optimism_spokepool.ts index e59ea14e1..98bf2e90b 100644 --- a/deploy/003_deploy_optimism_spokepool.ts +++ b/deploy/003_deploy_optimism_spokepool.ts @@ -1,27 +1,17 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { deployNewProxy } from "../utils/utils.hre"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, companionNetworks } = hre; - const { deploy } = deployments; +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - const { deployer } = await getNamedAccounts(); - - // Grab L1 addresses: - const { deployments: l1Deployments } = companionNetworks.l1; - const hubPool = await l1Deployments.get("HubPool"); - console.log(`Using l1 hub pool @ ${hubPool.address}`); - - await deploy("Optimism_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [ - hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic. - hubPool.address, - "0x0000000000000000000000000000000000000000", // timer - ], - }); + // Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's + // with deprecated spoke pool. + // Set hub pool as cross domain admin since it delegatecalls the Adapter logic. + const constructorArgs = [1_000_000, hubPool.address, hubPool.address]; + await deployNewProxy("Optimism_SpokePool", constructorArgs); }; module.exports = func; func.tags = ["OptimismSpokePool", "optimism"]; diff --git a/deploy/004_deploy_arbitrum_adapter.ts b/deploy/004_deploy_arbitrum_adapter.ts index c903aee16..f78541aea 100644 --- a/deploy/004_deploy_arbitrum_adapter.ts +++ b/deploy/004_deploy_arbitrum_adapter.ts @@ -1,9 +1,8 @@ import { L1_ADDRESS_MAP } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/005_deploy_arbitrum_spokepool.ts b/deploy/005_deploy_arbitrum_spokepool.ts index 7263d0dfb..2c57160f1 100644 --- a/deploy/005_deploy_arbitrum_spokepool.ts +++ b/deploy/005_deploy_arbitrum_spokepool.ts @@ -1,33 +1,24 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L2_ADDRESS_MAP } from "./consts"; +import { deployNewProxy } from "../utils/utils.hre"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, companionNetworks, getChainId } = hre; - const { deploy } = deployments; - - const { deployer } = await getNamedAccounts(); - - // Grab L1 addresses: - const { deployments: l1Deployments } = companionNetworks.l1; - const hubPool = await l1Deployments.get("HubPool"); - console.log(`Using l1 hub pool @ ${hubPool.address}`); - - const chainId = parseInt(await getChainId()); +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - await deploy("Arbitrum_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [ - L2_ADDRESS_MAP[chainId].l2GatewayRouter, // _l2GatewayRouter - hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic. - hubPool.address, - L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth - "0x0000000000000000000000000000000000000000", // timer - ], - }); + // Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's + // with deprecated spoke pool. + // Set hub pool as cross domain admin since it delegatecalls the Adapter logic. + const constructorArgs = [ + 1_000_000, + L2_ADDRESS_MAP[chainId].l2GatewayRouter, + hubPool.address, + hubPool.address, + L2_ADDRESS_MAP[chainId].l2Weth, + ]; + await deployNewProxy("Arbitrum_SpokePool", constructorArgs); }; module.exports = func; func.tags = ["ArbitrumSpokePool", "arbitrum"]; diff --git a/deploy/006_deploy_ethereum_adapter.ts b/deploy/006_deploy_ethereum_adapter.ts index a2f740f2f..6815cd6a3 100644 --- a/deploy/006_deploy_ethereum_adapter.ts +++ b/deploy/006_deploy_ethereum_adapter.ts @@ -1,7 +1,7 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; diff --git a/deploy/007_deploy_ethereum_spokepool.ts b/deploy/007_deploy_ethereum_spokepool.ts index a5ed8594e..35ce7fa5d 100644 --- a/deploy/007_deploy_ethereum_spokepool.ts +++ b/deploy/007_deploy_ethereum_spokepool.ts @@ -1,25 +1,19 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; +import { deployNewProxy } from "../utils/utils.hre"; import { L1_ADDRESS_MAP } from "./consts"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, getChainId } = hre; - const { deploy } = deployments; - - const { deployer } = await getNamedAccounts(); - - const chainId = parseInt(await getChainId()); +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - const hubPool = await deployments.get("HubPool"); - console.log(`Using l1 hub pool @ ${hubPool.address}`); + // Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's + // with deprecated spoke pool. + const constructorArgs = [1_000_000, hubPool.address, L1_ADDRESS_MAP[chainId].weth]; + await deployNewProxy("Ethereum_SpokePool", constructorArgs); - await deploy("Ethereum_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [hubPool.address, L1_ADDRESS_MAP[chainId].weth, "0x0000000000000000000000000000000000000000"], - }); + // Transfer ownership to hub pool. }; module.exports = func; func.tags = ["EthereumSpokePool", "mainnet"]; diff --git a/deploy/008_deploy_polygon_token_bridger_mainnet.ts b/deploy/008_deploy_polygon_token_bridger_mainnet.ts index 45327bc32..46b337f93 100644 --- a/deploy/008_deploy_polygon_token_bridger_mainnet.ts +++ b/deploy/008_deploy_polygon_token_bridger_mainnet.ts @@ -1,9 +1,8 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L1_ADDRESS_MAP, POLYGON_CHAIN_IDS } from "./consts"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/009_deploy_polygon_adapter.ts b/deploy/009_deploy_polygon_adapter.ts index 7c5902299..f45d8e8cb 100644 --- a/deploy/009_deploy_polygon_adapter.ts +++ b/deploy/009_deploy_polygon_adapter.ts @@ -1,9 +1,8 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L1_ADDRESS_MAP } from "./consts"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/010_deploy_polygon_token_bridger_polygon.ts b/deploy/010_deploy_polygon_token_bridger_polygon.ts index 1b8cee2cc..9ebd8003d 100644 --- a/deploy/010_deploy_polygon_token_bridger_polygon.ts +++ b/deploy/010_deploy_polygon_token_bridger_polygon.ts @@ -1,9 +1,8 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L1_ADDRESS_MAP } from "./consts"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/011_deploy_polygon_spokepool.ts b/deploy/011_deploy_polygon_spokepool.ts index 46ae71ec5..9efa271be 100644 --- a/deploy/011_deploy_polygon_spokepool.ts +++ b/deploy/011_deploy_polygon_spokepool.ts @@ -1,33 +1,28 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L2_ADDRESS_MAP } from "./consts"; +import { deployNewProxy } from "../utils/utils.hre"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, getChainId } = hre; - const { deploy } = deployments; - - const { deployer } = await getNamedAccounts(); - - const chainId = parseInt(await getChainId()); - const l1HubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); - const polygonTokenBridger = await deployments.get("PolygonTokenBridger"); +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - await deploy("Polygon_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [ - polygonTokenBridger.address, - l1HubPool.address, - l1HubPool.address, - L2_ADDRESS_MAP[chainId].wMatic, - L2_ADDRESS_MAP[chainId].fxChild, - "0x0000000000000000000000000000000000000000", - ], - }); + // Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's + // with deprecated spoke pool. + // Set hub pool as cross domain admin since it delegatecalls the Adapter logic. + const constructorArgs = [ + 1_000_000, + // The same token bridger must be deployed on mainnet and polygon, so its easier + // to reuse it. + "0x0330E9b4D0325cCfF515E81DFbc7754F2a02ac57", + hubPool.address, + hubPool.address, + L2_ADDRESS_MAP[chainId].wMatic, + L2_ADDRESS_MAP[chainId].fxChild, + ]; + await deployNewProxy("Polygon_SpokePool", constructorArgs); }; module.exports = func; -func.dependencies = ["PolygonTokenBridgerL2"]; func.tags = ["PolygonSpokePool", "polygon"]; diff --git a/deploy/012_deploy_boba_adapter.ts b/deploy/012_deploy_boba_adapter.ts index c1ab12744..89154d530 100644 --- a/deploy/012_deploy_boba_adapter.ts +++ b/deploy/012_deploy_boba_adapter.ts @@ -1,9 +1,8 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; import { L1_ADDRESS_MAP } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/013_deploy_boba_spokepool.ts b/deploy/013_deploy_boba_spokepool.ts index 16f87b029..d6d2bb824 100644 --- a/deploy/013_deploy_boba_spokepool.ts +++ b/deploy/013_deploy_boba_spokepool.ts @@ -1,28 +1,17 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { deployNewProxy } from "../utils/utils.hre"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { deployments, getNamedAccounts, companionNetworks } = hre; - const { deploy } = deployments; +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - const { deployer } = await getNamedAccounts(); - - // Grab L1 addresses: - const { deployments: l1Deployments } = companionNetworks.l1; - const hubPool = await l1Deployments.get("HubPool"); - console.log(`Using l1 hub pool @ ${hubPool.address}`); - - // Boba Spoke pool uses the same implementation as optimism, with no changes. - await deploy("Boba_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [ - hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic. - hubPool.address, - "0x0000000000000000000000000000000000000000", // timer - ], - }); + // Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's + // with deprecated spoke pool. + // Set hub pool as cross domain admin since it delegatecalls the Adapter logic. + const constructorArgs = [1_000_000, hubPool.address, hubPool.address]; + await deployNewProxy("Boba_SpokePool", constructorArgs); }; module.exports = func; func.tags = ["BobaSpokePool", "boba"]; diff --git a/deploy/014_deploy_config_store.ts b/deploy/014_deploy_config_store.ts index 8ae023e14..64ad8ad44 100644 --- a/deploy/014_deploy_config_store.ts +++ b/deploy/014_deploy_config_store.ts @@ -1,7 +1,7 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; diff --git a/deploy/015_deploy_zksync_adapter.ts b/deploy/015_deploy_zksync_adapter.ts index a78b14db8..a5703e177 100644 --- a/deploy/015_deploy_zksync_adapter.ts +++ b/deploy/015_deploy_zksync_adapter.ts @@ -1,7 +1,7 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; diff --git a/deploy/016_deploy_zksync_spokepool.ts b/deploy/016_deploy_zksync_spokepool.ts index e75b29a3b..c4aecb251 100644 --- a/deploy/016_deploy_zksync_spokepool.ts +++ b/deploy/016_deploy_zksync_spokepool.ts @@ -1,34 +1,23 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - +import { DeployFunction } from "hardhat-deploy/types"; import { L2_ADDRESS_MAP } from "./consts"; +import { deployNewProxy } from "../utils/utils.hre"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { - const { companionNetworks, getChainId, getNamedAccounts, deployments } = hre; - const { deploy } = deployments; - - const { deployer } = await getNamedAccounts(); - - // Grab L1 addresses: - const { deployments: l1Deployments } = companionNetworks.l1; - const hubPool = await l1Deployments.get("HubPool"); - console.log(`Using l1 hub pool @ ${hubPool.address}`); - - const chainId = parseInt(await getChainId()); +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool"); + const chainId = await hre.getChainId(); + console.log(`Using L1 (chainId ${chainId}) hub pool @ ${hubPool.address}`); - await deploy("ZkSync_SpokePool", { - from: deployer, - log: true, - skipIfAlreadyDeployed: true, - args: [ - L2_ADDRESS_MAP[chainId].zkErc20Bridge, - L2_ADDRESS_MAP[chainId].zkEthBridge, - hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the ZkSync_Adapter logic. - hubPool.address, - L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth - "0x0000000000000000000000000000000000000000", // timer - ], - }); + // Set hub pool as cross domain admin since it delegatecalls the Adapter logic. + const constructorArgs = [ + 0, // Start at 0 since this first time we're deploying this spoke pool. On future upgrades increase this. + L2_ADDRESS_MAP[chainId].zkErc20Bridge, + L2_ADDRESS_MAP[chainId].zkEthBridge, + hubPool.address, + hubPool.address, + L2_ADDRESS_MAP[chainId].l2Weth, + ]; + await deployNewProxy("ZkSync_SpokePool", constructorArgs); }; module.exports = func; func.tags = ["ZkSyncSpokePool", "zksync"]; diff --git a/deploy/017_deploy_ethereum_merkle_distributor.ts b/deploy/017_deploy_ethereum_merkle_distributor.ts index b126c6d01..3ae0a60f2 100644 --- a/deploy/017_deploy_ethereum_merkle_distributor.ts +++ b/deploy/017_deploy_ethereum_merkle_distributor.ts @@ -1,7 +1,7 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; diff --git a/deploy/018_deploy_arbitrum_rescueadapter.ts b/deploy/018_deploy_arbitrum_rescueadapter.ts index a7f1ab21e..a7454dc73 100644 --- a/deploy/018_deploy_arbitrum_rescueadapter.ts +++ b/deploy/018_deploy_arbitrum_rescueadapter.ts @@ -1,9 +1,8 @@ import { L1_ADDRESS_MAP } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/019_deploy_bond_token.ts b/deploy/019_deploy_bond_token.ts index c3b92f9a8..5e5c7717c 100644 --- a/deploy/019_deploy_bond_token.ts +++ b/deploy/019_deploy_bond_token.ts @@ -1,7 +1,7 @@ -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deployer } = await getNamedAccounts(); diff --git a/deploy/020_deploy_arbitrum_sendtoken_adapter.ts b/deploy/020_deploy_arbitrum_sendtoken_adapter.ts index be3eac53b..9ae219825 100644 --- a/deploy/020_deploy_arbitrum_sendtoken_adapter.ts +++ b/deploy/020_deploy_arbitrum_sendtoken_adapter.ts @@ -1,9 +1,8 @@ import { L1_ADDRESS_MAP } from "./consts"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; -import "hardhat-deploy"; -import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; - -const func = async function (hre: HardhatRuntimeEnvironment) { +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts, getChainId } = hre; const { deploy } = deployments; diff --git a/deploy/021_deploy_erc1155.ts b/deploy/021_deploy_erc1155.ts new file mode 100644 index 000000000..039c9005a --- /dev/null +++ b/deploy/021_deploy_erc1155.ts @@ -0,0 +1,19 @@ +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts } = hre; + const { deploy } = deployments; + + const { deployer } = await getNamedAccounts(); + + await deploy("MintableERC1155", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + args: [], + }); +}; + +module.exports = func; +func.tags = ["MintableERC1155"]; diff --git a/deploy/022_upgrade_spokepool.ts b/deploy/022_upgrade_spokepool.ts new file mode 100644 index 000000000..f409fcadd --- /dev/null +++ b/deploy/022_upgrade_spokepool.ts @@ -0,0 +1,30 @@ +import { DeployFunction } from "hardhat-deploy/types"; +import { getContractFactory } from "../utils"; +import * as deployments from "../deployments/deployments.json"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { upgrades, run, getChainId, getNamedAccounts } = hre; + const { deployer } = await getNamedAccounts(); + + const chainId = await getChainId(); + const spokePool = await deployments[chainId].SpokePool; + console.log(`Using spoke pool @ ${spokePool.address}`); + + // Deploy new implementation and validate that it can be used in upgrade, without actually upgrading it. + const newImplementation = await upgrades.prepareUpgrade( + spokePool.address, + await getContractFactory("Ethereum_SpokePool", deployer) + ); + console.log(`Can upgrade to new implementation @ ${newImplementation}`); + + // hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed + // is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy + // to the implementation's ABI on etherscan. + // https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify + await run("verify:verify", { + address: newImplementation, + }); +}; +module.exports = func; +func.tags = ["UpgradeSpokePool"]; diff --git a/deployments/deployments.json b/deployments/deployments.json index 2c506a823..abac68a23 100644 --- a/deployments/deployments.json +++ b/deployments/deployments.json @@ -6,7 +6,7 @@ "Arbitrum_SendTokensAdapter": { "address": "0xC06A68DF12376271817FcEBfb45Be996B0e1593E", "blockNumber": 16691987 }, "Boba_Adapter": { "address": "0x33B0Ec794c15D6Cc705818E70d4CaCe7bCfB5Af3", "blockNumber": 14716798 }, "Ethereum_Adapter": { "address": "0x527E872a5c3f0C7c24Fe33F2593cFB890a285084", "blockNumber": 14704381 }, - "SpokePool": { "address": "0x4D9079Bb4165aeb4084c526a32695dCfd2F77381", "blockNumber": 14819486 }, + "SpokePool": { "address": "0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5", "blockNumber": 17117454 }, "HubPool": { "address": "0xc186fA914353c44b2E33eBE05f21846F1048bEda", "blockNumber": 14819537 }, "LpTokenFactory": { "address": "0x7dB69eb9F52eD773E9b03f5068A1ea0275b2fD9d", "blockNumber": 14704307 }, "Optimism_Adapter": { "address": "0x22eD83A9eE26236486F57cE8385A247E5bFB71fF", "blockNumber": 14704379 }, @@ -25,15 +25,16 @@ "RateModelStore": { "address": "0x18a200A2427e243154EC8217890Bc08062afc5A2", "blockNumber": 10468968 } }, "5": { + "AcrossConfigStore": { "address": "0x122f64FC33366B801e009b9cCa80233aE9eBE5a3", "blockNumber": 8824980 }, "AcrossMerkleDistributor": { "address": "0xF633b72A4C2Fb73b77A379bf72864A825aD35b6D", "blockNumber": 7884371 }, - "Arbitrum_Adapter": { "address": "0xc169D58df5fdF52fC47d7b67d570449feE47BfE9", "blockNumber": 7306652 }, + "Arbitrum_Adapter": { "address": "0xDaF8d1326ECf17C46661D5852Ea74b420F9368Af", "blockNumber": 8842165 }, "Ethereum_Adapter": { "address": "0x7b1D5aEA5b1b8C325711AA4b4AaAacD5E1ea1994", "blockNumber": 7371150 }, - "SpokePool": { "address": "0xEc88d3C08E2939562Ff8188B4e30A52236C3FF09", "blockNumber": 7371157 }, + "SpokePool": { "address": "0x063fFa6C9748e3f0b9bA8ee3bbbCEe98d92651f7", "blockNumber": 8825017 }, "HubPool": { "address": "0x0e2817C49698cc0874204AeDf7c72Be2Bb7fCD5d", "blockNumber": 7370152 }, "LpTokenFactory": { "address": "0xD4B978681B55A94CF44a21ac9B1352e641D0838C", "blockNumber": 7370151 }, "ZkSync_Adapter": { "address": "0xAEED2E2FB1EFDc5aD10A7FB4d6bA6D71ce8aFA1F", "blockNumber": 7375174 } }, - "10": { "SpokePool": { "address": "0xa420b2d1c0841415A695b81E5B867BCD07Dff8C9", "blockNumber": 8747136 } }, + "10": { "SpokePool": { "address": "0x6f26Bf09B1C792e3228e5467807a900A503c0281", "blockNumber": 93903076 } }, "42": { "AcrossConfigStore": { "address": "0xDd74f7603e3fDA6435aEc91F8960a6b8b40415f3", "blockNumber": 31457380 }, "Ethereum_Adapter": { "address": "0x5b0539e0ED5273604bf13b4A30050d475E586a64", "blockNumber": 31457390 }, @@ -44,16 +45,18 @@ }, "69": { "SpokePool": { "address": "0x1954D4A36ac4fD8BEde42E59368565A92290E705", "blockNumber": 2537971 } }, "137": { + "MintableERC1155": { "address": "0xA15a90E7936A2F8B70E181E955760860D133e56B", "blockNumber": 40600414 }, "PolygonTokenBridger": { "address": "0x0330E9b4D0325cCfF515E81DFbc7754F2a02ac57", "blockNumber": 28604258 }, - "SpokePool": { "address": "0x69B5c72837769eF1e7C164Abc6515DcFf217F920", "blockNumber": 28604263 } + "SpokePool": { "address": "0x9295ee1d8C5b022Be115A2AD3c30C72E34e7F096", "blockNumber": 41908657 } }, "280": { "SpokePool": { "address": "0x467A26E2eAcf5f81b63016Dbb4F0828809e79fF5", "blockNumber": 1114933 } }, "288": { "SpokePool": { "address": "0xBbc6009fEfFc27ce705322832Cb2068F8C1e0A58", "blockNumber": 619993 } }, - "42161": { "SpokePool": { "address": "0xB88690461dDbaB6f04Dfad7df66B7725942FEb9C", "blockNumber": 12741972 } }, + "42161": { "SpokePool": { "address": "0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A", "blockNumber": 83868041 } }, "80001": { + "MintableERC1155": { "address": "0xe377d7C510fEbc64525f480e33306b21b30066F7", "blockNumber": 33352305 }, "PolygonTokenBridger": { "address": "0x97f102f2f73717e203f964Ad9940e4C2e79b8597", "blockNumber": 26276246 }, "SpokePool": { "address": "0x45fF03629D024b7763275e732a2d80202c18b31C", "blockNumber": 26276253 } }, "421611": { "SpokePool": { "address": "0x3BED21dAe767e4Df894B31b14aD32369cE4bad8b", "blockNumber": 10523275 } }, - "421613": { "SpokePool": { "address": "0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96", "blockNumber": 10698 } } + "421613": { "SpokePool": { "address": "0xD29C85F15DF544bA632C9E25829fd29d767d7978", "blockNumber": 16711650 } } } diff --git a/deployments/goerli/AcrossConfigStore.json b/deployments/goerli/AcrossConfigStore.json new file mode 100644 index 000000000..938dc2bca --- /dev/null +++ b/deployments/goerli/AcrossConfigStore.json @@ -0,0 +1,325 @@ +{ + "address": "0x122f64FC33366B801e009b9cCa80233aE9eBE5a3", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "UpdatedGlobalConfig", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "key", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "UpdatedTokenConfig", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "globalConfig", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1TokenConfig", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "updateGlobalConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "updateTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xef29c625bf4f3898d1812b90a88b17ea79de893f0ca77e1633ac9b5891354542", + "receipt": { + "to": null, + "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", + "contractAddress": "0x122f64FC33366B801e009b9cCa80233aE9eBE5a3", + "transactionIndex": 39, + "gasUsed": "959723", + "logsBloom": "0x00000000000008000000000000000004000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000040000400000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x835a68816b03fb1f0df28a23858fd3432c302c6b627010449febfcb41c88844c", + "transactionHash": "0xef29c625bf4f3898d1812b90a88b17ea79de893f0ca77e1633ac9b5891354542", + "logs": [ + { + "transactionIndex": 39, + "blockNumber": 8824980, + "transactionHash": "0xef29c625bf4f3898d1812b90a88b17ea79de893f0ca77e1633ac9b5891354542", + "address": "0x122f64FC33366B801e009b9cCa80233aE9eBE5a3", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009a8f92a830a5cb89a3816e3d267cb7791c16b04d" + ], + "data": "0x", + "logIndex": 81, + "blockHash": "0x835a68816b03fb1f0df28a23858fd3432c302c6b627010449febfcb41c88844c" + } + ], + "blockNumber": 8824980, + "cumulativeGasUsed": "6734102", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "e3638a53e1e5b7b0c7a6b5bbdc94b1ad", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"UpdatedGlobalConfig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"key\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"UpdatedTokenConfig\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"globalConfig\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1TokenConfig\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"updateGlobalConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"updateTokenConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract should not perform any validation on the setting values and should be owned by the governance system of the full contract suite..\",\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"updateGlobalConfig(bytes32,string)\":{\"params\":{\"key\":\"Key to update.\",\"value\":\"Value to update.\"}},\"updateTokenConfig(address,string)\":{\"params\":{\"l1Token\":\"the l1 token address to update value for.\",\"value\":\"Value to update.\"}}},\"title\":\"Allows admin to set and update configuration settings for full contract system. These settings are designed to be consumed by off-chain bots, rather than by other contracts.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"updateGlobalConfig(bytes32,string)\":{\"notice\":\"Updates global config.\"},\"updateTokenConfig(address,string)\":{\"notice\":\"Updates token config.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/AcrossConfigStore.sol\":\"AcrossConfigStore\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@uma/core/contracts/common/implementation/MultiCaller.sol\":{\"content\":\"// This contract is taken from Uniswap's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol)\\n// and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value\\n// set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits.\\npragma solidity ^0.8.0;\\n\\n/// @title MultiCaller\\n/// @notice Enables calling multiple methods in a single call to the contract\\ncontract MultiCaller {\\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results) {\\n require(msg.value == 0, \\\"Only multicall with 0 value\\\");\\n results = new bytes[](data.length);\\n for (uint256 i = 0; i < data.length; i++) {\\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\\n\\n if (!success) {\\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\\n if (result.length < 68) revert();\\n assembly {\\n result := add(result, 0x04)\\n }\\n revert(abi.decode(result, (string)));\\n }\\n\\n results[i] = result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbd4b1690b7d56f2fd7b61f3b9022c6b856c7dfee5a5aca547cf1403b906fdc0d\"},\"contracts/AcrossConfigStore.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity ^0.8.0;\\n\\nimport \\\"@uma/core/contracts/common/implementation/MultiCaller.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Allows admin to set and update configuration settings for full contract system. These settings are designed\\n * to be consumed by off-chain bots, rather than by other contracts.\\n * @dev This contract should not perform any validation on the setting values and should be owned by the governance\\n * system of the full contract suite..\\n */\\ncontract AcrossConfigStore is Ownable, MultiCaller {\\n // General dictionary where admin can associate variables with specific L1 tokens, like the Rate Model and Token\\n // Transfer Thresholds.\\n mapping(address => string) public l1TokenConfig;\\n\\n // General dictionary where admin can store global variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and\\n // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query.\\n mapping(bytes32 => string) public globalConfig;\\n\\n event UpdatedTokenConfig(address indexed key, string value);\\n event UpdatedGlobalConfig(bytes32 indexed key, string value);\\n\\n /**\\n * @notice Updates token config.\\n * @param l1Token the l1 token address to update value for.\\n * @param value Value to update.\\n */\\n function updateTokenConfig(address l1Token, string memory value) external onlyOwner {\\n l1TokenConfig[l1Token] = value;\\n emit UpdatedTokenConfig(l1Token, value);\\n }\\n\\n /**\\n * @notice Updates global config.\\n * @param key Key to update.\\n * @param value Value to update.\\n */\\n function updateGlobalConfig(bytes32 key, string calldata value) external onlyOwner {\\n globalConfig[key] = value;\\n emit UpdatedGlobalConfig(key, value);\\n }\\n}\\n\",\"keccak256\":\"0xacaa65ede2dcee0a24fd5d9940914c364be7e988f89cdaea1386e0474d51f6f7\",\"license\":\"AGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080806040523461005b5760008054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a361100090816100618239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c90816350fbbd011461009a57508063715018a6146100955780638098b875146100905780638da5cb5b1461008b5780639fdd403a14610086578063ac9650d814610081578063e5e818ae1461007c5763f2fde38b1461007757600080fd5b610926565b610729565b6105e0565b610502565b6104b0565b610413565b61033c565b3461010d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010d576100fd60406101099273ffffffffffffffffffffffffffffffffffffffff6100ef610110565b168152600160205220610200565b6040519182918261032b565b0390f35b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361013357565b600080fd5b90600182811c92168015610181575b602083101461015257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691610147565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176101fb57604052565b61018b565b6040519081600082549261021384610138565b9081845260019485811690816000146102835750600114610240575b505061023d925003826101ba565b90565b9093915060005260209081600020936000915b81831061026b57505061023d9350820101388061022f565b85548784018501529485019486945091830191610253565b905061023d9550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b820101388061022f565b60005b8381106102d85750506000910152565b81810151838201526020016102c8565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093610324815180928187528780880191016102c5565b0116010190565b90602061023d9281815201906102e8565b34610133576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010d57610374610a5b565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b67ffffffffffffffff81116101fb57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b346101335760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335761044a610110565b6024359067ffffffffffffffff8211610133573660238301121561013357816004013590610477826103d9565b9161048560405193846101ba565b80835236602482860101116101335760208160009260246104ae97018387013784010152610d5f565b005b346101335760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101335760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013357600435600052600260205261010961054c6040600020610200565b6040519182916020835260208301906102e8565b602080820190808352835180925260408301928160408460051b8301019501936000915b8483106105945750505050505090565b90919293949584806105d0837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516102e8565b9801930193019194939290610584565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610133576004803567ffffffffffffffff918282116101335736602383011215610133578181013592831161013357602490818301928236918660051b010111610133576106543415610ada565b61065d84610b57565b9360005b81811061067657604051806101098882610560565b600080610684838589610c49565b60409391610696855180938193610cae565b0390305af4906106a4610cbc565b918290156106d3575050906106ce916106bd8289610d4b565b526106c88188610d4b565b50610bbe565b610661565b868387926044825110610133578261072593856106f69401518301019101610cec565b92519283927f08c379a0000000000000000000000000000000000000000000000000000000008452830161032b565b0390fd5b346101335760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335767ffffffffffffffff600435602480358381116101335736602382011215610133578060040135938411610133573682858301011161013357610799610a5b565b60009383855260206002815260408620906107be836107b88454610138565b84610f30565b8690601f841160011461085157509161083e9181867f84c11a81ce8e8060e814e03c4606fe325e7a24ecc22ef7001254e27de3762f499796958a92610844575b50508260011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8460031b1c19161790555b6040519384930183610f84565b0390a280f35b86010135905085386107fe565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841661088484600052602060002090565b9289905b82821061090c5750509161083e9391857f84c11a81ce8e8060e814e03c4606fe325e7a24ecc22ef7001254e27de3762f4998979694106108d2575b5050600182811b019055610831565b867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19918701013516905538806108c3565b80600185968b8395978c0101358155019501930190610888565b346101335760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335761095d610110565b610965610a5b565b73ffffffffffffffffffffffffffffffffffffffff80911680156109d7576000918254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff600054163303610a7c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15610ae157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4f6e6c79206d756c746963616c6c207769746820302076616c756500000000006044820152fd5b67ffffffffffffffff81116101fb5760051b60200190565b90610b6182610b3f565b610b6e60405191826101ba565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610b9c8294610b3f565b019060005b828110610bad57505050565b806060602080938501015201610ba1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610beb5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9190811015610ca95760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561013357019081359167ffffffffffffffff8311610133576020018236038113610133579190565b610c1a565b908092918237016000815290565b3d15610ce7573d90610ccd826103d9565b91610cdb60405193846101ba565b82523d6000602084013e565b606090565b6020818303126101335780519067ffffffffffffffff8211610133570181601f82011215610133578051610d1f816103d9565b92610d2d60405194856101ba565b818452602082840101116101335761023d91602080850191016102c5565b8051821015610ca95760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff90610d7d610a5b565b1690816000526001602081815260406000209183519167ffffffffffffffff83116101fb57610db683610db08654610138565b86610f30565b80601f8411600114610e61575091610e31939181807f2170feb790d9bf809ba50947096322ec651593149b6f78e673e51c1c67cfe3fd9795600092610e36575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91921b9260031b1c19161790556040519182918261032b565b0390a2565b86015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610df6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084939416610e9686600052602060002090565b926000905b828210610f19575050918391610e3196947f2170feb790d9bf809ba50947096322ec651593149b6f78e673e51c1c67cfe3fd98969410610ee2575b5050811b0190556100fd565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880610ed6565b808785968294968c01518155019501930190610e9b565b90601f8111610f3e57505050565b600091825260208220906020601f850160051c83019410610f7a575b601f0160051c01915b828110610f6f57505050565b818155600101610f63565b9092508290610f5a565b90601f836040947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09360208652816020870152868601376000858286010152011601019056fea26469706673582212203c05d8358a45c791a110df40ff71f94d279750050c70155a559409bceaabc4ae64736f6c63430008120033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c90816350fbbd011461009a57508063715018a6146100955780638098b875146100905780638da5cb5b1461008b5780639fdd403a14610086578063ac9650d814610081578063e5e818ae1461007c5763f2fde38b1461007757600080fd5b610926565b610729565b6105e0565b610502565b6104b0565b610413565b61033c565b3461010d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010d576100fd60406101099273ffffffffffffffffffffffffffffffffffffffff6100ef610110565b168152600160205220610200565b6040519182918261032b565b0390f35b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361013357565b600080fd5b90600182811c92168015610181575b602083101461015257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691610147565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176101fb57604052565b61018b565b6040519081600082549261021384610138565b9081845260019485811690816000146102835750600114610240575b505061023d925003826101ba565b90565b9093915060005260209081600020936000915b81831061026b57505061023d9350820101388061022f565b85548784018501529485019486945091830191610253565b905061023d9550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b820101388061022f565b60005b8381106102d85750506000910152565b81810151838201526020016102c8565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093610324815180928187528780880191016102c5565b0116010190565b90602061023d9281815201906102e8565b34610133576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010d57610374610a5b565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b67ffffffffffffffff81116101fb57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b346101335760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335761044a610110565b6024359067ffffffffffffffff8211610133573660238301121561013357816004013590610477826103d9565b9161048560405193846101ba565b80835236602482860101116101335760208160009260246104ae97018387013784010152610d5f565b005b346101335760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346101335760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013357600435600052600260205261010961054c6040600020610200565b6040519182916020835260208301906102e8565b602080820190808352835180925260408301928160408460051b8301019501936000915b8483106105945750505050505090565b90919293949584806105d0837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516102e8565b9801930193019194939290610584565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610133576004803567ffffffffffffffff918282116101335736602383011215610133578181013592831161013357602490818301928236918660051b010111610133576106543415610ada565b61065d84610b57565b9360005b81811061067657604051806101098882610560565b600080610684838589610c49565b60409391610696855180938193610cae565b0390305af4906106a4610cbc565b918290156106d3575050906106ce916106bd8289610d4b565b526106c88188610d4b565b50610bbe565b610661565b868387926044825110610133578261072593856106f69401518301019101610cec565b92519283927f08c379a0000000000000000000000000000000000000000000000000000000008452830161032b565b0390fd5b346101335760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335767ffffffffffffffff600435602480358381116101335736602382011215610133578060040135938411610133573682858301011161013357610799610a5b565b60009383855260206002815260408620906107be836107b88454610138565b84610f30565b8690601f841160011461085157509161083e9181867f84c11a81ce8e8060e814e03c4606fe325e7a24ecc22ef7001254e27de3762f499796958a92610844575b50508260011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8460031b1c19161790555b6040519384930183610f84565b0390a280f35b86010135905085386107fe565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841661088484600052602060002090565b9289905b82821061090c5750509161083e9391857f84c11a81ce8e8060e814e03c4606fe325e7a24ecc22ef7001254e27de3762f4998979694106108d2575b5050600182811b019055610831565b867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19918701013516905538806108c3565b80600185968b8395978c0101358155019501930190610888565b346101335760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101335761095d610110565b610965610a5b565b73ffffffffffffffffffffffffffffffffffffffff80911680156109d7576000918254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff600054163303610a7c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15610ae157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4f6e6c79206d756c746963616c6c207769746820302076616c756500000000006044820152fd5b67ffffffffffffffff81116101fb5760051b60200190565b90610b6182610b3f565b610b6e60405191826101ba565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610b9c8294610b3f565b019060005b828110610bad57505050565b806060602080938501015201610ba1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610beb5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9190811015610ca95760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561013357019081359167ffffffffffffffff8311610133576020018236038113610133579190565b610c1a565b908092918237016000815290565b3d15610ce7573d90610ccd826103d9565b91610cdb60405193846101ba565b82523d6000602084013e565b606090565b6020818303126101335780519067ffffffffffffffff8211610133570181601f82011215610133578051610d1f816103d9565b92610d2d60405194856101ba565b818452602082840101116101335761023d91602080850191016102c5565b8051821015610ca95760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff90610d7d610a5b565b1690816000526001602081815260406000209183519167ffffffffffffffff83116101fb57610db683610db08654610138565b86610f30565b80601f8411600114610e61575091610e31939181807f2170feb790d9bf809ba50947096322ec651593149b6f78e673e51c1c67cfe3fd9795600092610e36575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91921b9260031b1c19161790556040519182918261032b565b0390a2565b86015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610df6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084939416610e9686600052602060002090565b926000905b828210610f19575050918391610e3196947f2170feb790d9bf809ba50947096322ec651593149b6f78e673e51c1c67cfe3fd98969410610ee2575b5050811b0190556100fd565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880610ed6565b808785968294968c01518155019501930190610e9b565b90601f8111610f3e57505050565b600091825260208220906020601f850160051c83019410610f7a575b601f0160051c01915b828110610f6f57505050565b818155600101610f63565b9092508290610f5a565b90601f836040947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09360208652816020870152868601376000858286010152011601019056fea26469706673582212203c05d8358a45c791a110df40ff71f94d279750050c70155a559409bceaabc4ae64736f6c63430008120033", + "devdoc": { + "details": "This contract should not perform any validation on the setting values and should be owned by the governance system of the full contract suite..", + "kind": "dev", + "methods": { + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "updateGlobalConfig(bytes32,string)": { + "params": { + "key": "Key to update.", + "value": "Value to update." + } + }, + "updateTokenConfig(address,string)": { + "params": { + "l1Token": "the l1 token address to update value for.", + "value": "Value to update." + } + } + }, + "title": "Allows admin to set and update configuration settings for full contract system. These settings are designed to be consumed by off-chain bots, rather than by other contracts.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "updateGlobalConfig(bytes32,string)": { + "notice": "Updates global config." + }, + "updateTokenConfig(address,string)": { + "notice": "Updates token config." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4154, + "contract": "contracts/AcrossConfigStore.sol:AcrossConfigStore", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 12748, + "contract": "contracts/AcrossConfigStore.sol:AcrossConfigStore", + "label": "l1TokenConfig", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_string_storage)" + }, + { + "astId": 12752, + "contract": "contracts/AcrossConfigStore.sol:AcrossConfigStore", + "label": "globalConfig", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_string_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_string_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_bytes32,t_string_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/goerli/solcInputs/e3638a53e1e5b7b0c7a6b5bbdc94b1ad.json b/deployments/goerli/solcInputs/e3638a53e1e5b7b0c7a6b5bbdc94b1ad.json new file mode 100644 index 000000000..c1ab45cfb --- /dev/null +++ b/deployments/goerli/solcInputs/e3638a53e1e5b7b0c7a6b5bbdc94b1ad.json @@ -0,0 +1,358 @@ +{ + "language": "Solidity", + "sources": { + "contracts/AcrossConfigStore.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/common/implementation/MultiCaller.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Allows admin to set and update configuration settings for full contract system. These settings are designed\n * to be consumed by off-chain bots, rather than by other contracts.\n * @dev This contract should not perform any validation on the setting values and should be owned by the governance\n * system of the full contract suite..\n */\ncontract AcrossConfigStore is Ownable, MultiCaller {\n // General dictionary where admin can associate variables with specific L1 tokens, like the Rate Model and Token\n // Transfer Thresholds.\n mapping(address => string) public l1TokenConfig;\n\n // General dictionary where admin can store global variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and\n // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query.\n mapping(bytes32 => string) public globalConfig;\n\n event UpdatedTokenConfig(address indexed key, string value);\n event UpdatedGlobalConfig(bytes32 indexed key, string value);\n\n /**\n * @notice Updates token config.\n * @param l1Token the l1 token address to update value for.\n * @param value Value to update.\n */\n function updateTokenConfig(address l1Token, string memory value) external onlyOwner {\n l1TokenConfig[l1Token] = value;\n emit UpdatedTokenConfig(l1Token, value);\n }\n\n /**\n * @notice Updates global config.\n * @param key Key to update.\n * @param value Value to update.\n */\n function updateGlobalConfig(bytes32 key, string calldata value) external onlyOwner {\n globalConfig[key] = value;\n emit UpdatedGlobalConfig(key, value);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/MultiCaller.sol": { + "content": "// This contract is taken from Uniswap's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol)\n// and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value\n// set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits.\npragma solidity ^0.8.0;\n\n/// @title MultiCaller\n/// @notice Enables calling multiple methods in a single call to the contract\ncontract MultiCaller {\n function multicall(bytes[] calldata data) external payable returns (bytes[] memory results) {\n require(msg.value == 0, \"Only multicall with 0 value\");\n results = new bytes[](data.length);\n for (uint256 i = 0; i < data.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./MerkleDistributorInterface.sol\";\n\n/**\n * Inspired by:\n * - https://github.com/pie-dao/vested-token-migration-app\n * - https://github.com/Uniswap/merkle-distributor\n * - https://github.com/balancer-labs/erc20-redeemable\n *\n * @title MerkleDistributor contract.\n * @notice Allows an owner to distribute any reward ERC20 to claimants according to Merkle roots. The owner can specify\n * multiple Merkle roots distributions with customized reward currencies.\n * @dev The Merkle trees are not validated in any way, so the system assumes the contract owner behaves honestly.\n */\ncontract MerkleDistributor is MerkleDistributorInterface, Ownable {\n using SafeERC20 for IERC20;\n\n // Windows are mapped to arbitrary indices.\n mapping(uint256 => Window) public merkleWindows;\n\n // Index of next created Merkle root.\n uint256 public nextCreatedIndex;\n\n // Track which accounts have claimed for each window index.\n // Note: uses a packed array of bools for gas optimization on tracking certain claims. Copied from Uniswap's contract.\n mapping(uint256 => mapping(uint256 => uint256)) private claimedBitMap;\n\n /****************************************\n * EVENTS\n ****************************************/\n event Claimed(\n address indexed caller,\n uint256 windowIndex,\n address indexed account,\n uint256 accountIndex,\n uint256 amount,\n address indexed rewardToken\n );\n event CreatedWindow(\n uint256 indexed windowIndex,\n uint256 rewardsDeposited,\n address indexed rewardToken,\n address owner\n );\n event WithdrawRewards(address indexed owner, uint256 amount, address indexed currency);\n event DeleteWindow(uint256 indexed windowIndex, address owner);\n\n /****************************\n * ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Set merkle root for the next available window index and seed allocations.\n * @notice Callable only by owner of this contract. Caller must have approved this contract to transfer\n * `rewardsToDeposit` amount of `rewardToken` or this call will fail. Importantly, we assume that the\n * owner of this contract correctly chooses an amount `rewardsToDeposit` that is sufficient to cover all\n * claims within the `merkleRoot`.\n * @param rewardsToDeposit amount of rewards to deposit to seed this allocation.\n * @param rewardToken ERC20 reward token.\n * @param merkleRoot merkle root describing allocation.\n * @param ipfsHash hash of IPFS object, conveniently stored for clients\n */\n function setWindow(\n uint256 rewardsToDeposit,\n address rewardToken,\n bytes32 merkleRoot,\n string calldata ipfsHash\n ) external onlyOwner {\n uint256 indexToSet = nextCreatedIndex;\n nextCreatedIndex = indexToSet + 1;\n\n _setWindow(indexToSet, rewardsToDeposit, rewardToken, merkleRoot, ipfsHash);\n }\n\n /**\n * @notice Delete merkle root at window index.\n * @dev Callable only by owner. Likely to be followed by a withdrawRewards call to clear contract state.\n * @param windowIndex merkle root index to delete.\n */\n function deleteWindow(uint256 windowIndex) external onlyOwner {\n delete merkleWindows[windowIndex];\n emit DeleteWindow(windowIndex, msg.sender);\n }\n\n /**\n * @notice Emergency method that transfers rewards out of the contract if the contract was configured improperly.\n * @dev Callable only by owner.\n * @param rewardCurrency rewards to withdraw from contract.\n * @param amount amount of rewards to withdraw.\n */\n function withdrawRewards(IERC20 rewardCurrency, uint256 amount) external onlyOwner {\n rewardCurrency.safeTransfer(msg.sender, amount);\n emit WithdrawRewards(msg.sender, amount, address(rewardCurrency));\n }\n\n /****************************\n * NON-ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Batch claims to reduce gas versus individual submitting all claims. Method will fail\n * if any individual claims within the batch would fail.\n * @dev Optimistically tries to batch together consecutive claims for the same account and same\n * reward token to reduce gas. Therefore, the most gas-cost-optimal way to use this method\n * is to pass in an array of claims sorted by account and reward currency. It also reverts\n * when any of individual `_claim`'s `amount` exceeds `remainingAmount` for its window.\n * @param claims array of claims to claim.\n */\n function claimMulti(Claim[] memory claims) public virtual override {\n uint256 batchedAmount;\n uint256 claimCount = claims.length;\n for (uint256 i = 0; i < claimCount; i++) {\n Claim memory _claim = claims[i];\n _verifyAndMarkClaimed(_claim);\n batchedAmount += _claim.amount;\n\n // If the next claim is NOT the same account or the same token (or this claim is the last one),\n // then disburse the `batchedAmount` to the current claim's account for the current claim's reward token.\n uint256 nextI = i + 1;\n IERC20 currentRewardToken = merkleWindows[_claim.windowIndex].rewardToken;\n if (\n nextI == claimCount ||\n // This claim is last claim.\n claims[nextI].account != _claim.account ||\n // Next claim account is different than current one.\n merkleWindows[claims[nextI].windowIndex].rewardToken != currentRewardToken\n // Next claim reward token is different than current one.\n ) {\n currentRewardToken.safeTransfer(_claim.account, batchedAmount);\n batchedAmount = 0;\n }\n }\n }\n\n /**\n * @notice Claim amount of reward tokens for account, as described by Claim input object.\n * @dev If the `_claim`'s `amount`, `accountIndex`, and `account` do not exactly match the\n * values stored in the merkle root for the `_claim`'s `windowIndex` this method\n * will revert. It also reverts when `_claim`'s `amount` exceeds `remainingAmount` for the window.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n */\n function claim(Claim memory _claim) public virtual override {\n _verifyAndMarkClaimed(_claim);\n merkleWindows[_claim.windowIndex].rewardToken.safeTransfer(_claim.account, _claim.amount);\n }\n\n /**\n * @notice Returns True if the claim for `accountIndex` has already been completed for the Merkle root at\n * `windowIndex`.\n * @dev This method will only work as intended if all `accountIndex`'s are unique for a given `windowIndex`.\n * The onus is on the Owner of this contract to submit only valid Merkle roots.\n * @param windowIndex merkle root to check.\n * @param accountIndex account index to check within window index.\n * @return True if claim has been executed already, False otherwise.\n */\n function isClaimed(uint256 windowIndex, uint256 accountIndex) public view returns (bool) {\n uint256 claimedWordIndex = accountIndex / 256;\n uint256 claimedBitIndex = accountIndex % 256;\n uint256 claimedWord = claimedBitMap[windowIndex][claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n /**\n * @notice Returns rewardToken set by admin for windowIndex.\n * @param windowIndex merkle root to check.\n * @return address Reward token address\n */\n function getRewardTokenForWindow(uint256 windowIndex) public view override returns (address) {\n return address(merkleWindows[windowIndex].rewardToken);\n }\n\n /**\n * @notice Returns True if leaf described by {account, amount, accountIndex} is stored in Merkle root at given\n * window index.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n * @return valid True if leaf exists.\n */\n function verifyClaim(Claim memory _claim) public view returns (bool valid) {\n bytes32 leaf = keccak256(abi.encodePacked(_claim.account, _claim.amount, _claim.accountIndex));\n return MerkleProof.verify(_claim.merkleProof, merkleWindows[_claim.windowIndex].merkleRoot, leaf);\n }\n\n /****************************\n * PRIVATE FUNCTIONS\n ****************************/\n\n // Mark claim as completed for `accountIndex` for Merkle root at `windowIndex`.\n function _setClaimed(uint256 windowIndex, uint256 accountIndex) private {\n uint256 claimedWordIndex = accountIndex / 256;\n uint256 claimedBitIndex = accountIndex % 256;\n claimedBitMap[windowIndex][claimedWordIndex] =\n claimedBitMap[windowIndex][claimedWordIndex] |\n (1 << claimedBitIndex);\n }\n\n // Store new Merkle root at `windowindex`. Pull `rewardsDeposited` from caller to seed distribution for this root.\n function _setWindow(\n uint256 windowIndex,\n uint256 rewardsDeposited,\n address rewardToken,\n bytes32 merkleRoot,\n string memory ipfsHash\n ) private {\n Window storage window = merkleWindows[windowIndex];\n window.merkleRoot = merkleRoot;\n window.remainingAmount = rewardsDeposited;\n window.rewardToken = IERC20(rewardToken);\n window.ipfsHash = ipfsHash;\n\n emit CreatedWindow(windowIndex, rewardsDeposited, rewardToken, msg.sender);\n\n window.rewardToken.safeTransferFrom(msg.sender, address(this), rewardsDeposited);\n }\n\n // Verify claim is valid and mark it as completed in this contract.\n function _verifyAndMarkClaimed(Claim memory _claim) internal {\n // Check claimed proof against merkle window at given index.\n require(verifyClaim(_claim), \"Incorrect merkle proof\");\n // Check the account has not yet claimed for this window.\n require(!isClaimed(_claim.windowIndex, _claim.accountIndex), \"Account has already claimed for this window\");\n\n // Proof is correct and claim has not occurred yet, mark claimed complete.\n _setClaimed(_claim.windowIndex, _claim.accountIndex);\n merkleWindows[_claim.windowIndex].remainingAmount -= _claim.amount;\n emit Claimed(\n msg.sender,\n _claim.windowIndex,\n _claim.account,\n _claim.accountIndex,\n _claim.amount,\n address(merkleWindows[_claim.windowIndex].rewardToken)\n );\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(\n bytes32[] calldata proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`,\n * consuming from one or the other at each step according to the instructions given by\n * `proofFlags`.\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributorInterface.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Concise list of functions in MerkleDistributor implementation that would be called by\n * a consuming external contract (such as the Across Protocol's AcceleratingDistributor).\n */\ninterface MerkleDistributorInterface {\n // A Window maps a Merkle root to a reward token address.\n struct Window {\n // Merkle root describing the distribution.\n bytes32 merkleRoot;\n // Remaining amount of deposited rewards that have not yet been claimed.\n uint256 remainingAmount;\n // Currency in which reward is processed.\n IERC20 rewardToken;\n // IPFS hash of the merkle tree. Can be used to independently fetch recipient proofs and tree. Note that the canonical\n // data type for storing an IPFS hash is a multihash which is the concatenation of \n // . We opted to store this in a string type to make it easier\n // for users to query the ipfs data without needing to reconstruct the multihash. to view the IPFS data simply\n // go to https://cloudflare-ipfs.com/ipfs/.\n string ipfsHash;\n }\n\n // Represents an account's claim for `amount` within the Merkle root located at the `windowIndex`.\n struct Claim {\n uint256 windowIndex;\n uint256 amount;\n uint256 accountIndex; // Used only for bitmap. Assumed to be unique for each claim.\n address account;\n bytes32[] merkleProof;\n }\n\n function claim(Claim memory _claim) external;\n\n function claimMulti(Claim[] memory claims) external;\n\n function getRewardTokenForWindow(uint256 windowIndex) external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../Address.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n if (error == ECDSA.RecoverError.NoError && recovered == signer) {\n return true;\n }\n\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length == 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1271.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/test/MockERC1271.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title MockERC1271\n * @notice Implements mocked ERC1271 contract for testing.\n */\ncontract MockERC1271 is IERC1271, Ownable {\n constructor(address originalOwner) {\n transferOwnership(originalOwner);\n }\n\n function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4 magicValue) {\n return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0);\n }\n}\n" + }, + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\n/**\n * @title MintableERC1155\n * @notice Ownable contract enabling owner to airdrop many recipients the same token ID at once\n */\ncontract MintableERC1155 is ERC1155, Ownable {\n // Maps `tokenId` to metadata URI `tokenURI`\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\n\n // We are passing an empty string as the `baseURI` because we use `_tokenURIs` instead\n // to allow for IPFS URIs.\n // solhint-disable-next-line\n constructor() ERC1155(\"\") {}\n\n /**\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\n * @param recipients List of airdrop recipients.\n * @param tokenId Token type to airdrop.\n * @param amount Amount of token types to airdrop.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256 amount\n ) public onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n _mint(recipients[i], tokenId, amount, \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\n }\n\n /**\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\n * @param tokenId Token type to set `tokenURI` for.\n * @param tokenURI URI of token metadata.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\n require(bytes(_tokenURIs[tokenId]).length == 0, \"uri already set\");\n\n _tokenURIs[tokenId] = tokenURI;\n emit URI(tokenURI, tokenId);\n }\n\n /**\n * @notice Returns metadata URI of token type `tokenId`.\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for all token types.\n * @param tokenId Token type to retrieve metadata URI for.\n */\n function uri(uint256 tokenId) public view override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "contracts/BondToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport \"./interfaces/HubPoolInterface.sol\";\nimport \"./external/WETH9.sol\";\n\ninterface ExtendedHubPoolInterface is HubPoolInterface {\n // Specify the automatically-implemented rootBundleProposal() getter.\n function rootBundleProposal() external pure returns (HubPoolInterface.RootBundle memory);\n}\n\n/**\n * @notice Across Bond Token (ABT).\n * ABT is a simple deposit contract based on WETH9. ABT is issued proportionally to any address that deposits Ether. It\n * imposes address-based permissioning on the WETH9 transferFrom() function in order to constrain the movement of ABT\n * into the Across v2 HubPool contract. When configured as the required HubPool bond token, ABT can dramatically reduce\n * the attack surface of the HubPool by requiring that addresses are explicitly approved before they can successfully\n * submit a root bundle proposal. The address-based permissioning does not constrain transfers that are needed to dispute\n * a root bundle proposal, so the ability of decentralised/unknown actors to dispute is unaffected.\n */\ncontract BondToken is WETH9, Ownable {\n using Address for address;\n\n ExtendedHubPoolInterface public immutable hubPool;\n\n /**\n * @notice Addresses that are permitted to make HubPool root bundle proposals.\n */\n mapping(address => bool) public proposers;\n\n /**\n * @notice Emitted on proposer permissions update.\n */\n event ProposerModified(address proposer, bool enabled);\n\n /**\n * @notice BondToken constructor.\n * @param _hubPool Address of the target HubPool contract.\n */\n constructor(ExtendedHubPoolInterface _hubPool) {\n name = \"Across Bond Token\";\n symbol = \"ABT\";\n hubPool = _hubPool;\n }\n\n /**\n * @notice Enable or disable an address as an allowed proposer. Emits a \"ProposerModified\" event on completion.\n * @param proposer Proposer address to modify.\n * @param enabled Boolean controlling whether the address is permitted to propose.\n */\n function setProposer(address proposer, bool enabled) external onlyOwner {\n proposers[proposer] = enabled;\n emit ProposerModified(proposer, enabled);\n }\n\n /**\n * @notice Transfer amt from src to dst. Prevents unauthorised root bundle proposals by blocking transfers to the\n * HubPool under the following conditions:\n * - The src address is not a pre-approved proposer, *and*\n * - The src address is the current proposer of a HubPool root bundle.\n * Falls back to the base implementation after verifying that the transfer is permitted.\n * @dev The require(..., \"Transfer not permitted\") statement is dependent on the internal ordering of HubPool\n * proposedRootBundle state variable updates, relative to calling bondToken.safeTransferFrom(). Changing the order\n * of HubPool actions may invalidate this verification. BondToken tests are implemented to detect this.\n * @param src Source address.\n * @param dst Destination address.\n * @param amt Amount to transfer.\n * @return True on success.\n */\n function transferFrom(\n address src,\n address dst,\n uint256 amt\n ) public override returns (bool) {\n if (dst == address(hubPool)) {\n require(proposers[src] || hubPool.rootBundleProposal().proposer != src, \"Transfer not permitted\");\n }\n return super.transferFrom(src, dst, amt);\n }\n}\n" + }, + "contracts/interfaces/HubPoolInterface.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Concise list of functions in HubPool implementation.\n */\ninterface HubPoolInterface {\n // This leaf is meant to be decoded in the HubPool to rebalance tokens between HubPool and SpokePool.\n struct PoolRebalanceLeaf {\n // This is used to know which chain to send cross-chain transactions to (and which SpokePool to send to).\n uint256 chainId;\n // Total LP fee amount per token in this bundle, encompassing all associated bundled relays.\n uint256[] bundleLpFees;\n // Represents the amount to push to or pull from the SpokePool. If +, the pool pays the SpokePool. If negative\n // the SpokePool pays the HubPool. There can be arbitrarily complex rebalancing rules defined offchain. This\n // number is only nonzero when the rules indicate that a rebalancing action should occur. When a rebalance does\n // occur, runningBalances must be set to zero for this token and netSendAmounts should be set to the previous\n // runningBalances + relays - deposits in this bundle. If non-zero then it must be set on the SpokePool's\n // RelayerRefundLeaf amountToReturn as -1 * this value to show if funds are being sent from or to the SpokePool.\n int256[] netSendAmounts;\n // This is only here to be emitted in an event to track a running unpaid balance between the L2 pool and the L1\n // pool. A positive number indicates that the HubPool owes the SpokePool funds. A negative number indicates that\n // the SpokePool owes the HubPool funds. See the comment above for the dynamics of this and netSendAmounts.\n int256[] runningBalances;\n // Used by data worker to mark which leaves should relay roots to SpokePools, and to otherwise organize leaves.\n // For example, each leaf should contain all the rebalance information for a single chain, but in the case where\n // the list of l1Tokens is very large such that they all can't fit into a single leaf that can be executed under\n // the block gas limit, then the data worker can use this groupIndex to organize them. Any leaves with\n // a groupIndex equal to 0 will relay roots to the SpokePool, so the data worker should ensure that only one\n // leaf for a specific chainId should have a groupIndex equal to 0.\n uint256 groupIndex;\n // Used as the index in the bitmap to track whether this leaf has been executed or not.\n uint8 leafId;\n // The bundleLpFees, netSendAmounts, and runningBalances are required to be the same length. They are parallel\n // arrays for the given chainId and should be ordered by the l1Tokens field. All whitelisted tokens with nonzero\n // relays on this chain in this bundle in the order of whitelisting.\n address[] l1Tokens;\n }\n\n // A data worker can optimistically store several merkle roots on this contract by staking a bond and calling\n // proposeRootBundle. By staking a bond, the data worker is alleging that the merkle roots all contain valid leaves\n // that can be executed later to:\n // - Send funds from this contract to a SpokePool or vice versa\n // - Send funds from a SpokePool to Relayer as a refund for a relayed deposit\n // - Send funds from a SpokePool to a deposit recipient to fulfill a \"slow\" relay\n // Anyone can dispute this struct if the merkle roots contain invalid leaves before the\n // challengePeriodEndTimestamp. Once the expiration timestamp is passed, executeRootBundle to execute a leaf\n // from the poolRebalanceRoot on this contract and it will simultaneously publish the relayerRefundRoot and\n // slowRelayRoot to a SpokePool. The latter two roots, once published to the SpokePool, contain\n // leaves that can be executed on the SpokePool to pay relayers or recipients.\n struct RootBundle {\n // Contains leaves instructing this contract to send funds to SpokePools.\n bytes32 poolRebalanceRoot;\n // Relayer refund merkle root to be published to a SpokePool.\n bytes32 relayerRefundRoot;\n // Slow relay merkle root to be published to a SpokePool.\n bytes32 slowRelayRoot;\n // This is a 1D bitmap, with max size of 256 elements, limiting us to 256 chainsIds.\n uint256 claimedBitMap;\n // Proposer of this root bundle.\n address proposer;\n // Number of pool rebalance leaves to execute in the poolRebalanceRoot. After this number\n // of leaves are executed, a new root bundle can be proposed\n uint8 unclaimedPoolRebalanceLeafCount;\n // When root bundle challenge period passes and this root bundle becomes executable.\n uint32 challengePeriodEndTimestamp;\n }\n\n // Each whitelisted L1 token has an associated pooledToken struct that contains all information used to track the\n // cumulative LP positions and if this token is enabled for deposits.\n struct PooledToken {\n // LP token given to LPs of a specific L1 token.\n address lpToken;\n // True if accepting new LP's.\n bool isEnabled;\n // Timestamp of last LP fee update.\n uint32 lastLpFeeUpdate;\n // Number of LP funds sent via pool rebalances to SpokePools and are expected to be sent\n // back later.\n int256 utilizedReserves;\n // Number of LP funds held in contract less utilized reserves.\n uint256 liquidReserves;\n // Number of LP funds reserved to pay out to LPs as fees.\n uint256 undistributedLpFees;\n }\n\n // Helper contracts to facilitate cross chain actions between HubPool and SpokePool for a specific network.\n struct CrossChainContract {\n address adapter;\n address spokePool;\n }\n\n function setPaused(bool pause) external;\n\n function emergencyDeleteProposal() external;\n\n function relaySpokePoolAdminFunction(uint256 chainId, bytes memory functionData) external;\n\n function setProtocolFeeCapture(address newProtocolFeeCaptureAddress, uint256 newProtocolFeeCapturePct) external;\n\n function setBond(IERC20 newBondToken, uint256 newBondAmount) external;\n\n function setLiveness(uint32 newLiveness) external;\n\n function setIdentifier(bytes32 newIdentifier) external;\n\n function setCrossChainContracts(\n uint256 l2ChainId,\n address adapter,\n address spokePool\n ) external;\n\n function enableL1TokenForLiquidityProvision(address l1Token) external;\n\n function disableL1TokenForLiquidityProvision(address l1Token) external;\n\n function addLiquidity(address l1Token, uint256 l1TokenAmount) external payable;\n\n function removeLiquidity(\n address l1Token,\n uint256 lpTokenAmount,\n bool sendEth\n ) external;\n\n function exchangeRateCurrent(address l1Token) external returns (uint256);\n\n function liquidityUtilizationCurrent(address l1Token) external returns (uint256);\n\n function liquidityUtilizationPostRelay(address l1Token, uint256 relayedAmount) external returns (uint256);\n\n function sync(address l1Token) external;\n\n function proposeRootBundle(\n uint256[] memory bundleEvaluationBlockNumbers,\n uint8 poolRebalanceLeafCount,\n bytes32 poolRebalanceRoot,\n bytes32 relayerRefundRoot,\n bytes32 slowRelayRoot\n ) external;\n\n function executeRootBundle(\n uint256 chainId,\n uint256 groupIndex,\n uint256[] memory bundleLpFees,\n int256[] memory netSendAmounts,\n int256[] memory runningBalances,\n uint8 leafId,\n address[] memory l1Tokens,\n bytes32[] memory proof\n ) external;\n\n function disputeRootBundle() external;\n\n function claimProtocolFeesCaptured(address l1Token) external;\n\n function setPoolRebalanceRoute(\n uint256 destinationChainId,\n address l1Token,\n address destinationToken\n ) external;\n\n function setDepositRoute(\n uint256 originChainId,\n uint256 destinationChainId,\n address originToken,\n bool depositsEnabled\n ) external;\n\n function poolRebalanceRoute(uint256 destinationChainId, address l1Token)\n external\n view\n returns (address destinationToken);\n\n function loadEthForL2Calls() external payable;\n}\n" + }, + "contracts/external/WETH9.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n/**\n * Copyright (C) 2015, 2016, 2017 Dapphub\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see .\n */\n\n/**\n * Imported as at commit 33d01d471437e1ab6861e4545ea4bb3895fd4d74 from:\n * UMAprotocol/protocol/packages/core/contracts/financial-templates/common/WETH9.sol\n * Changes applied post-import:\n * - Corrected SPDX-License-Identifier & reinstated GPLv3 license header.\n * - Permit transferFrom() to be overridden by marking it virtual.\n */\n\npragma solidity ^0.8.0;\n\ncontract WETH9 {\n string public name = \"Wrapped Ether\";\n string public symbol = \"WETH\";\n uint8 public decimals = 18;\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n receive() external payable {\n deposit();\n }\n\n fallback() external payable {\n deposit();\n }\n\n function deposit() public payable {\n balanceOf[msg.sender] += msg.value;\n emit Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 wad) public {\n require(balanceOf[msg.sender] >= wad);\n balanceOf[msg.sender] -= wad;\n payable(msg.sender).transfer(wad);\n emit Withdrawal(msg.sender, wad);\n }\n\n function totalSupply() public view returns (uint256) {\n return address(this).balance;\n }\n\n function approve(address guy, uint256 wad) public returns (bool) {\n allowance[msg.sender][guy] = wad;\n emit Approval(msg.sender, guy, wad);\n return true;\n }\n\n function transfer(address dst, uint256 wad) public returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n /**\n * @dev Local change: marked virtual to allow overriding.\n */\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) public virtual returns (bool) {\n require(balanceOf[src] >= wad);\n\n if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\n require(allowance[src][msg.sender] >= wad);\n allowance[src][msg.sender] -= wad;\n }\n\n balanceOf[src] -= wad;\n balanceOf[dst] += wad;\n\n emit Transfer(src, dst, wad);\n\n return true;\n }\n}\n" + }, + "contracts/test/MerkleLibTest.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"../MerkleLib.sol\";\nimport \"../interfaces/HubPoolInterface.sol\";\nimport \"../interfaces/SpokePoolInterface.sol\";\n\n/**\n * @notice Contract to test the MerkleLib.\n */\ncontract MerkleLibTest {\n mapping(uint256 => uint256) public claimedBitMap;\n\n uint256 public claimedBitMap1D;\n\n function verifyPoolRebalance(\n bytes32 root,\n HubPoolInterface.PoolRebalanceLeaf memory rebalance,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifyPoolRebalance(root, rebalance, proof);\n }\n\n function verifyRelayerRefund(\n bytes32 root,\n SpokePoolInterface.RelayerRefundLeaf memory refund,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifyRelayerRefund(root, refund, proof);\n }\n\n function verifySlowRelayFulfillment(\n bytes32 root,\n SpokePoolInterface.SlowFill memory slowFill,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifySlowRelayFulfillment(root, slowFill, proof);\n }\n\n function isClaimed(uint256 index) public view returns (bool) {\n return MerkleLib.isClaimed(claimedBitMap, index);\n }\n\n function setClaimed(uint256 index) public {\n MerkleLib.setClaimed(claimedBitMap, index);\n }\n\n function isClaimed1D(uint8 index) public view returns (bool) {\n return MerkleLib.isClaimed1D(claimedBitMap1D, index);\n }\n\n function setClaimed1D(uint8 index) public {\n claimedBitMap1D = MerkleLib.setClaimed1D(claimedBitMap1D, index);\n }\n}\n" + }, + "contracts/MerkleLib.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/SpokePoolInterface.sol\";\nimport \"./interfaces/HubPoolInterface.sol\";\n\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\n\n/**\n * @notice Library to help with merkle roots, proofs, and claims.\n */\nlibrary MerkleLib {\n /**\n * @notice Verifies that a repayment is contained within a merkle root.\n * @param root the merkle root.\n * @param rebalance the rebalance struct.\n * @param proof the merkle proof.\n * @return bool to signal if the pool rebalance proof correctly shows inclusion of the rebalance within the tree.\n */\n function verifyPoolRebalance(\n bytes32 root,\n HubPoolInterface.PoolRebalanceLeaf memory rebalance,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(rebalance)));\n }\n\n /**\n * @notice Verifies that a relayer refund is contained within a merkle root.\n * @param root the merkle root.\n * @param refund the refund struct.\n * @param proof the merkle proof.\n * @return bool to signal if the relayer refund proof correctly shows inclusion of the refund within the tree.\n */\n function verifyRelayerRefund(\n bytes32 root,\n SpokePoolInterface.RelayerRefundLeaf memory refund,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(refund)));\n }\n\n /**\n * @notice Verifies that a distribution is contained within a merkle root.\n * @param root the merkle root.\n * @param slowRelayFulfillment the relayData fulfillment struct.\n * @param proof the merkle proof.\n * @return bool to signal if the slow relay's proof correctly shows inclusion of the slow relay within the tree.\n */\n function verifySlowRelayFulfillment(\n bytes32 root,\n SpokePoolInterface.SlowFill memory slowRelayFulfillment,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(slowRelayFulfillment)));\n }\n\n // The following functions are primarily copied from\n // https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol with minor changes.\n\n /**\n * @notice Tests whether a claim is contained within a claimedBitMap mapping.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap.\n * @param index the index to check in the bitmap.\n * @return bool indicating if the index within the claimedBitMap has been marked as claimed.\n */\n function isClaimed(mapping(uint256 => uint256) storage claimedBitMap, uint256 index) internal view returns (bool) {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n uint256 claimedWord = claimedBitMap[claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n /**\n * @notice Marks an index in a claimedBitMap as claimed.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap.\n * @param index the index to mark in the bitmap.\n */\n function setClaimed(mapping(uint256 => uint256) storage claimedBitMap, uint256 index) internal {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex);\n }\n\n /**\n * @notice Tests whether a claim is contained within a 1D claimedBitMap mapping.\n * @param claimedBitMap a simple uint256 value, encoding a 1D bitmap.\n * @param index the index to check in the bitmap. Uint8 type enforces that index can't be > 255.\n * @return bool indicating if the index within the claimedBitMap has been marked as claimed.\n */\n function isClaimed1D(uint256 claimedBitMap, uint8 index) internal pure returns (bool) {\n uint256 mask = (1 << index);\n return claimedBitMap & mask == mask;\n }\n\n /**\n * @notice Marks an index in a claimedBitMap as claimed.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap. Uint8 type enforces that index\n * can't be > 255.\n * @param index the index to mark in the bitmap.\n * @return uint256 representing the modified input claimedBitMap with the index set to true.\n */\n function setClaimed1D(uint256 claimedBitMap, uint8 index) internal pure returns (uint256) {\n return claimedBitMap | (1 << index);\n }\n}\n" + }, + "contracts/interfaces/SpokePoolInterface.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @notice Contains common data structures and functions used by all SpokePool implementations.\n */\ninterface SpokePoolInterface {\n // This leaf is meant to be decoded in the SpokePool to pay out successful relayers.\n struct RelayerRefundLeaf {\n // This is the amount to return to the HubPool. This occurs when there is a PoolRebalanceLeaf netSendAmount that\n // is negative. This is just the negative of this value.\n uint256 amountToReturn;\n // Used to verify that this is being executed on the correct destination chainId.\n uint256 chainId;\n // This array designates how much each of those addresses should be refunded.\n uint256[] refundAmounts;\n // Used as the index in the bitmap to track whether this leaf has been executed or not.\n uint32 leafId;\n // The associated L2TokenAddress that these claims apply to.\n address l2TokenAddress;\n // Must be same length as refundAmounts and designates each address that must be refunded.\n address[] refundAddresses;\n }\n\n // This struct represents the data to fully specify a relay. If any portion of this data differs, the relay is\n // considered to be completely distinct. Only one relay for a particular depositId, chainId pair should be\n // considered valid and repaid. This data is hashed and inserted into the slow relay merkle root so that an off\n // chain validator can choose when to refund slow relayers.\n struct RelayData {\n // The address that made the deposit on the origin chain.\n address depositor;\n // The recipient address on the destination chain.\n address recipient;\n // The corresponding token address on the destination chain.\n address destinationToken;\n // The total relay amount before fees are taken out.\n uint256 amount;\n // Origin chain id.\n uint256 originChainId;\n // Destination chain id.\n uint256 destinationChainId;\n // The LP Fee percentage computed by the relayer based on the deposit's quote timestamp\n // and the HubPool's utilization.\n int64 realizedLpFeePct;\n // The relayer fee percentage specified in the deposit.\n int64 relayerFeePct;\n // The id uniquely identifying this deposit on the origin chain.\n uint32 depositId;\n // Data that is forwarded to the recipient.\n bytes message;\n }\n\n struct SlowFill {\n RelayData relayData;\n int256 payoutAdjustmentPct;\n }\n\n // Stores collection of merkle roots that can be published to this contract from the HubPool, which are referenced\n // by \"data workers\" via inclusion proofs to execute leaves in the roots.\n struct RootBundle {\n // Merkle root of slow relays that were not fully filled and whose recipient is still owed funds from the LP pool.\n bytes32 slowRelayRoot;\n // Merkle root of relayer refunds for successful relays.\n bytes32 relayerRefundRoot;\n // This is a 2D bitmap tracking which leaves in the relayer refund root have been claimed, with max size of\n // 256x(2^248) leaves per root.\n mapping(uint256 => uint256) claimedBitmap;\n }\n\n function setCrossDomainAdmin(address newCrossDomainAdmin) external;\n\n function setHubPool(address newHubPool) external;\n\n function setEnableRoute(\n address originToken,\n uint256 destinationChainId,\n bool enable\n ) external;\n\n function pauseDeposits(bool pause) external;\n\n function pauseFills(bool pause) external;\n\n function setDepositQuoteTimeBuffer(uint32 buffer) external;\n\n function relayRootBundle(bytes32 relayerRefundRoot, bytes32 slowRelayRoot) external;\n\n function emergencyDeleteRootBundle(uint256 rootBundleId) external;\n\n function deposit(\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 maxCount\n ) external payable;\n\n function speedUpDeposit(\n address depositor,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) external;\n\n function fillRelay(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n bytes memory message,\n uint256 maxCount\n ) external;\n\n function fillRelayWithUpdatedDeposit(\n address depositor,\n address recipient,\n address updatedRecipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n bytes memory message,\n bytes memory updatedMessage,\n bytes memory depositorSignature,\n uint256 maxCount\n ) external;\n\n function executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustment,\n bytes32[] memory proof\n ) external;\n\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) external;\n\n function chainId() external view returns (uint256);\n}\n" + }, + "contracts/SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./MerkleLib.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./interfaces/SpokePoolInterface.sol\";\nimport \"./upgradeable/MultiCallerUpgradeable.sol\";\nimport \"./upgradeable/EIP712CrossChainUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\n// This interface is expected to be implemented by any contract that expects to recieve messages from the SpokePool.\ninterface AcrossMessageHandler {\n function handleAcrossMessage(\n address tokenSent,\n uint256 amount,\n bytes memory message\n ) external;\n}\n\n/**\n * @title SpokePool\n * @notice Base contract deployed on source and destination chains enabling depositors to transfer assets from source to\n * destination. Deposit orders are fulfilled by off-chain relayers who also interact with this contract. Deposited\n * tokens are locked on the source chain and relayers send the recipient the desired token currency and amount\n * on the destination chain. Locked source chain tokens are later sent over the canonical token bridge to L1 HubPool.\n * Relayers are refunded with destination tokens out of this contract after another off-chain actor, a \"data worker\",\n * submits a proof that the relayer correctly submitted a relay on this SpokePool.\n */\nabstract contract SpokePool is\n SpokePoolInterface,\n UUPSUpgradeable,\n ReentrancyGuardUpgradeable,\n MultiCallerUpgradeable,\n EIP712CrossChainUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using AddressUpgradeable for address;\n\n // Address of the L1 contract that acts as the owner of this SpokePool. This should normally be set to the HubPool\n // address. The crossDomainAdmin address is unused when the SpokePool is deployed to the same chain as the HubPool.\n address public crossDomainAdmin;\n\n // Address of the L1 contract that will send tokens to and receive tokens from this contract to fund relayer\n // refunds and slow relays.\n address public hubPool;\n\n // Address of wrappedNativeToken contract for this network. If an origin token matches this, then the caller can\n // optionally instruct this contract to wrap native tokens when depositing (ie ETH->WETH or MATIC->WMATIC).\n WETH9Interface public wrappedNativeToken;\n\n // Any deposit quote times greater than or less than this value to the current contract time is blocked. Forces\n // caller to use an approximately \"current\" realized fee. Defaults to 1 hour.\n uint32 public depositQuoteTimeBuffer;\n\n // Count of deposits is used to construct a unique deposit identifier for this spoke pool.\n uint32 public numberOfDeposits;\n\n // Whether deposits and fills are disabled.\n bool public pausedFills;\n bool public pausedDeposits;\n\n // This contract can store as many root bundles as the HubPool chooses to publish here.\n RootBundle[] public rootBundles;\n\n // Origin token to destination token routings can be turned on or off, which can enable or disable deposits.\n mapping(address => mapping(uint256 => bool)) public enabledDepositRoutes;\n\n // Each relay is associated with the hash of parameters that uniquely identify the original deposit and a relay\n // attempt for that deposit. The relay itself is just represented as the amount filled so far. The total amount to\n // relay, the fees, and the agents are all parameters included in the hash key.\n mapping(bytes32 => uint256) public relayFills;\n\n // This keeps track of the worst-case liabilities due to fills.\n // It is never reset. Users should only rely on it to determine the worst-case increase in liabilities between\n // two points. This is used to provide frontrunning protection to ensure the relayer's assumptions about the state\n // upon which their expected repayments are based will not change before their transaction is mined.\n mapping(address => uint256) public fillCounter;\n\n // This keeps track of the total running deposits for each token. This allows depositors to protect themselves from\n // frontrunning that might change their worst-case quote.\n mapping(address => uint256) public depositCounter;\n\n // This tracks the number of identical refunds that have been requested.\n // The intention is to allow an off-chain system to know when this could be a duplicate and ensure that the other\n // requests are known and accounted for.\n mapping(bytes32 => uint256) public refundsRequested;\n\n uint256 public constant MAX_TRANSFER_SIZE = 1e36;\n\n // Note: this needs to be larger than the max transfer size to ensure that all slow fills are fillable, even if\n // their fees are negative.\n // It's important that it isn't too large, however, as it should be multipliable by ~2e18 without overflowing.\n // 1e40 * 2e18 = 2e58 << 2^255 ~= 5e76\n uint256 public constant SLOW_FILL_MAX_TOKENS_TO_SEND = 1e40;\n\n // Set max payout adjustment to something\n\n bytes32 public constant UPDATE_DEPOSIT_DETAILS_HASH =\n keccak256(\n \"UpdateDepositDetails(uint32 depositId,uint256 originChainId,int64 updatedRelayerFeePct,address updatedRecipient,bytes updatedMessage)\"\n );\n\n /****************************************\n * EVENTS *\n ****************************************/\n event SetXDomainAdmin(address indexed newAdmin);\n event SetHubPool(address indexed newHubPool);\n event EnabledDepositRoute(address indexed originToken, uint256 indexed destinationChainId, bool enabled);\n event SetDepositQuoteTimeBuffer(uint32 newBuffer);\n event FundsDeposited(\n uint256 amount,\n uint256 originChainId,\n uint256 indexed destinationChainId,\n int64 relayerFeePct,\n uint32 indexed depositId,\n uint32 quoteTimestamp,\n address originToken,\n address recipient,\n address indexed depositor,\n bytes message\n );\n event RequestedSpeedUpDeposit(\n int64 newRelayerFeePct,\n uint32 indexed depositId,\n address indexed depositor,\n address updatedRecipient,\n bytes updatedMessage,\n bytes depositorSignature\n );\n event FilledRelay(\n uint256 amount,\n uint256 totalFilledAmount,\n uint256 fillAmount,\n uint256 repaymentChainId,\n uint256 indexed originChainId,\n uint256 destinationChainId,\n int64 relayerFeePct,\n int64 realizedLpFeePct,\n uint32 indexed depositId,\n address destinationToken,\n address relayer,\n address indexed depositor,\n address recipient,\n bytes message,\n RelayExecutionInfo updatableRelayData\n );\n event RefundRequested(\n address indexed relayer,\n address refundToken,\n uint256 amount,\n uint256 indexed originChainId,\n uint256 destinationChainId,\n int64 realizedLpFeePct,\n uint32 indexed depositId,\n uint256 fillBlock,\n uint256 previousIdenticalRequests\n );\n event RelayedRootBundle(\n uint32 indexed rootBundleId,\n bytes32 indexed relayerRefundRoot,\n bytes32 indexed slowRelayRoot\n );\n event ExecutedRelayerRefundRoot(\n uint256 amountToReturn,\n uint256 indexed chainId,\n uint256[] refundAmounts,\n uint32 indexed rootBundleId,\n uint32 indexed leafId,\n address l2TokenAddress,\n address[] refundAddresses,\n address caller\n );\n event TokensBridged(\n uint256 amountToReturn,\n uint256 indexed chainId,\n uint32 indexed leafId,\n address indexed l2TokenAddress,\n address caller\n );\n event EmergencyDeleteRootBundle(uint256 indexed rootBundleId);\n event PausedDeposits(bool isPaused);\n event PausedFills(bool isPaused);\n\n /**\n * @notice Represents data used to fill a deposit.\n * @param relay Relay containing original data linked to deposit. Contains fields that can be\n * overridden by other parameters in the RelayExecution struct.\n * @param relayHash Hash of the relay data.\n * @param updatedRelayerFeePct Actual relayer fee pct to use for this relay.\n * @param updatedRecipient Actual recipient to use for this relay.\n * @param updatedMessage Actual message to use for this relay.\n * @param repaymentChainId Chain ID of the network that the relayer will receive refunds on.\n * @param maxTokensToSend Max number of tokens to pull from relayer.\n * @param maxCount Max count to protect the relayer from frontrunning.\n * @param slowFill Whether this is a slow fill.\n * @param payoutAdjustmentPct Adjustment to the payout amount. Can be used to increase or decrease the payout to\n * allow for rewards or penalties. Used in slow fills.\n */\n struct RelayExecution {\n RelayData relay;\n bytes32 relayHash;\n int64 updatedRelayerFeePct;\n address updatedRecipient;\n bytes updatedMessage;\n uint256 repaymentChainId;\n uint256 maxTokensToSend;\n uint256 maxCount;\n bool slowFill;\n int256 payoutAdjustmentPct;\n }\n\n /**\n * @notice Packs together information to include in FilledRelay event.\n * @dev This struct is emitted as opposed to its constituent parameters due to the limit on number of\n * parameters in an event.\n * @param recipient Recipient of the relayed funds.\n * @param message Message included in the relay.\n * @param relayerFeePct Relayer fee pct used for this relay.\n * @param isSlowRelay Whether this is a slow relay.\n * @param payoutAdjustmentPct Adjustment to the payout amount.\n */\n struct RelayExecutionInfo {\n address recipient;\n bytes message;\n int64 relayerFeePct;\n bool isSlowRelay;\n int256 payoutAdjustmentPct;\n }\n\n /**\n * Do not leave an implementation contract uninitialized. An uninitialized implementation contract can be\n * taken over by an attacker, which may impact the proxy. To prevent the implementation contract from being\n * used, you should invoke the _disableInitializers function in the constructor to automatically lock it when\n * it is deployed:\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Construct the base SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wrappedNativeTokenAddress wrappedNativeToken address for this network to set.\n */\n function __SpokePool_init(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool,\n address _wrappedNativeTokenAddress\n ) public onlyInitializing {\n numberOfDeposits = _initialDepositId;\n __EIP712_init(\"ACROSS-V2\", \"1.0.0\");\n __UUPSUpgradeable_init();\n __ReentrancyGuard_init();\n depositQuoteTimeBuffer = 3600;\n _setCrossDomainAdmin(_crossDomainAdmin);\n _setHubPool(_hubPool);\n wrappedNativeToken = WETH9Interface(_wrappedNativeTokenAddress);\n }\n\n /****************************************\n * MODIFIERS *\n ****************************************/\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n * @dev This should be set to cross domain admin for specific SpokePool.\n */\n modifier onlyAdmin() {\n _requireAdminSender();\n _;\n }\n\n modifier unpausedDeposits() {\n require(!pausedDeposits, \"Paused deposits\");\n _;\n }\n\n modifier unpausedFills() {\n require(!pausedFills, \"Paused fills\");\n _;\n }\n\n /**************************************\n * ADMIN FUNCTIONS *\n **************************************/\n\n // Allows cross domain admin to upgrade UUPS proxy implementation.\n function _authorizeUpgrade(address newImplementation) internal override onlyAdmin {}\n\n /**\n * @notice Pauses deposit-related functions. This is intended to be used if this contract is deprecated or when\n * something goes awry.\n * @dev Affects `deposit()` but not `speedUpDeposit()`, so that existing deposits can be sped up and still\n * relayed.\n * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it.\n */\n function pauseDeposits(bool pause) public override onlyAdmin nonReentrant {\n pausedDeposits = pause;\n emit PausedDeposits(pause);\n }\n\n /**\n * @notice Pauses fill-related functions. This is intended to be used if this contract is deprecated or when\n * something goes awry.\n * @dev Affects fillRelayWithUpdatedDeposit() and fillRelay().\n * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it.\n */\n function pauseFills(bool pause) public override onlyAdmin nonReentrant {\n pausedFills = pause;\n emit PausedFills(pause);\n }\n\n /**\n * @notice Change cross domain admin address. Callable by admin only.\n * @param newCrossDomainAdmin New cross domain admin.\n */\n function setCrossDomainAdmin(address newCrossDomainAdmin) public override onlyAdmin nonReentrant {\n _setCrossDomainAdmin(newCrossDomainAdmin);\n }\n\n /**\n * @notice Change L1 hub pool address. Callable by admin only.\n * @param newHubPool New hub pool.\n */\n function setHubPool(address newHubPool) public override onlyAdmin nonReentrant {\n _setHubPool(newHubPool);\n }\n\n /**\n * @notice Enable/Disable an origin token => destination chain ID route for deposits. Callable by admin only.\n * @param originToken Token that depositor can deposit to this contract.\n * @param destinationChainId Chain ID for where depositor wants to receive funds.\n * @param enabled True to enable deposits, False otherwise.\n */\n function setEnableRoute(\n address originToken,\n uint256 destinationChainId,\n bool enabled\n ) public override onlyAdmin nonReentrant {\n enabledDepositRoutes[originToken][destinationChainId] = enabled;\n emit EnabledDepositRoute(originToken, destinationChainId, enabled);\n }\n\n /**\n * @notice Change allowance for deposit quote time to differ from current block time. Callable by admin only.\n * @param newDepositQuoteTimeBuffer New quote time buffer.\n */\n function setDepositQuoteTimeBuffer(uint32 newDepositQuoteTimeBuffer) public override onlyAdmin nonReentrant {\n depositQuoteTimeBuffer = newDepositQuoteTimeBuffer;\n emit SetDepositQuoteTimeBuffer(newDepositQuoteTimeBuffer);\n }\n\n /**\n * @notice This method stores a new root bundle in this contract that can be executed to refund relayers, fulfill\n * slow relays, and send funds back to the HubPool on L1. This method can only be called by the admin and is\n * designed to be called as part of a cross-chain message from the HubPool's executeRootBundle method.\n * @param relayerRefundRoot Merkle root containing relayer refund leaves that can be individually executed via\n * executeRelayerRefundLeaf().\n * @param slowRelayRoot Merkle root containing slow relay fulfillment leaves that can be individually executed via\n * executeSlowRelayLeaf().\n */\n function relayRootBundle(bytes32 relayerRefundRoot, bytes32 slowRelayRoot) public override onlyAdmin nonReentrant {\n uint32 rootBundleId = uint32(rootBundles.length);\n RootBundle storage rootBundle = rootBundles.push();\n rootBundle.relayerRefundRoot = relayerRefundRoot;\n rootBundle.slowRelayRoot = slowRelayRoot;\n emit RelayedRootBundle(rootBundleId, relayerRefundRoot, slowRelayRoot);\n }\n\n /**\n * @notice This method is intended to only be used in emergencies where a bad root bundle has reached the\n * SpokePool.\n * @param rootBundleId Index of the root bundle that needs to be deleted. Note: this is intentionally a uint256\n * to ensure that a small input range doesn't limit which indices this method is able to reach.\n */\n function emergencyDeleteRootBundle(uint256 rootBundleId) public override onlyAdmin nonReentrant {\n // Deleting a struct containing a mapping does not delete the mapping in Solidity, therefore the bitmap's\n // data will still remain potentially leading to vulnerabilities down the line. The way around this would\n // be to iterate through every key in the mapping and resetting the value to 0, but this seems expensive and\n // would require a new list in storage to keep track of keys.\n //slither-disable-next-line mapping-deletion\n delete rootBundles[rootBundleId];\n emit EmergencyDeleteRootBundle(rootBundleId);\n }\n\n /**************************************\n * DEPOSITOR FUNCTIONS *\n **************************************/\n\n /**\n * @notice Called by user to bridge funds from origin to destination chain. Depositor will effectively lock\n * tokens in this contract and receive a destination token on the destination chain. The origin => destination\n * token mapping is stored on the L1 HubPool.\n * @notice The caller must first approve this contract to spend amount of originToken.\n * @notice The originToken => destinationChainId must be enabled.\n * @notice This method is payable because the caller is able to deposit native token if the originToken is\n * wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.\n * @param recipient Address to receive funds at on destination chain.\n * @param originToken Token to lock into this contract to initiate deposit.\n * @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.\n * @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.\n * @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.\n * @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid\n * to LP pool on HubPool.\n * @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n * Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.\n * @param maxCount used to protect the depositor from frontrunning to guarantee their quote remains valid.\n */\n function deposit(\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 maxCount\n ) public payable override nonReentrant unpausedDeposits {\n // Check that deposit route is enabled.\n require(enabledDepositRoutes[originToken][destinationChainId], \"Disabled route\");\n\n // We limit the relay fees to prevent the user spending all their funds on fees.\n require(SignedMath.abs(relayerFeePct) < 0.5e18, \"Invalid relayer fee\");\n require(amount <= MAX_TRANSFER_SIZE, \"Amount too large\");\n require(depositCounter[originToken] <= maxCount, \"Above max count\");\n\n // This function assumes that L2 timing cannot be compared accurately and consistently to L1 timing. Therefore,\n // block.timestamp is different from the L1 EVM's. Therefore, the quoteTimestamp must be within a configurable\n // buffer of this contract's block time to allow for this variance.\n // Note also that quoteTimestamp cannot be less than the buffer otherwise the following arithmetic can result\n // in underflow. This isn't a problem as the deposit will revert, but the error might be unexpected for clients.\n\n //slither-disable-next-line timestamp\n require(\n getCurrentTime() >= quoteTimestamp - depositQuoteTimeBuffer &&\n getCurrentTime() <= quoteTimestamp + depositQuoteTimeBuffer,\n \"invalid quote time\"\n );\n\n // Increment count of deposits so that deposit ID for this spoke pool is unique.\n uint32 newDepositId = numberOfDeposits++;\n depositCounter[originToken] += amount;\n\n // If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the\n // transaction then the user is sending ETH. In this case, the ETH should be deposited to wrappedNativeToken.\n if (originToken == address(wrappedNativeToken) && msg.value > 0) {\n require(msg.value == amount, \"msg.value must match amount\");\n wrappedNativeToken.deposit{ value: msg.value }();\n // Else, it is a normal ERC20. In this case pull the token from the user's wallet as per normal.\n // Note: this includes the case where the L2 user has WETH (already wrapped ETH) and wants to bridge them.\n // In this case the msg.value will be set to 0, indicating a \"normal\" ERC20 bridging action.\n } else IERC20Upgradeable(originToken).safeTransferFrom(msg.sender, address(this), amount);\n\n emit FundsDeposited(\n amount,\n chainId(),\n destinationChainId,\n relayerFeePct,\n newDepositId,\n quoteTimestamp,\n originToken,\n recipient,\n msg.sender,\n message\n );\n }\n\n /**\n * @notice Convenience method that depositor can use to signal to relayer to use updated fee.\n * @notice Relayer should only use events emitted by this function to submit fills with updated fees, otherwise they\n * risk their fills getting disputed for being invalid, for example if the depositor never actually signed the\n * update fee message.\n * @notice This function will revert if the depositor did not sign a message containing the updated fee for the\n * deposit ID stored in this contract. If the deposit ID is for another contract, or the depositor address is\n * incorrect, or the updated fee is incorrect, then the signature will not match and this function will revert.\n * @notice This function is not subject to a deposit pause on the off chance that deposits sent before all deposits\n * are paused have very low fees and the user wants to entice a relayer to fill them with a higher fee.\n * @param depositor Signer of the update fee message who originally submitted the deposit. If the deposit doesn't\n * exist, then the relayer will not be able to fill any relay, so the caller should validate that the depositor\n * did in fact submit a relay.\n * @param updatedRelayerFeePct New relayer fee that relayers can use.\n * @param depositId Deposit to update fee for that originated in this contract.\n * @param updatedRecipient New recipient address that should receive the tokens.\n * @param updatedMessage New message that should be provided to the recipient.\n * @param depositorSignature Signed message containing the depositor address, this contract chain ID, the updated\n * relayer fee %, and the deposit ID. This signature is produced by signing a hash of data according to the\n * EIP-712 standard. See more in the _verifyUpdateRelayerFeeMessage() comments.\n */\n function speedUpDeposit(\n address depositor,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) public override nonReentrant {\n require(SignedMath.abs(updatedRelayerFeePct) < 0.5e18, \"Invalid relayer fee\");\n\n _verifyUpdateDepositMessage(\n depositor,\n depositId,\n chainId(),\n updatedRelayerFeePct,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n\n // Assuming the above checks passed, a relayer can take the signature and the updated relayer fee information\n // from the following event to submit a fill with an updated fee %.\n emit RequestedSpeedUpDeposit(\n updatedRelayerFeePct,\n depositId,\n depositor,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n }\n\n /**************************************\n * RELAYER FUNCTIONS *\n **************************************/\n\n /**\n * @notice Called by relayer to fulfill part of a deposit by sending destination tokens to the recipient.\n * Relayer is expected to pass in unique identifying information for deposit that they want to fulfill, and this\n * relay submission will be validated by off-chain data workers who can dispute this relay if any part is invalid.\n * If the relay is valid, then the relayer will be refunded on their desired repayment chain. If relay is invalid,\n * then relayer will not receive any refund.\n * @notice All of the deposit data can be found via on-chain events from the origin SpokePool, except for the\n * realizedLpFeePct which is a function of the HubPool's utilization at the deposit quote time. This fee %\n * is deterministic based on the quote time, so the relayer should just compute it using the canonical algorithm\n * as described in a UMIP linked to the HubPool's identifier.\n * @param depositor Depositor on origin chain who set this chain as the destination chain.\n * @param recipient Specified recipient on this chain.\n * @param destinationToken Token to send to recipient. Should be mapped to the origin token, origin chain ID\n * and this chain ID via a mapping on the HubPool.\n * @param amount Full size of the deposit.\n * @param maxTokensToSend Max amount of tokens to send recipient. If higher than amount, then caller will\n * send recipient the full relay amount.\n * @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has\n * passed.\n * @param originChainId Chain of SpokePool where deposit originated.\n * @param realizedLpFeePct Fee % based on L1 HubPool utilization at deposit quote time. Deterministic based on\n * quote time.\n * @param relayerFeePct Fee % to keep as relayer, specified by depositor.\n * @param depositId Unique deposit ID on origin spoke pool.\n * @param message Message to send to recipient along with tokens.\n * @param maxCount Max count to protect the relayer from frontrunning.\n */\n function fillRelay(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n bytes memory message,\n uint256 maxCount\n ) public nonReentrant unpausedFills {\n // Each relay attempt is mapped to the hash of data uniquely identifying it, which includes the deposit data\n // such as the origin chain ID and the deposit ID, and the data in a relay attempt such as who the recipient\n // is, which chain and currency the recipient wants to receive funds on, and the relay fees.\n RelayExecution memory relayExecution = RelayExecution({\n relay: SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: chainId(),\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: relayerFeePct,\n updatedRecipient: recipient,\n updatedMessage: message,\n repaymentChainId: repaymentChainId,\n maxTokensToSend: maxTokensToSend,\n slowFill: false,\n payoutAdjustmentPct: 0,\n maxCount: maxCount\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n /**\n * @notice Called by relayer to execute same logic as calling fillRelay except that relayer is using an updated\n * relayer fee %. The fee % must have been emitted in a message cryptographically signed by the depositor.\n * @notice By design, the depositor probably emitted the message with the updated fee by calling speedUpDeposit().\n * @param depositor Depositor on origin chain who set this chain as the destination chain.\n * @param recipient Specified recipient on this chain.\n * @param destinationToken Token to send to recipient. Should be mapped to the origin token, origin chain ID\n * and this chain ID via a mapping on the HubPool.\n * @param amount Full size of the deposit.\n * @param maxTokensToSend Max amount of tokens to send recipient. If higher than amount, then caller will\n * send recipient the full relay amount.\n * @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has\n * passed.\n * @param originChainId Chain of SpokePool where deposit originated.\n * @param realizedLpFeePct Fee % based on L1 HubPool utilization at deposit quote time. Deterministic based on\n * quote time.\n * @param relayerFeePct Original fee % to keep as relayer set by depositor.\n * @param updatedRelayerFeePct New fee % to keep as relayer also specified by depositor.\n * @param depositId Unique deposit ID on origin spoke pool.\n * @param message Original message that was sent along with this deposit.\n * @param updatedMessage Modified message that the depositor signed when updating parameters.\n * @param depositorSignature Signed message containing the depositor address, this contract chain ID, the updated\n * relayer fee %, and the deposit ID. This signature is produced by signing a hash of data according to the\n * EIP-712 standard. See more in the _verifyUpdateRelayerFeeMessage() comments.\n * @param maxCount Max fill count to protect the relayer from frontrunning.\n */\n function fillRelayWithUpdatedDeposit(\n address depositor,\n address recipient,\n address updatedRecipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n bytes memory message,\n bytes memory updatedMessage,\n bytes memory depositorSignature,\n uint256 maxCount\n ) public override nonReentrant unpausedFills {\n RelayExecution memory relayExecution = RelayExecution({\n relay: SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: chainId(),\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: updatedRelayerFeePct,\n updatedRecipient: updatedRecipient,\n updatedMessage: updatedMessage,\n repaymentChainId: repaymentChainId,\n maxTokensToSend: maxTokensToSend,\n slowFill: false,\n payoutAdjustmentPct: 0,\n maxCount: maxCount\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n _verifyUpdateDepositMessage(\n depositor,\n depositId,\n originChainId,\n updatedRelayerFeePct,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n /**\n * @notice Caller signals to the system that they want a refund on this chain, which they set as the\n * `repaymentChainId` on the original fillRelay() call on the `destinationChainId`. An observer should be\n * be able to 1-to-1 match the emitted RefundRequested event with the FilledRelay event on the `destinationChainId`.\n * @dev This function could be used to artificially inflate the `fillCounter`, allowing the caller to \"frontrun\"\n * and cancel pending fills in the mempool. This would in the worst case censor fills at the cost of the caller's\n * gas costs. We don't view this as a major issue as the fill can be resubmitted and obtain the same incentive,\n * since incentives are based on validated refunds and would ignore these censoring attempts. This is no\n * different from calling `fillRelay` and setting msg.sender = recipient.\n * @dev Caller needs to pass in `fillBlock` that the FilledRelay event was emitted on the `destinationChainId`.\n * This is to make it hard to request a refund before a fill has been mined and to make lookups of the original\n * fill as simple as possible.\n * @param refundToken This chain's token equivalent for original fill destination token.\n * @param amount Original deposit amount.\n * @param originChainId Original origin chain ID.\n * @param destinationChainId Original destination chain ID.\n * @param realizedLpFeePct Original realized LP fee %.\n * @param depositId Original deposit ID.\n * @param maxCount Max count to protect the refund recipient from frontrunning.\n */\n function requestRefund(\n address refundToken,\n uint256 amount,\n uint256 originChainId,\n uint256 destinationChainId,\n int64 realizedLpFeePct,\n uint32 depositId,\n uint256 fillBlock,\n uint256 maxCount\n ) external nonReentrant {\n // Prevent unrealistic amounts from increasing fill counter too high.\n require(amount <= MAX_TRANSFER_SIZE, \"Amount too large\");\n\n // This allows the caller to add in frontrunning protection for quote validity.\n require(fillCounter[refundToken] <= maxCount, \"Above max count\");\n\n // Track duplicate refund requests.\n bytes32 refundHash = keccak256(\n abi.encode(\n msg.sender,\n refundToken,\n amount,\n originChainId,\n destinationChainId,\n realizedLpFeePct,\n depositId,\n fillBlock\n )\n );\n\n // Track duplicate requests so that an offchain actor knows if an identical request has already been made.\n // If so, it can check to ensure that that request was thrown out as invalid before honoring the duplicate.\n // In particular, this is meant to handle odd cases where an initial request is invalidated based on\n // timing, but can be validated by a later, identical request.\n uint256 previousIdenticalRequests = refundsRequested[refundHash]++;\n\n // Refund will take tokens out of this pool, increment the fill counter. This function should only be\n // called if a relayer from destinationChainId wants to take a refund on this chain, a different chain.\n // This type of repayment should only be possible for full fills, so the starting fill amount should\n // always be 0. Also, just like in _fillRelay we should revert if the first fill pre fees rounds to 0,\n // and in this case `amount` == `fillAmountPreFees`.\n require(amount > 0, \"Amount must be > 0\");\n _updateCountFromFill(\n 0,\n true, // The refund is being requested here, so it is local.\n amount,\n realizedLpFeePct,\n refundToken,\n false // Slow fills should never match with a Refund. This should be enforced by off-chain bundle builders.\n );\n\n emit RefundRequested(\n // Set caller as relayer. If caller is not relayer from destination chain that originally sent\n // fill, then off-chain validator should discard this refund attempt.\n msg.sender,\n refundToken,\n amount,\n originChainId,\n destinationChainId,\n realizedLpFeePct,\n depositId,\n fillBlock,\n previousIdenticalRequests\n );\n }\n\n /**************************************\n * DATA WORKER FUNCTIONS *\n **************************************/\n\n /**\n * @notice Executes a slow relay leaf stored as part of a root bundle. Will send the full amount remaining in the\n * relay to the recipient, less fees.\n * @dev This function assumes that the relay's destination chain ID is the current chain ID, which prevents\n * the caller from executing a slow relay intended for another chain on this chain.\n * @param depositor Depositor on origin chain who set this chain as the destination chain.\n * @param recipient Specified recipient on this chain.\n * @param destinationToken Token to send to recipient. Should be mapped to the origin token, origin chain ID\n * and this chain ID via a mapping on the HubPool.\n * @param amount Full size of the deposit.\n * @param originChainId Chain of SpokePool where deposit originated.\n * @param realizedLpFeePct Fee % based on L1 HubPool utilization at deposit quote time. Deterministic based on\n * quote time.\n * @param relayerFeePct Original fee % to keep as relayer set by depositor.\n * @param depositId Unique deposit ID on origin spoke pool.\n * @param rootBundleId Unique ID of root bundle containing slow relay root that this leaf is contained in.\n * @param message Message to send to the recipient if the recipient is a contract.\n * @param payoutAdjustment Adjustment to the payout amount. Can be used to increase or decrease the payout to allow\n * for rewards or penalties.\n * @param proof Inclusion proof for this leaf in slow relay root in root bundle.\n */\n function executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustment,\n bytes32[] memory proof\n ) public virtual override nonReentrant {\n _executeSlowRelayLeaf(\n depositor,\n recipient,\n destinationToken,\n amount,\n originChainId,\n chainId(),\n realizedLpFeePct,\n relayerFeePct,\n depositId,\n rootBundleId,\n message,\n payoutAdjustment,\n proof\n );\n }\n\n /**\n * @notice Executes a relayer refund leaf stored as part of a root bundle. Will send the relayer the amount they\n * sent to the recipient plus a relayer fee.\n * @param rootBundleId Unique ID of root bundle containing relayer refund root that this leaf is contained in.\n * @param relayerRefundLeaf Contains all data necessary to reconstruct leaf contained in root bundle and to\n * refund relayer. This data structure is explained in detail in the SpokePoolInterface.\n * @param proof Inclusion proof for this leaf in relayer refund root in root bundle.\n */\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) public virtual override nonReentrant {\n _executeRelayerRefundLeaf(rootBundleId, relayerRefundLeaf, proof);\n }\n\n /**************************************\n * VIEW FUNCTIONS *\n **************************************/\n\n /**\n * @notice Returns chain ID for this network.\n * @dev Some L2s like ZKSync don't support the CHAIN_ID opcode so we allow the implementer to override this.\n */\n function chainId() public view virtual override returns (uint256) {\n return block.chainid;\n }\n\n /**\n * @notice Gets the current time.\n * @return uint for the current timestamp.\n */\n function getCurrentTime() public view virtual returns (uint256) {\n return block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n // Verifies inclusion proof of leaf in root, sends relayer their refund, and sends to HubPool any rebalance\n // transfers.\n function _executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) internal {\n // Check integrity of leaf structure:\n require(relayerRefundLeaf.chainId == chainId(), \"Invalid chainId\");\n require(relayerRefundLeaf.refundAddresses.length == relayerRefundLeaf.refundAmounts.length, \"invalid leaf\");\n\n RootBundle storage rootBundle = rootBundles[rootBundleId];\n\n // Check that inclusionProof proves that relayerRefundLeaf is contained within the relayer refund root.\n // Note: This should revert if the relayerRefundRoot is uninitialized.\n require(MerkleLib.verifyRelayerRefund(rootBundle.relayerRefundRoot, relayerRefundLeaf, proof), \"Bad Proof\");\n\n // Verify the leafId in the leaf has not yet been claimed.\n require(!MerkleLib.isClaimed(rootBundle.claimedBitmap, relayerRefundLeaf.leafId), \"Already claimed\");\n\n // Set leaf as claimed in bitmap. This is passed by reference to the storage rootBundle.\n MerkleLib.setClaimed(rootBundle.claimedBitmap, relayerRefundLeaf.leafId);\n\n // Send each relayer refund address the associated refundAmount for the L2 token address.\n // Note: Even if the L2 token is not enabled on this spoke pool, we should still refund relayers.\n uint256 length = relayerRefundLeaf.refundAmounts.length;\n for (uint256 i = 0; i < length; ) {\n uint256 amount = relayerRefundLeaf.refundAmounts[i];\n if (amount > 0)\n IERC20Upgradeable(relayerRefundLeaf.l2TokenAddress).safeTransfer(\n relayerRefundLeaf.refundAddresses[i],\n amount\n );\n\n // OK because we assume refund array length won't be > types(uint256).max.\n // Based on the stress test results in /test/gas-analytics/SpokePool.RelayerRefundLeaf.ts, the UMIP should\n // limit the refund count in valid proposals to be ~800 so any RelayerRefundLeaves with > 800 refunds should\n // not make it to this stage.\n\n unchecked {\n ++i;\n }\n }\n\n // If leaf's amountToReturn is positive, then send L2 --> L1 message to bridge tokens back via\n // chain-specific bridging method.\n if (relayerRefundLeaf.amountToReturn > 0) {\n _bridgeTokensToHubPool(relayerRefundLeaf);\n\n emit TokensBridged(\n relayerRefundLeaf.amountToReturn,\n relayerRefundLeaf.chainId,\n relayerRefundLeaf.leafId,\n relayerRefundLeaf.l2TokenAddress,\n msg.sender\n );\n }\n\n emit ExecutedRelayerRefundRoot(\n relayerRefundLeaf.amountToReturn,\n relayerRefundLeaf.chainId,\n relayerRefundLeaf.refundAmounts,\n rootBundleId,\n relayerRefundLeaf.leafId,\n relayerRefundLeaf.l2TokenAddress,\n relayerRefundLeaf.refundAddresses,\n msg.sender\n );\n }\n\n // Verifies inclusion proof of leaf in root and sends recipient remainder of relay. Marks relay as filled.\n function _executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n uint256 destinationChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustmentPct,\n bytes32[] memory proof\n ) internal {\n RelayExecution memory relayExecution = RelayExecution({\n relay: SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: destinationChainId,\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: 0,\n updatedRecipient: recipient,\n updatedMessage: message,\n repaymentChainId: 0,\n maxTokensToSend: SLOW_FILL_MAX_TOKENS_TO_SEND,\n slowFill: true,\n payoutAdjustmentPct: payoutAdjustmentPct,\n maxCount: type(uint256).max\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n _verifySlowFill(relayExecution, rootBundleId, proof);\n\n // Note: use relayAmount as the max amount to send, so the relay is always completely filled by the contract's\n // funds in all cases. As this is a slow relay we set the relayerFeePct to 0. This effectively refunds the\n // relayer component of the relayerFee thereby only charging the depositor the LpFee.\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n\n // Note: Set repayment chain ID to 0 to indicate that there is no repayment to be made. The off-chain data\n // worker can use repaymentChainId=0 as a signal to ignore such relays for refunds. Also, set the relayerFeePct\n // to 0 as slow relays do not pay the caller of this method (depositor is refunded this fee).\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n function _setCrossDomainAdmin(address newCrossDomainAdmin) internal {\n require(newCrossDomainAdmin != address(0), \"Bad bridge router address\");\n crossDomainAdmin = newCrossDomainAdmin;\n emit SetXDomainAdmin(newCrossDomainAdmin);\n }\n\n function _setHubPool(address newHubPool) internal {\n require(newHubPool != address(0), \"Bad hub pool address\");\n hubPool = newHubPool;\n emit SetHubPool(newHubPool);\n }\n\n // Should be overriden by implementing contract depending on how L2 handles sending tokens to L1.\n function _bridgeTokensToHubPool(SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf) internal virtual;\n\n function _verifyUpdateDepositMessage(\n address depositor,\n uint32 depositId,\n uint256 originChainId,\n int64 updatedRelayerFeePct,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) internal view {\n // A depositor can request to modify an un-relayed deposit by signing a hash containing the updated\n // details and information uniquely identifying the deposit to relay. This information ensures\n // that this signature cannot be re-used for other deposits.\n // Note: We use the EIP-712 (https://eips.ethereum.org/EIPS/eip-712) standard for hashing and signing typed data.\n // Specifically, we use the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n // `eth_signedTypedDataV4` in MetaMask (https://docs.metamask.io/guide/signing-data.html).\n bytes32 expectedTypedDataV4Hash = _hashTypedDataV4(\n // EIP-712 compliant hash struct: https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct\n keccak256(\n abi.encode(\n UPDATE_DEPOSIT_DETAILS_HASH,\n depositId,\n originChainId,\n updatedRelayerFeePct,\n updatedRecipient,\n keccak256(updatedMessage)\n )\n ),\n // By passing in the origin chain id, we enable the verification of the signature on a different chain\n originChainId\n );\n _verifyDepositorSignature(depositor, expectedTypedDataV4Hash, depositorSignature);\n }\n\n // This function is isolated and made virtual to allow different L2's to implement chain specific recovery of\n // signers from signatures because some L2s might not support ecrecover. To be safe, consider always reverting\n // this function for L2s where ecrecover is different from how it works on Ethereum, otherwise there is the\n // potential to forge a signature from the depositor using a different private key than the original depositor's.\n function _verifyDepositorSignature(\n address depositor,\n bytes32 ethSignedMessageHash,\n bytes memory depositorSignature\n ) internal view virtual {\n // Note:\n // - We don't need to worry about reentrancy from a contract deployed at the depositor address since the method\n // `SignatureChecker.isValidSignatureNow` is a view method. Re-entrancy can happen, but it cannot affect state.\n // - EIP-1271 signatures are supported. This means that a signature valid now, may not be valid later and vice-versa.\n // - For an EIP-1271 signature to work, the depositor contract address must map to a deployed contract on the destination\n // chain that can validate the signature.\n // - Regular signatures from an EOA are also supported.\n bool isValid = SignatureChecker.isValidSignatureNow(depositor, ethSignedMessageHash, depositorSignature);\n require(isValid, \"invalid signature\");\n }\n\n function _verifySlowFill(\n RelayExecution memory relayExecution,\n uint32 rootBundleId,\n bytes32[] memory proof\n ) internal view {\n SlowFill memory slowFill = SlowFill({\n relayData: relayExecution.relay,\n payoutAdjustmentPct: relayExecution.payoutAdjustmentPct\n });\n\n require(\n MerkleLib.verifySlowRelayFulfillment(rootBundles[rootBundleId].slowRelayRoot, slowFill, proof),\n \"Invalid slow relay proof\"\n );\n }\n\n function _computeAmountPreFees(uint256 amount, int64 feesPct) private pure returns (uint256) {\n return (1e18 * amount) / uint256((int256(1e18) - feesPct));\n }\n\n function _computeAmountPostFees(uint256 amount, int256 feesPct) private pure returns (uint256) {\n return (amount * uint256(int256(1e18) - feesPct)) / 1e18;\n }\n\n function _getRelayHash(SpokePoolInterface.RelayData memory relayData) private pure returns (bytes32) {\n return keccak256(abi.encode(relayData));\n }\n\n // Unwraps ETH and does a transfer to a recipient address. If the recipient is a smart contract then sends wrappedNativeToken.\n function _unwrapwrappedNativeTokenTo(address payable to, uint256 amount) internal {\n if (address(to).isContract()) {\n IERC20Upgradeable(address(wrappedNativeToken)).safeTransfer(to, amount);\n } else {\n wrappedNativeToken.withdraw(amount);\n //slither-disable-next-line arbitrary-send-eth\n to.transfer(amount);\n }\n }\n\n /**\n * @notice Caller specifies the max amount of tokens to send to user. Based on this amount and the amount of the\n * relay remaining (as stored in the relayFills mapping), pull the amount of tokens from the caller\n * and send to the recipient.\n * @dev relayFills keeps track of pre-fee fill amounts as a convenience to relayers who want to specify round\n * numbers for the maxTokensToSend parameter or convenient numbers like 100 (i.e. relayers who will fully\n * fill any relay up to 100 tokens, and partial fill with 100 tokens for larger relays).\n * @dev Caller must approve this contract to transfer up to maxTokensToSend of the relayData.destinationToken.\n * The amount to be sent might end up less if there is insufficient relay amount remaining to be sent.\n */\n function _fillRelay(RelayExecution memory relayExecution) internal returns (uint256 fillAmountPreFees) {\n RelayData memory relayData = relayExecution.relay;\n // We limit the relay fees to prevent the user spending all their funds on fees. Note that 0.5e18 (i.e. 50%)\n // fees are just magic numbers. The important point is to prevent the total fee from being 100%, otherwise\n // computing the amount pre fees runs into divide-by-0 issues.\n require(\n SignedMath.abs(relayExecution.updatedRelayerFeePct) < 0.5e18 &&\n SignedMath.abs(relayData.realizedLpFeePct) < 0.5e18,\n \"invalid fees\"\n );\n\n require(relayData.amount <= MAX_TRANSFER_SIZE, \"Amount too large\");\n\n // Check that the relay has not already been completely filled. Note that the relays mapping will point to\n // the amount filled so far for a particular relayHash, so this will start at 0 and increment with each fill.\n require(relayFills[relayExecution.relayHash] < relayData.amount, \"relay filled\");\n\n // This allows the caller to add in frontrunning protection for quote validity.\n require(fillCounter[relayData.destinationToken] <= relayExecution.maxCount, \"Above max count\");\n\n // Derive the amount of the relay filled if the caller wants to send exactly maxTokensToSend tokens to\n // the recipient. For example, if the user wants to send 10 tokens to the recipient, the full relay amount\n // is 100, and the fee %'s total 5%, then this computation would return ~10.5, meaning that to fill 10.5/100\n // of the full relay size, the caller would need to send 10 tokens to the user.\n // This is equivalent to the amount to be sent by the relayer before fees have been taken out.\n fillAmountPreFees = _computeAmountPreFees(\n relayExecution.maxTokensToSend,\n (relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct)\n );\n // If fill amount minus fees, which is possible with small fill amounts and negative fees, then\n // revert.\n require(fillAmountPreFees > 0, \"fill amount pre fees is 0\");\n\n // If user's specified max amount to send is greater than the amount of the relay remaining pre-fees,\n // we'll pull exactly enough tokens to complete the relay.\n uint256 amountRemainingInRelay = relayData.amount - relayFills[relayExecution.relayHash];\n if (amountRemainingInRelay < fillAmountPreFees) {\n fillAmountPreFees = amountRemainingInRelay;\n }\n\n // Apply post-fees computation to amount that relayer will send to user. Rounding errors are possible\n // when computing fillAmountPreFees and then amountToSend, and we just want to enforce that\n // the error added to amountToSend is consistently applied to partial and full fills.\n uint256 amountToSend = _computeAmountPostFees(\n fillAmountPreFees,\n relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct\n );\n\n // This can only happen in a slow fill, where the contract is funding the relay.\n if (relayExecution.payoutAdjustmentPct != 0) {\n // If payoutAdjustmentPct is positive, then the recipient will receive more than the amount they\n // were originally expecting. If it is negative, then the recipient will receive less.\n // -1e18 is -100%. Because we cannot pay out negative values, that is the minimum.\n require(relayExecution.payoutAdjustmentPct >= -1e18, \"payoutAdjustmentPct too small\");\n\n // Allow the payout adjustment to go up to 1000% (i.e. 11x).\n // This is a sanity check to ensure the payouts do not grow too large via some sort of issue in bundle\n // construction.\n require(relayExecution.payoutAdjustmentPct <= 100e18, \"payoutAdjustmentPct too large\");\n\n // Note: since _computeAmountPostFees is typically intended for fees, the signage must be reversed.\n amountToSend = _computeAmountPostFees(amountToSend, -relayExecution.payoutAdjustmentPct);\n\n // Note: this error should never happen, since the maxTokensToSend is expected to be set much higher than\n // the amount, but it is here as a sanity check.\n require(amountToSend <= relayExecution.maxTokensToSend, \"Somehow hit maxTokensToSend!\");\n }\n\n // Since the first partial fill is used to update the fill counter for the entire refund amount, we don't have\n // a simple way to handle the case where follow-up partial fills take repayment on different chains. We'd\n // need a way to decrement the fill counter in this case (or increase deposit counter) to ensure that users\n // have adequate frontrunning protections.\n // Instead of adding complexity, we require that all partial fills set repayment chain equal to destination chain.\n // Note: .slowFill is checked because slow fills set repaymentChainId to 0.\n bool localRepayment = relayExecution.repaymentChainId == relayExecution.relay.destinationChainId;\n require(\n localRepayment || relayExecution.relay.amount == fillAmountPreFees || relayExecution.slowFill,\n \"invalid repayment chain\"\n );\n\n // Update fill counter.\n _updateCountFromFill(\n relayFills[relayExecution.relayHash],\n localRepayment,\n relayData.amount,\n relayData.realizedLpFeePct,\n relayData.destinationToken,\n relayExecution.slowFill\n );\n\n // relayFills keeps track of pre-fee fill amounts as a convenience to relayers who want to specify round\n // numbers for the maxTokensToSend parameter or convenient numbers like 100 (i.e. relayers who will fully\n // fill any relay up to 100 tokens, and partial fill with 100 tokens for larger relays).\n relayFills[relayExecution.relayHash] += fillAmountPreFees;\n\n // If relayer and receiver are the same address, there is no need to do any transfer, as it would result in no\n // net movement of funds.\n // Note: this is important because it means that relayers can intentionally self-relay in a capital efficient\n // way (no need to have funds on the destination).\n if (msg.sender == relayData.recipient) return fillAmountPreFees;\n\n // If relay token is wrappedNativeToken then unwrap and send native token.\n if (relayData.destinationToken == address(wrappedNativeToken)) {\n // Note: useContractFunds is True if we want to send funds to the recipient directly out of this contract,\n // otherwise we expect the caller to send funds to the recipient. If useContractFunds is True and the\n // recipient wants wrappedNativeToken, then we can assume that wrappedNativeToken is already in the\n // contract, otherwise we'll need the user to send wrappedNativeToken to this contract. Regardless, we'll\n // need to unwrap it to native token before sending to the user.\n if (!relayExecution.slowFill)\n IERC20Upgradeable(relayData.destinationToken).safeTransferFrom(msg.sender, address(this), amountToSend);\n _unwrapwrappedNativeTokenTo(payable(relayData.recipient), amountToSend);\n // Else, this is a normal ERC20 token. Send to recipient.\n } else {\n // Note: Similar to note above, send token directly from the contract to the user in the slow relay case.\n if (!relayExecution.slowFill)\n IERC20Upgradeable(relayData.destinationToken).safeTransferFrom(\n msg.sender,\n relayData.recipient,\n amountToSend\n );\n else IERC20Upgradeable(relayData.destinationToken).safeTransfer(relayData.recipient, amountToSend);\n }\n\n if (relayData.recipient.isContract() && relayData.message.length > 0) {\n AcrossMessageHandler(relayData.recipient).handleAcrossMessage(\n relayData.destinationToken,\n amountToSend,\n relayData.message\n );\n }\n }\n\n function _updateCountFromFill(\n uint256 startingFillAmount,\n bool localRepayment,\n uint256 totalFillAmount,\n int64 realizedLPFeePct,\n address token,\n bool useContractFunds\n ) internal {\n // If this is a slow fill, a first partial fill with repayment on another chain, or a partial fill has already happened, do nothing, as these\n // should not impact the count. Initial 0-fills will not reach this part of the code.\n if (useContractFunds || startingFillAmount > 0 || !localRepayment) return;\n fillCounter[token] += _computeAmountPostFees(totalFillAmount, realizedLPFeePct);\n }\n\n function _emitFillRelay(RelayExecution memory relayExecution, uint256 fillAmountPreFees) internal {\n RelayExecutionInfo memory relayExecutionInfo = RelayExecutionInfo({\n relayerFeePct: relayExecution.updatedRelayerFeePct,\n recipient: relayExecution.updatedRecipient,\n message: relayExecution.updatedMessage,\n isSlowRelay: relayExecution.slowFill,\n payoutAdjustmentPct: relayExecution.payoutAdjustmentPct\n });\n\n emit FilledRelay(\n relayExecution.relay.amount,\n relayFills[relayExecution.relayHash],\n fillAmountPreFees,\n relayExecution.repaymentChainId,\n relayExecution.relay.originChainId,\n relayExecution.relay.destinationChainId,\n relayExecution.relay.relayerFeePct,\n relayExecution.relay.realizedLpFeePct,\n relayExecution.relay.depositId,\n relayExecution.relay.destinationToken,\n msg.sender,\n relayExecution.relay.depositor,\n relayExecution.relay.recipient,\n relayExecution.relay.message,\n relayExecutionInfo\n );\n }\n\n // Implementing contract needs to override this to ensure that only the appropriate cross chain admin can execute\n // certain admin functions. For L2 contracts, the cross chain admin refers to some L1 address or contract, and for\n // L1, this would just be the same admin of the HubPool.\n function _requireAdminSender() internal virtual;\n\n // Added to enable the this contract to receive native token (ETH). Used when unwrapping wrappedNativeToken.\n receive() external payable {}\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure it's always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "contracts/external/interfaces/WETH9Interface.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @notice Interface for the WETH9 contract.\n */\ninterface WETH9Interface {\n /**\n * @notice Burn Wrapped Ether and receive native Ether.\n * @param wad Amount of WETH to unwrap and send to caller.\n */\n function withdraw(uint256 wad) external;\n\n /**\n * @notice Lock native Ether and mint Wrapped Ether ERC20\n * @dev msg.value is amount of Wrapped Ether to mint/Ether to lock.\n */\n function deposit() external payable;\n\n /**\n * @notice Get balance of WETH held by `guy`.\n * @param guy Address to get balance of.\n * @return wad Amount of WETH held by `guy`.\n */\n function balanceOf(address guy) external view returns (uint256 wad);\n\n /**\n * @notice Transfer `wad` of WETH from caller to `guy`.\n * @param guy Address to send WETH to.\n * @param wad Amount of WETH to send.\n * @return ok True if transfer succeeded.\n */\n function transfer(address guy, uint256 wad) external returns (bool);\n}\n" + }, + "contracts/upgradeable/MultiCallerUpgradeable.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title MultiCallerUpgradeable\n * @notice Logic is 100% copied from \"@uma/core/contracts/common/implementation/MultiCaller.sol\" but one\n * comment is added to clarify why we allow delegatecall() in this contract, which is typically unsafe for use in\n * upgradeable implementation contracts.\n * @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/faq#delegatecall-selfdestruct for more details.\n */\ncontract MultiCallerUpgradeable {\n function multicall(bytes[] calldata data) external returns (bytes[] memory results) {\n results = new bytes[](data.length);\n\n //slither-disable-start calls-loop\n for (uint256 i = 0; i < data.length; i++) {\n // Typically, implementation contracts used in the upgradeable proxy pattern shouldn't call `delegatecall`\n // because it could allow a malicious actor to call this implementation contract directly (rather than\n // through a proxy contract) and then selfdestruct() the contract, thereby freezing the upgradeable\n // proxy. However, since we're only delegatecall-ing into this contract, then we can consider this\n // use of delegatecall() safe.\n\n //slither-disable-start low-level-calls\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n //slither-disable-end low-level-calls\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n //slither-disable-next-line assembly\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n }\n //slither-disable-end calls-loop\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure its always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "contracts/upgradeable/EIP712CrossChainUpgradeable.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * This contract is based on OpenZeppelin's implementation:\n * https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/cryptography/EIP712Upgradeable.sol\n *\n * NOTE: Modified version that allows to build a domain separator that relies on a different chain id than the chain this\n * contract is deployed to. An example use case we want to support is:\n * - User A signs a message on chain with id = 1\n * - User B executes a method by verifying user A's EIP-712 compliant signature on a chain with id != 1\n */\nabstract contract EIP712CrossChainUpgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId)\");\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator depending on the `originChainId`.\n * @param originChainId Chain id of network where message originates from.\n * @return bytes32 EIP-712-compliant domain separator.\n */\n function _domainSeparatorV4(uint256 originChainId) internal view returns (bytes32) {\n return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, originChainId));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 structHash = keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * ));\n * bytes32 digest = _hashTypedDataV4(structHash, originChainId);\n * address signer = ECDSA.recover(digest, signature);\n * ```\n * @param structHash Hashed struct as defined in https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.\n * @param originChainId Chain id of network where message originates from.\n * @return bytes32 Hash digest that is recoverable via `EDCSA.recover`.\n */\n function _hashTypedDataV4(bytes32 structHash, uint256 originChainId) internal view virtual returns (bytes32) {\n return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(originChainId), structHash);\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure it's always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/draft-IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n function safeTransfer(\n IERC20Upgradeable token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20Upgradeable token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20Upgradeable token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../StringsUpgradeable.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {\n require(AddressUpgradeable.isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return AddressUpgradeable.verifyCallResult(success, returndata, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "contracts/test/MockSpokePool.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"../SpokePool.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n/**\n * @title MockSpokePool\n * @notice Implements abstract contract for testing.\n */\ncontract MockSpokePool is SpokePool, OwnableUpgradeable {\n uint256 private chainId_;\n uint256 private currentTime;\n\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool,\n address _wethAddress\n ) public initializer {\n __Ownable_init();\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wethAddress);\n currentTime = block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n function setCurrentTime(uint256 time) external {\n currentTime = time;\n }\n\n function getCurrentTime() public view override returns (uint256) {\n return currentTime;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {}\n\n function _requireAdminSender() internal override onlyOwner {} // solhint-disable-line no-empty-blocks\n\n function chainId() public view override(SpokePool) returns (uint256) {\n // If chainId_ is set then return it, else do nothing and return the parent chainId().\n return chainId_ == 0 ? super.chainId() : chainId_;\n }\n\n function setChainId(uint256 _chainId) public {\n chainId_ = _chainId;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/Ethereum_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n/**\n * @notice Ethereum L1 specific SpokePool. Used on Ethereum L1 to facilitate L2->L1 transfers.\n */\ncontract Ethereum_SpokePool is SpokePool, OwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Construct the Ethereum SpokePool.\n * @dev crossDomainAdmin is unused on this contract.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wethAddress Weth address for this network to set.\n */\n function initialize(\n uint32 _initialDepositId,\n address _hubPool,\n address _wethAddress\n ) public initializer {\n __Ownable_init();\n __SpokePool_init(_initialDepositId, _hubPool, _hubPool, _wethAddress);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {\n IERC20Upgradeable(relayerRefundLeaf.l2TokenAddress).safeTransfer(hubPool, relayerRefundLeaf.amountToReturn);\n }\n\n // The SpokePool deployed to the same network as the HubPool must be owned by the HubPool.\n // A core assumption of this contract system is that the HubPool is deployed on Ethereum.\n function _requireAdminSender() internal override onlyOwner {}\n}\n" + }, + "contracts/PolygonTokenBridger.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./Lockable.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Polygon Registry contract that stores their addresses.\ninterface PolygonRegistry {\n function erc20Predicate() external returns (address);\n}\n\n// Polygon ERC20Predicate contract that handles Plasma exits (only used for Matic).\ninterface PolygonERC20Predicate {\n function startExitWithBurntTokens(bytes calldata data) external;\n}\n\n// ERC20s (on polygon) compatible with polygon's bridge have a withdraw method.\ninterface PolygonIERC20Upgradeable is IERC20Upgradeable {\n function withdraw(uint256 amount) external;\n}\n\ninterface MaticToken {\n function withdraw(uint256 amount) external payable;\n}\n\n/**\n * @notice Contract deployed on Ethereum and Polygon to facilitate token transfers from Polygon to the HubPool and back.\n * @dev Because Polygon only allows withdrawals from a particular address to go to that same address on mainnet, we need to\n * have some sort of contract that can guarantee identical addresses on Polygon and Ethereum. This contract is intended\n * to be completely immutable, so it's guaranteed that the contract on each side is configured identically as long as\n * it is created via create2. create2 is an alternative creation method that uses a different address determination\n * mechanism from normal create.\n * Normal create: address = hash(deployer_address, deployer_nonce)\n * create2: address = hash(0xFF, sender, salt, bytecode)\n * This ultimately allows create2 to generate deterministic addresses that don't depend on the transaction count of the\n * sender.\n */\ncontract PolygonTokenBridger is Lockable {\n using SafeERC20Upgradeable for PolygonIERC20Upgradeable;\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n // Gas token for Polygon.\n MaticToken public constant maticToken = MaticToken(0x0000000000000000000000000000000000001010);\n\n // Should be set to HubPool on Ethereum, or unused on Polygon.\n address public immutable destination;\n\n // Registry that stores L1 polygon addresses.\n PolygonRegistry public immutable l1PolygonRegistry;\n\n // WETH contract on Ethereum.\n WETH9Interface public immutable l1Weth;\n\n // Wrapped Matic on Polygon\n address public immutable l2WrappedMatic;\n\n // Chain id for the L1 that this contract is deployed on or communicates with.\n // For example: if this contract were meant to facilitate transfers from polygon to mainnet, this value would be\n // the mainnet chainId 1.\n uint256 public immutable l1ChainId;\n\n // Chain id for the L2 that this contract is deployed on or communicates with.\n // For example: if this contract were meant to facilitate transfers from polygon to mainnet, this value would be\n // the polygon chainId 137.\n uint256 public immutable l2ChainId;\n\n modifier onlyChainId(uint256 chainId) {\n _requireChainId(chainId);\n _;\n }\n\n /**\n * @notice Constructs Token Bridger contract.\n * @param _destination Where to send tokens to for this network.\n * @param _l1PolygonRegistry L1 registry that stores updated addresses of polygon contracts. This should always be\n * set to the L1 registry regardless if whether it's deployed on L2 or L1.\n * @param _l1Weth L1 WETH address.\n * @param _l2WrappedMatic L2 address of wrapped matic token.\n * @param _l1ChainId the chain id for the L1 in this environment.\n * @param _l2ChainId the chain id for the L2 in this environment.\n */\n constructor(\n address _destination,\n PolygonRegistry _l1PolygonRegistry,\n WETH9Interface _l1Weth,\n address _l2WrappedMatic,\n uint256 _l1ChainId,\n uint256 _l2ChainId\n ) {\n //slither-disable-next-line missing-zero-check\n destination = _destination;\n l1PolygonRegistry = _l1PolygonRegistry;\n l1Weth = _l1Weth;\n //slither-disable-next-line missing-zero-check\n l2WrappedMatic = _l2WrappedMatic;\n l1ChainId = _l1ChainId;\n l2ChainId = _l2ChainId;\n }\n\n /**\n * @notice Called by Polygon SpokePool to send tokens over bridge to contract with the same address as this.\n * @notice The caller of this function must approve this contract to spend amount of token.\n * @param token Token to bridge.\n * @param amount Amount to bridge.\n */\n function send(PolygonIERC20Upgradeable token, uint256 amount) public nonReentrant onlyChainId(l2ChainId) {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n // In the wMatic case, this unwraps. For other ERC20s, this is the burn/send action.\n token.withdraw(token.balanceOf(address(this)));\n\n // This takes the token that was withdrawn and calls withdraw on the \"native\" ERC20.\n if (address(token) == l2WrappedMatic)\n maticToken.withdraw{ value: address(this).balance }(address(this).balance);\n }\n\n /**\n * @notice Called by someone to send tokens to the destination, which should be set to the HubPool.\n * @param token Token to send to destination.\n */\n function retrieve(IERC20Upgradeable token) public nonReentrant onlyChainId(l1ChainId) {\n if (address(token) == address(l1Weth)) {\n // For WETH, there is a pre-deposit step to ensure any ETH that has been sent to the contract is captured.\n //slither-disable-next-line arbitrary-send-eth\n l1Weth.deposit{ value: address(this).balance }();\n }\n token.safeTransfer(destination, token.balanceOf(address(this)));\n }\n\n /**\n * @notice Called to initiate an l1 exit (withdrawal) of matic tokens that have been sent over the plasma bridge.\n * @param data the proof data to trigger the exit. Can be generated using the maticjs-plasma package.\n */\n function callExit(bytes memory data) public nonReentrant onlyChainId(l1ChainId) {\n PolygonERC20Predicate erc20Predicate = PolygonERC20Predicate(l1PolygonRegistry.erc20Predicate());\n erc20Predicate.startExitWithBurntTokens(data);\n }\n\n receive() external payable {\n // This method is empty to avoid any gas expendatures that might cause transfers to fail.\n // Note: the fact that there is _no_ code in this function means that matic can be erroneously transferred in\n // to the contract on the polygon side. These tokens would be locked indefinitely since the receive function\n // cannot be called on the polygon side. While this does have some downsides, the lack of any functionality\n // in this function means that it has no chance of running out of gas on transfers, which is a much more\n // important benefit. This just makes the matic token risk similar to that of ERC20s that are erroneously\n // sent to the contract.\n }\n\n function _requireChainId(uint256 chainId) internal view {\n require(block.chainid == chainId, \"Cannot run method on this chain\");\n }\n}\n" + }, + "contracts/Lockable.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract\n * is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol\n * and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.\n * @dev The reason why we use this local contract instead of importing from uma/contracts is because of the addition\n * of the internal method `functionCallStackOriginatesFromOutsideThisContract` which doesn't exist in the one exported\n * by uma/contracts.\n */\ncontract Lockable {\n bool internal _notEntered;\n\n constructor() {\n // Storing an initial non-zero value makes deployment a bit more expensive, but in exchange the refund on every\n // call to nonReentrant will be lower in amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full\n // refund coming into effect.\n _notEntered = true;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a nonReentrant function from another nonReentrant function is not supported. It is possible to\n * prevent this from happening by making the nonReentrant function external, and making it call a private\n * function that does the actual state modification.\n */\n modifier nonReentrant() {\n _preEntranceCheck();\n _preEntranceSet();\n _;\n _postEntranceReset();\n }\n\n /**\n * @dev Designed to prevent a view-only method from being re-entered during a call to a nonReentrant() state-changing method.\n */\n modifier nonReentrantView() {\n _preEntranceCheck();\n _;\n }\n\n /**\n * @dev Returns true if the contract is currently in a non-entered state, meaning that the origination of the call\n * came from outside the contract. This is relevant with fallback/receive methods to see if the call came from ETH\n * being dropped onto the contract externally or due to ETH dropped on the the contract from within a method in this\n * contract, such as unwrapping WETH to ETH within the contract.\n */\n function functionCallStackOriginatesFromOutsideThisContract() internal view returns (bool) {\n return _notEntered;\n }\n\n // Internal methods are used to avoid copying the require statement's bytecode to every nonReentrant() method.\n // On entry into a function, _preEntranceCheck() should always be called to check if the function is being\n // re-entered. Then, if the function modifies state, it should call _postEntranceSet(), perform its logic, and\n // then call _postEntranceReset().\n // View-only methods can simply call _preEntranceCheck() to make sure that it is not being re-entered.\n function _preEntranceCheck() internal view {\n // On the first call to nonReentrant, _notEntered will be true\n require(_notEntered, \"ReentrancyGuard: reentrant call\");\n }\n\n function _preEntranceSet() internal {\n // Any calls to nonReentrant after this point will fail\n _notEntered = false;\n }\n\n function _postEntranceReset() internal {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _notEntered = true;\n }\n}\n" + }, + "contracts/test/PolygonERC20Test.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/common/implementation/ExpandedERC20.sol\";\nimport \"../PolygonTokenBridger.sol\";\n\n/**\n * @notice Simulated Polygon ERC20 for use in testing PolygonTokenBridger.\n */\ncontract PolygonERC20Test is ExpandedERC20 {\n constructor() ExpandedERC20(\"Polygon Test\", \"POLY_TEST\", 18) {} // solhint-disable-line no-empty-blocks\n\n function withdraw(uint256 amount) public {\n _burn(msg.sender, amount);\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/ExpandedERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./MultiRole.sol\";\nimport \"../interfaces/ExpandedIERC20.sol\";\n\n/**\n * @title An ERC20 with permissioned burning and minting. The contract deployer will initially\n * be the owner who is capable of adding new roles.\n */\ncontract ExpandedERC20 is ExpandedIERC20, ERC20, MultiRole {\n enum Roles {\n // Can set the minter and burner.\n Owner,\n // Addresses that can mint new tokens.\n Minter,\n // Addresses that can burn tokens that address owns.\n Burner\n }\n\n uint8 _decimals;\n\n /**\n * @notice Constructs the ExpandedERC20.\n * @param _tokenName The name which describes the new token.\n * @param _tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.\n * @param _tokenDecimals The number of decimals to define token precision.\n */\n constructor(\n string memory _tokenName,\n string memory _tokenSymbol,\n uint8 _tokenDecimals\n ) ERC20(_tokenName, _tokenSymbol) {\n _decimals = _tokenDecimals;\n _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);\n _createSharedRole(uint256(Roles.Minter), uint256(Roles.Owner), new address[](0));\n _createSharedRole(uint256(Roles.Burner), uint256(Roles.Owner), new address[](0));\n }\n\n function decimals() public view virtual override(ERC20) returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev Mints `value` tokens to `recipient`, returning true on success.\n * @param recipient address to mint to.\n * @param value amount of tokens to mint.\n * @return True if the mint succeeded, or False.\n */\n function mint(address recipient, uint256 value)\n external\n override\n onlyRoleHolder(uint256(Roles.Minter))\n returns (bool)\n {\n _mint(recipient, value);\n return true;\n }\n\n /**\n * @dev Burns `value` tokens owned by `msg.sender`.\n * @param value amount of tokens to burn.\n */\n function burn(uint256 value) external override onlyRoleHolder(uint256(Roles.Burner)) {\n _burn(msg.sender, value);\n }\n\n /**\n * @dev Burns `value` tokens owned by `recipient`.\n * @param recipient address to burn tokens from.\n * @param value amount of tokens to burn.\n * @return True if the burn succeeded, or False.\n */\n function burnFrom(address recipient, uint256 value)\n external\n override\n onlyRoleHolder(uint256(Roles.Burner))\n returns (bool)\n {\n _burn(recipient, value);\n return true;\n }\n\n /**\n * @notice Add Minter role to account.\n * @dev The caller must have the Owner role.\n * @param account The address to which the Minter role is added.\n */\n function addMinter(address account) external virtual override {\n addMember(uint256(Roles.Minter), account);\n }\n\n /**\n * @notice Add Burner role to account.\n * @dev The caller must have the Owner role.\n * @param account The address to which the Burner role is added.\n */\n function addBurner(address account) external virtual override {\n addMember(uint256(Roles.Burner), account);\n }\n\n /**\n * @notice Reset Owner role to account.\n * @dev The caller must have the Owner role.\n * @param account The new holder of the Owner role.\n */\n function resetOwner(address account) external virtual override {\n resetMember(uint256(Roles.Owner), account);\n }\n}\n" + }, + "@uma/core/contracts/common/interfaces/ExpandedIERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title ERC20 interface that includes burn and mint methods.\n */\nabstract contract ExpandedIERC20 is IERC20 {\n /**\n * @notice Burns a specific amount of the caller's tokens.\n * @dev Only burns the caller's tokens, so it is safe to leave this method permissionless.\n */\n function burn(uint256 value) external virtual;\n\n /**\n * @dev Burns `value` tokens owned by `recipient`.\n * @param recipient address to burn tokens from.\n * @param value amount of tokens to burn.\n */\n function burnFrom(address recipient, uint256 value) external virtual returns (bool);\n\n /**\n * @notice Mints tokens and adds them to the balance of the `to` address.\n * @dev This method should be permissioned to only allow designated parties to mint tokens.\n */\n function mint(address to, uint256 value) external virtual returns (bool);\n\n function addMinter(address account) external virtual;\n\n function addBurner(address account) external virtual;\n\n function resetOwner(address account) external virtual;\n}\n" + }, + "@uma/core/contracts/common/implementation/MultiRole.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nlibrary Exclusive {\n struct RoleMembership {\n address member;\n }\n\n function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {\n return roleMembership.member == memberToCheck;\n }\n\n function resetMember(RoleMembership storage roleMembership, address newMember) internal {\n require(newMember != address(0x0), \"Cannot set an exclusive role to 0x0\");\n roleMembership.member = newMember;\n }\n\n function getMember(RoleMembership storage roleMembership) internal view returns (address) {\n return roleMembership.member;\n }\n\n function init(RoleMembership storage roleMembership, address initialMember) internal {\n resetMember(roleMembership, initialMember);\n }\n}\n\nlibrary Shared {\n struct RoleMembership {\n mapping(address => bool) members;\n }\n\n function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {\n return roleMembership.members[memberToCheck];\n }\n\n function addMember(RoleMembership storage roleMembership, address memberToAdd) internal {\n require(memberToAdd != address(0x0), \"Cannot add 0x0 to a shared role\");\n roleMembership.members[memberToAdd] = true;\n }\n\n function removeMember(RoleMembership storage roleMembership, address memberToRemove) internal {\n roleMembership.members[memberToRemove] = false;\n }\n\n function init(RoleMembership storage roleMembership, address[] memory initialMembers) internal {\n for (uint256 i = 0; i < initialMembers.length; i++) {\n addMember(roleMembership, initialMembers[i]);\n }\n }\n}\n\n/**\n * @title Base class to manage permissions for the derived class.\n */\nabstract contract MultiRole {\n using Exclusive for Exclusive.RoleMembership;\n using Shared for Shared.RoleMembership;\n\n enum RoleType { Invalid, Exclusive, Shared }\n\n struct Role {\n uint256 managingRole;\n RoleType roleType;\n Exclusive.RoleMembership exclusiveRoleMembership;\n Shared.RoleMembership sharedRoleMembership;\n }\n\n mapping(uint256 => Role) private roles;\n\n event ResetExclusiveMember(uint256 indexed roleId, address indexed newMember, address indexed manager);\n event AddedSharedMember(uint256 indexed roleId, address indexed newMember, address indexed manager);\n event RemovedSharedMember(uint256 indexed roleId, address indexed oldMember, address indexed manager);\n\n /**\n * @notice Reverts unless the caller is a member of the specified roleId.\n */\n modifier onlyRoleHolder(uint256 roleId) {\n require(holdsRole(roleId, msg.sender), \"Sender does not hold required role\");\n _;\n }\n\n /**\n * @notice Reverts unless the caller is a member of the manager role for the specified roleId.\n */\n modifier onlyRoleManager(uint256 roleId) {\n require(holdsRole(roles[roleId].managingRole, msg.sender), \"Can only be called by a role manager\");\n _;\n }\n\n /**\n * @notice Reverts unless the roleId represents an initialized, exclusive roleId.\n */\n modifier onlyExclusive(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Exclusive, \"Must be called on an initialized Exclusive role\");\n _;\n }\n\n /**\n * @notice Reverts unless the roleId represents an initialized, shared roleId.\n */\n modifier onlyShared(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Shared, \"Must be called on an initialized Shared role\");\n _;\n }\n\n /**\n * @notice Whether `memberToCheck` is a member of roleId.\n * @dev Reverts if roleId does not correspond to an initialized role.\n * @param roleId the Role to check.\n * @param memberToCheck the address to check.\n * @return True if `memberToCheck` is a member of `roleId`.\n */\n function holdsRole(uint256 roleId, address memberToCheck) public view returns (bool) {\n Role storage role = roles[roleId];\n if (role.roleType == RoleType.Exclusive) {\n return role.exclusiveRoleMembership.isMember(memberToCheck);\n } else if (role.roleType == RoleType.Shared) {\n return role.sharedRoleMembership.isMember(memberToCheck);\n }\n revert(\"Invalid roleId\");\n }\n\n /**\n * @notice Changes the exclusive role holder of `roleId` to `newMember`.\n * @dev Reverts if the caller is not a member of the managing role for `roleId` or if `roleId` is not an\n * initialized, ExclusiveRole.\n * @param roleId the ExclusiveRole membership to modify.\n * @param newMember the new ExclusiveRole member.\n */\n function resetMember(uint256 roleId, address newMember) public onlyExclusive(roleId) onlyRoleManager(roleId) {\n roles[roleId].exclusiveRoleMembership.resetMember(newMember);\n emit ResetExclusiveMember(roleId, newMember, msg.sender);\n }\n\n /**\n * @notice Gets the current holder of the exclusive role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, exclusive role.\n * @param roleId the ExclusiveRole membership to check.\n * @return the address of the current ExclusiveRole member.\n */\n function getMember(uint256 roleId) public view onlyExclusive(roleId) returns (address) {\n return roles[roleId].exclusiveRoleMembership.getMember();\n }\n\n /**\n * @notice Adds `newMember` to the shared role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the\n * managing role for `roleId`.\n * @param roleId the SharedRole membership to modify.\n * @param newMember the new SharedRole member.\n */\n function addMember(uint256 roleId, address newMember) public onlyShared(roleId) onlyRoleManager(roleId) {\n roles[roleId].sharedRoleMembership.addMember(newMember);\n emit AddedSharedMember(roleId, newMember, msg.sender);\n }\n\n /**\n * @notice Removes `memberToRemove` from the shared role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the\n * managing role for `roleId`.\n * @param roleId the SharedRole membership to modify.\n * @param memberToRemove the current SharedRole member to remove.\n */\n function removeMember(uint256 roleId, address memberToRemove) public onlyShared(roleId) onlyRoleManager(roleId) {\n roles[roleId].sharedRoleMembership.removeMember(memberToRemove);\n emit RemovedSharedMember(roleId, memberToRemove, msg.sender);\n }\n\n /**\n * @notice Removes caller from the role, `roleId`.\n * @dev Reverts if the caller is not a member of the role for `roleId` or if `roleId` is not an\n * initialized, SharedRole.\n * @param roleId the SharedRole membership to modify.\n */\n function renounceMembership(uint256 roleId) public onlyShared(roleId) onlyRoleHolder(roleId) {\n roles[roleId].sharedRoleMembership.removeMember(msg.sender);\n emit RemovedSharedMember(roleId, msg.sender, msg.sender);\n }\n\n /**\n * @notice Reverts if `roleId` is not initialized.\n */\n modifier onlyValidRole(uint256 roleId) {\n require(roles[roleId].roleType != RoleType.Invalid, \"Attempted to use an invalid roleId\");\n _;\n }\n\n /**\n * @notice Reverts if `roleId` is initialized.\n */\n modifier onlyInvalidRole(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Invalid, \"Cannot use a pre-existing role\");\n _;\n }\n\n /**\n * @notice Internal method to initialize a shared role, `roleId`, which will be managed by `managingRoleId`.\n * `initialMembers` will be immediately added to the role.\n * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already\n * initialized.\n */\n function _createSharedRole(\n uint256 roleId,\n uint256 managingRoleId,\n address[] memory initialMembers\n ) internal onlyInvalidRole(roleId) {\n Role storage role = roles[roleId];\n role.roleType = RoleType.Shared;\n role.managingRole = managingRoleId;\n role.sharedRoleMembership.init(initialMembers);\n require(\n roles[managingRoleId].roleType != RoleType.Invalid,\n \"Attempted to use an invalid role to manage a shared role\"\n );\n }\n\n /**\n * @notice Internal method to initialize an exclusive role, `roleId`, which will be managed by `managingRoleId`.\n * `initialMember` will be immediately added to the role.\n * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already\n * initialized.\n */\n function _createExclusiveRole(\n uint256 roleId,\n uint256 managingRoleId,\n address initialMember\n ) internal onlyInvalidRole(roleId) {\n Role storage role = roles[roleId];\n role.roleType = RoleType.Exclusive;\n role.managingRole = managingRoleId;\n role.exclusiveRoleMembership.init(initialMember);\n require(\n roles[managingRoleId].roleType != RoleType.Invalid,\n \"Attempted to use an invalid role to manage an exclusive role\"\n );\n }\n}\n" + }, + "contracts/LpTokenFactory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/LpTokenFactoryInterface.sol\";\n\nimport \"@uma/core/contracts/common/implementation/ExpandedERC20.sol\";\n\n/**\n * @notice Factory to create new LP ERC20 tokens that represent a liquidity provider's position. HubPool is the\n * intended client of this contract.\n */\ncontract LpTokenFactory is LpTokenFactoryInterface {\n /**\n * @notice Deploys new LP token for L1 token. Sets caller as minter and burner of token.\n * @param l1Token L1 token to name in LP token name.\n * @return address of new LP token.\n */\n function createLpToken(address l1Token) public returns (address) {\n ExpandedERC20 lpToken = new ExpandedERC20(\n _concatenate(\"Across V2 \", IERC20Metadata(l1Token).name(), \" LP Token\"), // LP Token Name\n _concatenate(\"Av2-\", IERC20Metadata(l1Token).symbol(), \"-LP\"), // LP Token Symbol\n IERC20Metadata(l1Token).decimals() // LP Token Decimals\n );\n\n lpToken.addMinter(msg.sender); // Set the caller as the LP Token's minter.\n lpToken.addBurner(msg.sender); // Set the caller as the LP Token's burner.\n lpToken.resetOwner(msg.sender); // Set the caller as the LP Token's owner.\n\n return address(lpToken);\n }\n\n function _concatenate(\n string memory a,\n string memory b,\n string memory c\n ) internal pure returns (string memory) {\n return string(abi.encodePacked(a, b, c));\n }\n}\n" + }, + "contracts/interfaces/LpTokenFactoryInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @notice Factory to create new LP ERC20 tokens that represent a liquidity provider's position. HubPool is the\n * intended client of this contract.\n */\ninterface LpTokenFactoryInterface {\n /**\n * @notice Deploys new LP token for L1 token. Sets caller as minter and burner of token.\n * @param l1Token L1 token to name in LP token name.\n * @return address of new LP token.\n */\n function createLpToken(address l1Token) external returns (address);\n}\n" + }, + "contracts/Polygon_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./PolygonTokenBridger.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./interfaces/SpokePoolInterface.sol\";\n\n/**\n * @notice IFxMessageProcessor represents interface to process messages.\n */\ninterface IFxMessageProcessor {\n /**\n * @notice Called by FxChild upon receiving L1 message that targets this contract. Performs an additional check\n * that the L1 caller was the expected cross domain admin, and then delegate calls.\n * @notice Polygon bridge only executes this external function on the target Polygon contract when relaying\n * messages from L1, so all functions on this SpokePool are expected to originate via this call.\n * @dev stateId value isn't used because it isn't relevant for this method. It doesn't care what state sync\n * triggered this call.\n * @param rootMessageSender Original L1 sender of data.\n * @param data ABI encoded function call to execute on this contract.\n */\n function processMessageFromRoot(\n uint256 stateId,\n address rootMessageSender,\n bytes calldata data\n ) external;\n}\n\n/**\n * @notice Polygon specific SpokePool.\n */\ncontract Polygon_SpokePool is IFxMessageProcessor, SpokePool {\n using SafeERC20Upgradeable for PolygonIERC20Upgradeable;\n\n // Address of FxChild which sends and receives messages to and from L1.\n address public fxChild;\n\n // Contract deployed on L1 and L2 processes all cross-chain transfers between this contract and the the HubPool.\n // Required because bridging tokens from Polygon to Ethereum has special constraints.\n PolygonTokenBridger public polygonTokenBridger;\n\n // Internal variable that only flips temporarily to true upon receiving messages from L1. Used to authenticate that\n // the caller is the fxChild AND that the fxChild called processMessageFromRoot\n bool private callValidated;\n\n event PolygonTokensBridged(address indexed token, address indexed receiver, uint256 amount);\n event SetFxChild(address indexed newFxChild);\n event SetPolygonTokenBridger(address indexed polygonTokenBridger);\n event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender);\n\n // Note: validating calls this way ensures that strange calls coming from the fxChild won't be misinterpreted.\n // Put differently, just checking that msg.sender == fxChild is not sufficient.\n // All calls that have admin privileges must be fired from within the processMessageFromRoot method that's gone\n // through validation where the sender is checked and the root (mainnet) sender is also validated.\n // This modifier sets the callValidated variable so this condition can be checked in _requireAdminSender().\n modifier validateInternalCalls() {\n // Make sure callValidated is set to True only once at beginning of processMessageFromRoot, which prevents\n // processMessageFromRoot from being re-entered.\n require(!callValidated, \"callValidated already set\");\n\n // This sets a variable indicating that we're now inside a validated call.\n // Note: this is used by other methods to ensure that this call has been validated by this method and is not\n // spoofed. See comment for `_requireAdminSender` for more details.\n callValidated = true;\n\n _;\n\n // Reset callValidated to false to disallow admin calls after this method exits.\n callValidated = false;\n }\n\n /**\n * @notice Construct the Polygon SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _polygonTokenBridger Token routing contract that sends tokens from here to HubPool. Changeable by Admin.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wmaticAddress Replaces wrappedNativeToken for this network since MATIC is the native currency on polygon.\n * @param _fxChild FxChild contract, changeable by Admin.\n */\n function initialize(\n uint32 _initialDepositId,\n PolygonTokenBridger _polygonTokenBridger,\n address _crossDomainAdmin,\n address _hubPool,\n address _wmaticAddress, // Note: wmatic is used here since it is the token sent via msg.value on polygon.\n address _fxChild\n ) public initializer {\n callValidated = false;\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wmaticAddress);\n polygonTokenBridger = _polygonTokenBridger;\n //slither-disable-next-line missing-zero-check\n fxChild = _fxChild;\n }\n\n /********************************************************\n * POLYGON-SPECIFIC CROSS-CHAIN ADMIN FUNCTIONS *\n ********************************************************/\n\n /**\n * @notice Change FxChild address. Callable only by admin via processMessageFromRoot.\n * @param newFxChild New FxChild.\n */\n function setFxChild(address newFxChild) public onlyAdmin nonReentrant {\n //slither-disable-next-line missing-zero-check\n fxChild = newFxChild;\n emit SetFxChild(newFxChild);\n }\n\n /**\n * @notice Change polygonTokenBridger address. Callable only by admin via processMessageFromRoot.\n * @param newPolygonTokenBridger New Polygon Token Bridger contract.\n */\n function setPolygonTokenBridger(address payable newPolygonTokenBridger) public onlyAdmin nonReentrant {\n polygonTokenBridger = PolygonTokenBridger(newPolygonTokenBridger);\n emit SetPolygonTokenBridger(address(newPolygonTokenBridger));\n }\n\n /**\n * @notice Called by FxChild upon receiving L1 message that targets this contract. Performs an additional check\n * that the L1 caller was the expected cross domain admin, and then delegate calls.\n * @notice Polygon bridge only executes this external function on the target Polygon contract when relaying\n * messages from L1, so all functions on this SpokePool are expected to originate via this call.\n * @dev stateId value isn't used because it isn't relevant for this method. It doesn't care what state sync\n * triggered this call.\n * @param rootMessageSender Original L1 sender of data.\n * @param data ABI encoded function call to execute on this contract.\n */\n function processMessageFromRoot(\n uint256, /*stateId*/\n address rootMessageSender,\n bytes calldata data\n ) public validateInternalCalls {\n // Validation logic.\n require(msg.sender == fxChild, \"Not from fxChild\");\n require(rootMessageSender == crossDomainAdmin, \"Not from mainnet admin\");\n\n // This uses delegatecall to take the information in the message and process it as a function call on this contract.\n /// This is a safe delegatecall because its made to address(this) so there is no risk of delegating to a\n /// selfdestruct().\n //slither-disable-start low-level-calls\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, ) = address(this).delegatecall(data);\n //slither-disable-end low-level-calls\n require(success, \"delegatecall failed\");\n\n emit ReceivedMessageFromL1(msg.sender, rootMessageSender);\n }\n\n /**\n * @notice Allows the caller to trigger the wrapping of any unwrapped matic tokens.\n * @dev Unlike other ERC20 transfers, Matic transfers from L1 -> L2 bridging don't result in an L2 call into\n * the contract receiving the tokens, so wrapping must be done via a separate transaction. In other words,\n * we can't rely upon a `fallback()` method being triggered to wrap MATIC upon receiving it.\n */\n function wrap() public nonReentrant {\n _wrap();\n }\n\n /**\n * @notice Executes a relayer refund leaf stored as part of a root bundle. Will send the relayer the amount they\n * sent to the recipient plus a relayer fee.\n * @dev this is only overridden to wrap any matic the contract holds before running.\n * @param rootBundleId Unique ID of root bundle containing relayer refund root that this leaf is contained in.\n * @param relayerRefundLeaf Contains all data necessary to reconstruct leaf contained in root bundle and to\n * refund relayer. This data structure is explained in detail in the SpokePoolInterface.\n * @param proof Inclusion proof for this leaf in relayer refund root in root bundle.\n */\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) public override nonReentrant {\n _wrap();\n _executeRelayerRefundLeaf(rootBundleId, relayerRefundLeaf, proof);\n }\n\n /**\n * @notice Executes a slow relay leaf stored as part of a root bundle. Will send the full amount remaining in the\n * relay to the recipient, less fees.\n * @dev This function assumes that the relay's destination chain ID is the current chain ID, which prevents\n * the caller from executing a slow relay intended for another chain on this chain. This is only overridden to call\n * wrap before running the function.\n * @param depositor Depositor on origin chain who set this chain as the destination chain.\n * @param recipient Specified recipient on this chain.\n * @param destinationToken Token to send to recipient. Should be mapped to the origin token, origin chain ID\n * and this chain ID via a mapping on the HubPool.\n * @param amount Full size of the deposit.\n * @param originChainId Chain of SpokePool where deposit originated.\n * @param realizedLpFeePct Fee % based on L1 HubPool utilization at deposit quote time. Deterministic based on\n * quote time.\n * @param relayerFeePct Original fee % to keep as relayer set by depositor.\n * @param depositId Unique deposit ID on origin spoke pool.\n * @param rootBundleId Unique ID of root bundle containing slow relay root that this leaf is contained in.\n * @param proof Inclusion proof for this leaf in slow relay root in root bundle.\n */\n function executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustment,\n bytes32[] memory proof\n ) public virtual override nonReentrant {\n _wrap();\n _executeSlowRelayLeaf(\n depositor,\n recipient,\n destinationToken,\n amount,\n originChainId,\n chainId(),\n realizedLpFeePct,\n relayerFeePct,\n depositId,\n rootBundleId,\n message,\n payoutAdjustment,\n proof\n );\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {\n PolygonIERC20Upgradeable(relayerRefundLeaf.l2TokenAddress).safeIncreaseAllowance(\n address(polygonTokenBridger),\n relayerRefundLeaf.amountToReturn\n );\n\n // Note: WrappedNativeToken is WMATIC on matic, so this tells the tokenbridger that this is an unwrappable native token.\n polygonTokenBridger.send(\n PolygonIERC20Upgradeable(relayerRefundLeaf.l2TokenAddress),\n relayerRefundLeaf.amountToReturn\n );\n\n emit PolygonTokensBridged(relayerRefundLeaf.l2TokenAddress, address(this), relayerRefundLeaf.amountToReturn);\n }\n\n function _wrap() internal {\n uint256 balance = address(this).balance;\n //slither-disable-next-line arbitrary-send-eth\n if (balance > 0) wrappedNativeToken.deposit{ value: balance }();\n }\n\n // @dev: This contract will trigger admin functions internally via the `processMessageFromRoot`, which is why\n // the `callValidated` check is made below and why we use the `validateInternalCalls` modifier on\n // `processMessageFromRoot`. This prevents calling the admin functions from any other method besides\n // `processMessageFromRoot`.\n function _requireAdminSender() internal view override {\n require(callValidated, \"Must call processMessageFromRoot\");\n }\n}\n" + }, + "contracts/chain-adapters/ZkSync_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n// Importing `Operations` contract which has the `QueueType` type\nimport \"@matterlabs/zksync-contracts/l1/contracts/zksync/Operations.sol\";\n\ninterface ZkSyncLike {\n function requestL2Transaction(\n address _contractAddressL2,\n bytes calldata _calldata,\n uint256 _ergsLimit,\n bytes[] calldata _factoryDeps,\n QueueType _queueType\n ) external payable returns (bytes32 txHash);\n}\n\ninterface ZkBridgeLike {\n function deposit(\n address _to,\n address _l1Token,\n uint256 _amount,\n QueueType _queueType\n ) external payable returns (bytes32 txHash);\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to ZkSync.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract ZkSync_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n // We need to pay a fee to submit transactions to the L1 --> L2 priority queue:\n // https://v2-docs.zksync.io/dev/zksync-v2/l1-l2-interop.html#priority-queue\n\n // The fee for a transactionis equal to `txBaseCost * gasPrice` where `txBaseCost` depends on the ergsLimit\n // (ergs = gas on ZkSync) and the calldata length. More details here:\n // https://v2-docs.zksync.io/dev/guide/l1-l2.html#using-contract-interface-in-your-project\n\n // Generally, the ergsLimit and l2GasPrice params are a bit hard to set and may change in the future once ZkSync\n // is deployed to mainnet. On testnet, gas price is set to 0 and gas used is 0 so its hard to accurately forecast.\n uint256 public immutable l2GasPrice = 1e9;\n\n uint32 public immutable ergsLimit = 1_000_000;\n\n // Hardcode WETH address for L1 since it will not change:\n WETH9Interface public immutable l1Weth = WETH9Interface(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6);\n\n // Hardcode the following ZkSync system contract addresses to save gas on construction. This adapter can be\n // redeployed in the event that the following addresses change.\n\n // Main contract used to send L1 --> L2 messages. Fetchable via `zks_getMainContract` method on JSON RPC.\n ZkSyncLike public immutable zkSync = ZkSyncLike(0xa0F968EbA6Bbd08F28Dc061C7856C15725983395);\n // Bridges to send ERC20 and ETH to L2. Fetchable via `zks_getBridgeContracts` method on JSON RPC.\n ZkBridgeLike public immutable zkErc20Bridge = ZkBridgeLike(0x7786255495348c08F82C09C82352019fAdE3BF29);\n ZkBridgeLike public immutable zkEthBridge = ZkBridgeLike(0xcbebcD41CeaBBC85Da9bb67527F58d69aD4DfFf5);\n\n event ZkSyncMessageRelayed(bytes32 txHash);\n\n /**\n * @notice Send cross-chain message to target on ZkSync.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message, or the message\n * will get stuck.\n * @param target Contract on Arbitrum that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n uint256 txBaseCost = _contractHasSufficientEthBalance();\n\n // Parameters passed to requestL2Transaction:\n // _contractAddressL2 is a parameter that defines the address of the contract to be called.\n // _calldata is a parameter that contains the calldata of the transaction call. It can be encoded the\n // same way as on Ethereum.\n // _ergsLimit is a parameter that contains the ergs limit of the transaction call. You can learn more about\n // ergs and the zkSync fee system here: https://v2-docs.zksync.io/dev/zksync-v2/fee-model.html\n // _factoryDeps is a list of bytecodes. It should contain the bytecode of the contract being deployed.\n // If the contract being deployed is a factory contract, i.e. it can deploy other contracts, the array should also contain the bytecodes of the contracts that can be deployed by it.\n // _queueType is a parameter required for the priority mode functionality. For the testnet,\n // QueueType.Deque should always be supplied.\n bytes32 txHash = zkSync.requestL2Transaction{ value: txBaseCost }(\n target,\n message,\n ergsLimit,\n new bytes[](0),\n QueueType.Deque\n );\n\n emit MessageRelayed(target, message);\n emit ZkSyncMessageRelayed(txHash);\n }\n\n /**\n * @notice Bridge tokens to ZkSync.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message\n * or the message will get stuck.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused.\n uint256 amount,\n address to\n ) external payable override {\n uint256 txBaseCost = _contractHasSufficientEthBalance();\n\n // If the l1Token is WETH then unwrap it to ETH then send the ETH to the standard bridge along with the base\n // cost.\n bytes32 txHash;\n if (l1Token == address(l1Weth)) {\n l1Weth.withdraw(amount);\n // Must set L1Token address to 0x0: https://github.com/matter-labs/v2-testnet-contracts/blob/3a0651357bb685751c2163e4cc65a240b0f602ef/l1/contracts/bridge/L1EthBridge.sol#L78\n txHash = zkEthBridge.deposit{ value: txBaseCost + amount }(to, address(0), amount, QueueType.Deque);\n } else {\n IERC20(l1Token).safeIncreaseAllowance(address(zkErc20Bridge), amount);\n txHash = zkErc20Bridge.deposit{ value: txBaseCost }(to, l1Token, amount, QueueType.Deque);\n }\n\n emit TokensRelayed(l1Token, l2Token, amount, to);\n emit ZkSyncMessageRelayed(txHash);\n }\n\n /**\n * @notice Returns required amount of ETH to send a message.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public pure returns (uint256) {\n return l2GasPrice * ergsLimit;\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/interfaces/AdapterInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @notice Sends cross chain messages and tokens to contracts on a specific L2 network.\n * This interface is implemented by an adapter contract that is deployed on L1.\n */\n\ninterface AdapterInterface {\n event MessageRelayed(address target, bytes message);\n\n event TokensRelayed(address l1Token, address l2Token, uint256 amount, address to);\n\n /**\n * @notice Send message to `target` on L2.\n * @dev This method is marked payable because relaying the message might require a fee\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\n * to the target contract on L2.\n * @param target L2 address to send message to.\n * @param message Message to send to `target`.\n */\n function relayMessage(address target, bytes calldata message) external payable;\n\n /**\n * @notice Send `amount` of `l1Token` to `to` on L2. `l2Token` is the L2 address equivalent of `l1Token`.\n * @dev This method is marked payable because relaying the message might require a fee\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\n * to the target contract on L2.\n * @param l1Token L1 token to bridge.\n * @param l2Token L2 token to receive.\n * @param amount Amount of `l1Token` to bridge.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable;\n}\n" + }, + "@matterlabs/zksync-contracts/l1/contracts/zksync/Operations.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT OR Apache-2.0\n\n\n\n/// @notice Priority Operation container\n/// @param canonicalTxHash Hashed priority operation data that is needed to process the operation\n/// @param expirationBlock Expiration block number (ETH block) for this request (must be satisfied before)\n/// @param layer2Tip Additional payment to the operator as an incentive to perform the operation\nstruct PriorityOperation {\n bytes32 canonicalTxHash;\n uint64 expirationBlock;\n uint192 layer2Tip;\n}\n\n/// @notice A structure that stores all priority operations by ID\n/// used for easy acceptance as an argument in functions\nstruct StoredOperations {\n mapping(uint64 => PriorityOperation) inner;\n}\n\n/// @notice Indicator that the operation can interact with Rollup and Porter trees, or only with Rollup\nenum OpTree {\n Full,\n Rollup\n}\n\n/// @notice Priority operations queue type\nenum QueueType {\n Deque,\n HeapBuffer,\n Heap\n}\n" + }, + "contracts/chain-adapters/Succinct_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/SuccinctInterfaces.sol\";\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Succinct_Adapter is AdapterInterface {\n ITelepathyBroadcaster public immutable succinctSourceAmb;\n uint16 public immutable destinationChainId;\n\n // Special Succinct event for additional tracking information.\n event SuccinctMessageRelayed(bytes32 messageRoot, uint16 destinationChainId, address target, bytes message);\n\n /**\n * @notice Constructs new Adapter.\n * @param _succinctSourceAmb address of the SourceAmb succinct contract for sending messages.\n * @param _destinationChainId chainId of the destination.\n */\n constructor(ITelepathyBroadcaster _succinctSourceAmb, uint16 _destinationChainId) {\n succinctSourceAmb = _succinctSourceAmb;\n destinationChainId = _destinationChainId;\n }\n\n /**\n * @notice Send cross-chain message to target on the destination.\n * @param target Contract on the destination that will receive the message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n bytes32 messageRoot = succinctSourceAmb.send(destinationChainId, target, message);\n\n // Note: this emits two events. MessageRelayed for the sake of compatibility with other adapters.\n // It emits SuccinctMessageRelayed to encode additional tracking information that is Succinct-specific.\n emit MessageRelayed(target, message);\n emit SuccinctMessageRelayed(messageRoot, destinationChainId, target, message);\n }\n\n /**\n * @notice No-op relay tokens method.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n // This method is intentionally left as a no-op.\n // If the adapter is intended to be able to relay tokens, this method should be overriden.\n }\n}\n" + }, + "contracts/external/interfaces/SuccinctInterfaces.sol": { + "content": "pragma solidity ^0.8.0;\n\n// These interfaces are a subset of the Succinct interfaces here: https://github.com/succinctlabs/telepathy-contracts.\n\n// This interface should be implemented by any contract wanting to receive messages sent over the Succinct bridge.\ninterface ITelepathyHandler {\n function handleTelepathy(\n uint16 _sourceChainId,\n address _senderAddress,\n bytes memory _data\n ) external returns (bytes4);\n}\n\n// This interface represents the contract that we call into to send messages over the Succinct AMB.\ninterface ITelepathyBroadcaster {\n function send(\n uint16 _recipientChainId,\n address _recipientAddress,\n bytes calldata _data\n ) external returns (bytes32);\n}\n" + }, + "contracts/Succinct_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./external/interfaces/SuccinctInterfaces.sol\";\n\n/**\n * @notice Succinct Spoke pool.\n */\ncontract Succinct_SpokePool is SpokePool, ITelepathyHandler {\n // Address of the succinct AMB contract.\n address public succinctTargetAmb;\n\n // Chain where HubPool is deployed that is linked to this SpokePool.\n uint16 public hubChainId;\n\n // Warning: this variable should _never_ be touched outside of this contract. It is intentionally set to be\n // private. Leaving it set to true can permanently disable admin calls.\n bool private adminCallValidated;\n\n event SetSuccinctTargetAmb(address indexed newSuccinctTargetAmb);\n event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender);\n\n // Note: validating calls this way ensures that strange calls coming from the succinctTargetAmb won't be\n // misinterpreted. Put differently, just checking that msg.sender == succinctTargetAmb is not sufficient.\n // All calls that have admin privileges must be fired from within the handleTelepathy method that's gone\n // through validation where the sender is checked and the sender from the other chain is also validated.\n // This modifier sets the adminCallValidated variable so this condition can be checked in _requireAdminSender().\n modifier validateInternalCalls() {\n // Make sure adminCallValidated is set to True only once at beginning of processMessageFromRoot, which prevents\n // processMessageFromRoot from being re-entered.\n require(!adminCallValidated, \"adminCallValidated already set\");\n\n // This sets a variable indicating that we're now inside a validated call.\n // Note: this is used by other methods to ensure that this call has been validated by this method and is not\n // spoofed.\n adminCallValidated = true;\n\n _;\n\n // Reset adminCallValidated to false to disallow admin calls after this method exits.\n adminCallValidated = false;\n }\n\n /**\n * @notice Construct the Succinct SpokePool.\n * @param _hubChainId Chain ID of the chain where the HubPool is deployed.\n * @param _succinctTargetAmb Address of the succinct AMB contract.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wrappedNativeToken Address of the wrapped native token.\n */\n function initialize(\n uint16 _hubChainId,\n address _succinctTargetAmb,\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool,\n address _wrappedNativeToken\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wrappedNativeToken);\n succinctTargetAmb = _succinctTargetAmb;\n hubChainId = _hubChainId;\n }\n\n /**\n * @notice Admin can reset the succinct contract address.\n * @param _succinctTargetAmb Address of the succinct AMB contract.\n */\n function setSuccinctTargetAmb(address _succinctTargetAmb) external onlyAdmin {\n succinctTargetAmb = _succinctTargetAmb;\n emit SetSuccinctTargetAmb(_succinctTargetAmb);\n }\n\n /**\n * @notice This will be called by Succinct AMB on this network to relay a message sent from the HubPool.\n * @param _sourceChainId Chain ID of the chain where the message originated.\n * @param _senderAddress Address of the sender on the chain where the message originated.\n * @param _data Data to be received and executed on this contract.\n */\n function handleTelepathy(\n uint16 _sourceChainId,\n address _senderAddress,\n bytes memory _data\n ) external override validateInternalCalls returns (bytes4) {\n // Validate msg.sender as succinct, the x-chain sender as being the hubPool (the admin) and the source chain as\n // 1 (mainnet).\n require(msg.sender == succinctTargetAmb, \"caller not succinct AMB\");\n require(_senderAddress == hubPool, \"sender not hubPool\");\n require(_sourceChainId == hubChainId, \"source chain not hub chain\");\n\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, ) = address(this).delegatecall(_data);\n require(success, \"delegatecall failed\");\n\n emit ReceivedMessageFromL1(msg.sender, _senderAddress);\n return ITelepathyHandler.handleTelepathy.selector;\n }\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory) internal override {\n // This method is a no-op. If the chain intends to include bridging functionality, this must be overriden.\n // If not, leaving this unimplemented means this method may be triggered, but the result will be that no\n // balance is transferred.\n }\n\n // Check that the handleTelepathy method has validated the method to ensure the sender is authenticated.\n function _requireAdminSender() internal view override {\n require(adminCallValidated, \"Admin call not validated\");\n }\n}\n" + }, + "contracts/chain-adapters/Polygon_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Send tokens to Polygon.\n */\ninterface IRootChainManager {\n /**\n * @notice Send msg.value of ETH to Polygon\n * @param user Recipient of ETH on Polygon.\n */\n function depositEtherFor(address user) external payable;\n\n /**\n * @notice Send ERC20 tokens to Polygon.\n * @param user Recipient of L2 equivalent tokens on Polygon.\n * @param rootToken L1 Address of token to send.\n * @param depositData Data to pass to L2 including amount of tokens to send. Should be abi.encode(amount).\n */\n function depositFor(\n address user,\n address rootToken,\n bytes calldata depositData\n ) external;\n}\n\n/**\n * @notice Send arbitrary messages to Polygon.\n */\ninterface IFxStateSender {\n /**\n * @notice Send arbitrary message to Polygon.\n * @param _receiver Address on Polygon to receive message.\n * @param _data Message to send to `_receiver` on Polygon.\n */\n function sendMessageToChild(address _receiver, bytes calldata _data) external;\n}\n\n/**\n * @notice Similar to RootChainManager, but for Matic (Plasma) bridge.\n */\ninterface DepositManager {\n /**\n * @notice Send tokens to Polygon. Only used to send MATIC in this Polygon_Adapter.\n * @param token L1 token to send. Should be MATIC.\n * @param user Recipient of L2 equivalent tokens on Polygon.\n * @param amount Amount of `token` to send.\n */\n function depositERC20ForUser(\n address token,\n address user,\n uint256 amount\n ) external;\n}\n\n/**\n * @notice Sends cross chain messages Polygon L2 network.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Polygon_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n IRootChainManager public immutable rootChainManager;\n IFxStateSender public immutable fxStateSender;\n DepositManager public immutable depositManager;\n address public immutable erc20Predicate;\n address public immutable l1Matic;\n WETH9Interface public immutable l1Weth;\n\n /**\n * @notice Constructs new Adapter.\n * @param _rootChainManager RootChainManager Polygon system contract to deposit tokens over the PoS bridge.\n * @param _fxStateSender FxStateSender Polygon system contract to send arbitrary messages to L2.\n * @param _depositManager DepositManager Polygon system contract to deposit tokens over the Plasma bridge (Matic).\n * @param _erc20Predicate ERC20Predicate Polygon system contract to approve when depositing to the PoS bridge.\n * @param _l1Matic matic address on l1.\n * @param _l1Weth WETH address on L1.\n */\n constructor(\n IRootChainManager _rootChainManager,\n IFxStateSender _fxStateSender,\n DepositManager _depositManager,\n address _erc20Predicate,\n address _l1Matic,\n WETH9Interface _l1Weth\n ) {\n rootChainManager = _rootChainManager;\n fxStateSender = _fxStateSender;\n depositManager = _depositManager;\n erc20Predicate = _erc20Predicate;\n l1Matic = _l1Matic;\n l1Weth = _l1Weth;\n }\n\n /**\n * @notice Send cross-chain message to target on Polygon.\n * @param target Contract on Polygon that will receive message.\n * @param message Data to send to target.\n */\n\n function relayMessage(address target, bytes calldata message) external payable override {\n fxStateSender.sendMessageToChild(target, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Polygon.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(l1Weth)) {\n l1Weth.withdraw(amount);\n rootChainManager.depositEtherFor{ value: amount }(to);\n } else if (l1Token == l1Matic) {\n IERC20(l1Token).safeIncreaseAllowance(address(depositManager), amount);\n depositManager.depositERC20ForUser(l1Token, to, amount);\n } else {\n IERC20(l1Token).safeIncreaseAllowance(erc20Predicate, amount);\n rootChainManager.depositFor(to, l1Token, abi.encode(amount));\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Optimism_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Interface for Synthetix custom bridge to Optimism.\n */\ninterface SynthetixBridgeToOptimism is IL1StandardBridge {\n /**\n * @notice Send tokens to Optimism.\n * @param to Address to send tokens to on L2.\n * @param amount Amount of tokens to send.\n */\n function depositTo(address to, uint256 amount) external;\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to Optimism.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore it's only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Optimism_Adapter is CrossDomainEnabled, AdapterInterface {\n using SafeERC20 for IERC20;\n uint32 public immutable l2GasLimit = 2_000_000;\n\n WETH9Interface public immutable l1Weth;\n\n IL1StandardBridge public immutable l1StandardBridge;\n\n // Optimism has the ability to support \"custom\" bridges. These bridges are not supported by the canonical bridge\n // and so we need to store the address of the custom token and the associated bridge. In the event we want to\n // support a new token that is not supported by Optimism, we can add a new custom bridge for it and re-deploy the\n // adapter. A full list of custom optimism tokens and their associated bridges can be found here:\n // https://github.com/ethereum-optimism/ethereum-optimism.github.io/blob/master/optimism.tokenlist.json\n address public immutable dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n address public immutable daiOptimismBridge = 0x10E6593CDda8c58a1d0f14C5164B376352a55f2F;\n address public immutable snx = 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F;\n address public immutable snxOptimismBridge = 0x39Ea01a0298C315d149a490E34B59Dbf2EC7e48F;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Optimism system contract.\n * @param _l1StandardBridge Standard bridge contract.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge\n ) CrossDomainEnabled(_crossDomainMessenger) {\n l1Weth = _l1Weth;\n l1StandardBridge = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Optimism.\n * @param target Contract on Optimism that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, uint32(l2GasLimit), message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Optimism.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(l1Weth)) {\n l1Weth.withdraw(amount);\n l1StandardBridge.depositETHTo{ value: amount }(to, l2GasLimit, \"\");\n } else {\n address bridgeToUse = address(l1StandardBridge);\n\n // Check if the L1 token requires a custom bridge. If so, use that bridge over the standard bridge.\n if (l1Token == dai) bridgeToUse = daiOptimismBridge; // 1. DAI\n if (l1Token == snx) bridgeToUse = snxOptimismBridge; // 2. SNX\n\n IERC20(l1Token).safeIncreaseAllowance(bridgeToUse, amount);\n if (l1Token == snx) SynthetixBridgeToOptimism(bridgeToUse).depositTo(to, amount);\n else IL1StandardBridge(bridgeToUse).depositERC20To(l1Token, l2Token, to, amount, l2GasLimit, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/CrossDomainEnabled.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title CrossDomainEnabled\n * @dev Helper contract for contracts performing cross-domain communications between L1 and Optimism.\n * @dev This modifies the eth-optimism/CrossDomainEnabled contract only by changing state variables to be\n * immutable for use in contracts like the Optimism_Adapter which use delegateCall().\n */\ncontract CrossDomainEnabled {\n // Messenger contract used to send and recieve messages from the other domain.\n address public immutable messenger;\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on the current layer.\n */\n constructor(address _messenger) {\n messenger = _messenger;\n }\n\n /**\n * Enforces that the modified function is only callable by a specific cross-domain account.\n * @param _sourceDomainAccount The only account on the originating domain which is\n * authenticated to call this function.\n */\n modifier onlyFromCrossDomainAccount(address _sourceDomainAccount) {\n require(msg.sender == address(getCrossDomainMessenger()), \"invalid cross domain messenger\");\n\n require(\n getCrossDomainMessenger().xDomainMessageSender() == _sourceDomainAccount,\n \"invalid cross domain sender\"\n );\n\n _;\n }\n\n /**\n * Gets the messenger, usually from storage. This function is exposed in case a child contract\n * needs to override.\n * @return The address of the cross-domain messenger contract which should be used.\n */\n function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\n return ICrossDomainMessenger(messenger);\n }\n\n /**\n * Sends a message to an account on another domain\n * @param _crossDomainTarget The intended recipient on the destination domain\n * @param _message The data to send to the target (usually calldata to a function with\n * onlyFromCrossDomainAccount())\n * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n */\n function sendCrossDomainMessage(\n address _crossDomainTarget,\n uint32 _gasLimit,\n bytes calldata _message\n ) internal {\n // slither-disable-next-line reentrancy-events, reentrancy-benign\n getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\n }\n}\n" + }, + "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\nimport \"./IL1ERC20Bridge.sol\";\n\n/**\n * @title IL1StandardBridge\n */\ninterface IL1StandardBridge is IL1ERC20Bridge {\n /**********\n * Events *\n **********/\n event ETHDepositInitiated(\n address indexed _from,\n address indexed _to,\n uint256 _amount,\n bytes _data\n );\n\n event ETHWithdrawalFinalized(\n address indexed _from,\n address indexed _to,\n uint256 _amount,\n bytes _data\n );\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * @dev Deposit an amount of the ETH to the caller's balance on L2.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;\n\n /**\n * @dev Deposit an amount of ETH to a recipient's balance on L2.\n * @param _to L2 address to credit the withdrawal to.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositETHTo(\n address _to,\n uint32 _l2Gas,\n bytes calldata _data\n ) external payable;\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called\n * before the withdrawal is finalized.\n * @param _from L2 address initiating the transfer.\n * @param _to L1 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external;\n}\n" + }, + "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessenger {\n /**********\n * Events *\n **********/\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /*************\n * Variables *\n *************/\n\n function xDomainMessageSender() external view returns (address);\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * Sends a cross domain message to the target messenger.\n * @param _target Target contract address.\n * @param _message Message to send to the target.\n * @param _gasLimit Gas limit for the provided message.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _gasLimit\n ) external;\n}\n" + }, + "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IL1ERC20Bridge\n */\ninterface IL1ERC20Bridge {\n /**********\n * Events *\n **********/\n\n event ERC20DepositInitiated(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * @dev get the address of the corresponding L2 bridge contract.\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external returns (address);\n\n /**\n * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n * @param _l1Token Address of the L1 ERC20 we are depositing\n * @param _l2Token Address of the L1 respective L2 ERC20\n * @param _amount Amount of the ERC20 to deposit\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _l2Gas,\n bytes calldata _data\n ) external;\n\n /**\n * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n * @param _l1Token Address of the L1 ERC20 we are depositing\n * @param _l2Token Address of the L1 respective L2 ERC20\n * @param _to L2 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _l2Gas,\n bytes calldata _data\n ) external;\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n * L1 ERC20 token.\n * This call will fail if the initialized withdrawal from L2 has not been finalized.\n *\n * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n * @param _l2Token Address of L2 token where withdrawal was initiated.\n * @param _from L2 address initiating the transfer.\n * @param _to L1 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _data Data provided by the sender on L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external;\n}\n" + }, + "contracts/chain-adapters/Boba_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Boba. This is a modified version of the Optimism adapter\n * that excludes the custom bridging logic.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Boba_Adapter is CrossDomainEnabled, AdapterInterface {\n using SafeERC20 for IERC20;\n uint32 public immutable l2GasLimit = 2_000_000;\n\n WETH9Interface public immutable l1Weth;\n\n IL1StandardBridge public immutable l1StandardBridge;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Boba system contract.\n * @param _l1StandardBridge Standard bridge contract.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge\n ) CrossDomainEnabled(_crossDomainMessenger) {\n l1Weth = _l1Weth;\n l1StandardBridge = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Boba.\n * @param target Contract on Boba that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, uint32(l2GasLimit), message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Boba.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(l1Weth)) {\n l1Weth.withdraw(amount);\n l1StandardBridge.depositETHTo{ value: amount }(to, l2GasLimit, \"\");\n } else {\n IL1StandardBridge _l1StandardBridge = l1StandardBridge;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, l2GasLimit, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Mock_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Contract used for testing communication between HubPool and Adapter.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Mock_Adapter is AdapterInterface {\n event RelayMessageCalled(address target, bytes message, address caller);\n\n event RelayTokensCalled(address l1Token, address l2Token, uint256 amount, address to, address caller);\n\n Mock_Bridge public immutable bridge;\n\n constructor() {\n bridge = new Mock_Bridge();\n }\n\n function relayMessage(address target, bytes calldata message) external payable override {\n bridge.bridgeMessage(target, message);\n emit RelayMessageCalled(target, message, msg.sender);\n }\n\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n IERC20(l1Token).approve(address(bridge), amount);\n bridge.bridgeTokens(l1Token, amount);\n emit RelayTokensCalled(l1Token, l2Token, amount, to, msg.sender);\n }\n}\n\n// This contract is intended to \"act like\" a simple version of an L2 bridge.\n// It's primarily meant to better reflect how a true L2 bridge interaction might work to give better gas estimates.\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Mock_Bridge {\n event BridgedTokens(address token, uint256 amount);\n event BridgedMessage(address target, bytes message);\n\n mapping(address => uint256) public deposits;\n\n function bridgeTokens(address token, uint256 amount) public {\n IERC20(token).transferFrom(msg.sender, address(this), amount);\n deposits[token] += amount;\n emit BridgedTokens(token, amount);\n }\n\n function bridgeMessage(address target, bytes calldata message) public {\n emit BridgedMessage(target, message);\n }\n}\n" + }, + "contracts/chain-adapters/Ethereum_RescueAdapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice This adapter is built for emergencies to rescue funds from a Hub in the event of a misconfiguration or\n * security issue.\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Ethereum_RescueAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n address public immutable rescueAddress;\n\n /**\n * @notice Constructs new Adapter.\n * @param _rescueAddress Rescue address to send funds to.\n */\n constructor(address _rescueAddress) {\n rescueAddress = _rescueAddress;\n }\n\n /**\n * @notice Rescues the tokens from the calling contract.\n * @param message The encoded address of the ERC20 to send to the rescue addres.\n */\n function relayMessage(address, bytes memory message) external payable override {\n IERC20 tokenAddress = IERC20(abi.decode(message, (address)));\n\n // Transfer full balance of tokens to the rescue address.\n tokenAddress.safeTransfer(rescueAddress, tokenAddress.balanceOf(address(this)));\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"relayTokens disabled\");\n }\n}\n" + }, + "contracts/chain-adapters/Ethereum_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Ethereum SpokePool.\n * @notice This contract should always be deployed on the same chain as the HubPool, as it acts as a pass-through\n * contract between HubPool and SpokePool on the same chain. Its named \"Ethereum_Adapter\" because a core assumption\n * is that the HubPool will be deployed on Ethereum, so this adapter will be used to communicate between HubPool\n * and the Ethereum_SpokePool.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Ethereum_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Send message to target on Ethereum.\n * @notice This function, and contract overall, is not useful in practice except that the HubPool\n * expects to interact with the SpokePool via an Adapter, so when communicating to the Ethereum_SpokePool, it must\n * send messages via this pass-through contract.\n * @param target Contract that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n _executeCall(target, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Send tokens to target.\n * @param l1Token L1 token to send.\n * @param l2Token Unused parameter in this contract.\n * @param amount Amount of L1 tokens to send.\n * @param to recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused for ethereum since we are assuming that the HubPool is only deployed\n // on this network.\n uint256 amount,\n address to\n ) external payable override {\n IERC20(l1Token).safeTransfer(to, amount);\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n // Note: this snippet of code is copied from Governor.sol. Source: https://github.com/UMAprotocol/protocol/blob/5b37ea818a28479c01e458389a83c3e736306b17/packages/core/contracts/oracle/implementation/Governor.sol#L190-L207\n function _executeCall(address to, bytes memory data) private {\n // Note: this snippet of code is copied from Governor.sol and modified to not include any \"value\" field.\n\n bool success;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let inputData := add(data, 0x20)\n let inputDataSize := mload(data)\n // Hardcode value to be 0 for relayed governance calls in order to avoid addressing complexity of bridging\n // value cross-chain.\n success := call(gas(), to, 0, inputData, inputDataSize, 0, 0)\n }\n require(success, \"execute call failed\");\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport { ArbitrumL1ERC20GatewayLike } from \"./Arbitrum_Adapter.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice This adapter is built for emergencies to send funds from the Hub to a Spoke in the event that a spoke pool\n * received a duplicate root bundle relay, due to some replay issue.\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_SendTokensAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n uint256 public immutable l2MaxSubmissionCost = 0.01e18;\n uint256 public immutable l2GasPrice = 5e9;\n uint32 public constant RELAY_TOKENS_L2_GAS_LIMIT = 300_000;\n\n ArbitrumL1ERC20GatewayLike public immutable l1ERC20GatewayRouter;\n\n address public constant l2RefundL2Address = 0x428AB2BA90Eba0a4Be7aF34C9Ac451ab061AC010;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ERC20GatewayRouter ERC20 gateway router contract to send tokens to Arbitrum.\n */\n constructor(ArbitrumL1ERC20GatewayLike _l1ERC20GatewayRouter) {\n l1ERC20GatewayRouter = _l1ERC20GatewayRouter;\n }\n\n /**\n * @notice Send tokens to SpokePool. Enables HubPool admin to call relaySpokePoolAdminFunction that will trigger\n * this function.\n * @dev This performs similar logic to relayTokens in the normal Arbitrum_Adapter by sending tokens\n * the Arbitrum_SpokePool out of the HubPool.\n * @param message The encoded address of the ERC20 to send to the rescue address.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n (address l1Token, uint256 amount) = abi.decode(message, (address, uint256));\n\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance();\n\n // Approve the gateway, not the router, to spend the hub pool's balance. The gateway, which is different\n // per L1 token, will temporarily escrow the tokens to be bridged and pull them from this contract.\n address erc20Gateway = l1ERC20GatewayRouter.getGateway(l1Token);\n IERC20(l1Token).safeIncreaseAllowance(erc20Gateway, amount);\n\n // `outboundTransfer` expects that the caller includes a bytes message as the last param that includes the\n // maxSubmissionCost to use when creating an L2 retryable ticket: https://github.com/OffchainLabs/arbitrum/blob/e98d14873dd77513b569771f47b5e05b72402c5e/packages/arb-bridge-peripherals/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L232\n bytes memory data = abi.encode(l2MaxSubmissionCost, \"\");\n\n l1ERC20GatewayRouter.outboundTransferCustomRefund{ value: requiredL1CallValue }(\n l1Token,\n l2RefundL2Address,\n target,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n l2GasPrice,\n data\n );\n\n // Purposefully not emitting any events so as not to confuse off-chain monitors that track this event.\n // emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"relayTokens disabled\");\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public pure returns (uint256) {\n return l2MaxSubmissionCost + l2GasPrice * RELAY_TOKENS_L2_GAS_LIMIT;\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_Adapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Interface for Arbitrum's L1 Inbox contract used to send messages to Arbitrum.\n */\ninterface ArbitrumL1InboxLike {\n /**\n * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts\n * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error\n * @dev Caller must set msg.value equal to at least `maxSubmissionCost + maxGas * gasPriceBid`.\n * all msg.value will deposited to callValueRefundAddress on L2\n * @dev More details can be found here: https://developer.arbitrum.io/arbos/l1-to-l2-messaging\n * @param to destination L2 contract address\n * @param l2CallValue call value for retryable L2 message\n * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\n * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance\n * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param data ABI encoded data of L2 message\n * @return unique message number of the retryable transaction\n */\n function createRetryableTicket(\n address to,\n uint256 l2CallValue,\n uint256 maxSubmissionCost,\n address excessFeeRefundAddress,\n address callValueRefundAddress,\n uint256 gasLimit,\n uint256 maxFeePerGas,\n bytes calldata data\n ) external payable returns (uint256);\n\n /**\n * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts\n * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed\n * funds come from the deposit alone, rather than falling back on the user's L2 balance\n * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).\n * createRetryableTicket method is the recommended standard.\n * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error\n * @param to destination L2 contract address\n * @param l2CallValue call value for retryable L2 message\n * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\n * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance\n * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param data ABI encoded data of L2 message\n * @return unique message number of the retryable transaction\n */\n function unsafeCreateRetryableTicket(\n address to,\n uint256 l2CallValue,\n uint256 maxSubmissionCost,\n address excessFeeRefundAddress,\n address callValueRefundAddress,\n uint256 gasLimit,\n uint256 maxFeePerGas,\n bytes calldata data\n ) external payable returns (uint256);\n}\n\n/**\n * @notice Layer 1 Gateway contract for bridging standard ERC20s to Arbitrum.\n */\ninterface ArbitrumL1ERC20GatewayLike {\n /**\n * @notice Deprecated in favor of outboundTransferCustomRefund but still used in custom bridges\n * like the DAI bridge.\n * @dev Refunded to aliased L2 address of sender if sender has code on L1, otherwise to to sender's EOA on L2.\n * @param _l1Token L1 address of ERC20\n * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract),\n * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to\n * cancel the retryable ticket and receive callvalue refund\n * @param _amount Token Amount\n * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution\n * @param _gasPriceBid Gas price for L2 execution\n * @param _data encoded data from router and user\n * @return res abi encoded inbox sequence number\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n /**\n * @notice Deposit ERC20 token from Ethereum into Arbitrum.\n * @dev L2 address alias will not be applied to the following types of addresses on L1:\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * @param _l1Token L1 address of ERC20\n * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2\n * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract),\n * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to\n * cancel the retryable ticket and receive callvalue refund\n * @param _amount Token Amount\n * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution\n * @param _gasPriceBid Gas price for L2 execution\n * @param _data encoded data from router and user\n * @return res abi encoded inbox sequence number\n */\n function outboundTransferCustomRefund(\n address _l1Token,\n address _refundTo,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n /**\n * @notice get ERC20 gateway for token.\n * @param _token ERC20 address.\n * @return address of ERC20 gateway.\n */\n function getGateway(address _token) external view returns (address);\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to Arbitrum.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n // Amount of ETH allocated to pay for the base submission fee. The base submission fee is a parameter unique to\n // retryable transactions; the user is charged the base submission fee to cover the storage costs of keeping their\n // ticket’s calldata in the retry buffer. (current base submission fee is queryable via\n // ArbRetryableTx.getSubmissionPrice). ArbRetryableTicket precompile interface exists at L2 address\n // 0x000000000000000000000000000000000000006E.\n uint256 public constant l2MaxSubmissionCost = 0.01e18;\n\n // L2 Gas price bid for immediate L2 execution attempt (queryable via standard eth*gasPrice RPC)\n uint256 public constant l2GasPrice = 5e9; // 5 gWei\n\n uint32 public constant RELAY_TOKENS_L2_GAS_LIMIT = 300_000;\n uint32 public constant RELAY_MESSAGE_L2_GAS_LIMIT = 2_000_000;\n\n // This address on L2 receives extra ETH that is left over after relaying a message via the inbox.\n address public constant l2RefundL2Address = 0x428AB2BA90Eba0a4Be7aF34C9Ac451ab061AC010;\n\n ArbitrumL1InboxLike public immutable l1Inbox;\n\n ArbitrumL1ERC20GatewayLike public immutable l1ERC20GatewayRouter;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ArbitrumInbox Inbox helper contract to send messages to Arbitrum.\n * @param _l1ERC20GatewayRouter ERC20 gateway router contract to send tokens to Arbitrum.\n */\n constructor(ArbitrumL1InboxLike _l1ArbitrumInbox, ArbitrumL1ERC20GatewayLike _l1ERC20GatewayRouter) {\n l1Inbox = _l1ArbitrumInbox;\n l1ERC20GatewayRouter = _l1ERC20GatewayRouter;\n }\n\n /**\n * @notice Send cross-chain message to target on Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param target Contract on Arbitrum that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance(RELAY_MESSAGE_L2_GAS_LIMIT);\n\n l1Inbox.createRetryableTicket{ value: requiredL1CallValue }(\n target, // destAddr destination L2 contract address\n 0, // l2CallValue call value for retryable L2 message\n l2MaxSubmissionCost, // maxSubmissionCost Max gas deducted from user's L2 balance to cover base fee\n l2RefundL2Address, // excessFeeRefundAddress maxgas * gasprice - execution cost gets credited here on L2\n l2RefundL2Address, // callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n RELAY_MESSAGE_L2_GAS_LIMIT, // maxGas Max gas deducted from user's L2 balance to cover L2 execution\n l2GasPrice, // gasPriceBid price bid for L2 execution\n message // data ABI encoded data of L2 message\n );\n\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused for Arbitrum.\n uint256 amount,\n address to\n ) external payable override {\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance(RELAY_TOKENS_L2_GAS_LIMIT);\n\n // Approve the gateway, not the router, to spend the hub pool's balance. The gateway, which is different\n // per L1 token, will temporarily escrow the tokens to be bridged and pull them from this contract.\n address erc20Gateway = l1ERC20GatewayRouter.getGateway(l1Token);\n IERC20(l1Token).safeIncreaseAllowance(erc20Gateway, amount);\n\n // `outboundTransfer` expects that the caller includes a bytes message as the last param that includes the\n // maxSubmissionCost to use when creating an L2 retryable ticket: https://github.com/OffchainLabs/arbitrum/blob/e98d14873dd77513b569771f47b5e05b72402c5e/packages/arb-bridge-peripherals/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L232\n bytes memory data = abi.encode(l2MaxSubmissionCost, \"\");\n\n // Note: Legacy routers don't have the outboundTransferCustomRefund method, so default to using\n // outboundTransfer(). Legacy routers are used for the following tokens that are currently enabled:\n // - DAI: the implementation of `outboundTransfer` at the current DAI custom gateway\n // (https://etherscan.io/address/0xD3B5b60020504bc3489D6949d545893982BA3011#writeContract) sets the\n // sender as the refund address so the aliased HubPool should receive excess funds. Implementation here:\n // https://github.com/makerdao/arbitrum-dai-bridge/blob/11a80385e2622968069c34d401b3d54a59060e87/contracts/l1/L1DaiGateway.sol#L109\n if (l1Token == 0x6B175474E89094C44Da98b954EedeAC495271d0F) {\n // This means that the excess ETH to pay for the L2 transaction will be sent to the aliased\n // contract address on L2, which we'd have to retrieve via a custom adapter, the Arbitrum_RescueAdapter.\n // To do so, in a single transaction: 1) setCrossChainContracts to Arbitrum_RescueAdapter, 2) relayMessage\n // with function data = abi.encode(amountToRescue), 3) setCrossChainContracts back to this adapter.\n l1ERC20GatewayRouter.outboundTransfer{ value: requiredL1CallValue }(\n l1Token,\n to,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n l2GasPrice,\n data\n );\n } else {\n l1ERC20GatewayRouter.outboundTransferCustomRefund{ value: requiredL1CallValue }(\n l1Token,\n l2RefundL2Address,\n to,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n l2GasPrice,\n data\n );\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue(uint32 l2GasLimit) public pure returns (uint256) {\n return l2MaxSubmissionCost + l2GasPrice * l2GasLimit;\n }\n\n function _contractHasSufficientEthBalance(uint32 l2GasLimit) internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue(l2GasLimit);\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_RescueAdapter.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"./Arbitrum_Adapter.sol\"; // Used to import `ArbitrumL1ERC20GatewayLike` and `ArbitrumL1InboxLike`\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Meant to copy the Arbitrum_Adapter exactly in how it sends L1 --> L2 messages but is designed only to be\n * used by the owner of the HubPool to retrieve ETH held by its aliased address on L2. This ETH builds up because\n * `relayTokens` calls `l1ERC20GatewayRouter.outboundTransfer` which does not allow the caller to specify an L2 refund\n * address the same way that `l1Inbox.createRetryableTicket` does. This means that the alias address of the caller, the\n * HubPool in this case, receives ETH on L2. This Adapter can be used to send messages to Arbitrum specifically to send\n * transactions as if called by the aliased HubPool address.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_RescueAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n // Amount of ETH allocated to pay for the base submission fee. The base submission fee is a parameter unique to\n // retryable transactions; the user is charged the base submission fee to cover the storage costs of keeping their\n // ticket’s calldata in the retry buffer. (current base submission fee is queryable via\n // ArbRetryableTx.getSubmissionPrice). ArbRetryableTicket precompile interface exists at L2 address\n // 0x000000000000000000000000000000000000006E.\n uint256 public immutable l2MaxSubmissionCost = 0.01e18;\n\n // L2 Gas price bid for immediate L2 execution attempt (queryable via standard eth*gasPrice RPC)\n uint256 public immutable l2GasPrice = 5e9; // 5 gWei\n\n // Gas limit for immediate L2 execution attempt (can be estimated via NodeInterface.estimateRetryableTicket).\n // NodeInterface precompile interface exists at L2 address 0x00000000000000000000000000000000000000C8\n uint32 public immutable l2GasLimit = 2_000_000;\n\n // This address on L2 receives extra ETH that is left over after relaying a message via the inbox.\n address public immutable l2RefundL2Address;\n\n // L1 HubPool address aliased on L2: https://github.com/OffchainLabs/arbitrum/blob/master/docs/L1_L2_Messages.md#address-aliasing\n address public immutable aliasedL2HubPoolAddress = 0xd297fA914353c44B2e33EBE05F21846f1048CFeB;\n\n ArbitrumL1InboxLike public immutable l1Inbox;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ArbitrumInbox Inbox helper contract to send messages to Arbitrum.\n */\n constructor(ArbitrumL1InboxLike _l1ArbitrumInbox) {\n l1Inbox = _l1ArbitrumInbox;\n\n l2RefundL2Address = msg.sender;\n }\n\n /**\n * @notice Send cross-chain message to aliased hub pool address on Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param message Data to send to aliased hub pool.\n */\n function relayMessage(address, bytes memory message) external payable override {\n uint256 valueToReturn = abi.decode(message, (uint256));\n\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance();\n\n // In the rescue ETH setup, we send the transaction to the refund address, we provide a call value equal to the\n // amount we want to rescue, and we specify an empty calldata, since it's a simple ETH transfer.\n // Note: we use the unsafe version of createRetryableTicket because it doesn't require the msg.sender to pass\n // in arbTxCallValue in addition to maxSubmissionCost + maxGas * gasPriceBid.\n l1Inbox.unsafeCreateRetryableTicket{ value: requiredL1CallValue }(\n l2RefundL2Address, // destAddr destination L2 contract address\n valueToReturn, // l2CallValue call value for retryable L2 message\n l2MaxSubmissionCost, // maxSubmissionCost Max gas deducted from user's L2 balance to cover base fee\n l2RefundL2Address, // excessFeeRefundAddress maxgas * gasprice - execution cost gets credited here on L2\n l2RefundL2Address, // callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n l2GasLimit, // maxGas Max gas deducted from user's L2 balance to cover L2 execution\n l2GasPrice, // gasPriceBid price bid for L2 execution\n \"\" // data ABI encoded data of L2 message\n );\n\n emit MessageRelayed(aliasedL2HubPoolAddress, \"\");\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"useless function\");\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public pure returns (uint256) {\n return l2MaxSubmissionCost + l2GasPrice * l2GasLimit;\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/Ovm_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol\";\nimport \"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\";\nimport \"@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol\";\n\n// https://github.com/Synthetixio/synthetix/blob/5ca27785fad8237fb0710eac01421cafbbd69647/contracts/SynthetixBridgeToBase.sol#L50\ninterface SynthetixBridgeToBase {\n function withdrawTo(address to, uint256 amount) external;\n}\n\n/**\n * @notice OVM specific SpokePool. Uses OVM cross-domain-enabled logic to implement admin only access to functions. * Optimism and Boba each implement this spoke pool and set their chain specific contract addresses for l2Eth and l2Weth.\n */\ncontract Ovm_SpokePool is SpokePool {\n // \"l1Gas\" parameter used in call to bridge tokens from this contract back to L1 via IL2ERC20Bridge. Currently\n // unused by bridge but included for future compatibility.\n uint32 public l1Gas;\n\n // ETH is an ERC20 on OVM.\n address public l2Eth;\n\n // Address of the Optimism L2 messenger.\n address public messenger;\n\n // Address of custom bridge used to bridge Synthetix-related assets like SNX.\n address private constant SYNTHETIX_BRIDGE = 0x136b1EC699c62b0606854056f02dC7Bb80482d63;\n\n // Address of SNX ERC20\n address private constant SNX = 0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4;\n\n // Stores alternative token bridges to use for L2 tokens that don't go over the standard bridge. This is needed\n // to support non-standard ERC20 tokens on Optimism, such as DIA and SNX which both use custom bridges.\n mapping(address => address) public tokenBridges;\n\n event OptimismTokensBridged(address indexed l2Token, address target, uint256 numberOfTokensBridged, uint256 l1Gas);\n event SetL1Gas(uint32 indexed newL1Gas);\n event SetL2TokenBridge(address indexed l2Token, address indexed tokenBridge);\n\n /**\n * @notice Construct the OVM SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function __OvmSpokePool_init(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool,\n address _l2Eth,\n address _wrappedNativeToken\n ) public onlyInitializing {\n l1Gas = 5_000_000;\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wrappedNativeToken);\n messenger = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;\n //slither-disable-next-line missing-zero-check\n l2Eth = _l2Eth;\n }\n\n /*******************************************\n * OPTIMISM-SPECIFIC ADMIN FUNCTIONS *\n *******************************************/\n\n /**\n * @notice Change L1 gas limit. Callable only by admin.\n * @param newl1Gas New L1 gas limit to set.\n */\n function setL1GasLimit(uint32 newl1Gas) public onlyAdmin nonReentrant {\n l1Gas = newl1Gas;\n emit SetL1Gas(newl1Gas);\n }\n\n /**\n * @notice Set bridge contract for L2 token used to withdraw back to L1.\n * @dev If this mapping isn't set for an L2 token, then the standard bridge will be used to bridge this token.\n * @param tokenBridge Address of token bridge\n */\n function setTokenBridge(address l2Token, address tokenBridge) public onlyAdmin nonReentrant {\n tokenBridges[l2Token] = tokenBridge;\n emit SetL2TokenBridge(l2Token, tokenBridge);\n }\n\n /**************************************\n * DATA WORKER FUNCTIONS *\n **************************************/\n\n /**\n * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives\n * ETH over the canonical token bridge instead of WETH.\n * @inheritdoc SpokePool\n */\n function executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 totalRelayAmount,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustment,\n bytes32[] memory proof\n ) public override(SpokePool) nonReentrant {\n if (destinationToken == address(wrappedNativeToken)) _depositEthToWeth();\n\n _executeSlowRelayLeaf(\n depositor,\n recipient,\n destinationToken,\n totalRelayAmount,\n originChainId,\n chainId(),\n realizedLpFeePct,\n relayerFeePct,\n depositId,\n rootBundleId,\n message,\n payoutAdjustment,\n proof\n );\n }\n\n /**\n * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives\n * ETH over the canonical token bridge instead of WETH.\n * @inheritdoc SpokePool\n */\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) public override(SpokePool) nonReentrant {\n if (relayerRefundLeaf.l2TokenAddress == address(wrappedNativeToken)) _depositEthToWeth();\n\n _executeRelayerRefundLeaf(rootBundleId, relayerRefundLeaf, proof);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n // Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because\n // this SpokePool will receive ETH from the canonical token bridge instead of WETH. Its not sufficient to execute\n // this logic inside a fallback method that executes when this contract receives ETH because ETH is an ERC20\n // on the OVM.\n function _depositEthToWeth() internal {\n //slither-disable-next-line arbitrary-send-eth\n if (address(this).balance > 0) wrappedNativeToken.deposit{ value: address(this).balance }();\n }\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {\n // If the token being bridged is WETH then we need to first unwrap it to ETH and then send ETH over the\n // canonical bridge. On Optimism, this is address 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000.\n if (relayerRefundLeaf.l2TokenAddress == address(wrappedNativeToken)) {\n WETH9Interface(relayerRefundLeaf.l2TokenAddress).withdraw(relayerRefundLeaf.amountToReturn); // Unwrap into ETH.\n relayerRefundLeaf.l2TokenAddress = l2Eth; // Set the l2TokenAddress to ETH.\n }\n // Handle custom SNX bridge which doesn't conform to the standard bridge interface.\n if (relayerRefundLeaf.l2TokenAddress == SNX)\n SynthetixBridgeToBase(SYNTHETIX_BRIDGE).withdrawTo(\n hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.\n relayerRefundLeaf.amountToReturn // _amount.\n );\n else\n IL2ERC20Bridge(\n tokenBridges[relayerRefundLeaf.l2TokenAddress] == address(0)\n ? Lib_PredeployAddresses.L2_STANDARD_BRIDGE\n : tokenBridges[relayerRefundLeaf.l2TokenAddress]\n ).withdrawTo(\n relayerRefundLeaf.l2TokenAddress, // _l2Token. Address of the L2 token to bridge over.\n hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.\n relayerRefundLeaf.amountToReturn, // _amount.\n l1Gas, // _l1Gas. Unused, but included for potential forward compatibility considerations\n \"\" // _data. We don't need to send any data for the bridging action.\n );\n\n emit OptimismTokensBridged(relayerRefundLeaf.l2TokenAddress, hubPool, relayerRefundLeaf.amountToReturn, l1Gas);\n }\n\n // Apply OVM-specific transformation to cross domain admin address on L1.\n function _requireAdminSender() internal view override {\n require(\n LibOptimismUpgradeable.crossChainSender(messenger) == crossDomainAdmin,\n \"OVM_XCHAIN: wrong sender of cross-domain message\"\n );\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure its always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/optimism/LibOptimism.sol)\n\npragma solidity ^0.8.4;\n\nimport { ICrossDomainMessengerUpgradeable as Optimism_Bridge } from \"../../vendor/optimism/ICrossDomainMessengerUpgradeable.sol\";\nimport \"../errorsUpgradeable.sol\";\n\n/**\n * @dev Primitives for cross-chain aware contracts for https://www.optimism.io/[Optimism].\n * See the https://community.optimism.io/docs/developers/bridge/messaging/#accessing-msg-sender[documentation]\n * for the functionality used here.\n */\nlibrary LibOptimismUpgradeable {\n /**\n * @dev Returns whether the current function call is the result of a\n * cross-chain message relayed by `messenger`.\n */\n function isCrossChain(address messenger) internal view returns (bool) {\n return msg.sender == messenger;\n }\n\n /**\n * @dev Returns the address of the sender that triggered the current\n * cross-chain message through `messenger`.\n *\n * NOTE: {isCrossChain} should be checked before trying to recover the\n * sender, as it will revert with `NotCrossChainCall` if the current\n * function call is not the result of a cross-chain message.\n */\n function crossChainSender(address messenger) internal view returns (address) {\n if (!isCrossChain(messenger)) revert NotCrossChainCall();\n\n return Optimism_Bridge(messenger).xDomainMessageSender();\n }\n}\n" + }, + "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_PredeployAddresses\n */\nlibrary Lib_PredeployAddresses {\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n address payable internal constant OVM_ETH = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000);\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;\n address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n address internal constant L2_STANDARD_TOKEN_FACTORY =\n 0x4200000000000000000000000000000000000012;\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n}\n" + }, + "@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title IL2ERC20Bridge\n */\ninterface IL2ERC20Bridge {\n /**********\n * Events *\n **********/\n\n event WithdrawalInitiated(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n event DepositFinalized(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n event DepositFailed(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * @dev get the address of the corresponding L1 bridge contract.\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external returns (address);\n\n /**\n * @dev initiate a withdraw of some tokens to the caller's account on L1\n * @param _l2Token Address of L2 token where withdrawal was initiated.\n * @param _amount Amount of the token to withdraw.\n * param _l1Gas Unused, but included for potential forward compatibility considerations.\n * @param _data Optional data to forward to L1. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _l1Gas,\n bytes calldata _data\n ) external;\n\n /**\n * @dev initiate a withdraw of some token to a recipient's account on L1.\n * @param _l2Token Address of L2 token where withdrawal is initiated.\n * @param _to L1 adress to credit the withdrawal to.\n * @param _amount Amount of the token to withdraw.\n * param _l1Gas Unused, but included for potential forward compatibility considerations.\n * @param _data Optional data to forward to L1. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _l1Gas,\n bytes calldata _data\n ) external;\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @dev Complete a deposit from L1 to L2, and credits funds to the recipient's balance of this\n * L2 token. This call will fail if it did not originate from a corresponding deposit in\n * L1StandardTokenBridge.\n * @param _l1Token Address for the l1 token this is called with\n * @param _l2Token Address for the l2 token this is called with\n * @param _from Account to pull the deposit from on L2.\n * @param _to Address to receive the withdrawal at\n * @param _amount Amount of the token to withdraw\n * @param _data Data provider by the sender on L1. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/crosschain/errorsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)\n\npragma solidity ^0.8.4;\n\nerror NotCrossChainCall();\nerror InvalidCrossChainSender(address actual, address expected);\n" + }, + "@openzeppelin/contracts-upgradeable/vendor/optimism/ICrossDomainMessengerUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (vendor/optimism/ICrossDomainMessenger.sol)\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessengerUpgradeable {\n /**********\n * Events *\n **********/\n\n event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /*************\n * Variables *\n *************/\n\n function xDomainMessageSender() external view returns (address);\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * Sends a cross domain message to the target messenger.\n * @param _target Target contract address.\n * @param _message Message to send to the target.\n * @param _gasLimit Gas limit for the provided message.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _gasLimit\n ) external;\n}\n" + }, + "contracts/test/AcrossMessageHandlerMock.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"../SpokePool.sol\";\n\ncontract AcrossMessageHandlerMock is AcrossMessageHandler {\n function handleAcrossMessage(\n address tokenSent,\n uint256 amount,\n bytes memory message\n ) external override {}\n}\n" + }, + "contracts/ZkSync_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\n\ninterface ZkBridgeLike {\n function withdraw(\n address _to,\n address _l2Token,\n uint256 _amount\n ) external;\n}\n\n/**\n * @notice ZkSync specific SpokePool, intended to be compiled with `@matterlabs/hardhat-zksync-solc`.\n */\ncontract ZkSync_SpokePool is SpokePool {\n // On Ethereum, avoiding constructor parameters and putting them into constants reduces some of the gas cost\n // upon contract deployment. On zkSync the opposite is true: deploying the same bytecode for contracts,\n // while changing only constructor parameters can lead to substantial fee savings. So, the following params\n // are all set by passing in constructor params where possible.\n\n // However, this contract is expected to be deployed only once to ZkSync. Therefore, we should consider the cost\n // of reading mutable vs immutable storage. On Ethereum, mutable storage is more expensive than immutable bytecode.\n // But, we also want to be able to upgrade certain state variables.\n\n // Bridge used to withdraw ERC20's to L1: https://github.com/matter-labs/v2-testnet-contracts/blob/3a0651357bb685751c2163e4cc65a240b0f602ef/l2/contracts/bridge/L2ERC20Bridge.sol\n ZkBridgeLike public zkErc20Bridge;\n\n // Bridge used to send ETH to L1: https://github.com/matter-labs/v2-testnet-contracts/blob/3a0651357bb685751c2163e4cc65a240b0f602ef/l2/contracts/bridge/L2ETHBridge.sol\n ZkBridgeLike public zkEthBridge;\n\n event SetZkBridges(address indexed erc20Bridge, address indexed ethBridge);\n event ZkSyncTokensBridged(address indexed l2Token, address target, uint256 numberOfTokensBridged);\n\n /**\n * @notice Construct the ZkSync SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _zkErc20Bridge Address of L2 ERC20 gateway. Can be reset by admin.\n * @param _zkEthBridge Address of L2 ETH gateway. Can be reset by admin.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wethAddress Weth address for this network to set.\n */\n function initialize(\n uint32 _initialDepositId,\n ZkBridgeLike _zkErc20Bridge,\n ZkBridgeLike _zkEthBridge,\n address _crossDomainAdmin,\n address _hubPool,\n address _wethAddress\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wethAddress);\n _setZkBridges(_zkErc20Bridge, _zkEthBridge);\n }\n\n modifier onlyFromCrossDomainAdmin() {\n // Formal msg.sender of L1 --> L2 message will be L1 sender.\n require(msg.sender == crossDomainAdmin, \"Invalid sender\");\n _;\n }\n\n /**\n * @notice Returns chain ID for this network.\n * @dev ZKSync doesn't yet support the CHAIN_ID opcode so we override this, but it will be supported by mainnet\n * launch supposedly: https://v2-docs.zksync.io/dev/zksync-v2/temp-limits.html#temporarily-simulated-by-constant-values\n */\n function chainId() public pure override returns (uint256) {\n return 280;\n }\n\n /********************************************************\n * ZKSYNC-SPECIFIC CROSS-CHAIN ADMIN FUNCTIONS *\n ********************************************************/\n\n /**\n * @notice Change L2 token bridge addresses. Callable only by admin.\n * @param _zkErc20Bridge New address of L2 ERC20 gateway.\n * @param _zkEthBridge New address of L2 ETH gateway.\n */\n function setZkBridges(ZkBridgeLike _zkErc20Bridge, ZkBridgeLike _zkEthBridge) public onlyAdmin nonReentrant {\n _setZkBridges(_zkErc20Bridge, _zkEthBridge);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {\n (relayerRefundLeaf.l2TokenAddress == address(wrappedNativeToken) ? zkEthBridge : zkErc20Bridge).withdraw(\n hubPool,\n // Note: If ETH, must use 0x0: https://github.com/matter-labs/v2-testnet-contracts/blob/3a0651357bb685751c2163e4cc65a240b0f602ef/l2/contracts/bridge/L2ETHBridge.sol#L57\n relayerRefundLeaf.l2TokenAddress == address(wrappedNativeToken)\n ? address(0)\n : relayerRefundLeaf.l2TokenAddress,\n relayerRefundLeaf.amountToReturn\n );\n\n emit ZkSyncTokensBridged(relayerRefundLeaf.l2TokenAddress, hubPool, relayerRefundLeaf.amountToReturn);\n }\n\n function _setZkBridges(ZkBridgeLike _zkErc20Bridge, ZkBridgeLike _zkEthBridge) internal {\n zkErc20Bridge = _zkErc20Bridge;\n zkEthBridge = _zkEthBridge;\n emit SetZkBridges(address(_zkErc20Bridge), address(_zkEthBridge));\n }\n\n function _requireAdminSender() internal override onlyFromCrossDomainAdmin {}\n}\n" + }, + "contracts/Arbitrum_SpokePool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\n\ninterface StandardBridgeLike {\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable returns (bytes memory);\n}\n\n/**\n * @notice AVM specific SpokePool. Uses AVM cross-domain-enabled logic to implement admin only access to functions.\n */\ncontract Arbitrum_SpokePool is SpokePool {\n // Address of the Arbitrum L2 token gateway to send funds to L1.\n address public l2GatewayRouter;\n\n // Admin controlled mapping of arbitrum tokens to L1 counterpart. L1 counterpart addresses\n // are necessary params used when bridging tokens to L1.\n mapping(address => address) public whitelistedTokens;\n\n event ArbitrumTokensBridged(address indexed l1Token, address target, uint256 numberOfTokensBridged);\n event SetL2GatewayRouter(address indexed newL2GatewayRouter);\n event WhitelistedTokens(address indexed l2Token, address indexed l1Token);\n\n /**\n * @notice Construct the AVM SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _l2GatewayRouter Address of L2 token gateway. Can be reset by admin.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _wethAddress Weth address for this network to set.\n */\n function initialize(\n uint32 _initialDepositId,\n address _l2GatewayRouter,\n address _crossDomainAdmin,\n address _hubPool,\n address _wethAddress\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, _wethAddress);\n _setL2GatewayRouter(_l2GatewayRouter);\n }\n\n modifier onlyFromCrossDomainAdmin() {\n require(msg.sender == _applyL1ToL2Alias(crossDomainAdmin), \"ONLY_COUNTERPART_GATEWAY\");\n _;\n }\n\n /********************************************************\n * ARBITRUM-SPECIFIC CROSS-CHAIN ADMIN FUNCTIONS *\n ********************************************************/\n\n /**\n * @notice Change L2 gateway router. Callable only by admin.\n * @param newL2GatewayRouter New L2 gateway router.\n */\n function setL2GatewayRouter(address newL2GatewayRouter) public onlyAdmin nonReentrant {\n _setL2GatewayRouter(newL2GatewayRouter);\n }\n\n /**\n * @notice Add L2 -> L1 token mapping. Callable only by admin.\n * @param l2Token Arbitrum token.\n * @param l1Token Ethereum version of l2Token.\n */\n function whitelistToken(address l2Token, address l1Token) public onlyAdmin nonReentrant {\n _whitelistToken(l2Token, l1Token);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _bridgeTokensToHubPool(RelayerRefundLeaf memory relayerRefundLeaf) internal override {\n // Check that the Ethereum counterpart of the L2 token is stored on this contract.\n address ethereumTokenToBridge = whitelistedTokens[relayerRefundLeaf.l2TokenAddress];\n require(ethereumTokenToBridge != address(0), \"Uninitialized mainnet token\");\n //slither-disable-next-line unused-return\n StandardBridgeLike(l2GatewayRouter).outboundTransfer(\n ethereumTokenToBridge, // _l1Token. Address of the L1 token to bridge over.\n hubPool, // _to. Withdraw, over the bridge, to the l1 hub pool contract.\n relayerRefundLeaf.amountToReturn, // _amount.\n \"\" // _data. We don't need to send any data for the bridging action.\n );\n emit ArbitrumTokensBridged(address(0), hubPool, relayerRefundLeaf.amountToReturn);\n }\n\n function _setL2GatewayRouter(address _l2GatewayRouter) internal {\n l2GatewayRouter = _l2GatewayRouter;\n emit SetL2GatewayRouter(l2GatewayRouter);\n }\n\n function _whitelistToken(address _l2Token, address _l1Token) internal {\n whitelistedTokens[_l2Token] = _l1Token;\n emit WhitelistedTokens(_l2Token, _l1Token);\n }\n\n // L1 addresses are transformed during l1->l2 calls.\n // See https://developer.offchainlabs.com/docs/l1_l2_messages#address-aliasing for more information.\n // This cannot be pulled directly from Arbitrum contracts because their contracts are not 0.8.X compatible and\n // this operation takes advantage of overflows, whose behavior changed in 0.8.0.\n function _applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n // Allows overflows as explained above.\n unchecked {\n l2Address = address(uint160(l1Address) + uint160(0x1111000000000000000000000000000000001111));\n }\n }\n\n // Apply AVM-specific transformation to cross domain admin address on L1.\n function _requireAdminSender() internal override onlyFromCrossDomainAdmin {}\n}\n" + }, + "contracts/test/PolygonMocks.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract RootChainManagerMock {\n function depositEtherFor(address user) external payable {} // solhint-disable-line no-empty-blocks\n\n function depositFor(\n address user,\n address rootToken,\n bytes calldata depositData\n ) external {} // solhint-disable-line no-empty-blocks\n}\n\ncontract FxStateSenderMock {\n // solhint-disable-next-line no-empty-blocks\n function sendMessageToChild(address _receiver, bytes calldata _data) external {}\n}\n\ncontract DepositManagerMock {\n function depositERC20ForUser(\n address token,\n address user,\n uint256 amount // solhint-disable-next-line no-empty-blocks\n ) external {} // solhint-disable-line no-empty-blocks\n}\n\ncontract PolygonRegistryMock {\n // solhint-disable-next-line no-empty-blocks\n function erc20Predicate() external returns (address predicate) {}\n}\n\ncontract PolygonERC20PredicateMock {\n // solhint-disable-next-line no-empty-blocks\n function startExitWithBurntTokens(bytes calldata data) external {}\n}\n\ncontract PolygonERC20Mock is ERC20 {\n // solhint-disable-next-line no-empty-blocks\n constructor() ERC20(\"Test ERC20\", \"TEST\") {}\n\n // solhint-disable-next-line no-empty-blocks\n function withdraw(uint256 amount) external {}\n}\n" + }, + "@uma/core/contracts/oracle/interfaces/OptimisticOracleInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./FinderInterface.sol\";\n\n/**\n * @title Financial contract facing Oracle interface.\n * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.\n */\nabstract contract OptimisticOracleInterface {\n event RequestPrice(\n address indexed requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n address currency,\n uint256 reward,\n uint256 finalFee\n );\n event ProposePrice(\n address indexed requester,\n address indexed proposer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 proposedPrice,\n uint256 expirationTimestamp,\n address currency\n );\n event DisputePrice(\n address indexed requester,\n address indexed proposer,\n address indexed disputer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 proposedPrice\n );\n event Settle(\n address indexed requester,\n address indexed proposer,\n address indexed disputer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 price,\n uint256 payout\n );\n\n // Struct representing the state of a price request.\n enum State {\n Invalid, // Never requested.\n Requested, // Requested, no other actions taken.\n Proposed, // Proposed, but not expired or disputed yet.\n Expired, // Proposed, not disputed, past liveness.\n Disputed, // Disputed, but no DVM price returned yet.\n Resolved, // Disputed and DVM price is available.\n Settled // Final price has been set in the contract (can get here from Expired or Resolved).\n }\n\n // Struct representing a price request.\n struct Request {\n address proposer; // Address of the proposer.\n address disputer; // Address of the disputer.\n IERC20 currency; // ERC20 token used to pay rewards and fees.\n bool settled; // True if the request is settled.\n bool refundOnDispute; // True if the requester should be refunded their reward on dispute.\n int256 proposedPrice; // Price that the proposer submitted.\n int256 resolvedPrice; // Price resolved once the request is settled.\n uint256 expirationTime; // Time at which the request auto-settles without a dispute.\n uint256 reward; // Amount of the currency to pay to the proposer on settlement.\n uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.\n uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.\n uint256 customLiveness; // Custom liveness value set by the requester.\n }\n\n // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible\n // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses\n // to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n\n function defaultLiveness() external view virtual returns (uint256);\n\n function finder() external view virtual returns (FinderInterface);\n\n function getCurrentTime() external view virtual returns (uint256);\n\n // Note: this is required so that typechain generates a return value with named fields.\n mapping(bytes32 => Request) public requests;\n\n /**\n * @notice Requests a new price.\n * @param identifier price identifier being requested.\n * @param timestamp timestamp of the price being requested.\n * @param ancillaryData ancillary data representing additional args being passed with the price request.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay.\n * This can be changed with a subsequent call to setBond().\n */\n function requestPrice(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Set the proposal bond associated with a price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param bond custom bond amount to set.\n * @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be\n * changed again with a subsequent call to setBond().\n */\n function setBond(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n uint256 bond\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Sets the request to refund the reward if the proposal is disputed. This can help to \"hedge\" the caller\n * in the event of a dispute-caused delay. Note: in the event of a dispute, the winner still receives the other's\n * bond, so there is still profit to be made even if the reward is refunded.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n */\n function setRefundOnDispute(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual;\n\n /**\n * @notice Sets a custom liveness value for the request. Liveness is the amount of time a proposal must wait before\n * being auto-resolved.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param customLiveness new custom liveness.\n */\n function setCustomLiveness(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n uint256 customLiveness\n ) external virtual;\n\n /**\n * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come\n * from this proposal. However, any bonds are pulled from the caller.\n * @param proposer address to set as the proposer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePriceFor(\n address proposer,\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n int256 proposedPrice\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value for an existing price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will\n * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.\n * @param disputer address to set as the disputer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was value (the proposal was incorrect).\n */\n function disputePriceFor(\n address disputer,\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price value for an existing price request with an active proposal.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled\n * or settleable. Note: this method is not view so that this call may actually settle the price request if it\n * hasn't been settled.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return resolved price.\n */\n function settleAndGetPrice(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (int256);\n\n /**\n * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return payout the amount that the \"winner\" (proposer or disputer) receives on settlement. This amount includes\n * the returned bonds as well as additional rewards.\n */\n function settle(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (uint256 payout);\n\n /**\n * @notice Gets the current data structure containing all information about a price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return the Request data structure.\n */\n function getRequest(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (Request memory);\n\n /**\n * @notice Returns the state of a price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return the State enum value.\n */\n function getState(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (State);\n\n /**\n * @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price).\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return true if price has resolved or settled, false otherwise.\n */\n function hasPrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (bool);\n\n function stampAncillaryData(bytes memory ancillaryData, address requester)\n public\n view\n virtual\n returns (bytes memory);\n}\n" + }, + "@uma/core/contracts/oracle/interfaces/FinderInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Provides addresses of the live contracts implementing certain interfaces.\n * @dev Examples are the Oracle or Store interfaces.\n */\ninterface FinderInterface {\n /**\n * @notice Updates the address of the contract that implements `interfaceName`.\n * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.\n * @param implementationAddress address of the deployed contract that implements the interface.\n */\n function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;\n\n /**\n * @notice Gets the address of the contract that implements the given `interfaceName`.\n * @param interfaceName queried interface.\n * @return implementationAddress address of the deployed contract that implements the interface.\n */\n function getImplementationAddress(bytes32 interfaceName) external view returns (address);\n}\n" + }, + "@uma/core/contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/OptimisticOracleInterface.sol\";\n\n/**\n * @title Interface for the gas-cost-reduced version of the OptimisticOracle.\n * @notice Differences from normal OptimisticOracle:\n * - refundOnDispute: flag is removed, by default there are no refunds on disputes.\n * - customizing request parameters: In the OptimisticOracle, parameters like `bond` and `customLiveness` can be reset\n * after a request is already made via `requestPrice`. In the SkinnyOptimisticOracle, these parameters can only be\n * set in `requestPrice`, which has an expanded input set.\n * - settleAndGetPrice: Replaced by `settle`, which can only be called once per settleable request. The resolved price\n * can be fetched via the `Settle` event or the return value of `settle`.\n * - general changes to interface: Functions that interact with existing requests all require the parameters of the\n * request to modify to be passed as input. These parameters must match with the existing request parameters or the\n * function will revert. This change reflects the internal refactor to store hashed request parameters instead of the\n * full request struct.\n * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.\n */\nabstract contract SkinnyOptimisticOracleInterface {\n // Struct representing a price request. Note that this differs from the OptimisticOracleInterface's Request struct\n // in that refundOnDispute is removed.\n struct Request {\n address proposer; // Address of the proposer.\n address disputer; // Address of the disputer.\n IERC20 currency; // ERC20 token used to pay rewards and fees.\n bool settled; // True if the request is settled.\n int256 proposedPrice; // Price that the proposer submitted.\n int256 resolvedPrice; // Price resolved once the request is settled.\n uint256 expirationTime; // Time at which the request auto-settles without a dispute.\n uint256 reward; // Amount of the currency to pay to the proposer on settlement.\n uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.\n uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.\n uint256 customLiveness; // Custom liveness value set by the requester.\n }\n\n // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible\n // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses\n // to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n\n /**\n * @notice Requests a new price.\n * @param identifier price identifier being requested.\n * @param timestamp timestamp of the price being requested.\n * @param ancillaryData ancillary data representing additional args being passed with the price request.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.\n * @param customLiveness custom proposal liveness to set for request.\n * @return totalBond default bond + final fee that the proposer and disputer will be required to pay.\n */\n function requestPrice(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward,\n uint256 bond,\n uint256 customLiveness\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come\n * from this proposal. However, any bonds are pulled from the caller.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * propose a price for.\n * @param proposer address to set as the proposer.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePriceFor(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n address proposer,\n int256 proposedPrice\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value where caller is the proposer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * propose a price for.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Combines logic of requestPrice and proposePrice while taking advantage of gas savings from not having to\n * overwrite Request params that a normal requestPrice() => proposePrice() flow would entail. Note: The proposer\n * will receive any rewards that come from this proposal. However, any bonds are pulled from the caller.\n * @dev The caller is the requester, but the proposer can be customized.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.\n * @param customLiveness custom proposal liveness to set for request.\n * @param proposer address to set as the proposer.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function requestAndProposePriceFor(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward,\n uint256 bond,\n uint256 customLiveness,\n address proposer,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will\n * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * dispute.\n * @param disputer address to set as the disputer.\n * @param requester sender of the initial price request.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePriceFor(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n address disputer,\n address requester\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal where caller is the disputer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * dispute.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * settle.\n * @return payout the amount that the \"winner\" (proposer or disputer) receives on settlement. This amount includes\n * the returned bonds as well as additional rewards.\n * @return resolvedPrice the price that the request settled to.\n */\n function settle(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (uint256 payout, int256 resolvedPrice);\n\n /**\n * @notice Computes the current state of a price request. See the State enum for more details.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters.\n * @return the State.\n */\n function getState(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (OptimisticOracleInterface.State);\n\n /**\n * @notice Checks if a given request has resolved, expired or been settled (i.e the optimistic oracle has a price).\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters. The hash of these parameters must match with the request hash that is\n * associated with the price request unique ID {requester, identifier, timestamp, ancillaryData}, or this method\n * will revert.\n * @return boolean indicating true if price exists and false if not.\n */\n function hasPrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) public virtual returns (bool);\n\n /**\n * @notice Generates stamped ancillary data in the format that it would be used in the case of a price dispute.\n * @param ancillaryData ancillary data of the price being requested.\n * @param requester sender of the initial price request.\n * @return the stamped ancillary bytes.\n */\n function stampAncillaryData(bytes memory ancillaryData, address requester)\n public\n pure\n virtual\n returns (bytes memory);\n}\n" + }, + "@uma/core/contracts/oracle/interfaces/StoreInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../../common/implementation/FixedPoint.sol\";\n\n/**\n * @title Interface that allows financial contracts to pay oracle fees for their use of the system.\n */\ninterface StoreInterface {\n /**\n * @notice Pays Oracle fees in ETH to the store.\n * @dev To be used by contracts whose margin currency is ETH.\n */\n function payOracleFees() external payable;\n\n /**\n * @notice Pays oracle fees in the margin currency, erc20Address, to the store.\n * @dev To be used if the margin currency is an ERC20 token rather than ETH.\n * @param erc20Address address of the ERC20 token used to pay the fee.\n * @param amount number of tokens to transfer. An approval for at least this amount must exist.\n */\n function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external;\n\n /**\n * @notice Computes the regular oracle fees that a contract should pay for a period.\n * @param startTime defines the beginning time from which the fee is paid.\n * @param endTime end time until which the fee is paid.\n * @param pfc \"profit from corruption\", or the maximum amount of margin currency that a\n * token sponsor could extract from the contract through corrupting the price feed in their favor.\n * @return regularFee amount owed for the duration from start to end time for the given pfc.\n * @return latePenalty for paying the fee after the deadline.\n */\n function computeRegularFee(\n uint256 startTime,\n uint256 endTime,\n FixedPoint.Unsigned calldata pfc\n ) external view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty);\n\n /**\n * @notice Computes the final oracle fees that a contract should pay at settlement.\n * @param currency token used to pay the final fee.\n * @return finalFee amount due.\n */\n function computeFinalFee(address currency) external view returns (FixedPoint.Unsigned memory);\n}\n" + }, + "@uma/core/contracts/common/implementation/FixedPoint.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/utils/math/SignedSafeMath.sol\";\n\n/**\n * @title Library for fixed point arithmetic on uints\n */\nlibrary FixedPoint {\n using SafeMath for uint256;\n using SignedSafeMath for int256;\n\n // Supports 18 decimals. E.g., 1e18 represents \"1\", 5e17 represents \"0.5\".\n // For unsigned values:\n // This can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.\n uint256 private constant FP_SCALING_FACTOR = 10**18;\n\n // --------------------------------------- UNSIGNED -----------------------------------------------------------------------------\n struct Unsigned {\n uint256 rawValue;\n }\n\n /**\n * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**18)`.\n * @param a uint to convert into a FixedPoint.\n * @return the converted FixedPoint.\n */\n function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {\n return Unsigned(a.mul(FP_SCALING_FACTOR));\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if equal, or False.\n */\n function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue == fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if equal, or False.\n */\n function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue == b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue > fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue >= fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue < fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a < b`, or False.\n */\n function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue <= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue <= fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue <= b.rawValue;\n }\n\n /**\n * @notice The minimum of `a` and `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the minimum of `a` and `b`.\n */\n function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return a.rawValue < b.rawValue ? a : b;\n }\n\n /**\n * @notice The maximum of `a` and `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the maximum of `a` and `b`.\n */\n function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return a.rawValue > b.rawValue ? a : b;\n }\n\n /**\n * @notice Adds two `Unsigned`s, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the sum of `a` and `b`.\n */\n function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.add(b.rawValue));\n }\n\n /**\n * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the sum of `a` and `b`.\n */\n function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return add(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Subtracts two `Unsigned`s, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the difference of `a` and `b`.\n */\n function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.sub(b.rawValue));\n }\n\n /**\n * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the difference of `a` and `b`.\n */\n function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return sub(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return the difference of `a` and `b`.\n */\n function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return sub(fromUnscaledUint(a), b);\n }\n\n /**\n * @notice Multiplies two `Unsigned`s, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n // There are two caveats with this computation:\n // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is\n // stored internally as a uint256 ~10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which\n // would round to 3, but this computation produces the result 2.\n // No need to use SafeMath because FP_SCALING_FACTOR != 0.\n return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);\n }\n\n /**\n * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the product of `a` and `b`.\n */\n function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.mul(b));\n }\n\n /**\n * @notice Multiplies two `Unsigned`s and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n uint256 mulRaw = a.rawValue.mul(b.rawValue);\n uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;\n uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);\n if (mod != 0) {\n return Unsigned(mulFloor.add(1));\n } else {\n return Unsigned(mulFloor);\n }\n }\n\n /**\n * @notice Multiplies an `Unsigned` and an unscaled uint256 and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n // Since b is an uint, there is no risk of truncation and we can just mul it normally\n return Unsigned(a.rawValue.mul(b));\n }\n\n /**\n * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n // There are two caveats with this computation:\n // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.\n // 10^41 is stored internally as a uint256 10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which\n // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.\n return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));\n }\n\n /**\n * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.div(b));\n }\n\n /**\n * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a uint256 numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return div(fromUnscaledUint(a), b);\n }\n\n /**\n * @notice Divides one `Unsigned` by an `Unsigned` and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);\n uint256 divFloor = aScaled.div(b.rawValue);\n uint256 mod = aScaled.mod(b.rawValue);\n if (mod != 0) {\n return Unsigned(divFloor.add(1));\n } else {\n return Unsigned(divFloor);\n }\n }\n\n /**\n * @notice Divides one `Unsigned` by an unscaled uint256 and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n // Because it is possible that a quotient gets truncated, we can't just call \"Unsigned(a.rawValue.div(b))\"\n // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.\n // This creates the possibility of overflow if b is very large.\n return divCeil(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.\n * @dev This will \"floor\" the result.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return output is `a` to the power of `b`.\n */\n function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {\n output = fromUnscaledUint(1);\n for (uint256 i = 0; i < b; i = i.add(1)) {\n output = mul(output, a);\n }\n }\n\n // ------------------------------------------------- SIGNED -------------------------------------------------------------\n // Supports 18 decimals. E.g., 1e18 represents \"1\", 5e17 represents \"0.5\".\n // For signed values:\n // This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76.\n int256 private constant SFP_SCALING_FACTOR = 10**18;\n\n struct Signed {\n int256 rawValue;\n }\n\n function fromSigned(Signed memory a) internal pure returns (Unsigned memory) {\n require(a.rawValue >= 0, \"Negative value provided\");\n return Unsigned(uint256(a.rawValue));\n }\n\n function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) {\n require(a.rawValue <= uint256(type(int256).max), \"Unsigned too large\");\n return Signed(int256(a.rawValue));\n }\n\n /**\n * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`.\n * @param a int to convert into a FixedPoint.Signed.\n * @return the converted FixedPoint.Signed.\n */\n function fromUnscaledInt(int256 a) internal pure returns (Signed memory) {\n return Signed(a.mul(SFP_SCALING_FACTOR));\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a int256.\n * @return True if equal, or False.\n */\n function isEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue == fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if equal, or False.\n */\n function isEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue == b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue > fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue >= fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue < fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a < b`, or False.\n */\n function isLessThan(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue <= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue <= fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue <= b.rawValue;\n }\n\n /**\n * @notice The minimum of `a` and `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the minimum of `a` and `b`.\n */\n function min(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return a.rawValue < b.rawValue ? a : b;\n }\n\n /**\n * @notice The maximum of `a` and `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the maximum of `a` and `b`.\n */\n function max(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return a.rawValue > b.rawValue ? a : b;\n }\n\n /**\n * @notice Adds two `Signed`s, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the sum of `a` and `b`.\n */\n function add(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.add(b.rawValue));\n }\n\n /**\n * @notice Adds an `Signed` to an unscaled int, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the sum of `a` and `b`.\n */\n function add(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return add(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Subtracts two `Signed`s, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the difference of `a` and `b`.\n */\n function sub(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.sub(b.rawValue));\n }\n\n /**\n * @notice Subtracts an unscaled int256 from an `Signed`, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the difference of `a` and `b`.\n */\n function sub(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return sub(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Subtracts an `Signed` from an unscaled int256, reverting on overflow.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return the difference of `a` and `b`.\n */\n function sub(int256 a, Signed memory b) internal pure returns (Signed memory) {\n return sub(fromUnscaledInt(a), b);\n }\n\n /**\n * @notice Multiplies two `Signed`s, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mul(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n // There are two caveats with this computation:\n // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is\n // stored internally as an int256 ~10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which\n // would round to 3, but this computation produces the result 2.\n // No need to use SafeMath because SFP_SCALING_FACTOR != 0.\n return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR);\n }\n\n /**\n * @notice Multiplies an `Signed` and an unscaled int256, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the product of `a` and `b`.\n */\n function mul(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.mul(b));\n }\n\n /**\n * @notice Multiplies two `Signed`s and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n int256 mulRaw = a.rawValue.mul(b.rawValue);\n int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR;\n // Manual mod because SignedSafeMath doesn't support it.\n int256 mod = mulRaw % SFP_SCALING_FACTOR;\n if (mod != 0) {\n bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);\n int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);\n return Signed(mulTowardsZero.add(valueToAdd));\n } else {\n return Signed(mulTowardsZero);\n }\n }\n\n /**\n * @notice Multiplies an `Signed` and an unscaled int256 and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mulAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {\n // Since b is an int, there is no risk of truncation and we can just mul it normally\n return Signed(a.rawValue.mul(b));\n }\n\n /**\n * @notice Divides one `Signed` by an `Signed`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n // There are two caveats with this computation:\n // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.\n // 10^41 is stored internally as an int256 10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which\n // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.\n return Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue));\n }\n\n /**\n * @notice Divides one `Signed` by an unscaled int256, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b an int256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.div(b));\n }\n\n /**\n * @notice Divides one unscaled int256 by an `Signed`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a an int256 numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(int256 a, Signed memory b) internal pure returns (Signed memory) {\n return div(fromUnscaledInt(a), b);\n }\n\n /**\n * @notice Divides one `Signed` by an `Signed` and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR);\n int256 divTowardsZero = aScaled.div(b.rawValue);\n // Manual mod because SignedSafeMath doesn't support it.\n int256 mod = aScaled % b.rawValue;\n if (mod != 0) {\n bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);\n int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);\n return Signed(divTowardsZero.add(valueToAdd));\n } else {\n return Signed(divTowardsZero);\n }\n }\n\n /**\n * @notice Divides one `Signed` by an unscaled int256 and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b an int256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {\n // Because it is possible that a quotient gets truncated, we can't just call \"Signed(a.rawValue.div(b))\"\n // similarly to mulCeil with an int256 as the second parameter. Therefore we need to convert b into an Signed.\n // This creates the possibility of overflow if b is very large.\n return divAwayFromZero(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Raises an `Signed` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.\n * @dev This will \"floor\" the result.\n * @param a a FixedPoint.Signed.\n * @param b a uint256 (negative exponents are not allowed).\n * @return output is `a` to the power of `b`.\n */\n function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) {\n output = fromUnscaledInt(1);\n for (uint256 i = 0; i < b; i = i.add(1)) {\n output = mul(output, a);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedSafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler\n * now has built in overflow checking.\n */\nlibrary SignedSafeMath {\n /**\n * @dev Returns the multiplication of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(int256 a, int256 b) internal pure returns (int256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two signed integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(int256 a, int256 b) internal pure returns (int256) {\n return a / b;\n }\n\n /**\n * @dev Returns the subtraction of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(int256 a, int256 b) internal pure returns (int256) {\n return a - b;\n }\n\n /**\n * @dev Returns the addition of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(int256 a, int256 b) internal pure returns (int256) {\n return a + b;\n }\n}\n" + }, + "contracts/merkle-distributor/AcrossMerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title Extended MerkleDistributor contract.\n * @notice Adds additional constraints governing who can claim leaves from merkle windows.\n */\ncontract AcrossMerkleDistributor is MerkleDistributor {\n using SafeERC20 for IERC20;\n\n // Addresses that can claim on user's behalf.\n mapping(address => bool) public whitelistedClaimers;\n\n /****************************************\n * EVENTS\n ****************************************/\n event WhitelistedClaimer(address indexed claimer, bool indexed whitelist);\n event ClaimFor(\n address indexed caller,\n uint256 windowIndex,\n address indexed account,\n uint256 accountIndex,\n uint256 amount,\n address indexed rewardToken\n );\n\n /****************************\n * ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Updates whitelisted claimer status.\n * @dev Callable only by owner.\n * @param newContract Reset claimer contract to this address.\n * @param whitelist True to whitelist claimer, False otherwise.\n */\n function whitelistClaimer(address newContract, bool whitelist) external onlyOwner {\n whitelistedClaimers[newContract] = whitelist;\n emit WhitelistedClaimer(newContract, whitelist);\n }\n\n /****************************\n * NON-ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Batch claims to reduce gas versus individual submitting all claims. Method will fail\n * if any individual claims within the batch would fail.\n * @dev All claim recipients must be equal to msg.sender.\n * @param claims array of claims to claim.\n */\n function claimMulti(Claim[] memory claims) public override {\n uint256 claimCount = claims.length;\n for (uint256 i = 0; i < claimCount; i++) {\n require(claims[i].account == msg.sender, \"invalid claimer\");\n }\n super.claimMulti(claims);\n }\n\n /**\n * @notice Claim amount of reward tokens for account, as described by Claim input object.\n * @dev Claim recipient must be equal to msg.sender.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n */\n function claim(Claim memory _claim) public override {\n require(_claim.account == msg.sender, \"invalid claimer\");\n super.claim(_claim);\n }\n\n /**\n * @notice Executes merkle leaf claim on behaf of user. This can only be called by a trusted\n * claimer address. This function is designed to be called atomically with other transactions\n * that ultimately return the claimed amount to the rightful recipient. For example,\n * AcceleratingDistributor could call this function and then stake atomically on behalf of the user.\n * @dev Caller must be in whitelistedClaimers struct set to \"true\".\n * @param _claim leaf to claim.\n */\n\n function claimFor(Claim memory _claim) public {\n require(whitelistedClaimers[msg.sender], \"unwhitelisted claimer\");\n _verifyAndMarkClaimed(_claim);\n merkleWindows[_claim.windowIndex].rewardToken.safeTransfer(msg.sender, _claim.amount);\n emit ClaimFor(\n msg.sender,\n _claim.windowIndex,\n _claim.account,\n _claim.accountIndex,\n _claim.amount,\n address(merkleWindows[_claim.windowIndex].rewardToken)\n );\n }\n}\n" + }, + "@uma/core/contracts/oracle/interfaces/IdentifierWhitelistInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Interface for whitelists of supported identifiers that the oracle can provide prices for.\n */\ninterface IdentifierWhitelistInterface {\n /**\n * @notice Adds the provided identifier as a supported identifier.\n * @dev Price requests using this identifier will succeed after this call.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n */\n function addSupportedIdentifier(bytes32 identifier) external;\n\n /**\n * @notice Removes the identifier from the whitelist.\n * @dev Price requests using this identifier will no longer succeed after this call.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n */\n function removeSupportedIdentifier(bytes32 identifier) external;\n\n /**\n * @notice Checks whether an identifier is on the whitelist.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n * @return bool if the identifier is supported (or not).\n */\n function isIdentifierSupported(bytes32 identifier) external view returns (bool);\n}\n" + }, + "@uma/core/contracts/common/implementation/Testable.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./Timer.sol\";\n\n/**\n * @title Base class that provides time overrides, but only if being run in test mode.\n */\nabstract contract Testable {\n // If the contract is being run in production, then `timerAddress` will be the 0x0 address.\n // Note: this variable should be set on construction and never modified.\n address public timerAddress;\n\n /**\n * @notice Constructs the Testable contract. Called by child contracts.\n * @param _timerAddress Contract that stores the current time in a testing environment.\n * Must be set to 0x0 for production environments that use live time.\n */\n constructor(address _timerAddress) {\n timerAddress = _timerAddress;\n }\n\n /**\n * @notice Reverts if not running in test mode.\n */\n modifier onlyIfTest {\n require(timerAddress != address(0x0));\n _;\n }\n\n /**\n * @notice Sets the current time.\n * @dev Will revert if not running in test mode.\n * @param time timestamp to set current Testable time to.\n */\n function setCurrentTime(uint256 time) external onlyIfTest {\n Timer(timerAddress).setCurrentTime(time);\n }\n\n /**\n * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.\n * Otherwise, it will return the block timestamp.\n * @return uint for the current Testable timestamp.\n */\n function getCurrentTime() public view virtual returns (uint256) {\n if (timerAddress != address(0x0)) {\n return Timer(timerAddress).getCurrentTime();\n } else {\n return block.timestamp; // solhint-disable-line not-rely-on-time\n }\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/Timer.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Universal store of current contract time for testing environments.\n */\ncontract Timer {\n uint256 private currentTime;\n\n constructor() {\n currentTime = block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n /**\n * @notice Sets the current time.\n * @dev Will revert if not running in test mode.\n * @param time timestamp to set `currentTime` to.\n */\n function setCurrentTime(uint256 time) external {\n currentTime = time;\n }\n\n /**\n * @notice Gets the currentTime variable set in the Timer.\n * @return uint256 for the current Testable timestamp.\n */\n function getCurrentTime() public view returns (uint256) {\n return currentTime;\n }\n}\n" + }, + "@uma/core/contracts/oracle/implementation/Constants.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Stores common interface names used throughout the DVM by registration in the Finder.\n */\nlibrary OracleInterfaces {\n bytes32 public constant Oracle = \"Oracle\";\n bytes32 public constant IdentifierWhitelist = \"IdentifierWhitelist\";\n bytes32 public constant Store = \"Store\";\n bytes32 public constant FinancialContractsAdmin = \"FinancialContractsAdmin\";\n bytes32 public constant Registry = \"Registry\";\n bytes32 public constant CollateralWhitelist = \"CollateralWhitelist\";\n bytes32 public constant OptimisticOracle = \"OptimisticOracle\";\n bytes32 public constant OptimisticOracleV2 = \"OptimisticOracleV2\";\n bytes32 public constant Bridge = \"Bridge\";\n bytes32 public constant GenericHandler = \"GenericHandler\";\n bytes32 public constant SkinnyOptimisticOracle = \"SkinnyOptimisticOracle\";\n bytes32 public constant ChildMessenger = \"ChildMessenger\";\n bytes32 public constant OracleHub = \"OracleHub\";\n bytes32 public constant OracleSpoke = \"OracleSpoke\";\n}\n\n/**\n * @title Commonly re-used values for contracts associated with the OptimisticOracle.\n */\nlibrary OptimisticOracleConstraints {\n // Any price request submitted to the OptimisticOracle must contain ancillary data no larger than this value.\n // This value must be <= the Voting contract's `ancillaryBytesLimit` constant value otherwise it is possible\n // that a price can be requested to the OptimisticOracle successfully, but cannot be resolved by the DVM which\n // refuses to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n}\n" + }, + "@uma/core/contracts/common/interfaces/AddressWhitelistInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\ninterface AddressWhitelistInterface {\n function addToWhitelist(address newElement) external;\n\n function removeFromWhitelist(address newElement) external;\n\n function isOnWhitelist(address newElement) external view returns (bool);\n\n function getWhitelist() external view returns (address[] memory);\n}\n" + }, + "contracts/test/ArbitrumMocks.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\ncontract ArbitrumMockErc20GatewayRouter {\n function outboundTransferCustomRefund(\n address,\n address,\n address,\n uint256,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n return _data;\n }\n\n function outboundTransfer(\n address,\n address,\n uint256,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n return _data;\n }\n\n function getGateway(address) external view returns (address) {\n return address(this);\n }\n}\n" + }, + "contracts/test/SuccinctMocks.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\ncontract TelepathyBroadcasterMock {\n function send(\n uint16,\n address,\n bytes calldata\n ) external pure returns (bytes32) {\n return bytes32(0);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/polygon-mumbai/MintableERC1155.json b/deployments/polygon-mumbai/MintableERC1155.json new file mode 100644 index 000000000..e66d2b314 --- /dev/null +++ b/deployments/polygon-mumbai/MintableERC1155.json @@ -0,0 +1,703 @@ +{ + "address": "0xe377d7C510fEbc64525f480e33306b21b30066F7", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Airdrop", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_tokenURIs", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "airdrop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "setTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x8ac6eb2f2ae30d7b7477b22fbeec6357244189466e7b1cd081f55729c37272c5", + "receipt": { + "to": null, + "from": "0x52A79C01f10e6Ea89dED5c3f42F3a0EC362ed090", + "contractAddress": "0xe377d7C510fEbc64525f480e33306b21b30066F7", + "transactionIndex": 5, + "gasUsed": "1826593", + "logsBloom": "0x00000000000000020000000000000000000000000000000000800000000000000000000000000000000000000000000000008000000000000000000000000000001000000000000000000000000000800001000000000000000100000000000000000000020000000000000000000800000000000000000080000000000000400000000000000000000000000000000000000000000000000000000001000000200000000000000020000000000000000001000000000000000000000000004000000000000000000001000000000000000000000000000020100000000020200000000000000000000020000000000000000000000004000000000000100000", + "blockHash": "0x86e9eebe3aa9d2b5d9bebeb1e4eb29047029630d574939c3018a4dc741c09431", + "transactionHash": "0x8ac6eb2f2ae30d7b7477b22fbeec6357244189466e7b1cd081f55729c37272c5", + "logs": [ + { + "transactionIndex": 5, + "blockNumber": 33352305, + "transactionHash": "0x8ac6eb2f2ae30d7b7477b22fbeec6357244189466e7b1cd081f55729c37272c5", + "address": "0xe377d7C510fEbc64525f480e33306b21b30066F7", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000052a79c01f10e6ea89ded5c3f42f3a0ec362ed090" + ], + "data": "0x", + "logIndex": 11, + "blockHash": "0x86e9eebe3aa9d2b5d9bebeb1e4eb29047029630d574939c3018a4dc741c09431" + }, + { + "transactionIndex": 5, + "blockNumber": 33352305, + "transactionHash": "0x8ac6eb2f2ae30d7b7477b22fbeec6357244189466e7b1cd081f55729c37272c5", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000052a79c01f10e6ea89ded5c3f42f3a0ec362ed090", + "0x000000000000000000000000c26880a0af2ea0c7e8130e6ec47af756465452e8" + ], + "data": "0x0000000000000000000000000000000000000000000000000009bbea3c5f0f00000000000000000000000000000000000000000000000000202783a599152305000000000000000000000000000000000000000000001c9eeb8805e62bdb8195000000000000000000000000000000000000000000000000201dc7bb5cb61405000000000000000000000000000000000000000000001c9eeb91c1d0683a9095", + "logIndex": 12, + "blockHash": "0x86e9eebe3aa9d2b5d9bebeb1e4eb29047029630d574939c3018a4dc741c09431" + } + ], + "blockNumber": 33352305, + "cumulativeGasUsed": "2289787", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 3, + "solcInputHash": "200193942e0f09d7ebb5ccce1bc305e7", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Airdrop\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"_tokenURIs\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"airdrop\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"tokenURI\",\"type\":\"string\"}],\"name\":\"setTokenURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"}},\"kind\":\"dev\",\"methods\":{\"airdrop(uint256,address[],uint256)\":{\"details\":\"Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\",\"params\":{\"amount\":\"Amount of token types to airdrop.\",\"recipients\":\"List of airdrop recipients.\",\"tokenId\":\"Token type to airdrop.\"}},\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155-safeBatchTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"setTokenURI(uint256,string)\":{\"params\":{\"tokenId\":\"Token type to set `tokenURI` for.\",\"tokenURI\":\"URI of token metadata.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"uri(uint256)\":{\"details\":\"Instead of returning the same URI for *all* token types, we return the uri set by `setTokenURI` to allow IPFS URIs for all token types.\",\"params\":{\"tokenId\":\"Token type to retrieve metadata URI for.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"airdrop(uint256,address[],uint256)\":{\"notice\":\"Creates `amount` new tokens for `recipients` of token type `tokenId`.\"},\"setTokenURI(uint256,string)\":{\"notice\":\"Sets the URI for token of type `tokenId` to `tokenURI`.\"},\"uri(uint256)\":{\"notice\":\"Returns metadata URI of token type `tokenId`.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/erc1155/MintableERC1155.sol\":\"MintableERC1155\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: address zero is not a valid owner\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not token owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not token owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _balances[id][to] += amount;\\n emit TransferSingle(operator, address(0), to, id, amount);\\n\\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `from`\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `from` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address from,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n\\n emit TransferSingle(operator, from, address(0), id, amount);\\n\\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address from,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, from, address(0), ids, amounts);\\n\\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC1155: setting approval status for self\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x447a21c87433c0f11252912313a96f3454629ef88cca7a4eefbb283b3ec409f9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x6392f2cfe3a5ee802227fe7a2dfd47096d881aec89bddd214b35c5b46d3cd941\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa66d18b9a85458d28fc3304717964502ae36f7f8a2ff35bc83f6f85d74b03574\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/erc1155/MintableERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\n\\ncontract MintableERC1155 is ERC1155, Ownable {\\n mapping(uint256 => string) public _tokenURIs;\\n\\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\\n\\n // solhint-disable-next-line\\n constructor() ERC1155(\\\"\\\") {}\\n\\n /**\\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\\n * @param recipients List of airdrop recipients.\\n * @param tokenId Token type to airdrop.\\n * @param amount Amount of token types to airdrop.\\n */\\n function airdrop(\\n uint256 tokenId,\\n address[] memory recipients,\\n uint256 amount\\n ) public onlyOwner {\\n for (uint256 i = 0; i < recipients.length; i++) {\\n _mint(recipients[i], tokenId, amount, \\\"\\\");\\n }\\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\\n }\\n\\n /**\\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\\n * @param tokenId Token type to set `tokenURI` for.\\n * @param tokenURI URI of token metadata.\\n */\\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\\n require(bytes(_tokenURIs[tokenId]).length == 0, \\\"uri already set\\\");\\n\\n _tokenURIs[tokenId] = tokenURI;\\n emit URI(tokenURI, tokenId);\\n }\\n\\n /**\\n * @notice Returns metadata URI of token type `tokenId`.\\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\\n * `setTokenURI` to allow IPFS URIs for all token types.\\n * @param tokenId Token type to retrieve metadata URI for.\\n */\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return _tokenURIs[tokenId];\\n }\\n}\\n\",\"keccak256\":\"0x1ce6820f23820d4d6dbd48b168e6de51efe1216c4880e2f2e0bb3143d58d7ed5\",\"license\":\"AGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080346200012657602081016001600160401b03811182821017620001105760405260008091526002546001908181811c9116801562000105575b6020821014620000f157601f8111620000a7575b600283905560038054336001600160a01b03198216811790925560405191906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a3611fc990816200012c8239f35b60028352601f0160051c7f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace908101905b818110620000e657506200004e565b8381558201620000d7565b634e487b7160e01b83526022600452602483fd5b90607f16906200003a565b634e487b7160e01b600052604160045260246000fd5b600080fdfe6040608081526004908136101561001557600080fd5b600091823560e01c8062fdd58e146116c957806301ffc9a7146115da5780630bb78ec1146115815780630e89341c14611581578063162094c4146112b25780632eb2c2d614610ef65780634e1273f414610d44578063715018a614610ca3578063754e5e37146107e15780638da5cb5b1461078e578063a22cb4651461063a578063e985e9c5146105bd578063f242432a146101f55763f2fde38b146100ba57600080fd5b346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f1576100f1611717565b906100fa611af0565b73ffffffffffffffffffffffffffffffffffffffff80921692831561016e575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b5090346101f15760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15761022e611717565b8361023761173f565b916044359060643560843567ffffffffffffffff81116105b95761025e9036908901611a23565b9273ffffffffffffffffffffffffffffffffffffffff80931692338414801561059a575b61028b90611ccc565b861690610299821515611d57565b6102a281611f5d565b506102ac83611f5d565b50808652602096868852888720858852885283898820546102cf82821015611de2565b838952888a528a8920878a528a52038988205581875286885288872083885288528887206102fe858254611e6d565b905582858a51848152868b8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628c3392a43b61033a578580f35b889587946103948a51978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906118ea565b03925af186918161056b575b506104af5750506001906103b2611eb2565b6308c379a014610462575b506103d25750505b3880808381808080808580f35b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b61046a611ed0565b8061047557506103bd565b61045e859185519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff00000000000000000000000000000000000000000000000000000000160390506104df5750506103c5565b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b61058c919250843d8611610593575b61058481836117b5565b810190611e7a565b90386103a0565b503d61057a565b508386526001602090815288872033885290528786205460ff16610282565b8480fd5b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760ff816020936105fb611717565b61060361173f565b73ffffffffffffffffffffffffffffffffffffffff91821683526001875283832091168252855220549151911615158152f35b5080fd5b5090346101f157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f157610672611717565b90602435918215158093036105b95773ffffffffffffffffffffffffffffffffffffffff169283331461070c575033845260016020528084208385526020528084207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8416179055519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b50503461063657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5090346101f15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781359260249067ffffffffffffffff908235828111610636576108389036908701611a41565b9560448035610845611af0565b835b8951811015610c175773ffffffffffffffffffffffffffffffffffffffff61086f828c611c89565b51168851906020918281018181108a821117610bec578b528781528115610b6a57858c92898c8a948f6108a187611f5d565b506108ab8b611f5d565b5086845283895280842085855289528084206108c88c8254611e6d565b9055848482518981528d8c8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62843392a4843b610919575b50505050505050505061091490611c2d565b610847565b916109748493928a9796959351988997889687957ff23a6e61000000000000000000000000000000000000000000000000000000009d8e885233908801528601528401528c606484015260a0608484015260a48301906118ea565b03925af1889181610b4b575b50610a8d575050600190610992611eb2565b6308c379a014610a41575b506109b557610914905b9089858538898c828f610902565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b610a49611ed0565b80610a54575061099d565b61045e8c918b8d519485947f08c379a00000000000000000000000000000000000000000000000000000000086528501528301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016039050610abf57610914906109a7565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b610b63919250843d86116105935761058481836117b5565b9038610980565b5050897f455243313135353a206d696e7420746f20746865207a65726f206164647265738560218b6084958e51957f08c379a00000000000000000000000000000000000000000000000000000000087528601528401528201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b8a8960418f7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b89858984878251926080808501913386526020938487015285015285518091528160a08501960191855b828110610c7957867f13d0a346ea6c350592dd539c68d5ff6d61d6b8834695625d09834638717193e087808b8960608301520390a180f35b835173ffffffffffffffffffffffffffffffffffffffff1688529681019692810192600101610c41565b8334610d4157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d4157610cda611af0565b8073ffffffffffffffffffffffffffffffffffffffff6003547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b509134610d4157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d415767ffffffffffffffff83358181116101f157610d939036908601611a41565b906024359081116101f157610dab90369086016119c5565b938151855103610e7357508051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610dfb610de6856119ad565b94610df3875196876117b5565b8086526119ad565b013660208501375b8151811015610e5a5780610e4573ffffffffffffffffffffffffffffffffffffffff610e32610e559486611c89565b5116610e3e8389611c89565b5190611b6f565b610e4f8286611c89565b52611c2d565b610e03565b835160208082528190610e6f90820186611abc565b0390f35b60849060208551917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b50346101f1577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9160a0833601126112ae57610f30611717565b92610f3961173f565b9367ffffffffffffffff936044358581116112aa57610f5b90369083016119c5565b906064358681116112a657610f7390369083016119c5565b956084359081116112a657610f8b9036908301611a23565b9373ffffffffffffffffffffffffffffffffffffffff809416933385148015611287575b610fb890611ccc565b835188510361120457881694610fcf861515611d57565b895b8a85518210156110555790896110498a61105094610ffa85610ff3818d611c89565b5195611c89565b51938082526020908282528383208d84528252858d858520549061102083831015611de2565b838652858552868620908652845203848420558252818152828220908d83525220918254611e6d565b9055611c2d565b610fd1565b50509094939596929197848789518a81527f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6110938c830188611abc565b918083036020820152806110a833948b611abc565b0390a43b6110b4578880f35b865194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338c87015260248601526044850160a0905260a485016110ff91611abc565b8285820301606486015261111291611abc565b90838203016084840152611125916118ea565b0381885a94602095f18591816111e4575b506111b65750506001611147611eb2565b6308c379a014611165575b6103d25750505b38808080808080808880f35b61116d611ed0565b806111785750611152565b905061045e9160209450519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016036104df575050611159565b6111fd91925060203d81116105935761058481836117b5565b9038611136565b60848360208951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b50848a5260016020908152878b20338c529052868a205460ff16610faf565b8880fd5b8780fd5b8380fd5b50346101f157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15780359167ffffffffffffffff9060243582811161157d573660238201121561157d576113169036906024818701359101611948565b9261131f611af0565b84865260209281845261133483882054611762565b611521578587528184528287209185519182116114f557506113568254611762565b601f81116114b2575b5083601f82116001146113ef5791817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b969594926113de948a916113e4575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b519282849384528301906118ea565b0390a280f35b90508601513861139e565b828852848820907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316895b81811061149b5750926113de9492600192827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9a99989610611464575b5050811b0190556113cf565b8801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880611458565b91928760018192868c01518155019401920161141b565b828852848820601f830160051c8101918684106114eb575b601f0160051c01905b8181106114e0575061135f565b8881556001016114d3565b90915081906114ca565b8760416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b508260649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f75726920616c72656164792073657400000000000000000000000000000000006044820152fd5b8580fd5b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781610e6f93826115c79335825260205220611825565b90519182916020835260208301906118ea565b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15735907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101f157602092507fd9b67a2600000000000000000000000000000000000000000000000000000000821491821561169f575b8215611675575b50519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000001491503861166c565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149250611665565b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261063657602090611710611707611717565b60243590611b6f565b9051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b90600182811c921680156117ab575b602083101461177c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611771565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117f657604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b906040519182600082549261183984611762565b9081845260019485811690816000146118a85750600114611865575b5050611863925003836117b5565b565b9093915060005260209081600020936000915b81831061189057505061186393508201013880611855565b85548884018501529485019487945091830191611878565b90506118639550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611855565b919082519283825260005b8481106119345750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016118f5565b92919267ffffffffffffffff82116117f6576040519161199060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846117b5565b82948184528183011161173a578281602093846000960137010152565b67ffffffffffffffff81116117f65760051b60200190565b81601f8201121561173a578035916119dc836119ad565b926119ea60405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a14575050505090565b81358152908301908301611a06565b9080601f8301121561173a57816020611a3e93359101611948565b90565b81601f8201121561173a57803591611a58836119ad565b92611a6660405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a90575050505090565b813573ffffffffffffffffffffffffffffffffffffffff8116810361173a578152908301908301611a82565b90815180825260208080930193019160005b828110611adc575050505090565b835185529381019392810192600101611ace565b73ffffffffffffffffffffffffffffffffffffffff600354163303611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b73ffffffffffffffffffffffffffffffffffffffff16908115611ba957600052600060205260406000209060005260205260406000205490565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c5a5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8051821015611c9d5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b15611cd357565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206e6f7220617070726f76656400000000000000000000000000000000006064820152fd5b15611d5e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15611de957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b91908201809211611c5a57565b9081602091031261173a57517fffffffff000000000000000000000000000000000000000000000000000000008116810361173a5790565b60009060033d11611ebf57565b905060046000803e60005160e01c90565b600060443d10611a3e576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117611f4c57818401948551938411611f54573d85010160208487010111611f4c5750611a3e929101602001906117b5565b949350505050565b50949350505050565b604051906040820182811067ffffffffffffffff8211176117f65760405260018252602082016020368237825115611c9d57529056fea26469706673582212204649af28b2218246749413731aaab257fc72268b5a9c227716987edfd17c6b3e64736f6c63430008120033", + "deployedBytecode": "0x6040608081526004908136101561001557600080fd5b600091823560e01c8062fdd58e146116c957806301ffc9a7146115da5780630bb78ec1146115815780630e89341c14611581578063162094c4146112b25780632eb2c2d614610ef65780634e1273f414610d44578063715018a614610ca3578063754e5e37146107e15780638da5cb5b1461078e578063a22cb4651461063a578063e985e9c5146105bd578063f242432a146101f55763f2fde38b146100ba57600080fd5b346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f1576100f1611717565b906100fa611af0565b73ffffffffffffffffffffffffffffffffffffffff80921692831561016e575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b5090346101f15760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15761022e611717565b8361023761173f565b916044359060643560843567ffffffffffffffff81116105b95761025e9036908901611a23565b9273ffffffffffffffffffffffffffffffffffffffff80931692338414801561059a575b61028b90611ccc565b861690610299821515611d57565b6102a281611f5d565b506102ac83611f5d565b50808652602096868852888720858852885283898820546102cf82821015611de2565b838952888a528a8920878a528a52038988205581875286885288872083885288528887206102fe858254611e6d565b905582858a51848152868b8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628c3392a43b61033a578580f35b889587946103948a51978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906118ea565b03925af186918161056b575b506104af5750506001906103b2611eb2565b6308c379a014610462575b506103d25750505b3880808381808080808580f35b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b61046a611ed0565b8061047557506103bd565b61045e859185519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff00000000000000000000000000000000000000000000000000000000160390506104df5750506103c5565b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b61058c919250843d8611610593575b61058481836117b5565b810190611e7a565b90386103a0565b503d61057a565b508386526001602090815288872033885290528786205460ff16610282565b8480fd5b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760ff816020936105fb611717565b61060361173f565b73ffffffffffffffffffffffffffffffffffffffff91821683526001875283832091168252855220549151911615158152f35b5080fd5b5090346101f157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f157610672611717565b90602435918215158093036105b95773ffffffffffffffffffffffffffffffffffffffff169283331461070c575033845260016020528084208385526020528084207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8416179055519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b50503461063657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5090346101f15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781359260249067ffffffffffffffff908235828111610636576108389036908701611a41565b9560448035610845611af0565b835b8951811015610c175773ffffffffffffffffffffffffffffffffffffffff61086f828c611c89565b51168851906020918281018181108a821117610bec578b528781528115610b6a57858c92898c8a948f6108a187611f5d565b506108ab8b611f5d565b5086845283895280842085855289528084206108c88c8254611e6d565b9055848482518981528d8c8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62843392a4843b610919575b50505050505050505061091490611c2d565b610847565b916109748493928a9796959351988997889687957ff23a6e61000000000000000000000000000000000000000000000000000000009d8e885233908801528601528401528c606484015260a0608484015260a48301906118ea565b03925af1889181610b4b575b50610a8d575050600190610992611eb2565b6308c379a014610a41575b506109b557610914905b9089858538898c828f610902565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b610a49611ed0565b80610a54575061099d565b61045e8c918b8d519485947f08c379a00000000000000000000000000000000000000000000000000000000086528501528301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016039050610abf57610914906109a7565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b610b63919250843d86116105935761058481836117b5565b9038610980565b5050897f455243313135353a206d696e7420746f20746865207a65726f206164647265738560218b6084958e51957f08c379a00000000000000000000000000000000000000000000000000000000087528601528401528201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b8a8960418f7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b89858984878251926080808501913386526020938487015285015285518091528160a08501960191855b828110610c7957867f13d0a346ea6c350592dd539c68d5ff6d61d6b8834695625d09834638717193e087808b8960608301520390a180f35b835173ffffffffffffffffffffffffffffffffffffffff1688529681019692810192600101610c41565b8334610d4157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d4157610cda611af0565b8073ffffffffffffffffffffffffffffffffffffffff6003547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b509134610d4157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d415767ffffffffffffffff83358181116101f157610d939036908601611a41565b906024359081116101f157610dab90369086016119c5565b938151855103610e7357508051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610dfb610de6856119ad565b94610df3875196876117b5565b8086526119ad565b013660208501375b8151811015610e5a5780610e4573ffffffffffffffffffffffffffffffffffffffff610e32610e559486611c89565b5116610e3e8389611c89565b5190611b6f565b610e4f8286611c89565b52611c2d565b610e03565b835160208082528190610e6f90820186611abc565b0390f35b60849060208551917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b50346101f1577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9160a0833601126112ae57610f30611717565b92610f3961173f565b9367ffffffffffffffff936044358581116112aa57610f5b90369083016119c5565b906064358681116112a657610f7390369083016119c5565b956084359081116112a657610f8b9036908301611a23565b9373ffffffffffffffffffffffffffffffffffffffff809416933385148015611287575b610fb890611ccc565b835188510361120457881694610fcf861515611d57565b895b8a85518210156110555790896110498a61105094610ffa85610ff3818d611c89565b5195611c89565b51938082526020908282528383208d84528252858d858520549061102083831015611de2565b838652858552868620908652845203848420558252818152828220908d83525220918254611e6d565b9055611c2d565b610fd1565b50509094939596929197848789518a81527f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6110938c830188611abc565b918083036020820152806110a833948b611abc565b0390a43b6110b4578880f35b865194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338c87015260248601526044850160a0905260a485016110ff91611abc565b8285820301606486015261111291611abc565b90838203016084840152611125916118ea565b0381885a94602095f18591816111e4575b506111b65750506001611147611eb2565b6308c379a014611165575b6103d25750505b38808080808080808880f35b61116d611ed0565b806111785750611152565b905061045e9160209450519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016036104df575050611159565b6111fd91925060203d81116105935761058481836117b5565b9038611136565b60848360208951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b50848a5260016020908152878b20338c529052868a205460ff16610faf565b8880fd5b8780fd5b8380fd5b50346101f157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15780359167ffffffffffffffff9060243582811161157d573660238201121561157d576113169036906024818701359101611948565b9261131f611af0565b84865260209281845261133483882054611762565b611521578587528184528287209185519182116114f557506113568254611762565b601f81116114b2575b5083601f82116001146113ef5791817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b969594926113de948a916113e4575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b519282849384528301906118ea565b0390a280f35b90508601513861139e565b828852848820907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316895b81811061149b5750926113de9492600192827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9a99989610611464575b5050811b0190556113cf565b8801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880611458565b91928760018192868c01518155019401920161141b565b828852848820601f830160051c8101918684106114eb575b601f0160051c01905b8181106114e0575061135f565b8881556001016114d3565b90915081906114ca565b8760416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b508260649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f75726920616c72656164792073657400000000000000000000000000000000006044820152fd5b8580fd5b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781610e6f93826115c79335825260205220611825565b90519182916020835260208301906118ea565b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15735907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101f157602092507fd9b67a2600000000000000000000000000000000000000000000000000000000821491821561169f575b8215611675575b50519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000001491503861166c565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149250611665565b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261063657602090611710611707611717565b60243590611b6f565b9051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b90600182811c921680156117ab575b602083101461177c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611771565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117f657604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b906040519182600082549261183984611762565b9081845260019485811690816000146118a85750600114611865575b5050611863925003836117b5565b565b9093915060005260209081600020936000915b81831061189057505061186393508201013880611855565b85548884018501529485019487945091830191611878565b90506118639550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611855565b919082519283825260005b8481106119345750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016118f5565b92919267ffffffffffffffff82116117f6576040519161199060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846117b5565b82948184528183011161173a578281602093846000960137010152565b67ffffffffffffffff81116117f65760051b60200190565b81601f8201121561173a578035916119dc836119ad565b926119ea60405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a14575050505090565b81358152908301908301611a06565b9080601f8301121561173a57816020611a3e93359101611948565b90565b81601f8201121561173a57803591611a58836119ad565b92611a6660405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a90575050505090565b813573ffffffffffffffffffffffffffffffffffffffff8116810361173a578152908301908301611a82565b90815180825260208080930193019160005b828110611adc575050505090565b835185529381019392810192600101611ace565b73ffffffffffffffffffffffffffffffffffffffff600354163303611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b73ffffffffffffffffffffffffffffffffffffffff16908115611ba957600052600060205260406000209060005260205260406000205490565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c5a5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8051821015611c9d5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b15611cd357565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206e6f7220617070726f76656400000000000000000000000000000000006064820152fd5b15611d5e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15611de957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b91908201809211611c5a57565b9081602091031261173a57517fffffffff000000000000000000000000000000000000000000000000000000008116810361173a5790565b60009060033d11611ebf57565b905060046000803e60005160e01c90565b600060443d10611a3e576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117611f4c57818401948551938411611f54573d85010160208487010111611f4c5750611a3e929101602001906117b5565b949350505050565b50949350505050565b604051906040820182811067ffffffffffffffff8211176117f65760405260018252602082016020368237825115611c9d57529056fea26469706673582212204649af28b2218246749413731aaab257fc72268b5a9c227716987edfd17c6b3e64736f6c63430008120033", + "devdoc": { + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + } + }, + "kind": "dev", + "methods": { + "airdrop(uint256,address[],uint256)": { + "details": "Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.", + "params": { + "amount": "Amount of token types to airdrop.", + "recipients": "List of airdrop recipients.", + "tokenId": "Token type to airdrop." + } + }, + "balanceOf(address,uint256)": { + "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address." + }, + "balanceOfBatch(address[],uint256[])": { + "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length." + }, + "isApprovedForAll(address,address)": { + "details": "See {IERC1155-isApprovedForAll}." + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "See {IERC1155-safeBatchTransferFrom}." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "See {IERC1155-safeTransferFrom}." + }, + "setApprovalForAll(address,bool)": { + "details": "See {IERC1155-setApprovalForAll}." + }, + "setTokenURI(uint256,string)": { + "params": { + "tokenId": "Token type to set `tokenURI` for.", + "tokenURI": "URI of token metadata." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "uri(uint256)": { + "details": "Instead of returning the same URI for *all* token types, we return the uri set by `setTokenURI` to allow IPFS URIs for all token types.", + "params": { + "tokenId": "Token type to retrieve metadata URI for." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "airdrop(uint256,address[],uint256)": { + "notice": "Creates `amount` new tokens for `recipients` of token type `tokenId`." + }, + "setTokenURI(uint256,string)": { + "notice": "Sets the URI for token of type `tokenId` to `tokenURI`." + }, + "uri(uint256)": { + "notice": "Returns metadata URI of token type `tokenId`." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 138, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 144, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 146, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_uri", + "offset": 0, + "slot": "2", + "type": "t_string_storage" + }, + { + "astId": 7, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_owner", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 1878, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_tokenURIs", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_string_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_string_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/polygon-mumbai/solcInputs/200193942e0f09d7ebb5ccce1bc305e7.json b/deployments/polygon-mumbai/solcInputs/200193942e0f09d7ebb5ccce1bc305e7.json new file mode 100644 index 000000000..cb04c7ce8 --- /dev/null +++ b/deployments/polygon-mumbai/solcInputs/200193942e0f09d7ebb5ccce1bc305e7.json @@ -0,0 +1,61 @@ +{ + "language": "Solidity", + "sources": { + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\ncontract MintableERC1155 is ERC1155, Ownable {\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\n\n // solhint-disable-next-line\n constructor() ERC1155(\"\") {}\n\n /**\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\n * @param recipients List of airdrop recipients.\n * @param tokenId Token type to airdrop.\n * @param amount Amount of token types to airdrop.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256 amount\n ) public onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n _mint(recipients[i], tokenId, amount, \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\n }\n\n /**\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\n * @param tokenId Token type to set `tokenURI` for.\n * @param tokenURI URI of token metadata.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\n require(bytes(_tokenURIs[tokenId]).length == 0, \"uri already set\");\n\n _tokenURIs[tokenId] = tokenURI;\n emit URI(tokenURI, tokenId);\n }\n\n /**\n * @notice Returns metadata URI of token type `tokenId`.\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for all token types.\n * @param tokenId Token type to retrieve metadata URI for.\n */\n function uri(uint256 tokenId) public view override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/polygon-mumbai/solcInputs/2a98e0c4f048f0fda1d4cc9162127646.json b/deployments/polygon-mumbai/solcInputs/2a98e0c4f048f0fda1d4cc9162127646.json new file mode 100644 index 000000000..042e6dae4 --- /dev/null +++ b/deployments/polygon-mumbai/solcInputs/2a98e0c4f048f0fda1d4cc9162127646.json @@ -0,0 +1,91 @@ +{ + "language": "Solidity", + "sources": { + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol\";\n\nimport \"@openzeppelin/contracts/utils/Context.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\ncontract MintableERC1155 is ERC1155, Ownable {\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\n\n // solhint-disable-next-line\n constructor() ERC1155(\"\") {}\n\n /**\n * @dev Creates `amount` new tokens for `recipients` of token type `tokenId`.\n * @param recipients List of airdrop recipients.\n * @param tokenId Token type to airdrop.\n * @param amount Amount of token types to airdrop.\n *\n * NOTE: Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256 amount\n ) public onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n _mint(recipients[i], tokenId, amount, \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\n }\n\n /**\n * @dev Sets the URI for token of type `tokenId` to `tokenURI`.\n * @param tokenId Token type to set `tokenURI` for.\n * @param tokenURI URI of token metadata.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\n _tokenURIs[tokenId] = tokenURI;\n }\n\n /**\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for all token types.\n * @param tokenId Token type to retrieve metadata URI for.\n */\n function uri(uint256 tokenId) public view virtual override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/presets/ERC1155PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../extensions/ERC1155Burnable.sol\";\nimport \"../extensions/ERC1155Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC1155} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC1155PresetMinterPauser is Context, AccessControlEnumerable, ERC1155Burnable, ERC1155Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that\n * deploys the contract.\n */\n constructor(string memory uri) ERC1155(uri) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`, of token type `id`.\n *\n * See {ERC1155-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have minter role to mint\");\n\n _mint(to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.\n */\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have minter role to mint\");\n\n _mintBatch(to, ids, amounts, data);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId)\n public\n view\n virtual\n override(AccessControlEnumerable, ERC1155)\n returns (bool)\n {\n return super.supportsInterface(interfaceId);\n }\n\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override(ERC1155, ERC1155Pausable) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/extensions/ERC1155Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\n * own tokens and those that they have been approved to use.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Burnable is ERC1155 {\n function burn(\n address account,\n uint256 id,\n uint256 value\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n\n _burn(account, id, value);\n }\n\n function burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory values\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n\n _burnBatch(account, ids, values);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC1155 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Pausable is ERC1155, Pausable {\n /**\n * @dev See {ERC1155-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n require(!paused(), \"ERC1155Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/polygon-mumbai/solcInputs/c0d608dcade73b41bfb146ca48293092.json b/deployments/polygon-mumbai/solcInputs/c0d608dcade73b41bfb146ca48293092.json new file mode 100644 index 000000000..127623b2b --- /dev/null +++ b/deployments/polygon-mumbai/solcInputs/c0d608dcade73b41bfb146ca48293092.json @@ -0,0 +1,88 @@ +{ + "language": "Solidity", + "sources": { + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol\";\n\ncontract MintableERC1155 is ERC1155PresetMinterPauser {\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256[] amounts);\n\n constructor() ERC1155PresetMinterPauser(\"\") {}\n\n /**\n * @dev Creates `amounts[i]` new tokens for `recipients[i]` of toke type `tokenId`.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256[] memory amounts\n ) public {\n require(recipients.length == amounts.length, \"MintableERC1155: recipients and amounts length mismatch\");\n\n for (uint256 i = 0; i < recipients.length; i++) {\n mint(recipients[i], tokenId, amounts[i], \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amounts);\n }\n\n /**\n * @dev Sets the URI for token of type `tokenId` to `tokenURI`.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have minter role to set uri\");\n\n _tokenURIs[tokenId] = tokenURI;\n }\n\n /**\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for token types.\n */\n function uri(uint256 tokenId) public view virtual override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/presets/ERC1155PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../extensions/ERC1155Burnable.sol\";\nimport \"../extensions/ERC1155Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC1155} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC1155PresetMinterPauser is Context, AccessControlEnumerable, ERC1155Burnable, ERC1155Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that\n * deploys the contract.\n */\n constructor(string memory uri) ERC1155(uri) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`, of token type `id`.\n *\n * See {ERC1155-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have minter role to mint\");\n\n _mint(to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}.\n */\n function mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have minter role to mint\");\n\n _mintBatch(to, ids, amounts, data);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC1155Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC1155PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId)\n public\n view\n virtual\n override(AccessControlEnumerable, ERC1155)\n returns (bool)\n {\n return super.supportsInterface(interfaceId);\n }\n\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override(ERC1155, ERC1155Pausable) {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/extensions/ERC1155Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of {ERC1155} that allows token holders to destroy both their\n * own tokens and those that they have been approved to use.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Burnable is ERC1155 {\n function burn(\n address account,\n uint256 id,\n uint256 value\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n\n _burn(account, id, value);\n }\n\n function burnBatch(\n address account,\n uint256[] memory ids,\n uint256[] memory values\n ) public virtual {\n require(\n account == _msgSender() || isApprovedForAll(account, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n\n _burnBatch(account, ids, values);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC1155 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * _Available since v3.1._\n */\nabstract contract ERC1155Pausable is ERC1155, Pausable {\n /**\n * @dev See {ERC1155-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual override {\n super._beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n require(!paused(), \"ERC1155Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/polygon/MintableERC1155.json b/deployments/polygon/MintableERC1155.json new file mode 100644 index 000000000..b53bda8ff --- /dev/null +++ b/deployments/polygon/MintableERC1155.json @@ -0,0 +1,705 @@ +{ + "address": "0xA15a90E7936A2F8B70E181E955760860D133e56B", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Airdrop", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "_tokenURIs", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "airdrop", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "setTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x131a2505558806a1221cf4d15683766fb0e3a9681d15f4d309bd30764e81c66b", + "receipt": { + "to": null, + "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", + "contractAddress": "0xA15a90E7936A2F8B70E181E955760860D133e56B", + "transactionIndex": 51, + "gasUsed": "1826569", + "logsBloom": "0x000000000000000000000000000000000000000000000000008000000400000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000008000010000000000000001000000000000000000000200000000000000000008000000000000000000800000000400004000000000000000000000000000000000000000000000000000000008000000002000000000000000000000000000000000000000000000000000002c0000004000000000000000800001000000000000000000000000000000100000000020000001000000000000000000000000000002000000000000000000000000100000", + "blockHash": "0x1e40c21ca89ab7d2a7b7d6d21369c424a9991db72c2ade0ed2791568b65bb683", + "transactionHash": "0x131a2505558806a1221cf4d15683766fb0e3a9681d15f4d309bd30764e81c66b", + "logs": [ + { + "transactionIndex": 51, + "blockNumber": 40600414, + "transactionHash": "0x131a2505558806a1221cf4d15683766fb0e3a9681d15f4d309bd30764e81c66b", + "address": "0xA15a90E7936A2F8B70E181E955760860D133e56B", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009a8f92a830a5cb89a3816e3d267cb7791c16b04d" + ], + "data": "0x", + "logIndex": 221, + "blockHash": "0x1e40c21ca89ab7d2a7b7d6d21369c424a9991db72c2ade0ed2791568b65bb683" + }, + { + "transactionIndex": 51, + "blockNumber": 40600414, + "transactionHash": "0x131a2505558806a1221cf4d15683766fb0e3a9681d15f4d309bd30764e81c66b", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x0000000000000000000000009a8f92a830a5cb89a3816e3d267cb7791c16b04d", + "0x000000000000000000000000ef46d5fe753c988606e6f703260d816af53b03eb" + ], + "data": "0x000000000000000000000000000000000000000000000000009f60b7e625bd1f00000000000000000000000000000000000000000000000035c7083261d5d4cc00000000000000000000000000000000000000000000078fd0978d8e2f2eab7c0000000000000000000000000000000000000000000000003527a77a7bb017ad00000000000000000000000000000000000000000000078fd136ee461554689b", + "logIndex": 222, + "blockHash": "0x1e40c21ca89ab7d2a7b7d6d21369c424a9991db72c2ade0ed2791568b65bb683" + } + ], + "blockNumber": 40600414, + "cumulativeGasUsed": "10092215", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "ea9229ed188f1300c4a413d030dbf1b6", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Airdrop\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"_tokenURIs\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"recipients\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"airdrop\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"tokenURI\",\"type\":\"string\"}],\"name\":\"setTokenURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"}},\"kind\":\"dev\",\"methods\":{\"airdrop(uint256,address[],uint256)\":{\"details\":\"Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\",\"params\":{\"amount\":\"Amount of token types to airdrop.\",\"recipients\":\"List of airdrop recipients.\",\"tokenId\":\"Token type to airdrop.\"}},\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"See {IERC1155-safeBatchTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"See {IERC1155-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"setTokenURI(uint256,string)\":{\"params\":{\"tokenId\":\"Token type to set `tokenURI` for.\",\"tokenURI\":\"URI of token metadata.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"uri(uint256)\":{\"details\":\"Instead of returning the same URI for *all* token types, we return the uri set by `setTokenURI` to allow IPFS URIs for all token types.\",\"params\":{\"tokenId\":\"Token type to retrieve metadata URI for.\"}}},\"title\":\"MintableERC1155\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"airdrop(uint256,address[],uint256)\":{\"notice\":\"Creates `amount` new tokens for `recipients` of token type `tokenId`.\"},\"setTokenURI(uint256,string)\":{\"notice\":\"Sets the URI for token of type `tokenId` to `tokenURI`.\"},\"uri(uint256)\":{\"notice\":\"Returns metadata URI of token type `tokenId`.\"}},\"notice\":\"Ownable contract enabling owner to airdrop many recipients the same token ID at once\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/erc1155/MintableERC1155.sol\":\"MintableERC1155\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n using Address for address;\\n\\n // Mapping from token ID to account balances\\n mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n // Mapping from account to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n string private _uri;\\n\\n /**\\n * @dev See {_setURI}.\\n */\\n constructor(string memory uri_) {\\n _setURI(uri_);\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC1155MetadataURI-uri}.\\n *\\n * This implementation returns the same URI for *all* token types. It relies\\n * on the token type ID substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n * actual token type ID.\\n */\\n function uri(uint256) public view virtual override returns (string memory) {\\n return _uri;\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n require(account != address(0), \\\"ERC1155: address zero is not a valid owner\\\");\\n return _balances[id][account];\\n }\\n\\n /**\\n * @dev See {IERC1155-balanceOfBatch}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n override\\n returns (uint256[] memory)\\n {\\n require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n }\\n\\n return batchBalances;\\n }\\n\\n /**\\n * @dev See {IERC1155-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC1155-isApprovedForAll}.\\n */\\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n /**\\n * @dev See {IERC1155-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not token owner nor approved\\\"\\n );\\n _safeTransferFrom(from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev See {IERC1155-safeBatchTransferFrom}.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) public virtual override {\\n require(\\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n \\\"ERC1155: caller is not token owner nor approved\\\"\\n );\\n _safeBatchTransferFrom(from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n\\n emit TransferSingle(operator, from, to, id, amount);\\n\\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n _balances[id][to] += amount;\\n }\\n\\n emit TransferBatch(operator, from, to, ids, amounts);\\n\\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Sets a new URI for all token types, by relying on the token type ID\\n * substitution mechanism\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n *\\n * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n * URI or any of the amounts in the JSON file at said URI will be replaced by\\n * clients with the token type ID.\\n *\\n * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n * interpreted by clients as\\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n * for token type ID 0x4cce0.\\n *\\n * See {uri}.\\n *\\n * Because these URIs cannot be meaningfully represented by the {URI} event,\\n * this function emits no events.\\n */\\n function _setURI(string memory newuri) internal virtual {\\n _uri = newuri;\\n }\\n\\n /**\\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function _mint(\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _balances[id][to] += amount;\\n emit TransferSingle(operator, address(0), to, id, amount);\\n\\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function _mintBatch(\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {\\n require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n _balances[ids[i]][to] += amounts[i];\\n }\\n\\n emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens of token type `id` from `from`\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `from` must have at least `amount` tokens of token type `id`.\\n */\\n function _burn(\\n address from,\\n uint256 id,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n address operator = _msgSender();\\n uint256[] memory ids = _asSingletonArray(id);\\n uint256[] memory amounts = _asSingletonArray(amount);\\n\\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n\\n emit TransferSingle(operator, from, address(0), id, amount);\\n\\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n }\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n */\\n function _burnBatch(\\n address from,\\n uint256[] memory ids,\\n uint256[] memory amounts\\n ) internal virtual {\\n require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n address operator = _msgSender();\\n\\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n for (uint256 i = 0; i < ids.length; i++) {\\n uint256 id = ids[i];\\n uint256 amount = amounts[i];\\n\\n uint256 fromBalance = _balances[id][from];\\n require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[id][from] = fromBalance - amount;\\n }\\n }\\n\\n emit TransferBatch(operator, from, address(0), ids, amounts);\\n\\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC1155: setting approval status for self\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting\\n * and burning, as well as batched variants.\\n *\\n * The same hook is called on both single and batched variants. For single\\n * transfers, the length of the `id` and `amount` arrays will be 1.\\n *\\n * Calling conditions (for each `id` and `amount` pair):\\n *\\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * of token type `id` will be transferred to `to`.\\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n * for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n * will be burned.\\n * - `from` and `to` are never both zero.\\n * - `ids` and `amounts` have the same, non-zero length.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) internal virtual {}\\n\\n function _doSafeTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _doSafeBatchTransferAcceptanceCheck(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory amounts,\\n bytes memory data\\n ) private {\\n if (to.isContract()) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n }\\n } catch Error(string memory reason) {\\n revert(reason);\\n } catch {\\n revert(\\\"ERC1155: transfer to non ERC1155Receiver implementer\\\");\\n }\\n }\\n }\\n\\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n uint256[] memory array = new uint256[](1);\\n array[0] = element;\\n\\n return array;\\n }\\n}\\n\",\"keccak256\":\"0x447a21c87433c0f11252912313a96f3454629ef88cca7a4eefbb283b3ec409f9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\\n external\\n view\\n returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 amount,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x6392f2cfe3a5ee802227fe7a2dfd47096d881aec89bddd214b35c5b46d3cd941\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa66d18b9a85458d28fc3304717964502ae36f7f8a2ff35bc83f6f85d74b03574\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/erc1155/MintableERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\n\\n/**\\n * @title MintableERC1155\\n * @notice Ownable contract enabling owner to airdrop many recipients the same token ID at once\\n */\\ncontract MintableERC1155 is ERC1155, Ownable {\\n // Maps `tokenId` to metadata URI `tokenURI`\\n mapping(uint256 => string) public _tokenURIs;\\n\\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\\n\\n // We are passing an empty string as the `baseURI` because we use `_tokenURIs` instead\\n // to allow for IPFS URIs.\\n // solhint-disable-next-line\\n constructor() ERC1155(\\\"\\\") {}\\n\\n /**\\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\\n * @param recipients List of airdrop recipients.\\n * @param tokenId Token type to airdrop.\\n * @param amount Amount of token types to airdrop.\\n */\\n function airdrop(\\n uint256 tokenId,\\n address[] memory recipients,\\n uint256 amount\\n ) public onlyOwner {\\n for (uint256 i = 0; i < recipients.length; i++) {\\n _mint(recipients[i], tokenId, amount, \\\"\\\");\\n }\\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\\n }\\n\\n /**\\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\\n * @param tokenId Token type to set `tokenURI` for.\\n * @param tokenURI URI of token metadata.\\n */\\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\\n require(bytes(_tokenURIs[tokenId]).length == 0, \\\"uri already set\\\");\\n\\n _tokenURIs[tokenId] = tokenURI;\\n emit URI(tokenURI, tokenId);\\n }\\n\\n /**\\n * @notice Returns metadata URI of token type `tokenId`.\\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\\n * `setTokenURI` to allow IPFS URIs for all token types.\\n * @param tokenId Token type to retrieve metadata URI for.\\n */\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return _tokenURIs[tokenId];\\n }\\n}\\n\",\"keccak256\":\"0x3278a4a107e88bf5a9c63672ea4fb33f5e7fa86e2c089f73bafa681eb6bc3641\",\"license\":\"AGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080346200012657602081016001600160401b03811182821017620001105760405260008091526002546001908181811c9116801562000105575b6020821014620000f157601f8111620000a7575b600283905560038054336001600160a01b03198216811790925560405191906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a3611fc990816200012c8239f35b60028352601f0160051c7f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace908101905b818110620000e657506200004e565b8381558201620000d7565b634e487b7160e01b83526022600452602483fd5b90607f16906200003a565b634e487b7160e01b600052604160045260246000fd5b600080fdfe6040608081526004908136101561001557600080fd5b600091823560e01c8062fdd58e146116c957806301ffc9a7146115da5780630bb78ec1146115815780630e89341c14611581578063162094c4146112b25780632eb2c2d614610ef65780634e1273f414610d44578063715018a614610ca3578063754e5e37146107e15780638da5cb5b1461078e578063a22cb4651461063a578063e985e9c5146105bd578063f242432a146101f55763f2fde38b146100ba57600080fd5b346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f1576100f1611717565b906100fa611af0565b73ffffffffffffffffffffffffffffffffffffffff80921692831561016e575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b5090346101f15760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15761022e611717565b8361023761173f565b916044359060643560843567ffffffffffffffff81116105b95761025e9036908901611a23565b9273ffffffffffffffffffffffffffffffffffffffff80931692338414801561059a575b61028b90611ccc565b861690610299821515611d57565b6102a281611f5d565b506102ac83611f5d565b50808652602096868852888720858852885283898820546102cf82821015611de2565b838952888a528a8920878a528a52038988205581875286885288872083885288528887206102fe858254611e6d565b905582858a51848152868b8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628c3392a43b61033a578580f35b889587946103948a51978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906118ea565b03925af186918161056b575b506104af5750506001906103b2611eb2565b6308c379a014610462575b506103d25750505b3880808381808080808580f35b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b61046a611ed0565b8061047557506103bd565b61045e859185519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff00000000000000000000000000000000000000000000000000000000160390506104df5750506103c5565b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b61058c919250843d8611610593575b61058481836117b5565b810190611e7a565b90386103a0565b503d61057a565b508386526001602090815288872033885290528786205460ff16610282565b8480fd5b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760ff816020936105fb611717565b61060361173f565b73ffffffffffffffffffffffffffffffffffffffff91821683526001875283832091168252855220549151911615158152f35b5080fd5b5090346101f157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f157610672611717565b90602435918215158093036105b95773ffffffffffffffffffffffffffffffffffffffff169283331461070c575033845260016020528084208385526020528084207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8416179055519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b50503461063657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5090346101f15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781359260249067ffffffffffffffff908235828111610636576108389036908701611a41565b9560448035610845611af0565b835b8951811015610c175773ffffffffffffffffffffffffffffffffffffffff61086f828c611c89565b51168851906020918281018181108a821117610bec578b528781528115610b6a57858c92898c8a948f6108a187611f5d565b506108ab8b611f5d565b5086845283895280842085855289528084206108c88c8254611e6d565b9055848482518981528d8c8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62843392a4843b610919575b50505050505050505061091490611c2d565b610847565b916109748493928a9796959351988997889687957ff23a6e61000000000000000000000000000000000000000000000000000000009d8e885233908801528601528401528c606484015260a0608484015260a48301906118ea565b03925af1889181610b4b575b50610a8d575050600190610992611eb2565b6308c379a014610a41575b506109b557610914905b9089858538898c828f610902565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b610a49611ed0565b80610a54575061099d565b61045e8c918b8d519485947f08c379a00000000000000000000000000000000000000000000000000000000086528501528301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016039050610abf57610914906109a7565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b610b63919250843d86116105935761058481836117b5565b9038610980565b5050897f455243313135353a206d696e7420746f20746865207a65726f206164647265738560218b6084958e51957f08c379a00000000000000000000000000000000000000000000000000000000087528601528401528201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b8a8960418f7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b89858984878251926080808501913386526020938487015285015285518091528160a08501960191855b828110610c7957867f13d0a346ea6c350592dd539c68d5ff6d61d6b8834695625d09834638717193e087808b8960608301520390a180f35b835173ffffffffffffffffffffffffffffffffffffffff1688529681019692810192600101610c41565b8334610d4157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d4157610cda611af0565b8073ffffffffffffffffffffffffffffffffffffffff6003547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b509134610d4157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d415767ffffffffffffffff83358181116101f157610d939036908601611a41565b906024359081116101f157610dab90369086016119c5565b938151855103610e7357508051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610dfb610de6856119ad565b94610df3875196876117b5565b8086526119ad565b013660208501375b8151811015610e5a5780610e4573ffffffffffffffffffffffffffffffffffffffff610e32610e559486611c89565b5116610e3e8389611c89565b5190611b6f565b610e4f8286611c89565b52611c2d565b610e03565b835160208082528190610e6f90820186611abc565b0390f35b60849060208551917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b50346101f1577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9160a0833601126112ae57610f30611717565b92610f3961173f565b9367ffffffffffffffff936044358581116112aa57610f5b90369083016119c5565b906064358681116112a657610f7390369083016119c5565b956084359081116112a657610f8b9036908301611a23565b9373ffffffffffffffffffffffffffffffffffffffff809416933385148015611287575b610fb890611ccc565b835188510361120457881694610fcf861515611d57565b895b8a85518210156110555790896110498a61105094610ffa85610ff3818d611c89565b5195611c89565b51938082526020908282528383208d84528252858d858520549061102083831015611de2565b838652858552868620908652845203848420558252818152828220908d83525220918254611e6d565b9055611c2d565b610fd1565b50509094939596929197848789518a81527f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6110938c830188611abc565b918083036020820152806110a833948b611abc565b0390a43b6110b4578880f35b865194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338c87015260248601526044850160a0905260a485016110ff91611abc565b8285820301606486015261111291611abc565b90838203016084840152611125916118ea565b0381885a94602095f18591816111e4575b506111b65750506001611147611eb2565b6308c379a014611165575b6103d25750505b38808080808080808880f35b61116d611ed0565b806111785750611152565b905061045e9160209450519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016036104df575050611159565b6111fd91925060203d81116105935761058481836117b5565b9038611136565b60848360208951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b50848a5260016020908152878b20338c529052868a205460ff16610faf565b8880fd5b8780fd5b8380fd5b50346101f157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15780359167ffffffffffffffff9060243582811161157d573660238201121561157d576113169036906024818701359101611948565b9261131f611af0565b84865260209281845261133483882054611762565b611521578587528184528287209185519182116114f557506113568254611762565b601f81116114b2575b5083601f82116001146113ef5791817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b969594926113de948a916113e4575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b519282849384528301906118ea565b0390a280f35b90508601513861139e565b828852848820907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316895b81811061149b5750926113de9492600192827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9a99989610611464575b5050811b0190556113cf565b8801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880611458565b91928760018192868c01518155019401920161141b565b828852848820601f830160051c8101918684106114eb575b601f0160051c01905b8181106114e0575061135f565b8881556001016114d3565b90915081906114ca565b8760416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b508260649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f75726920616c72656164792073657400000000000000000000000000000000006044820152fd5b8580fd5b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781610e6f93826115c79335825260205220611825565b90519182916020835260208301906118ea565b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15735907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101f157602092507fd9b67a2600000000000000000000000000000000000000000000000000000000821491821561169f575b8215611675575b50519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000001491503861166c565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149250611665565b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261063657602090611710611707611717565b60243590611b6f565b9051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b90600182811c921680156117ab575b602083101461177c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611771565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117f657604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b906040519182600082549261183984611762565b9081845260019485811690816000146118a85750600114611865575b5050611863925003836117b5565b565b9093915060005260209081600020936000915b81831061189057505061186393508201013880611855565b85548884018501529485019487945091830191611878565b90506118639550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611855565b919082519283825260005b8481106119345750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016118f5565b92919267ffffffffffffffff82116117f6576040519161199060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846117b5565b82948184528183011161173a578281602093846000960137010152565b67ffffffffffffffff81116117f65760051b60200190565b81601f8201121561173a578035916119dc836119ad565b926119ea60405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a14575050505090565b81358152908301908301611a06565b9080601f8301121561173a57816020611a3e93359101611948565b90565b81601f8201121561173a57803591611a58836119ad565b92611a6660405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a90575050505090565b813573ffffffffffffffffffffffffffffffffffffffff8116810361173a578152908301908301611a82565b90815180825260208080930193019160005b828110611adc575050505090565b835185529381019392810192600101611ace565b73ffffffffffffffffffffffffffffffffffffffff600354163303611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b73ffffffffffffffffffffffffffffffffffffffff16908115611ba957600052600060205260406000209060005260205260406000205490565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c5a5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8051821015611c9d5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b15611cd357565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206e6f7220617070726f76656400000000000000000000000000000000006064820152fd5b15611d5e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15611de957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b91908201809211611c5a57565b9081602091031261173a57517fffffffff000000000000000000000000000000000000000000000000000000008116810361173a5790565b60009060033d11611ebf57565b905060046000803e60005160e01c90565b600060443d10611a3e576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117611f4c57818401948551938411611f54573d85010160208487010111611f4c5750611a3e929101602001906117b5565b949350505050565b50949350505050565b604051906040820182811067ffffffffffffffff8211176117f65760405260018252602082016020368237825115611c9d57529056fea2646970667358221220c3377770cdb03b603ff928387edb7dc3ad004b20210900a98759b0565733980764736f6c63430008120033", + "deployedBytecode": "0x6040608081526004908136101561001557600080fd5b600091823560e01c8062fdd58e146116c957806301ffc9a7146115da5780630bb78ec1146115815780630e89341c14611581578063162094c4146112b25780632eb2c2d614610ef65780634e1273f414610d44578063715018a614610ca3578063754e5e37146107e15780638da5cb5b1461078e578063a22cb4651461063a578063e985e9c5146105bd578063f242432a146101f55763f2fde38b146100ba57600080fd5b346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f1576100f1611717565b906100fa611af0565b73ffffffffffffffffffffffffffffffffffffffff80921692831561016e575050600354827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b5090346101f15760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15761022e611717565b8361023761173f565b916044359060643560843567ffffffffffffffff81116105b95761025e9036908901611a23565b9273ffffffffffffffffffffffffffffffffffffffff80931692338414801561059a575b61028b90611ccc565b861690610299821515611d57565b6102a281611f5d565b506102ac83611f5d565b50808652602096868852888720858852885283898820546102cf82821015611de2565b838952888a528a8920878a528a52038988205581875286885288872083885288528887206102fe858254611e6d565b905582858a51848152868b8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628c3392a43b61033a578580f35b889587946103948a51978896879586947ff23a6e61000000000000000000000000000000000000000000000000000000009c8d8752339087015260248601526044850152606484015260a0608484015260a48301906118ea565b03925af186918161056b575b506104af5750506001906103b2611eb2565b6308c379a014610462575b506103d25750505b3880808381808080808580f35b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b0390fd5b61046a611ed0565b8061047557506103bd565b61045e859185519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff00000000000000000000000000000000000000000000000000000000160390506104df5750506103c5565b61045e9250519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b61058c919250843d8611610593575b61058481836117b5565b810190611e7a565b90386103a0565b503d61057a565b508386526001602090815288872033885290528786205460ff16610282565b8480fd5b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760ff816020936105fb611717565b61060361173f565b73ffffffffffffffffffffffffffffffffffffffff91821683526001875283832091168252855220549151911615158152f35b5080fd5b5090346101f157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f157610672611717565b90602435918215158093036105b95773ffffffffffffffffffffffffffffffffffffffff169283331461070c575033845260016020528084208385526020528084207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8416179055519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a380f35b602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152fd5b50503461063657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126106365760209073ffffffffffffffffffffffffffffffffffffffff600354169051908152f35b5090346101f15760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781359260249067ffffffffffffffff908235828111610636576108389036908701611a41565b9560448035610845611af0565b835b8951811015610c175773ffffffffffffffffffffffffffffffffffffffff61086f828c611c89565b51168851906020918281018181108a821117610bec578b528781528115610b6a57858c92898c8a948f6108a187611f5d565b506108ab8b611f5d565b5086845283895280842085855289528084206108c88c8254611e6d565b9055848482518981528d8c8201527fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62843392a4843b610919575b50505050505050505061091490611c2d565b610847565b916109748493928a9796959351988997889687957ff23a6e61000000000000000000000000000000000000000000000000000000009d8e885233908801528601528401528c606484015260a0608484015260a48301906118ea565b03925af1889181610b4b575b50610a8d575050600190610992611eb2565b6308c379a014610a41575b506109b557610914905b9089858538898c828f610902565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152603460208201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e74657200000000000000000000000060608201520190565b610a49611ed0565b80610a54575061099d565b61045e8c918b8d519485947f08c379a00000000000000000000000000000000000000000000000000000000086528501528301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016039050610abf57610914906109a7565b61045e8989519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160809060208152602860208201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e7300000000000000000000000000000000000000000000000060608201520190565b610b63919250843d86116105935761058481836117b5565b9038610980565b5050897f455243313135353a206d696e7420746f20746865207a65726f206164647265738560218b6084958e51957f08c379a00000000000000000000000000000000000000000000000000000000087528601528401528201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b8a8960418f7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b89858984878251926080808501913386526020938487015285015285518091528160a08501960191855b828110610c7957867f13d0a346ea6c350592dd539c68d5ff6d61d6b8834695625d09834638717193e087808b8960608301520390a180f35b835173ffffffffffffffffffffffffffffffffffffffff1688529681019692810192600101610c41565b8334610d4157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d4157610cda611af0565b8073ffffffffffffffffffffffffffffffffffffffff6003547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b509134610d4157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610d415767ffffffffffffffff83358181116101f157610d939036908601611a41565b906024359081116101f157610dab90369086016119c5565b938151855103610e7357508051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610dfb610de6856119ad565b94610df3875196876117b5565b8086526119ad565b013660208501375b8151811015610e5a5780610e4573ffffffffffffffffffffffffffffffffffffffff610e32610e559486611c89565b5116610e3e8389611c89565b5190611b6f565b610e4f8286611c89565b52611c2d565b610e03565b835160208082528190610e6f90820186611abc565b0390f35b60849060208551917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860448201527f206d69736d6174636800000000000000000000000000000000000000000000006064820152fd5b50346101f1577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9160a0833601126112ae57610f30611717565b92610f3961173f565b9367ffffffffffffffff936044358581116112aa57610f5b90369083016119c5565b906064358681116112a657610f7390369083016119c5565b956084359081116112a657610f8b9036908301611a23565b9373ffffffffffffffffffffffffffffffffffffffff809416933385148015611287575b610fb890611ccc565b835188510361120457881694610fcf861515611d57565b895b8a85518210156110555790896110498a61105094610ffa85610ff3818d611c89565b5195611c89565b51938082526020908282528383208d84528252858d858520549061102083831015611de2565b838652858552868620908652845203848420558252818152828220908d83525220918254611e6d565b9055611c2d565b610fd1565b50509094939596929197848789518a81527f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb6110938c830188611abc565b918083036020820152806110a833948b611abc565b0390a43b6110b4578880f35b865194859384937fbc197c810000000000000000000000000000000000000000000000000000000098898652338c87015260248601526044850160a0905260a485016110ff91611abc565b8285820301606486015261111291611abc565b90838203016084840152611125916118ea565b0381885a94602095f18591816111e4575b506111b65750506001611147611eb2565b6308c379a014611165575b6103d25750505b38808080808080808880f35b61116d611ed0565b806111785750611152565b905061045e9160209450519384937f08c379a000000000000000000000000000000000000000000000000000000000855284015260248301906118ea565b7fffffffff0000000000000000000000000000000000000000000000000000000016036104df575050611159565b6111fd91925060203d81116105935761058481836117b5565b9038611136565b60848360208951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060448201527f6d69736d617463680000000000000000000000000000000000000000000000006064820152fd5b50848a5260016020908152878b20338c529052868a205460ff16610faf565b8880fd5b8780fd5b8380fd5b50346101f157817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15780359167ffffffffffffffff9060243582811161157d573660238201121561157d576113169036906024818701359101611948565b9261131f611af0565b84865260209281845261133483882054611762565b611521578587528184528287209185519182116114f557506113568254611762565b601f81116114b2575b5083601f82116001146113ef5791817f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b969594926113de948a916113e4575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b519282849384528301906118ea565b0390a280f35b90508601513861139e565b828852848820907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316895b81811061149b5750926113de9492600192827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b9a99989610611464575b5050811b0190556113cf565b8801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880611458565b91928760018192868c01518155019401920161141b565b828852848820601f830160051c8101918684106114eb575b601f0160051c01905b8181106114e0575061135f565b8881556001016114d3565b90915081906114ca565b8760416024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b508260649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600f60248201527f75726920616c72656164792073657400000000000000000000000000000000006044820152fd5b8580fd5b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15781610e6f93826115c79335825260205220611825565b90519182916020835260208301906118ea565b50346101f15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101f15735907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101f157602092507fd9b67a2600000000000000000000000000000000000000000000000000000000821491821561169f575b8215611675575b50519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000001491503861166c565b7f0e89341c0000000000000000000000000000000000000000000000000000000081149250611665565b50503461063657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261063657602090611710611707611717565b60243590611b6f565b9051908152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361173a57565b90600182811c921680156117ab575b602083101461177c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611771565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176117f657604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b906040519182600082549261183984611762565b9081845260019485811690816000146118a85750600114611865575b5050611863925003836117b5565b565b9093915060005260209081600020936000915b81831061189057505061186393508201013880611855565b85548884018501529485019487945091830191611878565b90506118639550602093507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201013880611855565b919082519283825260005b8481106119345750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016118f5565b92919267ffffffffffffffff82116117f6576040519161199060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601846117b5565b82948184528183011161173a578281602093846000960137010152565b67ffffffffffffffff81116117f65760051b60200190565b81601f8201121561173a578035916119dc836119ad565b926119ea60405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a14575050505090565b81358152908301908301611a06565b9080601f8301121561173a57816020611a3e93359101611948565b90565b81601f8201121561173a57803591611a58836119ad565b92611a6660405194856117b5565b808452602092838086019260051b82010192831161173a578301905b828210611a90575050505090565b813573ffffffffffffffffffffffffffffffffffffffff8116810361173a578152908301908301611a82565b90815180825260208080930193019160005b828110611adc575050505090565b835185529381019392810192600101611ace565b73ffffffffffffffffffffffffffffffffffffffff600354163303611b1157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b73ffffffffffffffffffffffffffffffffffffffff16908115611ba957600052600060205260406000209060005260205260406000205490565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201527f616c6964206f776e6572000000000000000000000000000000000000000000006064820152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611c5a5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8051821015611c9d5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b15611cd357565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201527f6572206e6f7220617070726f76656400000000000000000000000000000000006064820152fd5b15611d5e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b15611de957565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60448201527f72207472616e73666572000000000000000000000000000000000000000000006064820152fd5b91908201809211611c5a57565b9081602091031261173a57517fffffffff000000000000000000000000000000000000000000000000000000008116810361173a5790565b60009060033d11611ebf57565b905060046000803e60005160e01c90565b600060443d10611a3e576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117611f4c57818401948551938411611f54573d85010160208487010111611f4c5750611a3e929101602001906117b5565b949350505050565b50949350505050565b604051906040820182811067ffffffffffffffff8211176117f65760405260018252602082016020368237825115611c9d57529056fea2646970667358221220c3377770cdb03b603ff928387edb7dc3ad004b20210900a98759b0565733980764736f6c63430008120033", + "devdoc": { + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + } + }, + "kind": "dev", + "methods": { + "airdrop(uint256,address[],uint256)": { + "details": "Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.", + "params": { + "amount": "Amount of token types to airdrop.", + "recipients": "List of airdrop recipients.", + "tokenId": "Token type to airdrop." + } + }, + "balanceOf(address,uint256)": { + "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address." + }, + "balanceOfBatch(address[],uint256[])": { + "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length." + }, + "isApprovedForAll(address,address)": { + "details": "See {IERC1155-isApprovedForAll}." + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "See {IERC1155-safeBatchTransferFrom}." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "See {IERC1155-safeTransferFrom}." + }, + "setApprovalForAll(address,bool)": { + "details": "See {IERC1155-setApprovalForAll}." + }, + "setTokenURI(uint256,string)": { + "params": { + "tokenId": "Token type to set `tokenURI` for.", + "tokenURI": "URI of token metadata." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "uri(uint256)": { + "details": "Instead of returning the same URI for *all* token types, we return the uri set by `setTokenURI` to allow IPFS URIs for all token types.", + "params": { + "tokenId": "Token type to retrieve metadata URI for." + } + } + }, + "title": "MintableERC1155", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "airdrop(uint256,address[],uint256)": { + "notice": "Creates `amount` new tokens for `recipients` of token type `tokenId`." + }, + "setTokenURI(uint256,string)": { + "notice": "Sets the URI for token of type `tokenId` to `tokenURI`." + }, + "uri(uint256)": { + "notice": "Returns metadata URI of token type `tokenId`." + } + }, + "notice": "Ownable contract enabling owner to airdrop many recipients the same token ID at once", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 138, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 144, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 146, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_uri", + "offset": 0, + "slot": "2", + "type": "t_string_storage" + }, + { + "astId": 7, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_owner", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 1879, + "contract": "contracts/erc1155/MintableERC1155.sol:MintableERC1155", + "label": "_tokenURIs", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_string_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_string_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/polygon/solcInputs/ea9229ed188f1300c4a413d030dbf1b6.json b/deployments/polygon/solcInputs/ea9229ed188f1300c4a413d030dbf1b6.json new file mode 100644 index 000000000..8a801880f --- /dev/null +++ b/deployments/polygon/solcInputs/ea9229ed188f1300c4a413d030dbf1b6.json @@ -0,0 +1,61 @@ +{ + "language": "Solidity", + "sources": { + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\n/**\n * @title MintableERC1155\n * @notice Ownable contract enabling owner to airdrop many recipients the same token ID at once\n */\ncontract MintableERC1155 is ERC1155, Ownable {\n // Maps `tokenId` to metadata URI `tokenURI`\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\n\n // We are passing an empty string as the `baseURI` because we use `_tokenURIs` instead\n // to allow for IPFS URIs.\n // solhint-disable-next-line\n constructor() ERC1155(\"\") {}\n\n /**\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\n * @param recipients List of airdrop recipients.\n * @param tokenId Token type to airdrop.\n * @param amount Amount of token types to airdrop.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256 amount\n ) public onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n _mint(recipients[i], tokenId, amount, \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\n }\n\n /**\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\n * @param tokenId Token type to set `tokenURI` for.\n * @param tokenURI URI of token metadata.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\n require(bytes(_tokenURIs[tokenId]).length == 0, \"uri already set\");\n\n _tokenURIs[tokenId] = tokenURI;\n emit URI(tokenURI, tokenId);\n }\n\n /**\n * @notice Returns metadata URI of token type `tokenId`.\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for all token types.\n * @param tokenId Token type to retrieve metadata URI for.\n */\n function uri(uint256 tokenId) public view override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n public\n view\n virtual\n override\n returns (uint256[] memory)\n {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner nor approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(\n address from,\n uint256 id,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(\n address from,\n uint256[] memory ids,\n uint256[] memory amounts\n ) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts index c80f80d98..598e69dae 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,7 +3,7 @@ import * as dotenv from "dotenv"; import { HardhatUserConfig } from "hardhat/config"; import { getNodeUrl, getMnemonic } from "@uma/common"; -import "@nomiclabs/hardhat-etherscan"; +import "@nomiclabs/hardhat-etherscan"; // Must be above hardhat-upgrades import "@nomiclabs/hardhat-waffle"; import "@typechain/hardhat"; import "@matterlabs/hardhat-zksync-toolbox"; @@ -14,6 +14,7 @@ import "hardhat-deploy"; import "@openzeppelin/hardhat-upgrades"; // Custom tasks to add to HRE. +// eslint-disable-next-line node/no-missing-require require("./tasks/enableL1TokenAcrossEcosystem"); dotenv.config(); @@ -47,6 +48,7 @@ const config: HardhatUserConfig = { "contracts/Boba_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS, "contracts/Optimism_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS, "contracts/test/MockSpokePoolV2.sol": LARGE_CONTRACT_COMPILER_SETTINGS, + "contracts/test/MockOptimism_SpokePool.sol": LARGE_CONTRACT_COMPILER_SETTINGS, }, }, zksolc: { @@ -148,19 +150,23 @@ const config: HardhatUserConfig = { gasReporter: { enabled: process.env.REPORT_GAS !== undefined, currency: "USD" }, etherscan: { apiKey: { - mainnet: process.env.ETHERSCAN_API_KEY, - kovan: process.env.ETHERSCAN_API_KEY, - rinkeby: process.env.ETHERSCAN_API_KEY, - goerli: process.env.ETHERSCAN_API_KEY, - optimisticEthereum: process.env.OPTIMISM_ETHERSCAN_API_KEY, - optimisticKovan: process.env.OPTIMISM_ETHERSCAN_API_KEY, - arbitrumOne: process.env.ARBITRUM_ETHERSCAN_API_KEY, - arbitrumTestnet: process.env.ARBITRUM_ETHERSCAN_API_KEY, - polygon: process.env.POLYGON_ETHERSCAN_API_KEY, - polygonMumbai: process.env.POLYGON_ETHERSCAN_API_KEY, + mainnet: process.env.ETHERSCAN_API_KEY!, + kovan: process.env.ETHERSCAN_API_KEY!, + rinkeby: process.env.ETHERSCAN_API_KEY!, + goerli: process.env.ETHERSCAN_API_KEY!, + optimisticEthereum: process.env.OPTIMISM_ETHERSCAN_API_KEY!, + optimisticGoerli: process.env.OPTIMISM_ETHERSCAN_API_KEY!, + arbitrumOne: process.env.ARBITRUM_ETHERSCAN_API_KEY!, + arbitrumGoerli: process.env.ARBITRUM_ETHERSCAN_API_KEY!, + polygon: process.env.POLYGON_ETHERSCAN_API_KEY!, + polygonMumbai: process.env.POLYGON_ETHERSCAN_API_KEY!, }, }, namedAccounts: { deployer: 0 }, + typechain: { + outDir: "./typechain", + target: "ethers-v5", + }, }; export default config; diff --git a/index.ts b/index.ts index f32ced648..018dc8eb0 100644 --- a/index.ts +++ b/index.ts @@ -1,3 +1,3 @@ export * from "./typechain"; export * from "./src/DeploymentUtils"; -export * from "./utils/MerkleTree"; +export * from "./utils"; diff --git a/package.json b/package.json index d107ab06f..c2d3f86cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@across-protocol/contracts-v2", - "version": "2.0.2", + "version": "2.3.3", "author": "UMA Team", "license": "AGPL-3.0-only", "repository": { @@ -8,7 +8,7 @@ "url": "git+https://github.com/across-protocol/across-smart-contracts-v2.git" }, "engines": { - "node": ">=8.3.0" + "node": ">=16.18.0" }, "files": [ "/contracts/**/*.sol", @@ -33,34 +33,34 @@ }, "dependencies": { "@defi-wonderland/smock": "^2.3.4", - "@eth-optimism/contracts": "^0.5.11", - "@openzeppelin/contracts": "^4.7.3", - "@openzeppelin/contracts-upgradeable": "^4.8.0", + "@eth-optimism/contracts": "^0.5.40", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@openzeppelin/contracts": "4.9.2", + "@openzeppelin/contracts-upgradeable": "4.8.3", "@uma/common": "^2.29.0", "@uma/contracts-node": "^0.3.18", - "@uma/core": "^2.41.0", - "arb-bridge-eth": "^0.7.4", - "arb-bridge-peripherals": "^1.0.5" + "@uma/core": "^2.41.0" }, "devDependencies": { - "@matterlabs/hardhat-zksync-chai-matchers": "^0.1.1", - "@matterlabs/hardhat-zksync-deploy": "^0.6.2", - "@matterlabs/hardhat-zksync-solc": "^0.3.14", - "@matterlabs/hardhat-zksync-toolbox": "^0.1.1", - "@matterlabs/hardhat-zksync-verify": "^0.1.3", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", - "@nomiclabs/hardhat-ethers": "^2.0.5", - "@nomiclabs/hardhat-etherscan": "^3.0.3", - "@nomiclabs/hardhat-waffle": "^2.0.3", + "@matterlabs/hardhat-zksync-solc": "^0.3.6", + "@matterlabs/zksync-contracts": "^0.2.4", + "@nomiclabs/hardhat-ethers": "^2.2.3", + "@nomiclabs/hardhat-etherscan": "^3.1.7", + "@nomiclabs/hardhat-waffle": "2.0.3", "@openzeppelin/hardhat-upgrades": "^1.22.0", - "@typechain/ethers-v5": "^7.0.1", - "@typechain/hardhat": "^2.3.0", - "@types/chai": "^4.2.21", + "@pinata/sdk": "^2.1.0", + "@typechain/ethers-v5": "^11.0.0", + "@typechain/hardhat": "^8.0.0", + "@types/chai": "^4.3.5", "@types/mocha": "^9.0.0", "@types/node": "^12.0.0", "@typescript-eslint/eslint-plugin": "^4.29.1", "@typescript-eslint/parser": "^4.29.1", - "chai": "^4.2.0", + "arb-bridge-eth": "^0.7.4", + "arb-bridge-peripherals": "^1.0.5", + "chai": "^4.3.7", "dotenv": "^10.0.0", "eslint": "^7.29.0", "eslint-config-prettier": "^8.3.0", @@ -69,22 +69,22 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-promise": "^5.1.0", - "ethereum-waffle": "^3.4.0", + "ethereum-waffle": "3.4.0", "ethereumjs-util": "^7.1.4", - "ethers": "^5.5.4", - "hardhat": "^2.12.1-ir.0", + "ethers": "5.7.2", + "hardhat": "^2.14.0", "hardhat-deploy": "^0.11.12", "hardhat-gas-reporter": "^1.0.8", "husky": "^4.2.3", + "multiformats": "9.9.0", "prettier": "^2.3.2", "prettier-plugin-solidity": "^1.0.0-beta.13", "pretty-quick": "^2.0.1", "solhint": "^3.3.6", "solidity-coverage": "^0.7.16", "ts-node": "^10.1.0", - "typechain": "^5.1.2", - "typescript": "^4.5.2", - "zksync-web3": "^0.13.4" + "typechain": "^8.1.1", + "typescript": "^4.5.2" }, "husky": { "hooks": { diff --git a/scripts/arbitrumRescueAdapter.ts b/scripts/arbitrumRescueAdapter.ts index 7f6e4869d..c29d402d1 100644 --- a/scripts/arbitrumRescueAdapter.ts +++ b/scripts/arbitrumRescueAdapter.ts @@ -1,7 +1,7 @@ // @notice Prints bytes input you'll need to send ETH from L2 aliased HubPool address to l2 recipient address via // Arbitrum_RescueAdapter. -import { defaultAbiCoder, toWei } from "../test/utils"; +import { defaultAbiCoder, toWei } from "../utils/utils"; async function main() { const amountOfEth = toWei("2.9"); diff --git a/scripts/buildSampleTree.ts b/scripts/buildSampleTree.ts index b7e8dec4d..a871f773a 100644 --- a/scripts/buildSampleTree.ts +++ b/scripts/buildSampleTree.ts @@ -2,9 +2,9 @@ // test net. // @dev Modify constants to modify merkle leaves. Command: `yarn hardhat run ./scripts/buildSampleTree.ts` -import { toBN, getParamType, defaultAbiCoder, keccak256, toBNWeiWithDecimals } from "../test/utils"; +import { toBN, getParamType, defaultAbiCoder, keccak256, toBNWeiWithDecimals } from "../utils/utils"; import { MerkleTree } from "../utils/MerkleTree"; -import { RelayData } from "../test/fixtures/SpokePool.Fixture"; +import { SlowFill } from "../test/fixtures/SpokePool.Fixture"; import { PoolRebalanceLeaf, RelayerRefundLeaf } from "../test/MerkleLib.utils"; @@ -15,14 +15,14 @@ const RELAYER_REFUND_LEAF_COUNT = 1; const SLOW_RELAY_LEAF_COUNT = 1; const POOL_REBALANCE_NET_SEND_AMOUNT = 0.1; // Amount of tokens to send from HubPool to SpokePool const RELAYER_REFUND_AMOUNT_TO_RETURN = 0.1; // Amount of tokens to send from SpokePool to HubPool -const L1_TOKEN = "0x4dbcdf9b62e891a7cec5a2568c3f4faf9e8abe2b"; -const L2_TOKEN = "0x1E77ad77925Ac0075CF61Fb76bA35D884985019d"; -const DECIMALS = 6; +const L1_TOKEN = "0x40153ddfad90c49dbe3f5c9f96f2a5b25ec67461"; +const L2_TOKEN = "0x40153ddfad90c49dbe3f5c9f96f2a5b25ec67461"; +const DECIMALS = 18; const RELAYER_REFUND_ADDRESS_TO_REFUND = "0x9a8f92a830a5cb89a3816e3d267cb7791c16b04d"; const RELAYER_REFUND_AMOUNT_TO_REFUND = 0.1; // Amount of tokens to send out of SpokePool to relayer refund recipient const SLOW_RELAY_RECIPIENT_ADDRESS = "0x9a8f92a830a5cb89a3816e3d267cb7791c16b04d"; const SLOW_RELAY_AMOUNT = 0.1; // Amount of tokens to send out of SpokePool to slow relay recipient address -const SPOKE_POOL_CHAIN_ID = 421611; +const SPOKE_POOL_CHAIN_ID = 5; function tuplelifyLeaf(leaf: Object) { return JSON.stringify( @@ -120,19 +120,22 @@ async function main() { SLOW_RELAY_LEAF_COUNT > 1 ? "ves" : "f" }` ); - const leaves: RelayData[] = []; + const leaves: SlowFill[] = []; for (let i = 0; i < SLOW_RELAY_LEAF_COUNT; i++) { leaves.push({ - depositor: SLOW_RELAY_RECIPIENT_ADDRESS, - recipient: SLOW_RELAY_RECIPIENT_ADDRESS, - destinationToken: L2_TOKEN, - amount: toBNWeiWithDecimals(SLOW_RELAY_AMOUNT, DECIMALS), - originChainId: SPOKE_POOL_CHAIN_ID.toString(), - destinationChainId: SPOKE_POOL_CHAIN_ID.toString(), - realizedLpFeePct: toBN(0), - relayerFeePct: toBN(0), - depositId: i.toString(), - message: "0x", + relayData: { + depositor: SLOW_RELAY_RECIPIENT_ADDRESS, + recipient: SLOW_RELAY_RECIPIENT_ADDRESS, + destinationToken: L2_TOKEN, + amount: toBNWeiWithDecimals(SLOW_RELAY_AMOUNT, DECIMALS), + originChainId: SPOKE_POOL_CHAIN_ID.toString(), + destinationChainId: SPOKE_POOL_CHAIN_ID.toString(), + realizedLpFeePct: toBN(0), + relayerFeePct: toBN(0), + depositId: i.toString(), + message: "0x", + }, + payoutAdjustmentPct: toBN(0), }); console.group(); console.log(`- slowRelayLeaf ID#${i}: `, leaves[i]); @@ -146,9 +149,9 @@ async function main() { } amount of ${L2_TOKEN} to fulfill ${SLOW_RELAY_LEAF_COUNT} relays` ); - const paramType = await getParamType("MerkleLibTest", "verifySlowRelayFulfillment", "slowRelayFulfillment"); - const hashFn = (input: RelayData) => keccak256(defaultAbiCoder.encode([paramType!], [input])); - const tree = new MerkleTree(leaves, hashFn); + const paramType = await getParamType("MerkleLibTest", "verifySlowRelayFulfillment", "slowFill"); + const hashFn = (input: SlowFill) => keccak256(defaultAbiCoder.encode([paramType!], [input])); + const tree = new MerkleTree(leaves, hashFn); console.log("- Slow relay root: ", tree.getHexRoot()); console.group(); for (let i = 0; i < SLOW_RELAY_LEAF_COUNT; i++) { diff --git a/scripts/mintERC1155.ts b/scripts/mintERC1155.ts new file mode 100644 index 000000000..93bc21bd8 --- /dev/null +++ b/scripts/mintERC1155.ts @@ -0,0 +1,110 @@ +import { getContractFactory, ethers } from "../utils/utils"; +import { readFileSync } from "fs"; +import path from "path"; +import { getNodeUrl } from "@uma/common"; +import { hre } from "../utils/utils.hre"; + +const RECIPIENTS_CHUNK_SIZE = 100; // TODO: Still need to figure out which size is optimal + +/** + * Script to airdrop ERC1155 tokens to a list of recipients. The list of recipients need to be passed via a JSON file. + * ``` + * TOKEN_ID= \ + * RECIPIENTS= \ + * SKIP= \ + * yarn hardhat run ./scripts/mintERC1155.ts --network polygon-mumbai + * ``` + */ +async function main() { + const tokenId = parseInt(process.env.TOKEN_ID || "0"); + const skip = parseInt(process.env.SKIP || "0"); + const validRecipients = await parseAndValidateRecipients(); + + const [signer] = await ethers.getSigners(); + + const erc1155Deployment = await hre.deployments.get("MintableERC1155"); + const erc1155 = (await getContractFactory("MintableERC1155", { signer })).attach(erc1155Deployment.address); + + for (let i = skip; i < validRecipients.length; i = i + RECIPIENTS_CHUNK_SIZE) { + const recipientsChunk = validRecipients.slice(i, i + RECIPIENTS_CHUNK_SIZE); + console.log(`\nProcessing recipients in index range ${i} - ${i + RECIPIENTS_CHUNK_SIZE - 1}:`, { + first: recipientsChunk[0], + last: recipientsChunk[recipientsChunk.length - 1], + numRecipients: recipientsChunk.length, + }); + + const balanceOfBatch = await erc1155.balanceOfBatch(recipientsChunk, Array(recipientsChunk.length).fill(tokenId)); + + const alreadyMintedRecipients = recipientsChunk.filter((_, i) => balanceOfBatch[i].gt(0)); + const recipientsToMint = recipientsChunk.filter((_, i) => balanceOfBatch[i].eq(0)); + + if (alreadyMintedRecipients.length > 0) { + console.log(`Skipping ${alreadyMintedRecipients.length} already minted recipients...`); + } + + if (recipientsToMint.length === 0) { + console.log(`No recipients to mint for. Skipping chunk...`); + continue; + } + + console.log(`Minting token with id ${tokenId} to ${recipientsToMint.length} recipients...`); + const airdropTx = await erc1155.airdrop(tokenId, recipientsToMint, 1); + console.log("Tx hash:", airdropTx.hash); + await airdropTx.wait(); + console.log(`Successfully minted token to ${recipientsToMint.length} recipients in chunk`); + } +} + +async function parseAndValidateRecipients() { + const provider = new ethers.providers.JsonRpcProvider(getNodeUrl("mainnet", true, 1)); + + if (!process.env.RECIPIENTS) { + throw new Error("Missing path to a JSON file with the list of recipients. Pass it via env var RECIPIENTS="); + } + const recipientsFilePath = path.join(__dirname, "..", process.env.RECIPIENTS); + const recipientsFromFile: string[] = JSON.parse(readFileSync(recipientsFilePath, "utf8")); + + const resolvedRecipients = await Promise.all( + recipientsFromFile.map(async (r) => { + if (r.toLocaleLowerCase().endsWith(".eth")) { + try { + const resolvedAddress = await provider.resolveName(r); + if (!resolvedAddress) { + throw new Error(`Could not resolve ENS name: ${r}`); + } + return resolvedAddress; + } catch (error) { + console.error(error); + throw new Error(`Could not resolve ENS name: ${r}`); + } + } + return Promise.resolve(r); + }) + ); + + const invalidRecipients = resolvedRecipients.filter((r) => !ethers.utils.isAddress(r)); + + if (invalidRecipients.length > 0) { + throw new Error(`Invalid recipients: ${invalidRecipients}`); + } + + const duplicateAddresses = getDuplicateAddresses(resolvedRecipients); + if (duplicateAddresses.length > 0) { + throw new Error(`Recipients list contains duplicates ${Array.from(duplicateAddresses)}`); + } + + return resolvedRecipients.map((r) => ethers.utils.getAddress(r)); +} + +function getDuplicateAddresses(addresses: string[]) { + const checksummedAddresses = addresses.map((address) => ethers.utils.getAddress(address)); + return checksummedAddresses.filter((item, index) => checksummedAddresses.indexOf(item) !== index); +} + +main().then( + () => console.log("\nDone"), + (error) => { + console.log(error); + process.exitCode = 1; + } +); diff --git a/scripts/processHardhatExport.ts b/scripts/processHardhatExport.ts index 82ce721e9..f99658531 100644 --- a/scripts/processHardhatExport.ts +++ b/scripts/processHardhatExport.ts @@ -1,6 +1,8 @@ import fs from "fs"; import path from "path"; +import * as existingDeployments from "../deployments/deployments.json"; +export type Deployments = Record>; // Prunes the hardhat export file sent to the cache directory to only contain the deployment addresses of each contract // over the network of chains the Across v2 contracts are deployed on. Meant to be run as part of a publish process. export async function run(): Promise { @@ -8,13 +10,20 @@ export async function run(): Promise { const deploymentExport = require("../cache/massExport.json"); const castExport = deploymentExport as any; console.log("Generating exports on the following networks(if they have deployments)", Object.keys(castExport)); - const processedOutput: { [chainId: string]: { [name: string]: { address: string; blockNumber: number } } } = {}; + const processedOutput: Deployments = {}; Object.keys(castExport).forEach((chainId) => { if (castExport[chainId][0]) Object.keys(castExport[chainId][0].contracts).forEach((contractName) => { if (!processedOutput[chainId]) processedOutput[chainId] = {}; const address = castExport[chainId][0]?.contracts[contractName].address; const blockNumber = findDeploymentBlockNumber(castExport[chainId][0].name, contractName); + const existingBlockNumber = (existingDeployments as Deployments)[chainId][contractName].blockNumber; + console.log( + `Not updating ${contractName} as it has a later block number set in deployments.json than the one in deployments/${contractName}.json` + ); + const hasLaterBlockNumber = existingBlockNumber > blockNumber; + if (hasLaterBlockNumber) return; // If we have already found a later block number for this contract, then ignore this one. + // As its likely that we manually updated the `deployments` file and we don't want to override it. if (/.*_SpokePool/.test(contractName)) contractName = "SpokePool"; // Strip the network name from the spoke pool in the contractName. processedOutput[chainId][contractName] = { address, blockNumber }; }); diff --git a/scripts/setERC1155Metadata.ts b/scripts/setERC1155Metadata.ts new file mode 100644 index 000000000..202d27a8f --- /dev/null +++ b/scripts/setERC1155Metadata.ts @@ -0,0 +1,71 @@ +import { getContractFactory, ethers } from "../utils/utils"; +import { hre } from "../utils/utils.hre"; +import { readFileSync } from "fs"; +import path from "path"; +import { CID } from "multiformats/cid"; +import PinataSDK from "@pinata/sdk"; + +/** + * Script to upload metadata JSON file to IPFS via Pinata and set token uri. Make sure to set the env var + * `PINATA_JWT` in your .env file. Then you can run this script with: + * ``` + * TOKEN_ID= \ + * METADATA= \ + * yarn hardhat run ./scripts/setERC1155Metadata.ts --network polygon-mumbai + * ``` + */ +async function main() { + const tokenId = parseInt(process.env.TOKEN_ID || "0"); + const metadata = parseAndValidateMetadata(); + console.log(`Setting ERC1155 metadata for:`, { tokenId, metadata }); + + const pinata = new PinataSDK({ pinataJWTKey: process.env.PINATA_JWT }); + const pinResult = await pinata.pinJSONToIPFS(metadata, { pinataMetadata: { name: `${tokenId}-metadata.json` } }); + const metadataIpfsLink = `ipfs://${pinResult.IpfsHash}`; + console.log(`Successfully uploaded metadata to IPFS:`, metadataIpfsLink); + + const [signer] = await ethers.getSigners(); + const erc1155Deployment = await hre.deployments.get("MintableERC1155"); + const erc1155 = (await getContractFactory("MintableERC1155", { signer })).attach(erc1155Deployment.address); + const setTokenUriTx = await erc1155.setTokenURI(tokenId, metadataIpfsLink); + console.log(`Setting token uri...`); + console.log("Tx hash:", setTokenUriTx.hash); + await setTokenUriTx.wait(); + console.log(`Successfully set token uri`); +} + +function parseAndValidateMetadata() { + if (!process.env.METADATA) { + throw new Error("Missing path to a JSON file with token metadata. Pass it via env var METADATA="); + } + const metadataFilePath = path.join(__dirname, "..", process.env.METADATA); + const metadataFromFile: Record = JSON.parse(readFileSync(metadataFilePath, "utf8")); + const requiredKeys = ["name", "description", "image", "animation_url"]; + + if (!requiredKeys.every((k) => k in metadataFromFile)) { + throw new Error(`Invalid metadata: required keys ${requiredKeys}`); + } + + requireIpfsLink(metadataFromFile.image, "image"); + requireIpfsLink(metadataFromFile.animation_url, "animation_url"); + + return metadataFromFile; +} + +function requireIpfsLink(ipfsLink: string, key: string) { + // Make sure the image is an IPFS link + if (!ipfsLink.startsWith("ipfs://")) { + throw new Error(`Invalid metadata: '${key}' must be an IPFS link ipfs://`); + } + const cid = ipfsLink.split("ipfs://")[1]; + + CID.parse(cid); // throws if invalid +} + +main().then( + () => console.log("Done"), + (error) => { + console.log(error); + process.exitCode = 1; + } +); diff --git a/scripts/setupArbitrumSpokePool.ts b/scripts/setupArbitrumSpokePool.ts index cea9c8ba7..ccad624c5 100644 --- a/scripts/setupArbitrumSpokePool.ts +++ b/scripts/setupArbitrumSpokePool.ts @@ -1,25 +1,39 @@ // @notice Logs ABI-encoded function data that can be relayed from HubPool to ArbitrumSpokePool to set it up. -import { getContractFactory, ethers, hre } from "../test/utils"; -import * as consts from "../test/constants"; +import { getContractFactory, ethers } from "../utils/utils"; +import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../utils/constants"; async function main() { const [signer] = await ethers.getSigners(); - // We need to whitelist L2 --> L1 token mappings const spokePool = await getContractFactory("Arbitrum_SpokePool", { signer }); - const whitelistWeth = spokePool.interface.encodeFunctionData("whitelistToken", [ - "0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681", // L2 WETH - "0xc778417e063141139fce010982780140aa0cd5ab", // L1 WETH - ]); - console.log(`(WETH) whitelistToken: `, whitelistWeth); + const hubPool = await getContractFactory("HubPool", { signer }); - // USDC is also not verified on the rinkeby explorer so we should approve it to be spent by the spoke pool. - const ERC20 = await getContractFactory("ExpandedERC20", { signer }); - const usdc = await ERC20.attach("0x4dbcdf9b62e891a7cec5a2568c3f4faf9e8abe2b"); - const deployedHubPool = await hre.deployments.get("HubPool"); - const approval = await usdc.approve(deployedHubPool.address, consts.maxUint256); - console.log(`Approved USDC to be spent by HubPool @ ${deployedHubPool.address}: `, approval.hash); + // We need to whitelist all L2 --> L1 token mappings + // We'll use this to store all the call data we need to pass to HubPool#multicall. + const callData: string[] = []; + + const tokenSymbols = Object.values(TOKEN_SYMBOLS_MAP); + for (const token of tokenSymbols) { + // Setup Arbitrum: We need to call whitelistToken on Arbitrum SpokePool so that SpokePool + // is aware of L1 to L2 mappings. + const l1Token = token.addresses[CHAIN_IDs.MAINNET]; + const arbitrumToken = token.addresses[CHAIN_IDs.ARBITRUM]; + if (!l1Token || !arbitrumToken) { + console.log(`Token ${token.symbol} does not exist on both Arbitrum and Mainnet. Skipping...`); + continue; + } + const _callData = spokePool.interface.encodeFunctionData("whitelistToken", [arbitrumToken, l1Token]); + console.log(`Whitelisting mapping for ${token.symbol} on Arbitrum SpokePool: ${_callData}`); + const relayRootCallData = hubPool.interface.encodeFunctionData("relaySpokePoolAdminFunction", [ + CHAIN_IDs.ARBITRUM, + _callData, + ]); + callData.push(relayRootCallData); + } + + const multicallData = hubPool.interface.encodeFunctionData("multicall", [callData]); + console.log("Data to pass to HubPool#multicall()", multicallData); } main().then( diff --git a/scripts/setupOptimismSpokePool.ts b/scripts/setupOptimismSpokePool.ts index 75ee6e787..7600b411d 100644 --- a/scripts/setupOptimismSpokePool.ts +++ b/scripts/setupOptimismSpokePool.ts @@ -1,25 +1,38 @@ // @notice Logs ABI-encoded function data that can be relayed from HubPool to OptimismSpokePool to set it up. -import { getContractFactory, ethers, hre } from "../test/utils"; -import * as consts from "../test/constants"; +import { getContractFactory, ethers } from "../utils/utils"; +import { CHAIN_IDs } from "../utils/constants"; + +const customOptimismTokenBridges: Record = { + // DAI + "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1": "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65", +}; async function main() { const [signer] = await ethers.getSigners(); - // We need to set the token bridge for custom L2 tokens like DAI: - const spokePool = await getContractFactory("Optimism_SpokePool", { signer }); - const setTokenBridgeDai = spokePool.interface.encodeFunctionData("setTokenBridge", [ - "0xda10009cbd5d07dd0cecc66161fc93d7c9000da1", // L2 DAI - "0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65", // L2 DAI Custom Bridge - ]); - console.log(`(DAI) setTokenBridge: `, setTokenBridgeDai); - - // WETH is also not verified on the optimism explorer so we should approve it to be spent by the spoke pool. - const ERC20 = await getContractFactory("ExpandedERC20", { signer }); - const weth = await ERC20.attach("0x4200000000000000000000000000000000000006"); - const deployedSpokePool = await hre.deployments.get("Optimism_SpokePool"); - const approval = await weth.approve(deployedSpokePool.address, consts.maxUint256); - console.log(`Approved WETH to be spent by SpokePool @ ${deployedSpokePool.address}: `, approval.hash); + const spokePool = await getContractFactory("Ovm_SpokePool", { signer }); + const hubPool = await getContractFactory("HubPool", { signer }); + + // We need to whitelist all L2 --> L1 token mappings + // We'll use this to store all the call data we need to pass to HubPool#multicall. + const callData: string[] = []; + + for (const l2Token of Object.keys(customOptimismTokenBridges)) { + // Setup Optimism: We need to call setTokenBridge on Optimism SpokePool so that SpokePool + // is aware of L2 custom bridge mappings. + const bridge = customOptimismTokenBridges[l2Token]; + const _callData = spokePool.interface.encodeFunctionData("setTokenBridge", [l2Token, bridge]); + console.log(`Setting token bridge for ${l2Token} on Optimism SpokePool: ${_callData}`); + const relayRootCallData = hubPool.interface.encodeFunctionData("relaySpokePoolAdminFunction", [ + CHAIN_IDs.OPTIMISM, + _callData, + ]); + callData.push(relayRootCallData); + } + + const multicallData = hubPool.interface.encodeFunctionData("multicall", [callData]); + console.log("Data to pass to HubPool#multicall()", multicallData); } main().then( diff --git a/scripts/upgradeTo.ts b/scripts/upgradeTo.ts new file mode 100644 index 000000000..eafef2a2f --- /dev/null +++ b/scripts/upgradeTo.ts @@ -0,0 +1,21 @@ +import { ethers, getContractFactory } from "../utils/utils"; + +async function main() { + const [signer] = await ethers.getSigners(); + + const spokePool = await getContractFactory("Arbitrum_SpokePool", { signer }); + const upgradeTo = spokePool.interface.encodeFunctionData("upgradeTo", ["0xcdf08CB3d3436c3c21F277b6AD45E3D7aB1Ce12F"]); + console.log(`upgradeTo bytes: `, upgradeTo); + + console.log( + `Call relaySpokePoolAdminFunction() with the params [, ${upgradeTo}] on this hub pool: https://goerli.etherscan.io/address/0x0e2817C49698cc0874204AeDf7c72Be2Bb7fCD5d#writeContract` + ); +} + +main().then( + () => process.exit(0), + (error) => { + console.log(error); + process.exit(1); + } +); diff --git a/scripts/zkSync.ts b/scripts/zkSync.ts index 9d5ee7739..481683de7 100644 --- a/scripts/zkSync.ts +++ b/scripts/zkSync.ts @@ -2,7 +2,7 @@ // contains useful scripts to interact with zksync goerli contracts. To run, run: // yarn hardhat run ./scripts/zksync.ts --network zksync-goerli -import { getContractFactory, ethers, toBN, findArtifactFromPath } from "../test/utils"; +import { getContractFactory, ethers, toBN, findArtifactFromPath } from "../utils/utils"; import { Contract, ContractFactory } from "ethers"; import { assert } from "console"; diff --git a/tasks/enableL1TokenAcrossEcosystem.ts b/tasks/enableL1TokenAcrossEcosystem.ts index 1bb651ba5..8e7af8913 100644 --- a/tasks/enableL1TokenAcrossEcosystem.ts +++ b/tasks/enableL1TokenAcrossEcosystem.ts @@ -2,14 +2,13 @@ import { task } from "hardhat/config"; import assert from "assert"; import { findL2TokenForL1Token, askYesNoQuestion, zeroAddress, minimalSpokePoolInterface } from "./utils"; -const enabledChainIds = [1, 10, 137, 288, 42161]; // Supported mainnet chain IDs. +const enabledChainIds = [1, 10, 137, 42161]; // Supported mainnet chain IDs. task("enable-l1-token-across-ecosystem", "Enable a provided token across the entire ecosystem of supported chains") .addParam("chain1token", "Address of the token to enable, as defined on L1") .addFlag("execute", "Provide this flag if you would like to actually execute the transaction from the EOA") .addOptionalParam("chain10token", "Address of the token on chainID 10. Used to override the auto detect") .addOptionalParam("chain137token", "Address of the token on chainID 137. Used to override the auto detect") - .addOptionalParam("chain288token", "Address of the token on chainID 288. Used to override the auto detect") .addOptionalParam("chain42161token", "Address of the token on chainID 42161. Used to override the auto detect") .addOptionalParam( "customoptimismbridge", diff --git a/test-utils.ts b/test-utils.ts index ea4bdb17c..3ae2abe3e 100644 --- a/test-utils.ts +++ b/test-utils.ts @@ -8,4 +8,4 @@ export * from "./test/fixtures/HubPool.Fixture"; export * from "./test/fixtures/MerkleLib.Fixture"; export * from "./test/MerkleLib.utils"; export * from "./test/constants"; -export * from "./test/utils"; +export * from "./utils/utils"; diff --git a/test/BondToken.Admin.ts b/test/BondToken.Admin.ts index 2c5320e51..1d5021928 100644 --- a/test/BondToken.Admin.ts +++ b/test/BondToken.Admin.ts @@ -1,5 +1,5 @@ import { bondTokenFixture } from "./fixtures/BondToken.Fixture"; -import { Contract, ethers, SignerWithAddress, expect } from "./utils"; +import { Contract, ethers, SignerWithAddress, expect } from "../utils/utils"; let bondToken: Contract; let owner: SignerWithAddress, other: SignerWithAddress; diff --git a/test/BondToken.e2e.ts b/test/BondToken.e2e.ts index 3c78f3742..3cfce2a52 100644 --- a/test/BondToken.e2e.ts +++ b/test/BondToken.e2e.ts @@ -1,6 +1,6 @@ import { bondTokenFixture } from "./fixtures/BondToken.Fixture"; import { enableTokensForLP, hubPoolFixture } from "./fixtures/HubPool.Fixture"; -import { Contract, ethers, seedWallet, SignerWithAddress, expect } from "./utils"; +import { Contract, ethers, seedWallet, SignerWithAddress, expect } from "../utils/utils"; import { constructSimpleTree } from "./HubPool.ExecuteRootBundle"; import * as consts from "./constants"; diff --git a/test/BondToken.erc20.ts b/test/BondToken.erc20.ts index 09b4b9295..f5ddfb3ee 100644 --- a/test/BondToken.erc20.ts +++ b/test/BondToken.erc20.ts @@ -1,5 +1,5 @@ import { bondTokenFixture } from "./fixtures/BondToken.Fixture"; -import { Contract, ethers, seedWallet, SignerWithAddress, expect } from "./utils"; +import { Contract, ethers, seedWallet, SignerWithAddress, expect } from "../utils/utils"; import { bondAmount } from "./constants"; const bondTokenName = "Across Bond Token"; diff --git a/test/ConfigStore.ts b/test/ConfigStore.ts index e6e7de7f1..6bce7020b 100644 --- a/test/ConfigStore.ts +++ b/test/ConfigStore.ts @@ -1,4 +1,12 @@ -import { getContractFactory, SignerWithAddress, utf8ToHex, expect, Contract, ethers, randomAddress } from "./utils"; +import { + getContractFactory, + SignerWithAddress, + utf8ToHex, + expect, + Contract, + ethers, + randomAddress, +} from "../utils/utils"; import * as constants from "./constants"; let configStore: Contract; diff --git a/test/HubPool.Admin.ts b/test/HubPool.Admin.ts index 20bc0a3cf..9be350c42 100644 --- a/test/HubPool.Admin.ts +++ b/test/HubPool.Admin.ts @@ -1,7 +1,24 @@ -import { getContractFactory, SignerWithAddress, seedWallet, expect } from "./utils"; -import { Contract, ethers, randomAddress, utf8ToHex } from "./utils"; -import { originChainId, destinationChainId, bondAmount, zeroAddress, mockTreeRoot } from "./constants"; -import { mockSlowRelayRoot, finalFeeUsdc, finalFee, totalBond } from "./constants"; +import { + getContractFactory, + SignerWithAddress, + seedWallet, + expect, + Contract, + ethers, + randomAddress, + utf8ToHex, +} from "../utils/utils"; +import { + originChainId, + destinationChainId, + bondAmount, + zeroAddress, + mockTreeRoot, + mockSlowRelayRoot, + finalFeeUsdc, + finalFee, + totalBond, +} from "./constants"; import { hubPoolFixture } from "./fixtures/HubPool.Fixture"; let hubPool: Contract, weth: Contract, usdc: Contract; diff --git a/test/HubPool.DisputeRootBundle.ts b/test/HubPool.DisputeRootBundle.ts index 2c32e2dec..48597c2bf 100644 --- a/test/HubPool.DisputeRootBundle.ts +++ b/test/HubPool.DisputeRootBundle.ts @@ -1,5 +1,5 @@ import { parseAncillaryData } from "@uma/common"; -import { SignerWithAddress, seedWallet, expect, Contract, ethers } from "./utils"; +import { SignerWithAddress, seedWallet, expect, Contract, ethers } from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; diff --git a/test/HubPool.ExecuteRootBundle.ts b/test/HubPool.ExecuteRootBundle.ts index e458b47a5..bdd82ca9a 100644 --- a/test/HubPool.ExecuteRootBundle.ts +++ b/test/HubPool.ExecuteRootBundle.ts @@ -1,7 +1,17 @@ -import { toBNWei, SignerWithAddress, seedWallet, expect, Contract, ethers, randomAddress } from "./utils"; +import { MerkleTree } from "@uma/common"; +import { + toBNWei, + SignerWithAddress, + seedWallet, + expect, + Contract, + ethers, + randomAddress, + BigNumber, +} from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; -import { buildPoolRebalanceLeafTree, buildPoolRebalanceLeaves } from "./MerkleLib.utils"; +import { buildPoolRebalanceLeafTree, buildPoolRebalanceLeaves, PoolRebalanceLeaf } from "./MerkleLib.utils"; let hubPool: Contract, mockAdapter: Contract, weth: Contract, dai: Contract, mockSpoke: Contract, timer: Contract; let owner: SignerWithAddress, dataWorker: SignerWithAddress, liquidityProvider: SignerWithAddress; @@ -9,7 +19,12 @@ let l2Weth: string, l2Dai: string; // Construct the leaves that will go into the merkle tree. For this function create a simple set of leaves that will // repay two token to one chain Id with simple lpFee, netSend and running balance amounts. -export async function constructSimpleTree() { +export async function constructSimpleTree(): Promise<{ + wethToSendToL2: BigNumber; + daiToSend: BigNumber; + leaves: PoolRebalanceLeaf[]; + tree: MerkleTree; +}> { const wethToSendToL2 = toBNWei(100); const daiToSend = toBNWei(1000); const leaves = buildPoolRebalanceLeaves( diff --git a/test/HubPool.LiquidityProvision.ts b/test/HubPool.LiquidityProvision.ts index 91fd3c806..0d87523e9 100644 --- a/test/HubPool.LiquidityProvision.ts +++ b/test/HubPool.LiquidityProvision.ts @@ -1,4 +1,13 @@ -import { getContractFactory, fromWei, toBN, SignerWithAddress, seedWallet, expect, Contract, ethers } from "./utils"; +import { + getContractFactory, + fromWei, + toBN, + SignerWithAddress, + seedWallet, + expect, + Contract, + ethers, +} from "../utils/utils"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; import { amountToSeedWallets, amountToLp } from "./constants"; diff --git a/test/HubPool.LiquidityProvisionFees.ts b/test/HubPool.LiquidityProvisionFees.ts index 8d8547529..b38b60245 100644 --- a/test/HubPool.LiquidityProvisionFees.ts +++ b/test/HubPool.LiquidityProvisionFees.ts @@ -1,4 +1,4 @@ -import { expect, ethers, Contract, SignerWithAddress, seedWallet, toWei } from "./utils"; +import { expect, ethers, Contract, SignerWithAddress, seedWallet, toWei } from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "./MerkleLib.utils"; diff --git a/test/HubPool.LiquidityProvisionHaircut.ts b/test/HubPool.LiquidityProvisionHaircut.ts index d66b703a8..130e52e8b 100644 --- a/test/HubPool.LiquidityProvisionHaircut.ts +++ b/test/HubPool.LiquidityProvisionHaircut.ts @@ -1,4 +1,4 @@ -import { expect, ethers, Contract, SignerWithAddress, seedWallet, toWei } from "./utils"; +import { expect, ethers, Contract, SignerWithAddress, seedWallet, toWei } from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "./MerkleLib.utils"; diff --git a/test/HubPool.PooledTokenSynchronization.ts b/test/HubPool.PooledTokenSynchronization.ts index 2e370cbfb..119c6c66e 100644 --- a/test/HubPool.PooledTokenSynchronization.ts +++ b/test/HubPool.PooledTokenSynchronization.ts @@ -1,4 +1,4 @@ -import { expect, Contract, ethers, SignerWithAddress, toBNWei, seedWallet, toWei } from "./utils"; +import { expect, Contract, ethers, SignerWithAddress, toBNWei, seedWallet, toWei } from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "./MerkleLib.utils"; diff --git a/test/HubPool.ProposeRootBundle.ts b/test/HubPool.ProposeRootBundle.ts index 747016050..60d1d7f52 100644 --- a/test/HubPool.ProposeRootBundle.ts +++ b/test/HubPool.ProposeRootBundle.ts @@ -1,4 +1,4 @@ -import { SignerWithAddress, seedWallet, expect, Contract, ethers } from "./utils"; +import { SignerWithAddress, seedWallet, expect, Contract, ethers } from "../utils/utils"; import * as consts from "./constants"; import { hubPoolFixture } from "./fixtures/HubPool.Fixture"; diff --git a/test/HubPool.ProtocolFees.ts b/test/HubPool.ProtocolFees.ts index 1ecb96d9f..3574dd58f 100644 --- a/test/HubPool.ProtocolFees.ts +++ b/test/HubPool.ProtocolFees.ts @@ -1,4 +1,4 @@ -import { toWei, toBNWei, SignerWithAddress, seedWallet, expect, Contract, ethers } from "./utils"; +import { toWei, toBNWei, SignerWithAddress, seedWallet, expect, Contract, ethers } from "../utils/utils"; import { mockTreeRoot, finalFee, bondAmount, amountToLp, refundProposalLiveness, zeroAddress } from "./constants"; import { hubPoolFixture, enableTokensForLP } from "./fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "./MerkleLib.utils"; diff --git a/test/HubPool.Weth.ts b/test/HubPool.Weth.ts index 4af14e429..68c01edca 100644 --- a/test/HubPool.Weth.ts +++ b/test/HubPool.Weth.ts @@ -1,4 +1,4 @@ -import { toWei, toBN, SignerWithAddress, expect, Contract, ethers } from "./utils"; +import { toWei, toBN, SignerWithAddress, expect, Contract, ethers } from "../utils/utils"; import { hubPoolFixture } from "./fixtures/HubPool.Fixture"; let hubPool: Contract, weth: Contract; diff --git a/test/MerkleLib.Claims.ts b/test/MerkleLib.Claims.ts index 5ab9b2f8b..de4d427ad 100644 --- a/test/MerkleLib.Claims.ts +++ b/test/MerkleLib.Claims.ts @@ -1,5 +1,5 @@ import { merkleLibFixture } from "./fixtures/MerkleLib.Fixture"; -import { BigNumber, expect, Contract } from "./utils"; +import { BigNumber, expect, Contract } from "../utils/utils"; let merkleLibTest: Contract; diff --git a/test/MerkleLib.Proofs.ts b/test/MerkleLib.Proofs.ts index d336b3efe..81038b9df 100644 --- a/test/MerkleLib.Proofs.ts +++ b/test/MerkleLib.Proofs.ts @@ -1,8 +1,16 @@ import { PoolRebalanceLeaf, RelayerRefundLeaf } from "./MerkleLib.utils"; import { merkleLibFixture } from "./fixtures/MerkleLib.Fixture"; import { MerkleTree, EMPTY_MERKLE_ROOT } from "../utils/MerkleTree"; -import { expect, randomBigNumber, randomAddress, getParamType, defaultAbiCoder } from "./utils"; -import { keccak256, Contract, BigNumber } from "./utils"; +import { + expect, + randomBigNumber, + randomAddress, + getParamType, + defaultAbiCoder, + keccak256, + Contract, + BigNumber, +} from "../utils/utils"; let merkleLibTest: Contract; diff --git a/test/MerkleLib.utils.ts b/test/MerkleLib.utils.ts index 01f801d8b..f2ab700ce 100644 --- a/test/MerkleLib.utils.ts +++ b/test/MerkleLib.utils.ts @@ -1,7 +1,7 @@ -import { getParamType, expect, BigNumber, Contract, defaultAbiCoder, keccak256, toBNWei } from "./utils"; +import { getParamType, expect, BigNumber, Contract, defaultAbiCoder, keccak256, toBNWei } from "../utils/utils"; import { repaymentChainId, amountToReturn } from "./constants"; import { MerkleTree } from "../utils/MerkleTree"; -import { RelayData, SlowFill } from "./fixtures/SpokePool.Fixture"; +import { SlowFill } from "./fixtures/SpokePool.Fixture"; export interface PoolRebalanceLeaf { chainId: BigNumber; groupIndex: BigNumber; @@ -54,12 +54,16 @@ export function buildRelayerRefundLeaves( } export async function buildPoolRebalanceLeafTree(poolRebalanceLeaves: PoolRebalanceLeaf[]) { - for (let i = 0; i < poolRebalanceLeaves.length; i++) { - // The 4 provided parallel arrays must be of equal length. - expect(poolRebalanceLeaves[i].l1Tokens.length) - .to.equal(poolRebalanceLeaves[i].bundleLpFees.length) - .to.equal(poolRebalanceLeaves[i].netSendAmounts.length) - .to.equal(poolRebalanceLeaves[i].runningBalances.length); + for (const leaf of poolRebalanceLeaves) { + const { l1Tokens, bundleLpFees, netSendAmounts, runningBalances } = leaf; + + // l1Tokens, bundleLpFees and netSendAmounts must always be of equal length. + expect(l1Tokens.length).to.equal(bundleLpFees.length).to.equal(netSendAmounts.length); + + // runningBalances must be 1x or 2x as long as the other arrays (pre/post UBA). + if (runningBalances.length !== l1Tokens.length) { + expect(runningBalances.length).to.equal(2 * l1Tokens.length); + } } const paramType = await getParamType("MerkleLibTest", "verifyPoolRebalance", "rebalance"); diff --git a/test/SpokePool.Admin.ts b/test/SpokePool.Admin.ts index d2e14189a..fc9e4b91d 100644 --- a/test/SpokePool.Admin.ts +++ b/test/SpokePool.Admin.ts @@ -1,4 +1,5 @@ -import { expect, ethers, Contract, SignerWithAddress, getContractFactory, hre } from "./utils"; +import { expect, ethers, Contract, SignerWithAddress, getContractFactory } from "../utils/utils"; +import { hre } from "../utils/utils.hre"; import { spokePoolFixture } from "./fixtures/SpokePool.Fixture"; import { destinationChainId, mockRelayerRefundRoot, mockSlowRelayRoot } from "./constants"; diff --git a/test/SpokePool.Deposit.ts b/test/SpokePool.Deposit.ts index 308202fce..f330e0d1e 100644 --- a/test/SpokePool.Deposit.ts +++ b/test/SpokePool.Deposit.ts @@ -1,4 +1,4 @@ -import { expect, ethers, Contract, SignerWithAddress, seedWallet, toBN, toWei } from "./utils"; +import { expect, ethers, Contract, SignerWithAddress, seedWallet, toBN, toWei } from "../utils/utils"; import { spokePoolFixture, enableRoutes, getDepositParams } from "./fixtures/SpokePool.Fixture"; import { amountToSeedWallets, diff --git a/test/SpokePool.ExecuteRootBundle.ts b/test/SpokePool.ExecuteRootBundle.ts index e883a90e2..ee421a78e 100644 --- a/test/SpokePool.ExecuteRootBundle.ts +++ b/test/SpokePool.ExecuteRootBundle.ts @@ -1,4 +1,4 @@ -import { SignerWithAddress, seedContract, toBN, expect, Contract, ethers } from "./utils"; +import { SignerWithAddress, seedContract, toBN, expect, Contract, ethers, BigNumber } from "../utils/utils"; import * as consts from "./constants"; import { spokePoolFixture } from "./fixtures/SpokePool.Fixture"; import { buildRelayerRefundTree, buildRelayerRefundLeaves } from "./MerkleLib.utils"; @@ -56,7 +56,9 @@ describe("SpokePool Root Bundle Execution", function () { expect(relayTokensEvents[0].args?.leafId).to.equal(0); expect(relayTokensEvents[0].args?.chainId).to.equal(destinationChainId); expect(relayTokensEvents[0].args?.amountToReturn).to.equal(consts.amountToReturn); - expect(relayTokensEvents[0].args?.refundAmounts).to.deep.equal([consts.amountToRelay, consts.amountToRelay]); + expect((relayTokensEvents[0].args?.refundAmounts as BigNumber[]).map((v) => v.toString())).to.deep.equal( + [consts.amountToRelay, consts.amountToRelay].map((v) => v.toString()) + ); expect(relayTokensEvents[0].args?.refundAddresses).to.deep.equal([relayer.address, rando.address]); expect(relayTokensEvents[0].args?.caller).to.equal(dataWorker.address); diff --git a/test/SpokePool.Relay.ts b/test/SpokePool.Relay.ts index 2f376555b..34aa95854 100644 --- a/test/SpokePool.Relay.ts +++ b/test/SpokePool.Relay.ts @@ -1,4 +1,14 @@ -import { expect, Contract, ethers, SignerWithAddress, seedWallet, toWei, toBN, BigNumber, createFake } from "./utils"; +import { + expect, + Contract, + ethers, + SignerWithAddress, + seedWallet, + toWei, + toBN, + BigNumber, + createFake, +} from "../utils/utils"; import { spokePoolFixture, getRelayHash, @@ -7,6 +17,7 @@ import { getFillRelayUpdatedFeeParams, } from "./fixtures/SpokePool.Fixture"; import * as consts from "./constants"; +import { MAX_UINT_VAL } from "@uma/common"; let spokePool: Contract, weth: Contract, erc20: Contract, destErc20: Contract, erc1271: Contract; let depositor: SignerWithAddress, recipient: SignerWithAddress, relayer: SignerWithAddress; @@ -36,19 +47,32 @@ describe("SpokePool Relayer Logic", async function () { destErc20.address ); + // Partial relay: + // Can't fill when paused: await spokePool.connect(depositor).pauseFills(true); await expect(spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, consts.amountToRelay))).to.be .reverted; await spokePool.connect(depositor).pauseFills(false); - await expect(spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, consts.amountToRelay))) + // Must set repayment chain == destination chain for partial fills: + await expect( + spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, consts.amountToRelay, consts.repaymentChainId)) + ).to.be.revertedWith("invalid repayment chain"); + + await expect( + spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, consts.amountToRelay, consts.destinationChainId)) + ) .to.emit(spokePool, "FilledRelay") .withArgs( relayData.amount, consts.amountToRelayPreFees, consts.amountToRelayPreFees, - consts.repaymentChainId, + consts.destinationChainId, toBN(relayData.originChainId), toBN(relayData.destinationChainId), relayData.relayerFeePct, @@ -59,7 +83,7 @@ describe("SpokePool Relayer Logic", async function () { relayData.depositor, relayData.recipient, relayData.message, - [relayData.recipient, relayData.message, relayData.relayerFeePct, false] + [relayData.recipient, relayData.message, relayData.relayerFeePct, false, "0"] ); // The collateral should have transferred from relayer to recipient. @@ -80,7 +104,9 @@ describe("SpokePool Relayer Logic", async function () { // pulls exactly enough tokens to complete the relay. const fullRelayAmount = consts.amountToDeposit; const fullRelayAmountPostFees = fullRelayAmount.mul(consts.totalPostFeesPct).div(toBN(consts.oneHundredPct)); - await spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, fullRelayAmount)); + await spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, fullRelayAmount, consts.destinationChainId)); expect(await destErc20.balanceOf(relayer.address)).to.equal( consts.amountToSeedWallets.sub(fullRelayAmountPostFees) ); @@ -89,6 +115,43 @@ describe("SpokePool Relayer Logic", async function () { // Fill amount should be equal to full relay amount. expect(await spokePool.relayFills(relayHash)).to.equal(fullRelayAmount); }); + it("Repayment chain is set correctly", async function () { + // Can set repayment chain if full fill. + const { relayData } = getRelayHash( + depositor.address, + recipient.address, + consts.firstDepositId, + consts.originChainId, + consts.destinationChainId, + destErc20.address + ); + + // Changed consts.amountToRelay to relayData.amount to make it a full fill + await expect( + spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, relayData.amount, consts.repaymentChainId)) + ) + .to.emit(spokePool, "FilledRelay") + .withArgs( + relayData.amount, + relayData.amount, + relayData.amount, + consts.repaymentChainId, + toBN(relayData.originChainId), + toBN(relayData.destinationChainId), + relayData.relayerFeePct, + relayData.realizedLpFeePct, + toBN(relayData.depositId), + relayData.destinationToken, + relayer.address, + relayData.depositor, + relayData.recipient, + relayData.message, + [relayData.recipient, relayData.message, relayData.relayerFeePct, false, "0"] + ); + + // Repayment on another chain doesn't increment fill counter. + expect(await spokePool.fillCounter(relayData.destinationToken)).to.equal(0); + }); it("Fill count increment local repayment", async function () { const { relayData } = getRelayHash( depositor.address, @@ -109,6 +172,112 @@ describe("SpokePool Relayer Logic", async function () { .div(consts.oneHundredPct); expect(await spokePool.fillCounter(relayData.destinationToken)).to.equal(fillCountIncrement); }); + it("Requested refund increments fill count", async function () { + const { relayData } = getRelayHash( + depositor.address, + recipient.address, + consts.firstDepositId, + consts.originChainId, + consts.destinationChainId, + destErc20.address + ); + + const maxFillCount = relayData.amount; + + await expect( + spokePool.connect(relayer).requestRefund( + destErc20.address, + relayData.amount, + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + relayData.depositId, + 11, // Use any block number for this test. + maxFillCount + ) + ) + .to.emit(spokePool, "RefundRequested") + .withArgs( + relayer.address, + destErc20.address, + relayData.amount, + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + toBN(relayData.depositId), + 11, + 0 + ); + + // Fill count should be set. + const fillCountIncrement = relayData.amount + .mul(consts.oneHundredPct.sub(relayData.realizedLpFeePct)) + .div(consts.oneHundredPct); + expect(await spokePool.fillCounter(relayData.destinationToken)).to.equal(fillCountIncrement); + + // Reverts if max fill count or max fill amount is exceeded + await expect( + spokePool.connect(relayer).requestRefund( + destErc20.address, + MAX_UINT_VAL, // Too large + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + relayData.depositId, + 0, + maxFillCount + ) + ).to.be.revertedWith("Amount too large"); + await expect( + spokePool.connect(relayer).requestRefund( + destErc20.address, + relayData.amount, + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + relayData.depositId, + 0, + fillCountIncrement.sub(1) // Can't be less than existing fill counter + ) + ).to.be.revertedWith("Above max count"); + await expect( + spokePool.connect(relayer).requestRefund( + destErc20.address, + 0, // Too small + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + relayData.depositId, + 0, + maxFillCount + ) + ).to.be.revertedWith("Amount must be > 0"); + + await expect( + spokePool.connect(relayer).requestRefund( + destErc20.address, + relayData.amount, + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + relayData.depositId, + 11, // Use any block number for this test. + maxFillCount + ) + ) + .to.emit(spokePool, "RefundRequested") + .withArgs( + relayer.address, + destErc20.address, + relayData.amount, + consts.originChainId, + consts.destinationChainId, + relayData.realizedLpFeePct, + toBN(relayData.depositId), + 11, + 1 // Incremented refund count. + ); + }); it("Relaying WETH correctly unwraps into ETH", async function () { const { relayHash, relayData } = getRelayHash( depositor.address, @@ -120,7 +289,9 @@ describe("SpokePool Relayer Logic", async function () { ); const startingRecipientBalance = await recipient.getBalance(); - await spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, consts.amountToRelay)); + await spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, consts.amountToRelay, consts.destinationChainId)); // The collateral should have unwrapped to ETH and then transferred to recipient. expect(await weth.balanceOf(relayer.address)).to.equal(consts.amountToSeedWallets.sub(consts.amountToRelay)); @@ -144,16 +315,44 @@ describe("SpokePool Relayer Logic", async function () { "0x1234" ); - await spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, consts.amountToRelay)); + await spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, consts.amountToRelay, consts.destinationChainId)); expect(acrossMessageHandler.handleAcrossMessage).to.have.been.calledOnceWith( weth.address, consts.amountToRelay, + false, + relayer.address, + "0x1234" + ); + }); + it("Handler is called with correct params", async function () { + const acrossMessageHandler = await createFake("AcrossMessageHandlerMock"); + const { relayData } = getRelayHash( + depositor.address, + acrossMessageHandler.address, + consts.firstDepositId, + consts.originChainId, + consts.destinationChainId, + weth.address, + undefined, + undefined, + undefined, "0x1234" ); - // The collateral should have not unwrapped to ETH and then transferred to recipient. - expect(await weth.balanceOf(acrossMessageHandler.address)).to.equal(consts.amountToRelay); + // Handler is called with full fill and relayer address. + await spokePool + .connect(depositor) + .fillRelay(...getFillRelayParams(relayData, relayData.amount, consts.destinationChainId)); + expect(acrossMessageHandler.handleAcrossMessage).to.have.been.calledOnceWith( + weth.address, + relayData.amount.mul(consts.totalPostFeesPct).div(toBN(consts.oneHundredPct)), + true, // True because fill completed deposit. + depositor.address, // Custom relayer + "0x1234" + ); }); it("Self-relay transfers no tokens", async function () { const largeRelayAmount = consts.amountToSeedWallets.mul(100); @@ -168,7 +367,9 @@ describe("SpokePool Relayer Logic", async function () { ); // This should work, despite the amount being quite large. - await spokePool.connect(relayer).fillRelay(...getFillRelayParams(relayData, largeRelayAmount)); + await spokePool + .connect(relayer) + .fillRelay(...getFillRelayParams(relayData, largeRelayAmount, consts.destinationChainId)); // Balance should be the same as before. expect(await weth.balanceOf(relayer.address)).to.equal(consts.amountToSeedWallets); @@ -195,7 +396,7 @@ describe("SpokePool Relayer Logic", async function () { consts.depositRelayerFeePct ).relayData, consts.amountToRelay, - consts.repaymentChainId + consts.destinationChainId ) ) ).to.be.revertedWith("invalid fees"); @@ -216,7 +417,7 @@ describe("SpokePool Relayer Logic", async function () { toWei("0.5") ).relayData, consts.amountToRelay, - consts.repaymentChainId + consts.destinationChainId ) ) ).to.be.revertedWith("invalid fees"); @@ -248,7 +449,7 @@ describe("SpokePool Relayer Logic", async function () { destErc20.address ).relayData, toBN("1"), // relay any amount - consts.repaymentChainId + consts.destinationChainId ) ) ).to.be.revertedWith("relay filled"); @@ -264,7 +465,7 @@ describe("SpokePool Relayer Logic", async function () { destErc20.address ).relayData, toBN("1"), // relay any amount - consts.repaymentChainId, + consts.destinationChainId, BigNumber.from(0) ) ) @@ -303,7 +504,7 @@ async function testUpdatedFeeSignaling(depositorAddress: string) { updatedMessage ); - // Cannot set new relayer fee pct >= 50% + // Cannot set new relayer fee pct >= 50% or <= -50% await expect( spokePool .connect(relayer) @@ -315,7 +516,19 @@ async function testUpdatedFeeSignaling(depositorAddress: string) { updatedMessage, signature ) - ).to.be.revertedWith("invalid relayer fee"); + ).to.be.revertedWith("Invalid relayer fee"); + await expect( + spokePool + .connect(relayer) + .speedUpDeposit( + depositorAddress, + toWei("0.5").mul(-1), + consts.firstDepositId, + updatedRecipient, + updatedMessage, + signature + ) + ).to.be.revertedWith("Invalid relayer fee"); await expect( spokePool @@ -407,20 +620,23 @@ async function testUpdatedFeeSignaling(depositorAddress: string) { } async function testfillRelayWithUpdatedDeposit(depositorAddress: string) { + const acrossMessageHandler = await createFake("AcrossMessageHandlerMock"); + const updatedRecipient = acrossMessageHandler.address; + const updatedMessage = "0x1234"; + // The relay should succeed just like before with the same amount of tokens pulled from the relayer's wallet, // however the filled amount should have increased since the proportion of the relay filled would increase with a // higher fee. const { relayHash, relayData } = getRelayHash( depositorAddress, - recipient.address, + depositor.address, consts.firstDepositId, consts.originChainId, consts.destinationChainId, destErc20.address ); - - const updatedRecipient = depositor.address; - const updatedMessage = "0x1234"; + expect(relayData.message).to.not.equal(updatedMessage); + expect(relayData.recipient).to.not.equal(updatedRecipient); const { signature } = await modifyRelayHelper( consts.modifiedRelayerFeePct, @@ -439,7 +655,7 @@ async function testfillRelayWithUpdatedDeposit(depositorAddress: string) { consts.amountToRelay, consts.modifiedRelayerFeePct, signature, - undefined, + consts.destinationChainId, updatedRecipient, updatedMessage ) @@ -450,7 +666,7 @@ async function testfillRelayWithUpdatedDeposit(depositorAddress: string) { relayData.amount, consts.amountToRelayPreModifiedFees, consts.amountToRelayPreModifiedFees, - consts.repaymentChainId, + consts.destinationChainId, toBN(relayData.originChainId), toBN(relayData.destinationChainId), relayData.relayerFeePct, @@ -466,28 +682,32 @@ async function testfillRelayWithUpdatedDeposit(depositorAddress: string) { updatedMessage, consts.modifiedRelayerFeePct, // Applied relayer fee % should be diff from original fee %. false, + "0", ] ); - // relayExecution.relay.amount, - // relayFills[relayExecution.relayHash], - // fillAmountPreFees, - // relayExecution.repaymentChainId, - // relayExecution.relay.originChainId, - // relayExecution.relay.destinationChainId, - // relayExecution.relay.relayerFeePct, - // relayExecution.relay.realizedLpFeePct, - // relayExecution.relay.depositId, - // relayExecution.relay.destinationToken, - // msg.sender, - // relayExecution.relay.depositor, - // relayExecution.relay.recipient, - // relayExecution.relay.message, - // relayExecutionInfo + // Check that updated message and recipient are used with executed fill: + const amountActuallySent = await destErc20.balanceOf(acrossMessageHandler.address); + expect(acrossMessageHandler.handleAcrossMessage).to.have.been.calledOnceWith( + relayData.destinationToken, + amountActuallySent, + false, + relayer.address, + updatedMessage + ); // The collateral should have transferred from relayer to recipient. - expect(await destErc20.balanceOf(relayer.address)).to.equal(consts.amountToSeedWallets.sub(consts.amountToRelay)); - expect(await destErc20.balanceOf(recipient.address)).to.equal(consts.amountToRelay); + const relayerBalance = await destErc20.balanceOf(relayer.address); + const expectedRelayerBalance = consts.amountToSeedWallets.sub(consts.amountToRelay); + + // Note: We need to add an error bound of 1 wei to the expected balance because of the possibility + // of rounding errors with the modified fees. The unmodified fees result in clean numbers but the modified fee does not. + expect(relayerBalance.gte(expectedRelayerBalance.sub(1)) || relayerBalance.lte(expectedRelayerBalance.add(1))).to.be + .true; + const recipientBalance = amountActuallySent; + const expectedRecipientBalance = consts.amountToRelay; + expect(recipientBalance.gte(expectedRecipientBalance.sub(1)) || recipientBalance.lte(expectedRecipientBalance.add(1))) + .to.be.true; // Fill amount should be be set taking into account modified fees. expect(await spokePool.relayFills(relayHash)).to.equal(consts.amountToRelayPreModifiedFees); @@ -524,7 +744,7 @@ async function testUpdatedFeeSignatureFailCases(depositorAddress: string) { consts.amountToRelay, consts.modifiedRelayerFeePct, incorrectFeeSignature, - undefined, + consts.destinationChainId, updatedRecipient, updatedMessage ) @@ -549,7 +769,7 @@ async function testUpdatedFeeSignatureFailCases(depositorAddress: string) { consts.amountToRelay, consts.modifiedRelayerFeePct, incorrectDepositIdSignature, - undefined, + consts.destinationChainId, updatedRecipient, updatedMessage ) @@ -572,7 +792,7 @@ async function testUpdatedFeeSignatureFailCases(depositorAddress: string) { consts.amountToRelay, consts.modifiedRelayerFeePct, incorrectChainIdSignature, - undefined, + consts.destinationChainId, updatedRecipient, updatedMessage ) @@ -597,7 +817,7 @@ async function testUpdatedFeeSignatureFailCases(depositorAddress: string) { consts.amountToRelay, consts.modifiedRelayerFeePct, incorrectSignerSignature, - undefined, + consts.destinationChainId, updatedRecipient, updatedMessage ) diff --git a/test/SpokePool.RelayRootBundle.ts b/test/SpokePool.RelayRootBundle.ts index e6142e7a3..16a66e338 100644 --- a/test/SpokePool.RelayRootBundle.ts +++ b/test/SpokePool.RelayRootBundle.ts @@ -1,4 +1,4 @@ -import { expect, Contract, ethers, SignerWithAddress } from "./utils"; +import { expect, Contract, ethers, SignerWithAddress } from "../utils/utils"; import { spokePoolFixture } from "./fixtures/SpokePool.Fixture"; import { mockRelayerRefundRoot, mockSlowRelayRoot } from "./constants"; diff --git a/test/SpokePool.SlowRelay.ts b/test/SpokePool.SlowRelay.ts index ddad9e3b6..4e5be614e 100644 --- a/test/SpokePool.SlowRelay.ts +++ b/test/SpokePool.SlowRelay.ts @@ -8,7 +8,8 @@ import { randomAddress, randomBigNumber, BigNumber, -} from "./utils"; + toWei, +} from "../utils/utils"; import { spokePoolFixture, enableRoutes, getExecuteSlowRelayParams, SlowFill } from "./fixtures/SpokePool.Fixture"; import { getFillRelayParams, getRelayHash } from "./fixtures/SpokePool.Fixture"; import { MerkleTree } from "../utils/MerkleTree"; @@ -47,8 +48,8 @@ describe("SpokePool Slow Relay Logic", async function () { await seedWallet(relayer, [destErc20], weth, consts.amountToSeedWallets); // Send tokens to the spoke pool for repayment. - await destErc20.connect(depositor).transfer(spokePool.address, fullRelayAmountPostFees); - await weth.connect(depositor).transfer(spokePool.address, fullRelayAmountPostFees); + await destErc20.connect(depositor).transfer(spokePool.address, fullRelayAmountPostFees.mul(10)); + await weth.connect(depositor).transfer(spokePool.address, fullRelayAmountPostFees.div(2)); // Approve spoke pool to take relayer's tokens. await destErc20.connect(relayer).approve(spokePool.address, fullRelayAmountPostFees); @@ -73,7 +74,7 @@ describe("SpokePool Slow Relay Logic", async function () { depositId: randomBigNumber(2).toString(), message: randomBigNumber(100).toHexString(), }, - payoutAdjustmentPct: "0", + payoutAdjustmentPct: toBN(0), }); } @@ -91,7 +92,7 @@ describe("SpokePool Slow Relay Logic", async function () { depositId: consts.firstDepositId.toString(), message: erc20Message, }, - payoutAdjustmentPct: "0", + payoutAdjustmentPct: ethers.utils.parseEther("9"), // 10x payout. }); // WETH @@ -108,7 +109,41 @@ describe("SpokePool Slow Relay Logic", async function () { depositId: consts.firstDepositId.toString(), message: wethMessage, }, - payoutAdjustmentPct: "0", + payoutAdjustmentPct: ethers.utils.parseEther("-0.5"), // 50% payout. + }); + + // Broken payout adjustment, too small. + slowFills.push({ + relayData: { + depositor: depositor.address, + recipient: recipient.address, + destinationToken: weth.address, + amount: consts.amountToRelay, + originChainId: consts.originChainId.toString(), + destinationChainId: consts.destinationChainId.toString(), + realizedLpFeePct: consts.realizedLpFeePct, + relayerFeePct: consts.depositRelayerFeePct, + depositId: consts.firstDepositId.toString(), + message: wethMessage, + }, + payoutAdjustmentPct: ethers.utils.parseEther("-1.01"), // Over -100% payout. + }); + + // Broken payout adjustment, too large. + slowFills.push({ + relayData: { + depositor: depositor.address, + recipient: recipient.address, + destinationToken: destErc20.address, + amount: consts.amountToRelay, + originChainId: consts.originChainId.toString(), + destinationChainId: consts.destinationChainId.toString(), + realizedLpFeePct: consts.realizedLpFeePct, + relayerFeePct: consts.depositRelayerFeePct, + depositId: consts.firstDepositId.toString(), + message: erc20Message, + }, + payoutAdjustmentPct: ethers.utils.parseEther("101"), // 10000% payout is the limit. }); tree = await buildSlowRelayTree(slowFills); @@ -131,14 +166,14 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, erc20Message, - ZERO, + ethers.utils.parseEther("9"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === destErc20.address)!) ) ) ).to.changeTokenBalances( destErc20, [spokePool, recipient], - [fullRelayAmountPostFees.mul(-1), fullRelayAmountPostFees] + [fullRelayAmountPostFees.mul(10).mul(-1), fullRelayAmountPostFees.mul(10)] ); }); @@ -160,7 +195,7 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, erc20Message, - ZERO, + ethers.utils.parseEther("9"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === destErc20.address)!) ) ) @@ -186,6 +221,7 @@ describe("SpokePool Slow Relay Logic", async function () { erc20Message, 0, // Should not have an applied relayerFeePct for slow relay fills. true, + "9000000000000000000", ] ); }); @@ -206,11 +242,11 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, wethMessage, - ZERO, + ethers.utils.parseEther("-0.5"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === weth.address)!) ) ) - ).to.changeTokenBalances(weth, [spokePool], [fullRelayAmountPostFees.mul(-1)]); + ).to.changeTokenBalances(weth, [spokePool], [fullRelayAmountPostFees.div(2).mul(-1)]); }); it("Simple SlowRelay ETH balance", async function () { @@ -229,40 +265,45 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, wethMessage, - ZERO, + ethers.utils.parseEther("-0.5"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === weth.address)!) ) ) - ).to.changeEtherBalance(recipient, fullRelayAmountPostFees); + ).to.changeEtherBalance(recipient, fullRelayAmountPostFees.div(2)); }); it("Partial SlowRelay ERC20 balances", async function () { - // Work out a partial amount to fill normally. This should be 1/4 of the total amount post fees, minus - // the associated deposit relayer fee that is allocated to the fast relayer. - const partialAmountPostFees = fullRelayAmountPostFees - .mul(toBN(consts.oneHundredPct).sub(consts.depositRelayerFeePct).div(consts.oneHundredPct)) - .div(4); - const leftoverPostFees = fullRelayAmountPostFees.sub(partialAmountPostFees); - - await spokePool - .connect(relayer) - .fillRelay( - ...getFillRelayParams( - getRelayHash( - depositor.address, - recipient.address, - consts.firstDepositId, - consts.originChainId, - consts.destinationChainId, - destErc20.address, - consts.amountToRelay, - undefined, - undefined, - erc20Message - ).relayData, - partialAmountPostFees - ) - ); + // Work out a partial amount to fill. Send 1/4 of full amount. + const partialAmount = consts.amountToRelay.mul(toWei("0.25")).div(consts.oneHundredPct); + // This is the amount that we will actually send to the recipient post-fees. + const partialAmountPostFees = partialAmount + .mul(consts.oneHundredPct.sub(consts.depositRelayerFeePct).sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); + // This is the on-chain remaining amount of the relay. + const remainingFillAmount = consts.amountToRelay.sub(partialAmount); + // This is the amount sent to recipient after the slow fill removes the realized LP fee. The relayer fee is credited back to user. + const slowFillAmountPostFees = remainingFillAmount + .mul(consts.oneHundredPct.sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); + await spokePool.connect(relayer).fillRelay( + ...getFillRelayParams( + getRelayHash( + depositor.address, + recipient.address, + consts.firstDepositId, + consts.originChainId, + consts.destinationChainId, + destErc20.address, + consts.amountToRelay, + undefined, + undefined, + erc20Message + ).relayData, + partialAmountPostFees, // Set post fee amount as max amount to send so that relay filled amount is + // decremented by exactly the `partialAmount`. + consts.destinationChainId // Partial fills must set repayment chain to destination. + ) + ); await expect(() => spokePool .connect(relayer) @@ -278,18 +319,26 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, erc20Message, - ZERO, + ethers.utils.parseEther("9"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === destErc20.address)!) ) ) - ).to.changeTokenBalances(destErc20, [spokePool, recipient], [leftoverPostFees.mul(-1), leftoverPostFees]); + ).to.changeTokenBalances( + destErc20, + [spokePool, recipient], + [slowFillAmountPostFees.mul(10).mul(-1), slowFillAmountPostFees.mul(10)] + ); }); it("Partial SlowRelay WETH balance", async function () { - const partialAmountPostFees = fullRelayAmountPostFees - .mul(toBN(consts.oneHundredPct).sub(consts.depositRelayerFeePct).div(consts.oneHundredPct)) - .div(4); - const leftoverPostFees = fullRelayAmountPostFees.sub(partialAmountPostFees); + const partialAmount = consts.amountToRelay.mul(toWei("0.25")).div(consts.oneHundredPct); + const partialAmountPostFees = partialAmount + .mul(consts.oneHundredPct.sub(consts.depositRelayerFeePct).sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); + const remainingFillAmount = consts.amountToRelay.sub(partialAmount); + const slowFillAmountPostFees = remainingFillAmount + .mul(consts.oneHundredPct.sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); await spokePool .connect(relayer) @@ -307,7 +356,8 @@ describe("SpokePool Slow Relay Logic", async function () { undefined, wethMessage ).relayData, - partialAmountPostFees + partialAmountPostFees, + consts.destinationChainId ) ); @@ -326,18 +376,22 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, wethMessage, - ZERO, + ethers.utils.parseEther("-0.5"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === weth.address)!) ) ) - ).to.changeTokenBalances(weth, [spokePool], [leftoverPostFees.mul(-1)]); + ).to.changeTokenBalances(weth, [spokePool], [slowFillAmountPostFees.div(2).mul(-1)]); }); it("Partial SlowRelay ETH balance", async function () { - const partialAmountPostFees = fullRelayAmountPostFees - .mul(toBN(consts.oneHundredPct).sub(consts.depositRelayerFeePct).div(consts.oneHundredPct)) - .div(4); - const leftoverPostFees = fullRelayAmountPostFees.sub(partialAmountPostFees); + const partialAmount = consts.amountToRelay.mul(toWei("0.25")).div(consts.oneHundredPct); + const partialAmountPostFees = partialAmount + .mul(consts.oneHundredPct.sub(consts.depositRelayerFeePct).sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); + const remainingFillAmount = consts.amountToRelay.sub(partialAmount); + const slowFillAmountPostFees = remainingFillAmount + .mul(consts.oneHundredPct.sub(consts.realizedLpFeePct)) + .div(consts.oneHundredPct); await spokePool .connect(relayer) @@ -355,7 +409,8 @@ describe("SpokePool Slow Relay Logic", async function () { undefined, wethMessage ).relayData, - partialAmountPostFees + partialAmountPostFees, + consts.destinationChainId ) ); @@ -374,11 +429,69 @@ describe("SpokePool Slow Relay Logic", async function () { consts.firstDepositId, 0, wethMessage, - ZERO, + ethers.utils.parseEther("-0.5"), tree.getHexProof(slowFills.find((slowFill) => slowFill.relayData.destinationToken === weth.address)!) ) ) - ).to.changeEtherBalance(recipient, leftoverPostFees); + ).to.changeEtherBalance(recipient, slowFillAmountPostFees.div(2)); + }); + + it("Payout adjustment too large", async function () { + await expect( + spokePool + .connect(relayer) + .executeSlowRelayLeaf( + ...getExecuteSlowRelayParams( + depositor.address, + recipient.address, + destErc20.address, + consts.amountToRelay, + consts.originChainId, + consts.realizedLpFeePct, + consts.depositRelayerFeePct, + consts.firstDepositId, + 0, + erc20Message, + ethers.utils.parseEther("101"), + tree.getHexProof( + slowFills.find( + (slowFill) => + slowFill.relayData.destinationToken === destErc20.address && + slowFill.payoutAdjustmentPct.eq(ethers.utils.parseEther("101")) + )! + ) + ) + ) + ).to.revertedWith("payoutAdjustmentPct too large"); + }); + + it("Payout adjustment too small", async function () { + await expect( + spokePool + .connect(relayer) + .executeSlowRelayLeaf( + ...getExecuteSlowRelayParams( + depositor.address, + recipient.address, + weth.address, + consts.amountToRelay, + consts.originChainId, + consts.realizedLpFeePct, + consts.depositRelayerFeePct, + consts.firstDepositId, + 0, + wethMessage, + ethers.utils.parseEther("-1.01"), + tree.getHexProof( + slowFills.find( + (slowFill) => + slowFill.relayData.destinationToken === weth.address && + slowFill.payoutAdjustmentPct.eq(ethers.utils.parseEther("-1.01")) + )! + ) + ) + ) + ).to.revertedWith("payoutAdjustmentPct too small"); }); it("Bad proof: Relay data is correct except that destination chain ID doesn't match spoke pool's", async function () { diff --git a/test/SpokePool.Upgrades.ts b/test/SpokePool.Upgrades.ts index 1f6065cb3..38b2b2079 100644 --- a/test/SpokePool.Upgrades.ts +++ b/test/SpokePool.Upgrades.ts @@ -1,4 +1,5 @@ -import { expect, ethers, Contract, SignerWithAddress, hre, randomAddress } from "./utils"; +import { expect, ethers, Contract, SignerWithAddress, randomAddress } from "../utils/utils"; +import { hre } from "../utils/utils.hre"; import { spokePoolFixture } from "./fixtures/SpokePool.Fixture"; let spokePool: Contract; diff --git a/test/chain-adapters/Arbitrum_Adapter.ts b/test/chain-adapters/Arbitrum_Adapter.ts index 063dffac3..9405a5d46 100644 --- a/test/chain-adapters/Arbitrum_Adapter.ts +++ b/test/chain-adapters/Arbitrum_Adapter.ts @@ -9,8 +9,10 @@ import { toWei, defaultAbiCoder, toBN, -} from "../utils"; -import { getContractFactory, seedWallet, randomAddress } from "../utils"; + getContractFactory, + seedWallet, + randomAddress, +} from "../../utils/utils"; import { hubPoolFixture, enableTokensForLP } from "../fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "../MerkleLib.utils"; diff --git a/test/chain-adapters/Arbitrum_SendTokensAdapter.ts b/test/chain-adapters/Arbitrum_SendTokensAdapter.ts index 04684a020..d4aebd1cd 100644 --- a/test/chain-adapters/Arbitrum_SendTokensAdapter.ts +++ b/test/chain-adapters/Arbitrum_SendTokensAdapter.ts @@ -9,8 +9,8 @@ import { toWei, defaultAbiCoder, toBN, -} from "../utils"; -import { getContractFactory, seedWallet, randomAddress } from "../utils"; +} from "../../utils/utils"; +import { getContractFactory, seedWallet, randomAddress } from "../../utils/utils"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; let hubPool: Contract, arbitrumAdapter: Contract, weth: Contract, mockSpoke: Contract; diff --git a/test/chain-adapters/Ethereum_Adapter.ts b/test/chain-adapters/Ethereum_Adapter.ts index 5ee0a44b2..c2103a1c0 100644 --- a/test/chain-adapters/Ethereum_Adapter.ts +++ b/test/chain-adapters/Ethereum_Adapter.ts @@ -1,6 +1,14 @@ import * as consts from "../constants"; -import { ethers, expect, Contract, SignerWithAddress, randomAddress, hre } from "../utils"; -import { getContractFactory, seedWallet } from "../utils"; +import { + ethers, + expect, + Contract, + SignerWithAddress, + randomAddress, + getContractFactory, + seedWallet, +} from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture, enableTokensForLP } from "../fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "../MerkleLib.utils"; diff --git a/test/chain-adapters/Optimism_Adapter.ts b/test/chain-adapters/Optimism_Adapter.ts index 0a4b689b2..4e6b719e2 100644 --- a/test/chain-adapters/Optimism_Adapter.ts +++ b/test/chain-adapters/Optimism_Adapter.ts @@ -1,6 +1,15 @@ import { sampleL2Gas, amountToLp, mockTreeRoot, refundProposalLiveness, bondAmount } from "./../constants"; -import { ethers, expect, Contract, FakeContract, SignerWithAddress, createFake, hre } from "../utils"; -import { getContractFactory, seedWallet, randomAddress } from "../utils"; +import { + ethers, + expect, + Contract, + FakeContract, + SignerWithAddress, + createFake, + getContractFactory, + seedWallet, + randomAddress, +} from "../../utils/utils"; import { hubPoolFixture, enableTokensForLP } from "../fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "../MerkleLib.utils"; diff --git a/test/chain-adapters/Polygon_Adapter.ts b/test/chain-adapters/Polygon_Adapter.ts index 3809cb58b..2ce46fe9f 100644 --- a/test/chain-adapters/Polygon_Adapter.ts +++ b/test/chain-adapters/Polygon_Adapter.ts @@ -1,6 +1,16 @@ import { amountToLp, mockTreeRoot, refundProposalLiveness, bondAmount, mockSlowRelayRoot } from "./../constants"; -import { ethers, expect, Contract, FakeContract, SignerWithAddress } from "../utils"; -import { createFake, getContractFactory, seedWallet, randomAddress, hre } from "../utils"; +import { + ethers, + expect, + Contract, + FakeContract, + SignerWithAddress, + createFake, + getContractFactory, + seedWallet, + randomAddress, +} from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture, enableTokensForLP } from "../fixtures/HubPool.Fixture"; import { constructSingleChainTree } from "../MerkleLib.utils"; import { TokenRolesEnum } from "@uma/common"; diff --git a/test/chain-adapters/Succinct_Adapter.ts b/test/chain-adapters/Succinct_Adapter.ts index 7970a114c..3f1dcd4cf 100644 --- a/test/chain-adapters/Succinct_Adapter.ts +++ b/test/chain-adapters/Succinct_Adapter.ts @@ -1,5 +1,5 @@ -import { ethers, expect, Contract, FakeContract, SignerWithAddress } from "../utils"; -import { createFake, getContractFactory, randomAddress } from "../utils"; +import { ethers, expect, Contract, FakeContract, SignerWithAddress } from "../../utils/utils"; +import { createFake, getContractFactory, randomAddress } from "../../utils/utils"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; let hubPool: Contract, succinctAdapter: Contract, mockSpoke: Contract; diff --git a/test/chain-specific-spokepools/Arbitrum_SpokePool.ts b/test/chain-specific-spokepools/Arbitrum_SpokePool.ts index e692ffab8..087490d34 100644 --- a/test/chain-specific-spokepools/Arbitrum_SpokePool.ts +++ b/test/chain-specific-spokepools/Arbitrum_SpokePool.ts @@ -1,6 +1,17 @@ import { mockTreeRoot, amountToReturn, amountHeldByPool, zeroAddress } from "../constants"; -import { ethers, expect, Contract, FakeContract, SignerWithAddress, createFake, toWei } from "../utils"; -import { getContractFactory, seedContract, avmL1ToL2Alias, hre } from "../utils"; +import { + ethers, + expect, + Contract, + FakeContract, + SignerWithAddress, + createFake, + toWei, + getContractFactory, + seedContract, + avmL1ToL2Alias, +} from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; import { constructSingleRelayerRefundTree } from "../MerkleLib.utils"; diff --git a/test/chain-specific-spokepools/Ethereum_SpokePool.ts b/test/chain-specific-spokepools/Ethereum_SpokePool.ts index 4fa3bafd4..46fed70e0 100644 --- a/test/chain-specific-spokepools/Ethereum_SpokePool.ts +++ b/test/chain-specific-spokepools/Ethereum_SpokePool.ts @@ -1,6 +1,6 @@ import { mockTreeRoot, amountToReturn, amountHeldByPool } from "../constants"; -import { ethers, expect, Contract, SignerWithAddress, hre } from "../utils"; -import { getContractFactory, seedContract } from "../utils"; +import { ethers, expect, Contract, SignerWithAddress, getContractFactory, seedContract } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; import { constructSingleRelayerRefundTree } from "../MerkleLib.utils"; diff --git a/test/chain-specific-spokepools/Optimism_SpokePool.ts b/test/chain-specific-spokepools/Optimism_SpokePool.ts index 5caaf871d..f9e360659 100644 --- a/test/chain-specific-spokepools/Optimism_SpokePool.ts +++ b/test/chain-specific-spokepools/Optimism_SpokePool.ts @@ -1,25 +1,35 @@ import { mockTreeRoot, amountToReturn, amountHeldByPool } from "../constants"; -import { ethers, expect, Contract, FakeContract, SignerWithAddress, createFake, toWei } from "../utils"; -import { getContractFactory, seedContract, hre } from "../utils"; +import { + ethers, + expect, + Contract, + FakeContract, + SignerWithAddress, + createFake, + toWei, + getContractFactory, + seedContract, +} from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; + import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; import { constructSingleRelayerRefundTree } from "../MerkleLib.utils"; -let hubPool: Contract, optimismSpokePool: Contract, timer: Contract, dai: Contract, weth: Contract; +let hubPool: Contract, optimismSpokePool: Contract, dai: Contract, weth: Contract; let l2Dai: string; let owner: SignerWithAddress, relayer: SignerWithAddress, rando: SignerWithAddress; -let crossDomainMessenger: FakeContract, l2StandardBridge: FakeContract, l2Weth: FakeContract; +let crossDomainMessenger: FakeContract, l2StandardBridge: FakeContract; + +const l2Eth = "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000"; describe("Optimism Spoke Pool", function () { beforeEach(async function () { [owner, relayer, rando] = await ethers.getSigners(); - ({ weth, dai, l2Dai, hubPool, timer } = await hubPoolFixture()); + ({ weth, dai, l2Dai, hubPool } = await hubPoolFixture()); // Create the fake at the optimism cross domain messenger and l2StandardBridge pre-deployment addresses. crossDomainMessenger = await createFake("L2CrossDomainMessenger", "0x4200000000000000000000000000000000000007"); - l2StandardBridge = await createFake("L2StandardBridge", "0x4200000000000000000000000000000000000010"); - - // Set l2Weth to the address deployed on the optimism predeploy. - l2Weth = await createFake("WETH9", "0x4200000000000000000000000000000000000006"); + l2StandardBridge = await createFake("MockBedrockL2StandardBridge", "0x4200000000000000000000000000000000000010"); await hre.network.provider.request({ method: "hardhat_impersonateAccount", @@ -28,8 +38,8 @@ describe("Optimism Spoke Pool", function () { await owner.sendTransaction({ to: crossDomainMessenger.address, value: toWei("1") }); optimismSpokePool = await hre.upgrades.deployProxy( - await getContractFactory("Optimism_SpokePool", owner), - [0, owner.address, hubPool.address], + await getContractFactory("MockOptimism_SpokePool", owner), + [weth.address, l2Eth, 0, owner.address, hubPool.address], { kind: "uups" } ); @@ -143,20 +153,25 @@ describe("Optimism Spoke Pool", function () { }); it("Bridge ETH to hub pool correctly calls the Standard L2 Bridge for WETH, including unwrap", async function () { const { leaves, tree } = await constructSingleRelayerRefundTree( - l2Weth.address, + weth.address, await optimismSpokePool.callStatic.chainId() ); crossDomainMessenger.xDomainMessageSender.returns(owner.address); + await optimismSpokePool.connect(crossDomainMessenger.wallet).relayRootBundle(tree.getHexRoot(), mockTreeRoot); - await optimismSpokePool.connect(relayer).executeRelayerRefundLeaf(0, leaves[0], tree.getHexProof(leaves[0])); // When sending l2Weth we should see two differences from the previous test: 1) there should be a call to l2WETH to // unwrap l2WETH to l2ETH. 2) the address in the l2StandardBridge that is withdrawn should no longer be l2WETH but // switched to l2ETH as this is what is sent over the canonical Optimism bridge when sending ETH. - expect(l2Weth.withdraw).to.have.been.calledOnce; - expect(l2Weth.withdraw).to.have.been.calledWith(amountToReturn); + + // Executing the refund leaf should cause spoke pool to unwrap WETH to ETH to prepare to send it as msg.value + // to the L2StandardBridge. This results in a net decrease in WETH balance. + await expect(() => + optimismSpokePool.connect(relayer).executeRelayerRefundLeaf(0, leaves[0], tree.getHexProof(leaves[0])) + ).to.changeTokenBalance(weth, optimismSpokePool, amountToReturn.mul(-1)); + expect(l2StandardBridge.withdrawTo).to.have.been.calledWithValue(amountToReturn); + expect(l2StandardBridge.withdrawTo).to.have.been.calledOnce; - const l2Eth = "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000"; expect(l2StandardBridge.withdrawTo).to.have.been.calledWith(l2Eth, hubPool.address, amountToReturn, 5000000, "0x"); }); }); diff --git a/test/chain-specific-spokepools/Polygon_SpokePool.ts b/test/chain-specific-spokepools/Polygon_SpokePool.ts index eece58145..8ad4c3eac 100644 --- a/test/chain-specific-spokepools/Polygon_SpokePool.ts +++ b/test/chain-specific-spokepools/Polygon_SpokePool.ts @@ -1,6 +1,18 @@ import { mockTreeRoot, amountToReturn, amountHeldByPool, zeroAddress, TokenRolesEnum } from "../constants"; -import { ethers, expect, Contract, SignerWithAddress, getContractFactory, createFake } from "../utils"; -import { seedContract, toWei, randomBigNumber, seedWallet, FakeContract, hre } from "../utils"; +import { + ethers, + expect, + Contract, + SignerWithAddress, + getContractFactory, + createFake, + seedContract, + toWei, + randomBigNumber, + seedWallet, + FakeContract, +} from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; import { constructSingleRelayerRefundTree } from "../MerkleLib.utils"; import { randomBytes } from "crypto"; diff --git a/test/chain-specific-spokepools/Succinct_SpokePool.ts b/test/chain-specific-spokepools/Succinct_SpokePool.ts index f4035a156..28e94b166 100644 --- a/test/chain-specific-spokepools/Succinct_SpokePool.ts +++ b/test/chain-specific-spokepools/Succinct_SpokePool.ts @@ -1,4 +1,5 @@ -import { ethers, expect, Contract, SignerWithAddress, getContractFactory, hre } from "../utils"; +import { ethers, expect, Contract, SignerWithAddress, getContractFactory } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; let succinctSpokePool: Contract, timer: Contract, weth: Contract; @@ -32,16 +33,17 @@ describe("Succinct Spoke Pool", function () { // Wrong origin chain id address. await expect( succinctSpokePool.connect(succinctTargetAmb).handleTelepathy(44, hubPool.address, setCrossDomainAdminData) - ).to.be.reverted; + ).to.be.revertedWith("source chain not hub chain"); // Wrong rootMessageSender address. await expect( succinctSpokePool.connect(succinctTargetAmb).handleTelepathy(l1ChainId, rando.address, setCrossDomainAdminData) - ).be.reverted; + ).be.revertedWith("sender not hubPool"); // Wrong calling address. - await expect(succinctSpokePool.connect(rando).handleTelepathy(l1ChainId, hubPool.address, setCrossDomainAdminData)) - .to.be.reverted; + await expect( + succinctSpokePool.connect(rando).handleTelepathy(l1ChainId, hubPool.address, setCrossDomainAdminData) + ).to.be.revertedWith("caller not succinct AMB"); await succinctSpokePool .connect(succinctTargetAmb) diff --git a/test/constants.ts b/test/constants.ts index 1a671efe8..c5b36312a 100644 --- a/test/constants.ts +++ b/test/constants.ts @@ -1,4 +1,4 @@ -import { toWei, utf8ToHex, toBN, createRandomBytes32 } from "./utils"; +import { toWei, utf8ToHex, toBN, createRandomBytes32 } from "../utils/utils"; import { ethers } from "ethers"; diff --git a/test/erc1155/MintableERC1155.ts b/test/erc1155/MintableERC1155.ts new file mode 100644 index 000000000..7b434eb30 --- /dev/null +++ b/test/erc1155/MintableERC1155.ts @@ -0,0 +1,60 @@ +import { ethers, getContractFactory, SignerWithAddress, Contract, expect } from "../../utils/utils"; + +let mintableErc1155: Contract; + +let accounts: SignerWithAddress[]; +let contractCreator: SignerWithAddress; +let otherAccount1: SignerWithAddress; +let otherAccount2: SignerWithAddress; +let recipients: string[]; + +describe("MintableERC1155", () => { + beforeEach(async () => { + accounts = await ethers.getSigners(); + [contractCreator, otherAccount1, otherAccount2] = accounts; + recipients = [otherAccount1.address, otherAccount2.address]; + mintableErc1155 = await (await getContractFactory("MintableERC1155", contractCreator)).deploy(); + }); + + describe("#airdrop()", () => { + const tokenId = 0; + + it("revert if not called by owner", async () => { + await expect(mintableErc1155.connect(otherAccount1).airdrop(tokenId, recipients, 1)).to.be.revertedWith( + "Ownable: caller is not the owner" + ); + }); + + it("mint token to recipients", async () => { + expect(await mintableErc1155.connect(contractCreator).airdrop(tokenId, recipients, 1)) + .to.emit(mintableErc1155, "Airdrop") + .withArgs(contractCreator.address, tokenId, recipients, 1); + + expect(await mintableErc1155.balanceOf(otherAccount1.address, tokenId)).to.equal(1); + expect(await mintableErc1155.balanceOf(otherAccount2.address, tokenId)).to.equal(1); + }); + }); + + describe("#setTokenURI() + #uri()", () => { + it("revert if not called by owner", async () => { + await expect(mintableErc1155.connect(otherAccount1).setTokenURI(0, "uri")).to.be.revertedWith( + "Ownable: caller is not the owner" + ); + }); + + it("revert if uri already set", async () => { + await mintableErc1155.connect(contractCreator).setTokenURI(0, "test"); + + await expect(mintableErc1155.connect(contractCreator).setTokenURI(0, "new uri")).to.be.revertedWith( + "uri already set" + ); + }); + + it("set token uri", async () => { + expect(await mintableErc1155.connect(contractCreator).setTokenURI(1, "test")) + .to.emit(mintableErc1155, "URI") + .withArgs(1, "test"); + expect(await mintableErc1155.uri(1)).to.equal("test"); + }); + }); +}); diff --git a/test/fixtures/BondToken.Fixture.ts b/test/fixtures/BondToken.Fixture.ts index c1224d631..a736452ad 100644 --- a/test/fixtures/BondToken.Fixture.ts +++ b/test/fixtures/BondToken.Fixture.ts @@ -1,4 +1,5 @@ -import { Contract, getContractFactory, hre } from "../utils"; +import { Contract, getContractFactory } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { hubPoolFixture } from "./HubPool.Fixture"; export const bondTokenFixture = hre.deployments.createFixture(async ({ ethers }, hubPool?: Contract) => { diff --git a/test/fixtures/HubPool.Fixture.ts b/test/fixtures/HubPool.Fixture.ts index 79cb9ccd6..065e47e4d 100644 --- a/test/fixtures/HubPool.Fixture.ts +++ b/test/fixtures/HubPool.Fixture.ts @@ -1,4 +1,5 @@ -import { getContractFactory, randomAddress, hre, Contract, Signer } from "../utils"; +import { getContractFactory, randomAddress, Contract, Signer } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { originChainId, bondAmount, refundProposalLiveness, finalFee } from "../constants"; import { repaymentChainId, finalFeeUsdc, TokenRolesEnum } from "../constants"; import { umaEcosystemFixture } from "./UmaEcosystem.Fixture"; diff --git a/test/fixtures/MerkleLib.Fixture.ts b/test/fixtures/MerkleLib.Fixture.ts index 2eb9d94f2..7d545911c 100644 --- a/test/fixtures/MerkleLib.Fixture.ts +++ b/test/fixtures/MerkleLib.Fixture.ts @@ -1,7 +1,7 @@ -import { getContractFactory } from "../utils"; -import hre from "hardhat"; +import { Contract, getContractFactory } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; -export const merkleLibFixture = hre.deployments.createFixture(async ({ deployments }) => { +export const merkleLibFixture: () => Promise<{ merkleLibTest: Contract }> = hre.deployments.createFixture(async () => { const [signer] = await hre.ethers.getSigners(); const merkleLibTest = await (await getContractFactory("MerkleLibTest", { signer })).deploy(); return { merkleLibTest }; diff --git a/test/fixtures/SpokePool.Fixture.ts b/test/fixtures/SpokePool.Fixture.ts index e2c0083e1..35ca2e31e 100644 --- a/test/fixtures/SpokePool.Fixture.ts +++ b/test/fixtures/SpokePool.Fixture.ts @@ -1,4 +1,6 @@ -import { getContractFactory, SignerWithAddress, Contract, hre, ethers, BigNumber, defaultAbiCoder } from "../utils"; +import { getContractFactory, SignerWithAddress, Contract, ethers, BigNumber, defaultAbiCoder } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; + import * as consts from "../constants"; export const spokePoolFixture = hre.deployments.createFixture(async ({ ethers }) => { @@ -181,7 +183,7 @@ export interface RelayData { export interface SlowFill { relayData: RelayData; - payoutAdjustmentPct: string; + payoutAdjustmentPct: BigNumber; } export function getRelayHash( diff --git a/test/fixtures/UmaEcosystem.Fixture.ts b/test/fixtures/UmaEcosystem.Fixture.ts index 780956512..f51e5c06e 100644 --- a/test/fixtures/UmaEcosystem.Fixture.ts +++ b/test/fixtures/UmaEcosystem.Fixture.ts @@ -1,8 +1,17 @@ -import { getContractFactory, utf8ToHex, hre } from "../utils"; +import { getContractFactory, utf8ToHex, Contract } from "../../utils/utils"; +import { hre } from "../../utils/utils.hre"; import { refundProposalLiveness, zeroRawValue, identifier } from "../constants"; import { interfaceName } from "@uma/common"; -export const umaEcosystemFixture = hre.deployments.createFixture(async ({ ethers }) => { +export const umaEcosystemFixture: () => Promise<{ + timer: Contract; + finder: Contract; + collateralWhitelist: Contract; + identifierWhitelist: Contract; + store: Contract; + optimisticOracle: Contract; + mockOracle: Contract; +}> = hre.deployments.createFixture(async ({ ethers }) => { const [signer] = await ethers.getSigners(); // Deploy the UMA ecosystem contracts. diff --git a/test/gas-analytics/BondToken.erc20.ts b/test/gas-analytics/BondToken.erc20.ts index 55ad2534a..80c0021a2 100644 --- a/test/gas-analytics/BondToken.erc20.ts +++ b/test/gas-analytics/BondToken.erc20.ts @@ -1,6 +1,6 @@ import { proposeRootBundle } from "../BondToken.e2e"; import { bondAmount, maxUint256 } from "../constants"; -import { Contract, ethers, seedWallet, SignerWithAddress, toBN } from "../utils"; +import { Contract, ethers, seedWallet, SignerWithAddress, toBN } from "../../utils/utils"; import { bondTokenFixture } from "../fixtures/BondToken.Fixture"; import { hubPoolFixture } from "../fixtures/HubPool.Fixture"; diff --git a/test/gas-analytics/HubPool.RootExecution.ts b/test/gas-analytics/HubPool.RootExecution.ts index 95c02143b..05a4216ab 100644 --- a/test/gas-analytics/HubPool.RootExecution.ts +++ b/test/gas-analytics/HubPool.RootExecution.ts @@ -1,10 +1,22 @@ -import { toBNWei, toBN, SignerWithAddress, seedWallet, Contract, ethers, hre, expect } from "../utils"; -import { getContractFactory, BigNumber, randomAddress, createRandomBytes32 } from "../utils"; +import { + toBNWei, + toBN, + SignerWithAddress, + seedWallet, + Contract, + ethers, + expect, + getContractFactory, + BigNumber, + randomAddress, + createRandomBytes32, +} from "../../utils/utils"; import { deployErc20 } from "./utils"; import * as consts from "../constants"; import { hubPoolFixture, enableTokensForLP } from "../fixtures/HubPool.Fixture"; import { buildPoolRebalanceLeafTree, buildPoolRebalanceLeaves, PoolRebalanceLeaf } from "../MerkleLib.utils"; import { MerkleTree } from "../../utils/MerkleTree"; +import { hre } from "../../utils/utils.hre"; require("dotenv").config(); diff --git a/test/gas-analytics/SpokePool.Deposit.ts b/test/gas-analytics/SpokePool.Deposit.ts index e342a9a62..002186837 100644 --- a/test/gas-analytics/SpokePool.Deposit.ts +++ b/test/gas-analytics/SpokePool.Deposit.ts @@ -1,4 +1,4 @@ -import { toBNWei, SignerWithAddress, Contract, ethers, seedWallet, toBN } from "../utils"; +import { toBNWei, SignerWithAddress, Contract, ethers, seedWallet, toBN } from "../../utils/utils"; import { constructDepositParams, sendDeposit, warmSpokePool } from "./utils"; import * as constants from "../constants"; import { spokePoolFixture } from "../fixtures/SpokePool.Fixture"; diff --git a/test/gas-analytics/SpokePool.Relay.ts b/test/gas-analytics/SpokePool.Relay.ts index 92a857d8b..8483aa9ec 100644 --- a/test/gas-analytics/SpokePool.Relay.ts +++ b/test/gas-analytics/SpokePool.Relay.ts @@ -1,4 +1,4 @@ -import { toBNWei, SignerWithAddress, Contract, ethers, seedWallet, toBN } from "../utils"; +import { toBNWei, SignerWithAddress, Contract, ethers, seedWallet, toBN } from "../../utils/utils"; import { constructRelayParams, warmSpokePool, sendRelay } from "./utils"; import * as constants from "../constants"; import { spokePoolFixture } from "../fixtures/SpokePool.Fixture"; diff --git a/test/gas-analytics/SpokePool.RelayerRefundLeafExecution.ts b/test/gas-analytics/SpokePool.RelayerRefundLeafExecution.ts index 2ddd5e9cd..0db7d70a7 100644 --- a/test/gas-analytics/SpokePool.RelayerRefundLeafExecution.ts +++ b/test/gas-analytics/SpokePool.RelayerRefundLeafExecution.ts @@ -1,5 +1,5 @@ -import { toBNWei, SignerWithAddress, Contract, ethers, BigNumber, expect } from "../utils"; -import { seedContract, toBN, seedWallet } from "../utils"; +import { toBNWei, SignerWithAddress, Contract, ethers, BigNumber, expect } from "../../utils/utils"; +import { seedContract, toBN, seedWallet } from "../../utils/utils"; import { deployErc20, warmSpokePool } from "./utils"; import * as consts from "../constants"; import { spokePoolFixture } from "../fixtures/SpokePool.Fixture"; diff --git a/test/gas-analytics/SpokePool.SlowRelayLeafExecution.ts b/test/gas-analytics/SpokePool.SlowRelayLeafExecution.ts index 43d55962b..87140d94f 100644 --- a/test/gas-analytics/SpokePool.SlowRelayLeafExecution.ts +++ b/test/gas-analytics/SpokePool.SlowRelayLeafExecution.ts @@ -1,5 +1,5 @@ -import { toBNWei, SignerWithAddress, Contract, ethers, toBN, expect } from "../utils"; -import { seedContract, seedWallet, BigNumber } from "../utils"; +import { toBNWei, SignerWithAddress, Contract, ethers, toBN, expect } from "../../utils/utils"; +import { seedContract, seedWallet, BigNumber } from "../../utils/utils"; import { deployErc20, warmSpokePool } from "./utils"; import * as consts from "../constants"; import { spokePoolFixture, RelayData, SlowFill } from "../fixtures/SpokePool.Fixture"; @@ -49,7 +49,7 @@ async function constructSimpleTree( depositId: i.toString(), message: "0x", }, - payoutAdjustmentPct: "0", + payoutAdjustmentPct: toBN(0), }); } const tree = await buildSlowRelayTree(slowFills); diff --git a/test/gas-analytics/utils.ts b/test/gas-analytics/utils.ts index 4a1fa5680..02054a0d8 100644 --- a/test/gas-analytics/utils.ts +++ b/test/gas-analytics/utils.ts @@ -1,4 +1,4 @@ -import { SignerWithAddress, getContractFactory, BigNumber, toBN, Contract } from "../utils"; +import { SignerWithAddress, getContractFactory, BigNumber, toBN, Contract } from "../../utils/utils"; import * as consts from "../constants"; import { getDepositParams, getRelayHash, getFillRelayParams, enableRoutes } from "../fixtures/SpokePool.Fixture"; @@ -39,7 +39,11 @@ export function constructRelayParams( relayAmount: BigNumber ) { const { relayData } = getRelayHash(depositor, recipient, depositId, 1, consts.destinationChainId, relayTokenAddress); - return getFillRelayParams(relayData, relayAmount); + return getFillRelayParams( + relayData, + relayAmount, + relayAmount.eq(relayData.amount) ? consts.repaymentChainId : consts.destinationChainId + ); } export async function sendRelay( _spokePool: Contract, diff --git a/test/merkle-distributor/MerkleDistributor.ts b/test/merkle-distributor/MerkleDistributor.ts index 3d9d18d90..8f1653511 100644 --- a/test/merkle-distributor/MerkleDistributor.ts +++ b/test/merkle-distributor/MerkleDistributor.ts @@ -1,16 +1,6 @@ /* eslint-disable no-unused-expressions */ -import { - ethers, - getContractFactory, - SignerWithAddress, - Contract, - toWei, - toBN, - expect, - keccak256, - defaultAbiCoder, -} from "../utils"; +import { ethers, getContractFactory, SignerWithAddress, Contract, toWei, toBN, expect } from "../../utils/utils"; import { deployErc20 } from "../gas-analytics/utils"; import { MAX_UINT_VAL, MerkleTree } from "@uma/common"; diff --git a/tsconfig.json b/tsconfig.json index fd3a07f14..7e8995796 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,8 @@ "./typechain", "./index.ts", "./test-utils.ts", - "tasks/enableL1TokenAcrossEcosystem.ts" + "tasks/enableL1TokenAcrossEcosystem.ts", + "utils/utils.ts" ], "files": ["./hardhat.config.ts"] } diff --git a/utils/MerkleTree.ts b/utils/MerkleTree.ts index f9410bbfb..4096feb48 100644 --- a/utils/MerkleTree.ts +++ b/utils/MerkleTree.ts @@ -1 +1,4 @@ -export { MerkleTree, EMPTY_MERKLE_ROOT } from "@uma/common"; +// The package `@uma/common` can not be tree-shaken and contains some modules that are not +// compatible with the browser. This is a temporary fix to avoid bundling the whole package +// until we can fix the issue upstream. +export { MerkleTree, EMPTY_MERKLE_ROOT } from "@uma/common/dist/MerkleTree"; diff --git a/utils/constants.ts b/utils/constants.ts new file mode 100644 index 000000000..62b6b4ced --- /dev/null +++ b/utils/constants.ts @@ -0,0 +1,189 @@ +export const CHAIN_IDs = { + MAINNET: 1, + OPTIMISM: 10, + ARBITRUM: 42161, + BOBA: 288, + POLYGON: 137, + GOERLI: 5, + MUMBAI: 80001, + ARBITRUM_GOERLI: 421613, + OPTIMISM_GOERLI: 420, +}; + +// NOTE: All addresses should be checksummed +export const TOKEN_SYMBOLS_MAP = { + ACX: { + name: "ACX", + symbol: "ACX", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F", + [CHAIN_IDs.OPTIMISM]: "0xFf733b2A3557a7ed6697007ab5D11B79FdD1b76B", + [CHAIN_IDs.POLYGON]: "0xF328b73B6c685831F238c30a23Fc19140CB4D8FC", + [CHAIN_IDs.BOBA]: "0x96821b258955587069F680729cD77369C0892B40", + [CHAIN_IDs.ARBITRUM]: "0x53691596d1BCe8CEa565b84d4915e69e03d9C99d", + [CHAIN_IDs.GOERLI]: "0x40153DdFAd90C49dbE3F5c9F96f2a5B25ec67461", + }, + }, + BAL: { + name: "Balancer", + symbol: "BAL", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0xba100000625a3754423978a60c9317c58a424e3D", + [CHAIN_IDs.OPTIMISM]: "0xFE8B128bA8C78aabC59d4c64cEE7fF28e9379921", + [CHAIN_IDs.POLYGON]: "0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3", + [CHAIN_IDs.ARBITRUM]: "0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8", + }, + }, + BADGER: { + name: "Badger", + symbol: "BADGER", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x3472A5A71965499acd81997a54BBA8D852C6E53d", + [CHAIN_IDs.POLYGON]: "0x1FcbE5937B0cc2adf69772D228fA4205aCF4D9b2", + [CHAIN_IDs.ARBITRUM]: "0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E", + }, + }, + BOBA: { + name: "Boba", + symbol: "BOBA", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc", + [CHAIN_IDs.BOBA]: "0xa18bF3994C0Cc6E3b63ac420308E5383f53120D7", + }, + }, + DAI: { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + [CHAIN_IDs.OPTIMISM]: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", + [CHAIN_IDs.POLYGON]: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + [CHAIN_IDs.BOBA]: "0xf74195Bb8a5cf652411867c5C2C5b8C2a402be35", + [CHAIN_IDs.ARBITRUM]: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", + [CHAIN_IDs.GOERLI]: "0x5C221E77624690fff6dd741493D735a17716c26B", + }, + }, + ETH: { + name: "Ether", + symbol: "ETH", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + [CHAIN_IDs.OPTIMISM]: "0x4200000000000000000000000000000000000006", + [CHAIN_IDs.POLYGON]: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + [CHAIN_IDs.BOBA]: "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + [CHAIN_IDs.ARBITRUM]: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + [CHAIN_IDs.GOERLI]: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", + }, + }, + MATIC: { + name: "Matic", + symbol: "MATIC", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + [CHAIN_IDs.GOERLI]: "0x499d11E0b6eAC7c0593d8Fb292DCBbF815Fb29Ae", + [CHAIN_IDs.MUMBAI]: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", + }, + }, + POOL: { + name: "PoolTogether", + symbol: "POOL", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e", + [CHAIN_IDs.OPTIMISM]: "0x395Ae52bB17aef68C2888d941736A71dC6d4e125", + [CHAIN_IDs.POLYGON]: "0x25788a1a171ec66Da6502f9975a15B609fF54CF6", + }, + }, + SNX: { + name: "Synthetix", + symbol: "SNX", + decimals: 18, + // Based on https://github.com/Synthetixio/synthetix-docs/blob/fe83d0757977b1cb7f69796126e71a66295bf264/content/addresses.md + addresses: { + [CHAIN_IDs.MAINNET]: "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", + [CHAIN_IDs.OPTIMISM]: "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4", + [CHAIN_IDs.GOERLI]: "0x51f44ca59b867E005e48FA573Cb8df83FC7f7597", + [CHAIN_IDs.OPTIMISM_GOERLI]: "0x2E5ED97596a8368EB9E44B1f3F25B2E813845303", + }, + }, + UMA: { + name: "UMA", + symbol: "UMA", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828", + [CHAIN_IDs.OPTIMISM]: "0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea", + [CHAIN_IDs.POLYGON]: "0x3066818837c5e6eD6601bd5a91B0762877A6B731", + [CHAIN_IDs.BOBA]: "0x780f33Ad21314d9A1Ffb6867Fe53d48a76Ec0D16", + [CHAIN_IDs.ARBITRUM]: "0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22", + }, + }, + USDC: { + name: "USD Coin", + symbol: "USDC", + decimals: 6, + addresses: { + [CHAIN_IDs.MAINNET]: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + [CHAIN_IDs.OPTIMISM]: "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", + [CHAIN_IDs.POLYGON]: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + [CHAIN_IDs.BOBA]: "0x66a2A913e447d6b4BF33EFbec43aAeF87890FBbc", + [CHAIN_IDs.ARBITRUM]: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + [CHAIN_IDs.GOERLI]: "0xd35CCeEAD182dcee0F148EbaC9447DA2c4D449c4", + [CHAIN_IDs.MUMBAI]: "0xe6b8a5CF854791412c1f6EFC7CAf629f5Df1c747", + }, + }, + USDT: { + name: "USDT", + symbol: "USDT", + decimals: 6, + addresses: { + [CHAIN_IDs.MAINNET]: "0xdAC17F958D2ee523a2206206994597C13D831ec7", + [CHAIN_IDs.OPTIMISM]: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", + [CHAIN_IDs.POLYGON]: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", + [CHAIN_IDs.BOBA]: "0x5DE1677344D3Cb0D7D465c10b72A8f60699C062d", + [CHAIN_IDs.ARBITRUM]: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", + }, + }, + WBTC: { + name: "Wrapped Bitcoin", + symbol: "WBTC", + decimals: 8, + addresses: { + [CHAIN_IDs.MAINNET]: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + [CHAIN_IDs.OPTIMISM]: "0x68f180fcCe6836688e9084f035309E29Bf0A2095", + [CHAIN_IDs.POLYGON]: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + [CHAIN_IDs.BOBA]: "0xdc0486f8bf31DF57a952bcd3c1d3e166e3d9eC8b", + [CHAIN_IDs.ARBITRUM]: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", + }, + }, + WETH: { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + [CHAIN_IDs.OPTIMISM]: "0x4200000000000000000000000000000000000006", + [CHAIN_IDs.POLYGON]: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + [CHAIN_IDs.BOBA]: "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000", + [CHAIN_IDs.ARBITRUM]: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + [CHAIN_IDs.GOERLI]: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", + }, + }, + WMATIC: { + name: "Matic", + symbol: "WMATIC", + decimals: 18, + addresses: { + [CHAIN_IDs.MAINNET]: "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + [CHAIN_IDs.GOERLI]: "0x499d11E0b6eAC7c0593d8Fb292DCBbF815Fb29Ae", + [CHAIN_IDs.MUMBAI]: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", + }, + }, +}; diff --git a/utils/index.ts b/utils/index.ts new file mode 100644 index 000000000..d2f151b47 --- /dev/null +++ b/utils/index.ts @@ -0,0 +1,3 @@ +export * from "./utils"; +export * from "./MerkleTree"; +export * from "./constants"; diff --git a/utils/utils.hre.ts b/utils/utils.hre.ts new file mode 100644 index 000000000..b7c5a1ba6 --- /dev/null +++ b/utils/utils.hre.ts @@ -0,0 +1,22 @@ +import { getContractFactory } from "./utils"; +import hre from "hardhat"; + +export async function deployNewProxy(name: string, args: (number | string)[]): Promise { + const { run, upgrades } = hre; + + const proxy = await upgrades.deployProxy(await getContractFactory(name, {}), args, { kind: "uups" }); + const instance = await proxy.deployed(); + console.log(`New ${name} proxy deployed @ ${instance.address}`); + const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address); + console.log(`${name} implementation deployed @ ${implementationAddress}`); + + // hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed + // is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy + // to the implementation's ABI on etherscan. + // https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify + await run("verify:verify", { + address: instance.address, + }); +} + +export { hre }; diff --git a/test/utils.ts b/utils/utils.ts similarity index 95% rename from test/utils.ts rename to utils/utils.ts index eddb50c7f..b4c86aca7 100644 --- a/test/utils.ts +++ b/utils/utils.ts @@ -5,14 +5,13 @@ import * as chai from "chai"; import { getBytecode, getAbi } from "@uma/contracts-node"; import * as optimismContracts from "@eth-optimism/contracts"; import { smock, FakeContract } from "@defi-wonderland/smock"; -chai.use(smock.matchers); -import hre from "hardhat"; +import { FactoryOptions } from "hardhat/types"; import { ethers } from "hardhat"; import { BigNumber, Signer, Contract, ContractFactory } from "ethers"; -import { FactoryOptions } from "hardhat/types"; - export { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +chai.use(smock.matchers); + function isFactoryOptions(signerOrFactoryOptions: Signer | FactoryOptions): signerOrFactoryOptions is FactoryOptions { return "signer" in signerOrFactoryOptions || "libraries" in signerOrFactoryOptions; } @@ -70,7 +69,7 @@ function getArbitrumArtifact(contractName: string) { // Fetch the artifact from the publish package's artifacts directory. function getLocalArtifact(contractName: string) { - const artifactsPath = `${__dirname}/../../artifacts/contracts`; + const artifactsPath = path.join(__dirname, "../../artifacts/contracts"); return findArtifactFromPath(contractName, artifactsPath); } @@ -165,7 +164,10 @@ export async function getParamType(contractName: string, functionName: string, p export async function createFake(contractName: string, targetAddress: string = "") { const contractFactory = await getContractFactory(contractName, new ethers.VoidSigner(ethers.constants.AddressZero)); - return targetAddress !== "" ? smock.fake(contractFactory, { address: targetAddress }) : smock.fake(contractFactory); + return smock.fake(contractFactory.interface.fragments, { + address: targetAddress === "" ? undefined : targetAddress, + provider: contractFactory.signer.provider, + }); } function avmL1ToL2Alias(l1Address: string) { @@ -180,4 +182,4 @@ function avmL1ToL2Alias(l1Address: string) { const { defaultAbiCoder, keccak256 } = ethers.utils; -export { avmL1ToL2Alias, expect, Contract, ethers, hre, BigNumber, defaultAbiCoder, keccak256, FakeContract, Signer }; +export { avmL1ToL2Alias, expect, Contract, ethers, BigNumber, defaultAbiCoder, keccak256, FakeContract, Signer }; diff --git a/yarn.lock b/yarn.lock index c31194d3f..8cb287fb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -213,6 +213,42 @@ resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -311,7 +347,16 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@eth-optimism/contracts@^0.5.11", "@eth-optimism/contracts@^0.5.5": +"@eth-optimism/contracts@^0.5.40": + version "0.5.40" + resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.5.40.tgz#d13a04a15ea947a69055e6fc74d87e215d4c936a" + integrity sha512-MrzV0nvsymfO/fursTB7m/KunkPsCndltVgfdHaT1Aj5Vi6R/doKIGGkOofHX+8B6VMZpuZosKCMQ5lQuqjt8w== + dependencies: + "@eth-optimism/core-utils" "0.12.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + +"@eth-optimism/contracts@^0.5.5": version "0.5.15" resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.5.15.tgz#71f538172acc1bab0894ead13468a7063b078adf" integrity sha512-UP3YnxuYebZS4Py2KMTE5AbkuEu/Yk/EtX9AOm0xLCxh+htet2oQ/GahwleLIq8mW2pFtchzc4zARYUJal49ug== @@ -321,6 +366,28 @@ "@ethersproject/abstract-signer" "^5.5.0" "@ethersproject/hardware-wallets" "^5.5.0" +"@eth-optimism/core-utils@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.12.0.tgz#6337e4599a34de23f8eceb20378de2a2de82b0ea" + integrity sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/providers" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bufio "^1.0.7" + chai "^4.3.4" + "@eth-optimism/core-utils@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.8.0.tgz#d2ab90aaea0a7df13157bf3f461c9a8d1893f2ac" @@ -341,17 +408,17 @@ node-fetch "^2.6.1" "@ethereum-waffle/chai@^3.4.0": - version "3.4.3" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.3.tgz#a2fbaa583f02164c6a5c755df488f45482f6f382" - integrity sha512-yu1DCuyuEvoQFP9PCbHqiycGxwKUrZ24yc/DsjkBlLAQ3OSLhbmlbMiz804YFymWCNsFmobEATp6kBuUDexo7w== + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== dependencies: - "@ethereum-waffle/provider" "^3.4.1" + "@ethereum-waffle/provider" "^3.4.4" ethers "^5.5.2" "@ethereum-waffle/compiler@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" - integrity sha512-a2wxGOoB9F1QFRE+Om7Cz2wn+pxM/o7a0a6cbwhaS2lECJgFzeN9xEkVrKahRkF4gEfXGcuORg4msP0Asxezlw== + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== dependencies: "@resolver-engine/imports" "^0.3.3" "@resolver-engine/imports-fs" "^0.3.3" @@ -365,29 +432,29 @@ ts-generator "^0.1.1" typechain "^3.0.0" -"@ethereum-waffle/ens@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.1.tgz#0f1b7ac4fc156641c18accd60f8ce256e2c475cf" - integrity sha512-xSjNWnT2Iwii3J3XGqD+F5yLEOzQzLHNLGfI5KIXdtQ4FHgReW/AMGRgPPLi+n+SP08oEQWJ3sEKrvbFlwJuaA== +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== dependencies: "@ensdomains/ens" "^0.4.4" "@ensdomains/resolver" "^0.2.4" ethers "^5.5.2" "@ethereum-waffle/mock-contract@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.1.tgz#dfd53a6e184f5e4c5e1119a8aef67f2d88914497" - integrity sha512-h9yChF7IkpJLODg/o9/jlwKwTcXJLSEIq3gewgwUJuBHnhPkJGekcZvsTbximYc+e42QUZrDUATSuTCIryeCEA== + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== dependencies: "@ethersproject/abi" "^5.5.0" ethers "^5.5.2" -"@ethereum-waffle/provider@^3.4.0", "@ethereum-waffle/provider@^3.4.1": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.1.tgz#d59f5741d5ee96a7d5501f455709b38d81c8be2f" - integrity sha512-5iDte7c9g9N1rTRE/P4npwk1Hus/wA2yH850X6sP30mr1IrwSG9NKn6/2SOQkAVJnh9jqyLVg2X9xCODWL8G4A== +"@ethereum-waffle/provider@^3.4.0", "@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== dependencies: - "@ethereum-waffle/ens" "^3.3.1" + "@ethereum-waffle/ens" "^3.4.4" ethers "^5.5.2" ganache-core "^2.13.2" patch-package "^6.2.2" @@ -636,7 +703,7 @@ "@ethersproject/logger" "^5.0.8" "@ethersproject/rlp" "^5.0.7" -"@ethersproject/address@5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.0.9", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.5.0": +"@ethersproject/address@5.5.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.0.9", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== @@ -647,7 +714,7 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -712,7 +779,7 @@ "@ethersproject/logger" "^5.0.8" bn.js "^4.4.0" -"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.13", "@ethersproject/bignumber@^5.0.5", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.5.0": +"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@^5.0.13", "@ethersproject/bignumber@^5.0.5", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== @@ -721,7 +788,7 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -737,14 +804,14 @@ dependencies: "@ethersproject/logger" "^5.0.8" -"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.0.9", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.5.0": +"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.0.9", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== @@ -758,14 +825,14 @@ dependencies: "@ethersproject/bignumber" "^5.0.13" -"@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.0.8", "@ethersproject/constants@^5.5.0": +"@ethersproject/constants@5.5.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.0.8", "@ethersproject/constants@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== dependencies: "@ethersproject/bignumber" "^5.5.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== @@ -803,7 +870,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" -"@ethersproject/contracts@5.7.0": +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== @@ -845,7 +912,7 @@ "@ethersproject/properties" "^5.0.7" "@ethersproject/strings" "^5.0.8" -"@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.10", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": +"@ethersproject/hash@5.5.0", "@ethersproject/hash@^5.0.10", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== @@ -859,7 +926,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/strings" "^5.5.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": +"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== @@ -993,7 +1060,7 @@ "@ethersproject/bytes" "^5.0.9" js-sha3 "0.5.7" -"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.0.7", "@ethersproject/keccak256@^5.5.0": +"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.0.7", "@ethersproject/keccak256@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== @@ -1001,7 +1068,7 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -1014,12 +1081,12 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.10.tgz#fd884688b3143253e0356ef92d5f22d109d2e026" integrity sha512-0y2T2NqykDrbPM3Zw9RSbPkDOxwChAL8detXaom76CfYoGxsOnRP/zTX8OUAV+x9LdwzgbWvWmeXrc0M7SuDZw== -"@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.0.8", "@ethersproject/logger@^5.5.0": +"@ethersproject/logger@5.5.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.0.8", "@ethersproject/logger@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== @@ -1076,14 +1143,14 @@ dependencies: "@ethersproject/logger" "^5.0.8" -"@ethersproject/properties@5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.0.7", "@ethersproject/properties@^5.5.0": +"@ethersproject/properties@5.5.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.0.7", "@ethersproject/properties@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== dependencies: "@ethersproject/logger" "^5.5.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== @@ -1166,7 +1233,7 @@ bech32 "1.1.4" ws "7.4.6" -"@ethersproject/providers@5.7.2": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -1345,7 +1412,7 @@ "@ethersproject/constants" "^5.0.8" "@ethersproject/logger" "^5.0.8" -"@ethersproject/strings@5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.0.8", "@ethersproject/strings@^5.5.0": +"@ethersproject/strings@5.5.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.0.8", "@ethersproject/strings@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== @@ -1354,7 +1421,7 @@ "@ethersproject/constants" "^5.5.0" "@ethersproject/logger" "^5.5.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== @@ -1966,6 +2033,14 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@morgan-stanley/ts-mocking-bird@^0.6.2": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz#2e4b60d42957bab3b50b67dbf14c3da2f62a39f7" + integrity sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA== + dependencies: + lodash "^4.17.16" + uuid "^7.0.3" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -1997,6 +2072,19 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nomicfoundation/ethereumjs-block@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" + integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + "@nomicfoundation/ethereumjs-block@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" @@ -2009,6 +2097,25 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-blockchain@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" + integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-ethash" "3.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + "@nomicfoundation/ethereumjs-blockchain@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" @@ -2027,6 +2134,14 @@ lru-cache "^5.1.1" memory-level "^1.0.0" +"@nomicfoundation/ethereumjs-common@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" + integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.1" + crc-32 "^1.2.0" + "@nomicfoundation/ethereumjs-common@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" @@ -2035,6 +2150,18 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" crc-32 "^1.2.0" +"@nomicfoundation/ethereumjs-ethash@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" + integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-ethash@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" @@ -2047,6 +2174,20 @@ bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-evm@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" + integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== + dependencies: + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + "@nomicfoundation/ethereumjs-evm@^1.0.0", "@nomicfoundation/ethereumjs-evm@^1.0.0-rc.3": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" @@ -2061,11 +2202,28 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" +"@nomicfoundation/ethereumjs-rlp@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" + integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== + "@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== +"@nomicfoundation/ethereumjs-statemanager@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" + integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + js-sdsl "^4.1.4" + "@nomicfoundation/ethereumjs-statemanager@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" @@ -2079,6 +2237,17 @@ ethereum-cryptography "0.1.3" functional-red-black-tree "^1.0.1" +"@nomicfoundation/ethereumjs-trie@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" + integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@types/readable-stream" "^2.3.13" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + "@nomicfoundation/ethereumjs-trie@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" @@ -2089,6 +2258,18 @@ ethereum-cryptography "0.1.3" readable-stream "^3.6.0" +"@nomicfoundation/ethereumjs-tx@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" + integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-tx@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" @@ -2099,6 +2280,15 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-util@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" + integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== + dependencies: + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-util@^8.0.0", "@nomicfoundation/ethereumjs-util@^8.0.0-rc.3": version "8.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" @@ -2107,7 +2297,26 @@ "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@^6.0.0", "@nomicfoundation/ethereumjs-vm@^6.0.0-rc.3": +"@nomicfoundation/ethereumjs-vm@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" + integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/ethereumjs-vm@^6.0.0-rc.3": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== @@ -2215,7 +2424,7 @@ fs-extra "^7.0.1" node-fetch "^2.6.0" -"@nomiclabs/hardhat-ethers@^2.0.2", "@nomiclabs/hardhat-ethers@^2.0.5": +"@nomiclabs/hardhat-ethers@^2.0.2": version "2.0.5" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.5.tgz#131b0da1b71680d5a01569f916ae878229d326d3" integrity sha512-A2gZAGB6kUvLx+kzM92HKuUF33F1FSe90L0TmkXkT2Hh0OKRpvWZURUSU2nghD2yC4DzfEZ3DftfeHGvZ2JTUw== @@ -2225,6 +2434,11 @@ resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.1.tgz#8057b43566a0e41abeb8142064a3c0d3f23dca86" integrity sha512-RHWYwnxryWR8hzRmU4Jm/q4gzvXpetUOJ4OPlwH2YARcDB+j79+yAYCwO0lN1SUOb4++oOTJEe6AWLEc42LIvg== +"@nomiclabs/hardhat-ethers@^2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== + "@nomiclabs/hardhat-etherscan@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.2.tgz#e8f8e2c7d773b42f18a27afe4bb71267d3546646" @@ -2238,18 +2452,21 @@ semver "^6.3.0" undici "^4.14.1" -"@nomiclabs/hardhat-etherscan@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz#ca54a03351f3de41f9f5240e37bea9d64fa24e64" - integrity sha512-OfNtUKc/ZwzivmZnnpwWREfaYncXteKHskn3yDnz+fPBZ6wfM4GR+d5RwjREzYFWE+o5iR9ruXhWw/8fejWM9g== +"@nomiclabs/hardhat-etherscan@^3.1.7": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz#72e3d5bd5d0ceb695e097a7f6f5ff6fcbf062b9a" + integrity sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ== dependencies: "@ethersproject/abi" "^5.1.2" "@ethersproject/address" "^5.0.2" - cbor "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" debug "^4.1.1" fs-extra "^7.0.1" + lodash "^4.17.11" semver "^6.3.0" - undici "^4.14.1" + table "^6.8.0" + undici "^5.14.0" "@nomiclabs/hardhat-truffle5@^2.0.0": version "2.0.5" @@ -2262,7 +2479,7 @@ ethereumjs-util "^7.1.3" fs-extra "^7.0.1" -"@nomiclabs/hardhat-waffle@^2.0.3": +"@nomiclabs/hardhat-waffle@2.0.3": version "2.0.3" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== @@ -2293,24 +2510,19 @@ source-map-support "^0.5.19" "@openzeppelin/contracts-0.8@npm:@openzeppelin/contracts@^4.3.2": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" - integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== + version "4.8.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" + integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== "@openzeppelin/contracts-upgradeable@3.4.2": version "3.4.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-3.4.2.tgz#2c2a1b0fa748235a1f495b6489349776365c51b3" integrity sha512-mDlBS17ymb2wpaLcrqRYdnBAmP1EwqhOXMvqWk2c5Q1N1pm5TkiCtXM9Xzznh4bYsQBq0aIWEkFFE2+iLSN1Tw== -"@openzeppelin/contracts-upgradeable@^4.2.0": - version "4.7.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" - integrity sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A== - -"@openzeppelin/contracts-upgradeable@^4.8.0": - version "4.8.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0.tgz#26688982f46969018e3ed3199e72a07c8d114275" - integrity sha512-5GeFgqMiDlqGT8EdORadp1ntGF0qzWZLmEY7Wbp/yVhN7/B3NNzCxujuI77ktlyG81N3CUZP8cZe3ZAQ/cW10w== +"@openzeppelin/contracts-upgradeable@4.8.3", "@openzeppelin/contracts-upgradeable@^4.2.0": + version "4.8.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz#6b076a7b751811b90fe3a172a7faeaa603e13a3f" + integrity sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg== "@openzeppelin/contracts@3.4.1-solc-0.7-2": version "3.4.1-solc-0.7-2" @@ -2332,10 +2544,10 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.4.2.tgz#4e889c9c66e736f7de189a53f8ba5b8d789425c2" integrity sha512-NyJV7sJgoGYqbtNUWgzzOGW4T6rR19FmX1IJgXGdapGPWsuMelGJn9h03nos0iqfforCbCB0iYIR0MtIuIFLLw== -"@openzeppelin/contracts@^4.2.0", "@openzeppelin/contracts@^4.3.2", "@openzeppelin/contracts@^4.7.3": - version "4.7.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" - integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== +"@openzeppelin/contracts@4.9.2", "@openzeppelin/contracts@^4.2.0", "@openzeppelin/contracts@^4.3.2": + version "4.9.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1" + integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg== "@openzeppelin/hardhat-upgrades@^1.22.0": version "1.22.0" @@ -2374,6 +2586,16 @@ proper-lockfile "^4.1.1" solidity-ast "^0.4.15" +"@pinata/sdk@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@pinata/sdk/-/sdk-2.1.0.tgz#d61aa8f21ec1206e867f4b65996db52b70316945" + integrity sha512-hkS0tcKtsjf9xhsEBs2Nbey5s+Db7x5rlOH9TaWHBXkJ7IwwOs2xnEDigNaxAHKjYAwcw+m2hzpO5QgOfeF7Zw== + dependencies: + axios "^0.21.1" + form-data "^2.3.3" + is-ipfs "^0.6.0" + path "^0.12.7" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -2971,6 +3193,14 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== +"@typechain/ethers-v5@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-11.0.0.tgz#8a11b34a386a30eed34375d05a09f893f7df838f" + integrity sha512-JDAvOjtzGuEQukgArIEseHznS2+v+vG3TpfODjNj4tu1kgmVu66G9gk7THOO04HJ5q+OJSLx9b46lc3GRGPIVA== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + "@typechain/ethers-v5@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" @@ -2978,18 +3208,10 @@ dependencies: ethers "^5.0.2" -"@typechain/ethers-v5@^7.0.1": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz#d559cffe0efe6bdbc20e644b817f6fa8add5e8f8" - integrity sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - -"@typechain/hardhat@^2.3.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.1.tgz#1e8a6e3795e115a5d5348526282b5c597fab0b78" - integrity sha512-BQV8OKQi0KAzLXCdsPO0pZBNQQ6ra8A2ucC26uFX/kquRBtJu1yEyWnVSmtr07b5hyRoJRpzUeINLnyqz4/MAw== +"@typechain/hardhat@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-8.0.0.tgz#60568b7a2d0260cc741fb0830a8caee8eb06ac64" + integrity sha512-XUVbqlMx8tJTOmzZCD/r196CidtNWAnTBZRcYxjLTKgcJMvc/kHQpWBnVMMB5QHxVKpYpCiz8g07FYCpG8rrjA== dependencies: fs-extra "^9.1.0" @@ -3010,20 +3232,20 @@ dependencies: bignumber.js "*" -"@types/bn.js@*", "@types/bn.js@5.1.0", "@types/bn.js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" - integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== - dependencies: - "@types/node" "*" - -"@types/bn.js@5.1.1": +"@types/bn.js@*", "@types/bn.js@5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== dependencies: "@types/node" "*" +"@types/bn.js@5.1.0", "@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -3031,14 +3253,12 @@ dependencies: "@types/node" "*" -"@types/chai-as-promised@^7.1.3": - version "7.1.5" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== - dependencies: - "@types/chai" "*" +"@types/chai@*", "@types/chai@^4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== -"@types/chai@*", "@types/chai@^4.2.0", "@types/chai@^4.2.21": +"@types/chai@^4.2.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== @@ -3142,9 +3362,9 @@ integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== "@types/node-fetch@^2.5.5": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" - integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== dependencies: "@types/node" "*" form-data "^3.0.0" @@ -3191,6 +3411,14 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + "@types/resolve@^0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -3206,24 +3434,24 @@ "@types/node" "*" "@types/sinon-chai@^3.2.3": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.8.tgz#5871d09ab50d671d8e6dd72e9073f8e738ac61dc" - integrity sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g== + version "3.2.9" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" + integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== dependencies: "@types/chai" "*" "@types/sinon" "*" "@types/sinon@*": - version "10.0.11" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42" - integrity sha512-dmZsHlBsKUtBpHriNjlK0ndlvEh8dcb9uV9Afsbt89QIyydpC7NcR+nWlAhASfy3GHnxTl4FX/aKE7XZUt/B4g== + version "10.0.15" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" + integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== dependencies: "@types/sinonjs__fake-timers" "*" "@types/sinonjs__fake-timers@*": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" - integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== "@types/underscore@*": version "1.11.4" @@ -3713,7 +3941,7 @@ adm-zip@^0.4.16: aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== aes-js@^3.1.1, aes-js@^3.1.2: version "3.1.2" @@ -3916,7 +4144,7 @@ argv@^0.0.2: arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== arr-flatten@^1.1.0: version "1.1.0" @@ -3926,12 +4154,12 @@ arr-flatten@^1.1.0: arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== array-back@^1.0.3, array-back@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== dependencies: typical "^2.6.0" @@ -3942,6 +4170,24 @@ array-back@^2.0.0: dependencies: typical "^2.6.1" +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -3976,7 +4222,7 @@ array-uniq@1.0.3, array-uniq@^1.0.3: array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== array.prototype.flat@^1.2.5: version "1.2.5" @@ -3987,6 +4233,17 @@ array.prototype.flat@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + arrify@^2.0.0, arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -4027,7 +4284,7 @@ assertion-error@^1.1.0: assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== ast-parents@0.0.1: version "0.0.1" @@ -4075,13 +4332,20 @@ async@2.6.2: dependencies: lodash "^4.17.11" -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== dependencies: lodash "^4.17.14" +async@^2.6.1: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -4924,7 +5188,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -4934,7 +5198,7 @@ braces@^3.0.1, braces@~3.0.2: brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-level@^1.0.1: version "1.0.1" @@ -5113,6 +5377,11 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "^4.3.0" +bufio@^1.0.7: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" + integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== + buildcheck@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.3.tgz#70451897a95d80f7807e68fc412eb2e7e35ff4d5" @@ -5133,14 +5402,14 @@ bytes@3.1.2: bytewise-core@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" - integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== dependencies: typewise-core "^1.2" bytewise@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" - integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== dependencies: bytewise-core "^1.2.2" typewise "^1.0.3" @@ -5176,7 +5445,7 @@ cacheable-request@^6.0.0: cachedown@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" - integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= + integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== dependencies: abstract-leveldown "^2.4.1" lru-cache "^3.2.0" @@ -5246,6 +5515,11 @@ caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001312: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -5271,7 +5545,7 @@ cbor@^5.0.2, cbor@^5.1.0, cbor@^5.2.0: bignumber.js "^9.0.1" nofilter "^1.0.4" -cbor@^8.0.0: +cbor@^8.0.0, cbor@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== @@ -5298,6 +5572,19 @@ chai@^4.2.0, chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" +chai@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk-pipe@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk-pipe/-/chalk-pipe-3.0.0.tgz#57dfd9b9dae6615d32a2dd611ac691f8aff47504" @@ -5452,7 +5739,7 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -cids@^0.7.1: +cids@^0.7.1, cids@~0.7.0: version "0.7.5" resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== @@ -5463,6 +5750,17 @@ cids@^0.7.1: multicodec "^1.0.0" multihashes "~0.4.15" +cids@~0.8.0: + version "0.8.3" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.8.3.tgz#aaf48ac8ed857c3d37dad94d8db1d8c9407b92db" + integrity sha512-yoXTbV3llpm+EBGWKeL9xKtksPE/s6DPoDSY4fn8I8TEW1zehWXPSB0pwAXVDlLaOlrw+sNynj995uD9abmPhA== + dependencies: + buffer "^5.6.0" + class-is "^1.1.0" + multibase "^1.0.0" + multicodec "^1.0.1" + multihashes "^1.0.1" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -5571,7 +5869,7 @@ code-point-at@^1.0.0: collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -5650,6 +5948,26 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + commander@2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" @@ -5783,7 +6101,7 @@ cookiejar@^2.1.1: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-compat@^3.21.0: version "3.21.1" @@ -6084,7 +6402,7 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-eql@^4.0.1: +deep-eql@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== @@ -6103,7 +6421,7 @@ deep-equal@~1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0: +deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -6148,17 +6466,25 @@ define-properties@^1.1.2, define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" @@ -6598,6 +6924,60 @@ es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.20.4, es-abstract@^1.21.2: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -7270,7 +7650,7 @@ ethereum-protocol@^1.0.1: resolved "https://registry.yarnpkg.com/ethereum-protocol/-/ethereum-protocol-1.0.1.tgz#b7d68142f4105e0ae7b5e178cf42f8d4dc4b93cf" integrity sha512-3KLX1mHuEsBW0dKG+c6EOJS1NBNqdCICvZW9sInmZTt5aY0oxmHVggYRE0lJu1tcnMD1K+AKHdLi6U43Awm1Vg== -ethereum-waffle@^3.4.0: +ethereum-waffle@3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" integrity sha512-ADBqZCkoSA5Isk486ntKJVjFEawIiC+3HxNqpJqONvh3YXBTNiRfXvJtGuAFLXPG91QaqkGqILEHANAo7j/olQ== @@ -7284,7 +7664,7 @@ ethereum-waffle@^3.4.0: ethereumjs-abi@0.6.5: version "0.6.5" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= + integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" @@ -7416,7 +7796,7 @@ ethereumjs-util@7.0.9: ethjs-util "0.1.6" rlp "^2.2.4" -ethereumjs-util@7.1.5, ethereumjs-util@^7.1.5: +ethereumjs-util@7.1.5, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -7451,7 +7831,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3, ethereumjs-util@^7.1.4: +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3, ethereumjs-util@^7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== @@ -7565,7 +7945,7 @@ ethers@5.0.32: "@ethersproject/web" "5.0.14" "@ethersproject/wordlists" "5.0.10" -ethers@5.7.2: +ethers@5.7.2, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -7616,7 +7996,7 @@ ethers@^4.0.0-beta.1, ethers@^4.0.32, ethers@^4.0.40: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.1, ethers@^5.0.13, ethers@^5.0.2, ethers@^5.5.0, ethers@^5.5.2, ethers@^5.5.4: +ethers@^5.0.13, ethers@^5.5.0, ethers@^5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.4.tgz#e1155b73376a2f5da448e4a33351b57a885f4352" integrity sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw== @@ -7750,7 +8130,7 @@ exit-on-epipe@~1.0.1: expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -7811,14 +8191,14 @@ ext@^1.1.2: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -7976,7 +8356,7 @@ file-uri-to-path@1.0.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -8006,11 +8386,18 @@ finalhandler@~1.1.2: find-replace@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== dependencies: array-back "^1.0.4" test-value "^2.1.0" +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@3.0.0, find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -8113,7 +8500,7 @@ flatted@^3.1.0: flow-stoplight@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= + integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== fmix@^0.1.0: version "0.1.0" @@ -8147,7 +8534,7 @@ for-each@^0.3.3, for-each@~0.3.3: for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== foreach@^2.0.5: version "2.0.5" @@ -8159,7 +8546,7 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -form-data@^2.2.0: +form-data@^2.2.0, form-data@^2.3.3: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== @@ -8213,7 +8600,7 @@ fp-ts@^1.0.0: fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" @@ -8274,7 +8661,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -8316,11 +8703,26 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.2.2, functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + ganache-core@^2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" @@ -8433,6 +8835,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-port@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" @@ -8473,7 +8885,7 @@ get-symbol-description@^1.0.0: get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== getpass@^0.1.1: version "0.1.7" @@ -8514,7 +8926,19 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.2.0, glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.2.0: +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0, glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -8589,6 +9013,13 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -8698,6 +9129,13 @@ google-p12-pem@^4.0.0: dependencies: node-forge "^1.3.1" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + got@9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -8735,7 +9173,12 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +graceful-fs@^4.1.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -8855,23 +9298,23 @@ hardhat-watcher@^2.1.1: dependencies: chokidar "^3.4.3" -hardhat@^2.12.1-ir.0: - version "2.12.1-ir.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.1-ir.0.tgz#4972a0777e5806cce6b54cf258c52570c58d141a" - integrity sha512-z5TGBaf3tpY92zcDmifPyYdQa1EGuLAcOlmqQUd0wR93Yua8UCdNyZHk+P2PNBJK4sm/DYt5d3DJbaFMN24sog== +hardhat@^2.14.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.14.0.tgz#b60c74861494aeb1b50803cf04cc47865a42b87a" + integrity sha512-73jsInY4zZahMSVFurSK+5TNCJTXMv+vemvGia0Ac34Mm19fYp6vEPVGF3sucbumszsYxiTT2TbS8Ii2dsDSoQ== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@nomicfoundation/ethereumjs-vm" "^6.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-vm" "7.0.1" "@nomicfoundation/solidity-analyzer" "^0.1.0" "@sentry/node" "^5.18.1" "@types/bn.js" "^5.1.0" @@ -8907,7 +9350,7 @@ hardhat@^2.12.1-ir.0: source-map-support "^0.5.13" stacktrace-parser "^0.1.10" tsort "0.0.1" - undici "^5.4.0" + undici "^5.14.0" uuid "^8.3.2" ws "^7.4.6" @@ -8977,6 +9420,11 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -8992,12 +9440,24 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== -has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -9024,7 +9484,7 @@ has-unicode@^2.0.0: has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -9033,7 +9493,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -9042,12 +9502,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -9105,7 +9565,7 @@ header-case@^1.0.0: heap@0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" - integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= + integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== highlight.js@^10.4.1: version "10.7.3" @@ -9135,7 +9595,7 @@ highlightjs-solidity@^2.0.5: hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -9350,6 +9810,11 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -9383,6 +9848,15 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -9407,6 +9881,11 @@ io-ts@1.10.4: dependencies: fp-ts "^1.0.0" +ip-regex@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -9415,7 +9894,7 @@ ipaddr.js@1.9.1: is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== dependencies: kind-of "^3.0.2" @@ -9434,6 +9913,15 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -9481,6 +9969,11 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -9488,6 +9981,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + is-core-module@^2.8.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" @@ -9498,7 +9998,7 @@ is-core-module@^2.8.0, is-core-module@^2.8.1: is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== dependencies: kind-of "^3.0.2" @@ -9547,7 +10047,7 @@ is-docker@^2.0.0: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" @@ -9612,6 +10112,25 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= +is-ip@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" + integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== + dependencies: + ip-regex "^4.0.0" + +is-ipfs@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/is-ipfs/-/is-ipfs-0.6.3.tgz#82a5350e0a42d01441c40b369f8791e91404c497" + integrity sha512-HyRot1dvLcxImtDqPxAaY1miO6WsiP/z7Yxpg2qpaLWv5UdhAPtLvHJ4kMLM0w8GSl8AFsVF23PHe1LzuWrUlQ== + dependencies: + bs58 "^4.0.1" + cids "~0.7.0" + mafmt "^7.0.0" + multiaddr "^7.2.1" + multibase "~0.6.0" + multihashes "~0.4.13" + is-lower-case@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" @@ -9619,7 +10138,7 @@ is-lower-case@^1.1.0: dependencies: lower-case "^1.1.0" -is-negative-zero@^2.0.1: +is-negative-zero@^2.0.1, is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== @@ -9634,7 +10153,7 @@ is-number-object@^1.0.4: is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" @@ -9688,6 +10207,13 @@ is-shared-array-buffer@^1.0.1: resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-stream-ended@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" @@ -9717,6 +10243,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array@^1.1.3, is-typed-array@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" @@ -9755,7 +10292,7 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= -is-weakref@^1.0.1: +is-weakref@^1.0.1, is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== @@ -9784,6 +10321,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -9797,14 +10339,14 @@ iso-url@~0.4.7: isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== isstream@~0.1.2: version "0.1.2" @@ -9819,6 +10361,11 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +js-sdsl@^4.1.4: + version "4.4.0" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" + integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== + js-sha3@0.5.7, js-sha3@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" @@ -10126,14 +10673,14 @@ keyv@^3.0.0: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" @@ -10537,7 +11084,7 @@ lodash@4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10581,12 +11128,12 @@ long@^5.0.0: looper@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" - integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= + integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== looper@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" - integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== loose-envify@^1.0.0: version "1.4.0" @@ -10634,7 +11181,7 @@ lru-cache@5.1.1, lru-cache@^5.1.1: lru-cache@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== dependencies: pseudomap "^1.0.1" @@ -10658,7 +11205,14 @@ ltgt@^2.1.2, ltgt@~2.2.0: ltgt@~2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" - integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= + integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== + +mafmt@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/mafmt/-/mafmt-7.1.0.tgz#4126f6d0eded070ace7dbbb6fb04977412d380b5" + integrity sha512-vpeo9S+hepT3k2h5iFxzEHvvR0GPBx9uKaErmnRzYNcaKb03DgOArjEMlgG4a9LcuZZ89a3I8xbeto487n26eA== + dependencies: + multiaddr "^7.3.0" make-dir@^3.0.0: version "3.1.0" @@ -10675,12 +11229,12 @@ make-error@^1.1.1: map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" @@ -10867,7 +11421,15 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.2: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== @@ -10950,7 +11512,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== "minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4: version "3.1.2" @@ -10985,6 +11547,11 @@ minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@~1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -11166,6 +11733,18 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multiaddr@^7.2.1, multiaddr@^7.3.0: + version "7.5.0" + resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-7.5.0.tgz#976c88e256e512263445ab03b3b68c003d5f485e" + integrity sha512-GvhHsIGDULh06jyb6ev+VfREH9evJCFIRnh3jUt9iEZ6XDbyoisZRFEI9bMvK/AiR6y66y6P+eoBw9mBYMhMvw== + dependencies: + buffer "^5.5.0" + cids "~0.8.0" + class-is "^1.1.0" + is-ip "^3.1.0" + multibase "^0.7.0" + varint "^5.0.0" + multibase@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" @@ -11174,6 +11753,14 @@ multibase@^0.7.0: base-x "^3.0.8" buffer "^5.5.0" +multibase@^1.0.0, multibase@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-1.0.1.tgz#4adbe1de0be8a1ab0274328b653c3f1903476724" + integrity sha512-KcCxpBVY8fdVKu4dJMAahq4F/2Z/9xqEjIiR7PiMe7LRGeorFn2NLmicN6nLBCqQvft6MG2Lc9X5P0IdyvnxEw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + multibase@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" @@ -11189,7 +11776,7 @@ multicodec@^0.5.5: dependencies: varint "^5.0.0" -multicodec@^1.0.0: +multicodec@^1.0.0, multicodec@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== @@ -11197,7 +11784,12 @@ multicodec@^1.0.0: buffer "^5.6.0" varint "^5.0.0" -multihashes@^0.4.15, multihashes@~0.4.15: +multiformats@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +multihashes@^0.4.15, multihashes@~0.4.13, multihashes@~0.4.15: version "0.4.21" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== @@ -11206,6 +11798,15 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" +multihashes@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-1.0.1.tgz#a89415d68283cf6287c6e219e304e75ce7fb73fe" + integrity sha512-S27Tepg4i8atNiFaU5ZOm3+gl3KQlUanLs/jWcBxQHFttgq+5x1OgbQmf2d8axJ/48zYGBd/wT9d723USMFduw== + dependencies: + buffer "^5.6.0" + multibase "^1.0.1" + varint "^5.0.0" + multimatch@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" @@ -11531,7 +12132,7 @@ object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1 object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -11547,6 +12148,11 @@ object-inspect@^1.11.0, object-inspect@^1.9.0, object-inspect@~1.12.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -11568,7 +12174,7 @@ object-keys@~0.4.0: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" @@ -11592,7 +12198,17 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1: +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.0.3: version "2.1.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== @@ -11601,10 +12217,21 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1 define-properties "^1.1.3" es-abstract "^1.19.1" +object.getownpropertydescriptors@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.21.2" + safe-array-concat "^1.0.0" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" @@ -11625,7 +12252,7 @@ obliterator@^2.0.0: oboe@2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== dependencies: http-https "^1.0.0" @@ -11916,7 +12543,7 @@ pascal-case@^2.0.0: pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== patch-package@6.2.2: version "6.2.2" @@ -11937,23 +12564,24 @@ patch-package@6.2.2: tmp "^0.0.33" patch-package@^6.2.2: - version "6.4.7" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" - integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== dependencies: "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" + chalk "^4.1.2" cross-spawn "^6.0.5" find-yarn-workspace-root "^2.0.0" - fs-extra "^7.0.1" + fs-extra "^9.0.0" is-ci "^2.0.0" klaw-sync "^6.0.0" - minimist "^1.2.0" + minimist "^1.2.6" open "^7.4.2" rimraf "^2.6.3" semver "^5.6.0" slash "^2.0.0" tmp "^0.0.33" + yaml "^1.10.2" path-browserify@^1.0.0: version "1.0.1" @@ -12028,6 +12656,14 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +path@^0.12.7: + version "0.12.7" + resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" + integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== + dependencies: + process "^0.11.1" + util "^0.10.3" + pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" @@ -12054,7 +12690,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -12103,7 +12739,7 @@ please-upgrade-node@^3.2.0: posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== postinstall-postinstall@^2.1.0: version "2.1.0" @@ -12199,7 +12835,12 @@ prettier@^1.14.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.1.2, prettier@^2.3.2: +prettier@^2.1.2, prettier@^2.3.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +prettier@^2.3.2: version "2.5.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== @@ -12231,7 +12872,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.10: +process@^0.11.1, process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= @@ -12353,7 +12994,7 @@ prr@~1.0.1: pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== psl@^1.1.28: version "1.8.0" @@ -12375,7 +13016,7 @@ public-encrypt@^4.0.0: pull-cat@^1.1.9: version "1.1.11" resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" - integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= + integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== pull-defer@^0.2.2: version "0.2.3" @@ -12398,7 +13039,7 @@ pull-level@^2.0.3: pull-live@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" - integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= + integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== dependencies: pull-cat "^1.1.9" pull-stream "^3.4.0" @@ -12406,17 +13047,17 @@ pull-live@^1.0.1: pull-pushable@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" - integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.6.14" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" - integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== pull-window@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" - integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= + integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== dependencies: looper "^2.0.0" @@ -12583,7 +13224,7 @@ readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -12596,7 +13237,29 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@^2.0.5, readable-stream@^2.2.8, readable-stream@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^3.1.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -12643,6 +13306,11 @@ recursive-readdir@^2.2.2: dependencies: minimatch "3.0.4" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + regenerate@^1.2.1: version "1.4.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" @@ -12688,6 +13356,15 @@ regexp.prototype.flags@^1.2.0: call-bind "^1.0.2" define-properties "^1.1.3" +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -12727,7 +13404,7 @@ repeat-element@^1.1.2: repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== repeating@^2.0.0: version "2.0.1" @@ -12844,7 +13521,7 @@ resolve-from@^4.0.0: resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve@1.1.x: version "1.1.7" @@ -12858,7 +13535,7 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.8.1, resolve@~1.22.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.20.0, resolve@~1.22.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -12867,6 +13544,15 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.20 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.8.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -13004,6 +13690,16 @@ rxjs@^7.2.0: dependencies: tslib "^2.1.0" +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -13021,10 +13717,19 @@ safe-event-emitter@^1.0.1: dependencies: events "^3.0.0" +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" @@ -13701,7 +14406,7 @@ stacktrace-parser@^0.1.10: static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -13751,6 +14456,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -13786,6 +14496,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trim@~1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" @@ -13803,6 +14522,15 @@ string.prototype.trimend@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" @@ -13811,6 +14539,15 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -13993,6 +14730,16 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -14014,6 +14761,17 @@ table@^6.0.9: string-width "^4.2.3" strip-ansi "^6.0.1" +table@^6.8.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + taffydb@2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" @@ -14132,7 +14890,7 @@ teeny-request@^8.0.0: test-value@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== dependencies: array-back "^1.0.3" typical "^2.6.0" @@ -14234,7 +14992,7 @@ to-fast-properties@^2.0.0: to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" @@ -14246,7 +15004,7 @@ to-readable-stream@^1.0.0: to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -14311,6 +15069,17 @@ truffle-deploy-registry@^0.5.1: mkdirp "^0.5.1" rimraf "^2.6.3" +ts-command-line-args@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.0.tgz#7eeed3a6937b2612ea08a0794cf9d43fbbea89c4" + integrity sha512-Ff7Xt04WWCjj/cmPO9eWTJX3qpBZWuPWyQYG1vnxJao+alWWYjwJBc5aYz3h5p5dE08A6AnpkgiCtP/0KXXBYw== + dependencies: + "@morgan-stanley/ts-mocking-bird" "^0.6.2" + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + ts-essentials@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" @@ -14479,22 +15248,31 @@ typechain@^3.0.0: ts-essentials "^6.0.3" ts-generator "^0.1.1" -typechain@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.2.0.tgz#10525a44773a34547eb2eed8978cb72c0a39a0f4" - integrity sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw== +typechain@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" + integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== dependencies: "@types/prettier" "^2.1.1" - command-line-args "^4.0.7" - debug "^4.1.1" + debug "^4.3.1" fs-extra "^7.0.0" - glob "^7.1.6" + glob "7.1.7" js-sha3 "^0.8.0" lodash "^4.17.15" mkdirp "^1.0.4" - prettier "^2.1.2" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" ts-essentials "^7.0.1" +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -14515,24 +15293,34 @@ typescript@^4.5.2: typewise-core@^1.2, typewise-core@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" - integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== typewise@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" - integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== dependencies: typewise-core "^1.2.0" typewiselite@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" - integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= + integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== typical@^2.6.0, typical@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== u2f-api@0.2.7: version "0.2.7" @@ -14569,6 +15357,16 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + underscore@1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" @@ -14594,10 +15392,10 @@ undici@^4.14.1: resolved "https://registry.yarnpkg.com/undici/-/undici-4.14.1.tgz#7633b143a8a10d6d63335e00511d071e8d52a1d9" integrity sha512-WJ+g+XqiZcATcBaUeluCajqy4pEDcQfK1vy+Fo+bC4/mqXI9IIQD/XWHLS70fkGUT6P52Drm7IFslO651OdLPQ== -undici@^5.4.0: - version "5.19.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.19.1.tgz#92b1fd3ab2c089b5a6bd3e579dcda8f1934ebf6d" - integrity sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A== +undici@^5.14.0: + version "5.21.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.21.0.tgz#b00dfc381f202565ab7f52023222ab862bb2494f" + integrity sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA== dependencies: busboy "^1.6.0" @@ -14641,7 +15439,7 @@ unpipe@1.0.0, unpipe@~1.0.0: unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -14668,7 +15466,7 @@ uri-js@^4.2.2: urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== url-parse-lax@^1.0.0: version "1.0.0" @@ -14733,15 +15531,24 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util.promisify@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" - integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" + integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" + call-bind "^1.0.2" + define-properties "^1.2.0" for-each "^0.3.3" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.1" + has-proto "^1.0.1" + has-symbols "^1.0.3" + object.getownpropertydescriptors "^2.1.6" + safe-array-concat "^1.0.0" + +util@^0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" util@^0.12.0: version "0.12.4" @@ -14775,6 +15582,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + uuid@^8.0.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -16106,6 +16918,18 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.7" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -16174,6 +16998,14 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + workerpool@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" @@ -16357,7 +17189,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0: +yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==